Author: markt Date: Tue Nov 28 20:49:45 2017 New Revision: 1816571 URL: http://svn.apache.org/viewvc?rev=1816571&view=rev Log: Refactor sendfile with compression support in mind. Use an approach similar to HTTP/1.1 so the StreamProcessor will have visibility of whether sendfile is in use when deciding whether or not to compress.
Added: tomcat/trunk/java/org/apache/coyote/http2/SendfileData.java (with props) Modified: tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java Modified: tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java?rev=1816571&r1=1816570&r2=1816571&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java (original) +++ tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java Tue Nov 28 20:49:45 2017 @@ -16,10 +16,8 @@ */ package org.apache.coyote.http2; -import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; -import java.nio.MappedByteBuffer; import java.nio.channels.CompletionHandler; import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; @@ -264,47 +262,37 @@ public class Http2AsyncUpgradeHandler ex } @Override - protected SendfileState processSendfile(Stream stream) { - String fileName = (String) stream.getCoyoteRequest().getAttribute( - org.apache.coyote.Constants.SENDFILE_FILENAME_ATTR); - if (fileName != null) { - java.nio.file.Path path = new File(fileName).toPath(); - SendfileData sendfile = new SendfileData(); - sendfile.pos = ((Long) stream.getCoyoteRequest().getAttribute( - org.apache.coyote.Constants.SENDFILE_FILE_START_ATTR)).longValue(); - sendfile.end = ((Long) stream.getCoyoteRequest().getAttribute( - org.apache.coyote.Constants.SENDFILE_FILE_END_ATTR)).longValue(); - sendfile.left = sendfile.end - sendfile.pos; + protected SendfileState processSendfile(SendfileData sendfile) { + if (sendfile != null) { try { - try (FileChannel channel = FileChannel.open(path, StandardOpenOption.READ)) { + try (FileChannel channel = FileChannel.open(sendfile.path, StandardOpenOption.READ)) { sendfile.mappedBuffer = channel.map(MapMode.READ_ONLY, sendfile.pos, sendfile.end - sendfile.pos); - sendfile.stream = stream; } // Reserve as much as possible right away int reservation = (sendfile.end - sendfile.pos > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) (sendfile.end - sendfile.pos); - sendfile.streamReservation = stream.reserveWindowSize(reservation, true); - sendfile.connectionReservation = reserveWindowSize(stream, sendfile.streamReservation); + sendfile.streamReservation = sendfile.stream.reserveWindowSize(reservation, true); + sendfile.connectionReservation = reserveWindowSize(sendfile.stream, sendfile.streamReservation); } catch (IOException e) { return SendfileState.ERROR; } // Actually perform the write int frameSize = Integer.min(getMaxFrameSize(), sendfile.connectionReservation); - boolean finished = (frameSize == sendfile.left) && stream.getCoyoteResponse().getTrailerFields() == null; + boolean finished = (frameSize == sendfile.left) && sendfile.stream.getCoyoteResponse().getTrailerFields() == null; // Need to check this now since sending end of stream will change this. - boolean writeable = stream.canWrite(); + boolean writeable = sendfile.stream.canWrite(); byte[] header = new byte[9]; ByteUtil.setThreeBytes(header, 0, frameSize); header[3] = FrameType.DATA.getIdByte(); if (finished) { header[4] = FLAG_END_OF_STREAM; - stream.sentEndOfStream(); - if (!stream.isActive()) { + sendfile.stream.sentEndOfStream(); + if (!sendfile.stream.isActive()) { activeRemoteStreamCount.decrementAndGet(); } } if (writeable) { - ByteUtil.set31Bits(header, 5, stream.getIdentifier().intValue()); + ByteUtil.set31Bits(header, 5, sendfile.stream.getIdentifier().intValue()); sendfile.mappedBuffer.limit(sendfile.mappedBuffer.position() + frameSize); socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(), TimeUnit.MILLISECONDS, sendfile, COMPLETE_WRITE_WITH_COMPLETION, @@ -397,19 +385,6 @@ public class Http2AsyncUpgradeHandler ex } } - protected class SendfileData { - protected Stream stream; - // Note: a mapped buffer is a special construct with an underlying file - // that doesn't need to be closed - protected MappedByteBuffer mappedBuffer; - protected int frameSize; - protected long left; - protected int streamReservation; - protected int connectionReservation; - protected long pos; - protected long end; - } - protected class AsyncPingManager extends PingManager { @Override public void sendPing(boolean force) throws IOException { Modified: tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java?rev=1816571&r1=1816570&r2=1816571&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java (original) +++ tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java Tue Nov 28 20:49:45 2017 @@ -808,14 +808,15 @@ class Http2UpgradeHandler extends Abstra * Process send file (if supported) for the given stream. The appropriate * request attributes should be set before calling this method. * - * @param stream The stream to process + * @param sendfileData The stream and associated data to process * * @return The result of the send file processing */ - protected SendfileState processSendfile(Stream stream) { + protected SendfileState processSendfile(SendfileData sendfileData) { return SendfileState.DONE; } + private synchronized Set<AbstractStream> releaseBackLog(int increment) { Set<AbstractStream> result = new HashSet<>(); if (backLogSize < increment) { Added: tomcat/trunk/java/org/apache/coyote/http2/SendfileData.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/SendfileData.java?rev=1816571&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/SendfileData.java (added) +++ tomcat/trunk/java/org/apache/coyote/http2/SendfileData.java Tue Nov 28 20:49:45 2017 @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.coyote.http2; + +import java.nio.MappedByteBuffer; +import java.nio.file.Path; + +class SendfileData { + Path path; + Stream stream; + // Note: a mapped buffer is a special construct with an underlying file + // that doesn't need to be closed + MappedByteBuffer mappedBuffer; + int frameSize; + long left; + int streamReservation; + int connectionReservation; + long pos; + long end; +} \ No newline at end of file Propchange: tomcat/trunk/java/org/apache/coyote/http2/SendfileData.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java?rev=1816571&r1=1816570&r2=1816571&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java (original) +++ tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java Tue Nov 28 20:49:45 2017 @@ -16,6 +16,7 @@ */ package org.apache.coyote.http2; +import java.io.File; import java.io.IOException; import java.util.Iterator; @@ -45,6 +46,7 @@ class StreamProcessor extends AbstractPr private final Http2UpgradeHandler handler; private final Stream stream; + private SendfileData sendfileData = null; private SendfileState sendfileState = null; @@ -101,11 +103,30 @@ class StreamProcessor extends AbstractPr @Override protected final void prepareResponse() throws IOException { response.setCommitted(true); + if (handler.hasAsyncIO() && handler.getProtocol().getUseSendfile()) { + prepareSendfile(); + } prepareHeaders(response); stream.writeHeaders(); } + private void prepareSendfile() { + String fileName = (String) stream.getCoyoteRequest().getAttribute( + org.apache.coyote.Constants.SENDFILE_FILENAME_ATTR); + if (fileName != null) { + sendfileData.path = new File(fileName).toPath(); + sendfileData = new SendfileData(); + sendfileData.pos = ((Long) stream.getCoyoteRequest().getAttribute( + org.apache.coyote.Constants.SENDFILE_FILE_START_ATTR)).longValue(); + sendfileData.end = ((Long) stream.getCoyoteRequest().getAttribute( + org.apache.coyote.Constants.SENDFILE_FILE_END_ATTR)).longValue(); + sendfileData.left = sendfileData.end - sendfileData.pos; + sendfileData.stream = stream; + } + } + + static void prepareHeaders(Response coyoteResponse) { MimeHeaders headers = coyoteResponse.getMimeHeaders(); int statusCode = coyoteResponse.getStatus(); @@ -135,7 +156,7 @@ class StreamProcessor extends AbstractPr @Override protected final void finishResponse() throws IOException { - sendfileState = handler.processSendfile(stream); + sendfileState = handler.processSendfile(sendfileData); if (!(sendfileState == SendfileState.PENDING)) { stream.getOutputBuffer().close(); } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org