You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2017/11/28 20:49:46 UTC

svn commit: r1816571 - in /tomcat/trunk/java/org/apache/coyote/http2: Http2AsyncUpgradeHandler.java Http2UpgradeHandler.java SendfileData.java StreamProcessor.java

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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org