Author: markt
Date: Thu Jan 15 09:21:17 2015
New Revision: 1652003

URL: http://svn.apache.org/r1652003
Log:
InputBuffer refactoring. All compiles but not yet tested.

Added:
    tomcat/trunk/java/org/apache/tomcat/util/net/SocketBufferHandler.java   
(with props)
Modified:
    tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java
    tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java
    tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java
    tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java
    tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java
    tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapperBase.java

Modified: tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java?rev=1652003&r1=1652002&r2=1652003&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java 
(original)
+++ tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java Thu 
Jan 15 09:21:17 2015
@@ -80,7 +80,8 @@ public class InternalNioInputBuffer exte
 
         wrapper = socketWrapper;
 
-        int bufLength = headerBufferSize + 
wrapper.getSocket().getBufHandler().getReadBuffer().capacity();
+        int bufLength = headerBufferSize +
+                wrapper.getSocket().getBufHandler().getReadBuffer().capacity();
         if (buf == null || buf.length < bufLength) {
             buf = new byte[bufLength];
         }

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java?rev=1652003&r1=1652002&r2=1652003&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Thu Jan 15 
09:21:17 2015
@@ -2387,7 +2387,13 @@ public class AprEndpoint extends Abstrac
                 sslOutputBuffer = null;
             }
 
-            socketWriteBuffer = ByteBuffer.allocateDirect(6 * 1500);
+            socketBufferHandler = new SocketBufferHandler(6 * 1500, 6 * 1500, 
true);
+        }
+
+
+        @Override
+        protected void resetSocketBufferHandler(Long socket) {
+            socketBufferHandler.reset();
         }
 
 
@@ -2571,19 +2577,16 @@ public class AprEndpoint extends Abstrac
 
 
         private void doWriteInternal() throws IOException {
-            if (!writeBufferFlipped) {
-                socketWriteBuffer.flip();
-                writeBufferFlipped = true;
-            }
-
             int thisTime;
 
+            ByteBuffer socketWriteBuffer = 
socketBufferHandler.getWriteBuffer();
             do {
                 thisTime = 0;
                 if (getEndpoint().isSSLEnabled()) {
                     if (sslOutputBuffer.remaining() == 0) {
                         // Buffer was fully written last time around
                         sslOutputBuffer.clear();
+                        socketBufferHandler.configureWriteBufferForRead();
                         transfer(socketWriteBuffer, sslOutputBuffer);
                         sslOutputBuffer.flip();
                     } else {
@@ -2598,9 +2601,9 @@ public class AprEndpoint extends Abstrac
                                 sslOutputBuffer.position() + sslWritten);
                     }
                 } else {
-                    thisTime = Socket.sendb(getSocket().longValue(),
-                            socketWriteBuffer, socketWriteBuffer.position(),
-                            socketWriteBuffer.limit() - 
socketWriteBuffer.position());
+                    socketBufferHandler.configureWriteBufferForRead();
+                    thisTime = Socket.sendb(getSocket().longValue(), 
socketWriteBuffer,
+                            socketWriteBuffer.position(), 
socketWriteBuffer.remaining());
                 }
                 if (Status.APR_STATUS_IS_EAGAIN(-thisTime)) {
                     thisTime = 0;
@@ -2617,10 +2620,6 @@ public class AprEndpoint extends Abstrac
                 socketWriteBuffer.position(socketWriteBuffer.position() + 
thisTime);
             } while ((thisTime > 0 || getBlockingStatus()) && 
socketWriteBuffer.hasRemaining());
 
-            if (socketWriteBuffer.remaining() == 0) {
-                socketWriteBuffer.clear();
-                writeBufferFlipped = false;
-            }
             // If there is data left in the buffer the socket will be 
registered for
             // write further up the stack. This is to ensure the socket is only
             // registered for write once as both container and user code can 
trigger

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java?rev=1652003&r1=1652002&r2=1652003&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java Thu Jan 15 
09:21:17 2015
@@ -26,8 +26,6 @@ import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
-import org.apache.tomcat.util.net.SecureNio2Channel.ApplicationBufferHandler;
-
 /**
  * Base class for a SocketChannel wrapper used by the endpoint.
  * This way, logic for a SSL socket channel remains the same as for
@@ -39,9 +37,9 @@ public class Nio2Channel implements Asyn
 
     protected AsynchronousSocketChannel sc = null;
     protected SocketWrapperBase<Nio2Channel> socket = null;
-    protected ApplicationBufferHandler bufHandler;
+    protected final SocketBufferHandler bufHandler;
 
-    public Nio2Channel(ApplicationBufferHandler bufHandler) {
+    public Nio2Channel(SocketBufferHandler bufHandler) {
         this.bufHandler = bufHandler;
     }
 
@@ -96,7 +94,7 @@ public class Nio2Channel implements Asyn
         return sc.isOpen();
     }
 
-    public ApplicationBufferHandler getBufHandler() {
+    public SocketBufferHandler getBufHandler() {
         return bufHandler;
     }
 

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java?rev=1652003&r1=1652002&r2=1652003&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java Thu Jan 15 
09:21:17 2015
@@ -54,7 +54,6 @@ import org.apache.tomcat.util.ExceptionU
 import org.apache.tomcat.util.buf.ByteBufferHolder;
 import org.apache.tomcat.util.collections.SynchronizedStack;
 import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
-import org.apache.tomcat.util.net.SecureNio2Channel.ApplicationBufferHandler;
 import org.apache.tomcat.util.net.jsse.NioX509KeyManager;
 
 /**
@@ -477,13 +476,13 @@ public class Nio2Endpoint extends Abstra
                 if (sslContext != null) {
                     SSLEngine engine = createSSLEngine();
                     int appBufferSize = 
engine.getSession().getApplicationBufferSize();
-                    NioBufferHandler bufhandler = new NioBufferHandler(
+                    SocketBufferHandler bufhandler = new SocketBufferHandler(
                             Math.max(appBufferSize, 
socketProperties.getAppReadBufSize()),
                             Math.max(appBufferSize, 
socketProperties.getAppWriteBufSize()),
                             socketProperties.getDirectBuffer());
                     channel = new SecureNio2Channel(engine, bufhandler, this);
                 } else {
-                    NioBufferHandler bufhandler = new NioBufferHandler(
+                    SocketBufferHandler bufhandler = new SocketBufferHandler(
                             socketProperties.getAppReadBufSize(),
                             socketProperties.getAppWriteBufSize(),
                             socketProperties.getDirectBuffer());
@@ -818,8 +817,6 @@ public class Nio2Endpoint extends Abstra
                                 writeNotify = true;
                             }
                             writePending.release();
-                            socketWriteBuffer.clear();
-                            writeBufferFlipped = false;
                         }
                     }
                     if (writeNotify && nestedWriteCompletionCount.get().get() 
== 0) {
@@ -874,8 +871,6 @@ public class Nio2Endpoint extends Abstra
                                 writeNotify = true;
                             }
                             writePending.release();
-                            socketWriteBuffer.clear();
-                            writeBufferFlipped = false;
                         }
                     }
                     if (writeNotify && nestedWriteCompletionCount.get().get() 
== 0) {
@@ -913,8 +908,16 @@ public class Nio2Endpoint extends Abstra
             super.reset(channel, soTimeout);
             upgradeInit = false;
             sendfileData = null;
-            // Channel will be null when socket is being closed.
-            socketWriteBuffer = (channel == null) ? null : 
channel.getBufHandler().getWriteBuffer();
+        }
+
+
+        @Override
+        protected void resetSocketBufferHandler(Nio2Channel socket) {
+            if (socket == null) {
+                socketBufferHandler = null;
+            } else {
+                socketBufferHandler = socket.getBufHandler();
+            }
         }
 
         @Override
@@ -1136,7 +1139,8 @@ public class Nio2Endpoint extends Abstra
                 if (writePending.tryAcquire()) {
                     // No pending completion handler, so writing to the main 
buffer
                     // is possible
-                    int thisTime = transfer(buf, off, len, socketWriteBuffer);
+                    socketBufferHandler.configureWriteBufferForWrite();
+                    int thisTime = transfer(buf, off, len, 
socketBufferHandler.getWriteBuffer());
                     len = len - thisTime;
                     off = off + thisTime;
                     if (len > 0) {
@@ -1158,13 +1162,13 @@ public class Nio2Endpoint extends Abstra
         @Override
         protected void doWrite(boolean block) throws IOException {
             try {
-                socketWriteBuffer.flip();
-                while (socketWriteBuffer.hasRemaining()) {
-                    if (getSocket().write(socketWriteBuffer).get(getTimeout(), 
TimeUnit.MILLISECONDS).intValue() < 0) {
+                socketBufferHandler.configureWriteBufferForRead();
+                while (socketBufferHandler.getWriteBuffer().hasRemaining()) {
+                    if 
(getSocket().write(socketBufferHandler.getWriteBuffer()).get(getTimeout(),
+                            TimeUnit.MILLISECONDS).intValue() < 0) {
                         throw new 
EOFException(sm.getString("iob.failedwrite"));
                     }
                 }
-                socketWriteBuffer.clear();
             } catch (ExecutionException e) {
                 if (e.getCause() instanceof IOException) {
                     throw (IOException) e.getCause();
@@ -1204,15 +1208,12 @@ public class Nio2Endpoint extends Abstra
         private boolean flushNonBlocking(boolean hasPermit) {
             synchronized (writeCompletionHandler) {
                 if (hasPermit || writePending.tryAcquire()) {
-                    if (!writeBufferFlipped) {
-                        socketWriteBuffer.flip();
-                        writeBufferFlipped = true;
-                    }
+                    socketBufferHandler.configureWriteBufferForRead();
                     if (bufferedWrites.size() > 0) {
                         // Gathering write of the main buffer plus all 
leftovers
                         ArrayList<ByteBuffer> arrayList = new ArrayList<>();
-                        if (socketWriteBuffer.hasRemaining()) {
-                            arrayList.add(socketWriteBuffer);
+                        if 
(socketBufferHandler.getWriteBuffer().hasRemaining()) {
+                            
arrayList.add(socketBufferHandler.getWriteBuffer());
                         }
                         for (ByteBufferHolder buffer : bufferedWrites) {
                             buffer.flip();
@@ -1222,15 +1223,14 @@ public class Nio2Endpoint extends Abstra
                         ByteBuffer[] array = arrayList.toArray(new 
ByteBuffer[arrayList.size()]);
                         getSocket().write(array, 0, array.length, getTimeout(),
                                 TimeUnit.MILLISECONDS, array, 
gatheringWriteCompletionHandler);
-                    } else if (socketWriteBuffer.hasRemaining()) {
+                    } else if 
(socketBufferHandler.getWriteBuffer().hasRemaining()) {
                         // Regular write
-                        getSocket().write(socketWriteBuffer, getTimeout(),
-                                TimeUnit.MILLISECONDS, socketWriteBuffer, 
writeCompletionHandler);
+                        
getSocket().write(socketBufferHandler.getWriteBuffer(), getTimeout(),
+                                TimeUnit.MILLISECONDS, 
socketBufferHandler.getWriteBuffer(),
+                                writeCompletionHandler);
                     } else {
                         // Nothing was written
                         writePending.release();
-                        socketWriteBuffer.clear();
-                        writeBufferFlipped = false;
                     }
                 }
                 return hasDataToWrite();
@@ -1241,7 +1241,8 @@ public class Nio2Endpoint extends Abstra
         @Override
         public boolean hasDataToWrite() {
             synchronized (writeCompletionHandler) {
-                return hasMoreDataToFlush() || bufferedWrites.size() > 0 || 
getError() != null;
+                return !socketBufferHandler.isWriteBufferEmpty() ||
+                        bufferedWrites.size() > 0 || getError() != null;
             }
         }
 
@@ -1287,31 +1288,8 @@ public class Nio2Endpoint extends Abstra
     }
 
 
-    // ------------------------------------------------ Application Buffer 
Handler
-    public static class NioBufferHandler implements ApplicationBufferHandler {
-        private ByteBuffer readbuf = null;
-        private ByteBuffer writebuf = null;
-
-        public NioBufferHandler(int readsize, int writesize, boolean direct) {
-            if ( direct ) {
-                readbuf = ByteBuffer.allocateDirect(readsize);
-                writebuf = ByteBuffer.allocateDirect(writesize);
-            }else {
-                readbuf = ByteBuffer.allocate(readsize);
-                writebuf = ByteBuffer.allocate(writesize);
-            }
-        }
-
-        @Override
-        public ByteBuffer getReadBuffer() {return readbuf;}
-        @Override
-        public ByteBuffer getWriteBuffer() {return writebuf;}
-
-    }
-
     // ------------------------------------------------ Handler Inner Interface
 
-
     /**
      * Bare bones interface used for socket processing. Per thread data is to 
be
      * stored in the ThreadWithAttributes extra folders, or alternately in

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java?rev=1652003&r1=1652002&r2=1652003&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java Thu Jan 15 
09:21:17 2015
@@ -24,7 +24,6 @@ import java.nio.channels.Selector;
 import java.nio.channels.SocketChannel;
 
 import org.apache.tomcat.util.net.NioEndpoint.Poller;
-import org.apache.tomcat.util.net.SecureNioChannel.ApplicationBufferHandler;
 import org.apache.tomcat.util.res.StringManager;
 
 /**
@@ -44,13 +43,13 @@ public class NioChannel implements ByteC
 
     protected SocketChannel sc = null;
 
-    protected ApplicationBufferHandler bufHandler;
+    protected final SocketBufferHandler bufHandler;
 
     protected Poller poller;
 
     protected boolean sendFile = false;
 
-    public NioChannel(SocketChannel channel, ApplicationBufferHandler 
bufHandler) {
+    public NioChannel(SocketChannel channel, SocketBufferHandler bufHandler) {
         this.sc = channel;
         this.bufHandler = bufHandler;
     }
@@ -61,19 +60,15 @@ public class NioChannel implements ByteC
      * @throws IOException If a problem was encountered resetting the channel
      */
     public void reset() throws IOException {
-        bufHandler.getReadBuffer().clear();
-        // TODO AJP and HTTPS have different expectations for the state of
-        // the buffer at the start of a read. These need to be reconciled.
-        bufHandler.getReadBuffer().limit(0);
-        bufHandler.getWriteBuffer().clear();
+        bufHandler.reset();
         this.sendFile = false;
     }
 
     public int getBufferSize() {
         if ( bufHandler == null ) return 0;
         int size = 0;
-        size += 
bufHandler.getReadBuffer()!=null?bufHandler.getReadBuffer().capacity():0;
-        size += 
bufHandler.getWriteBuffer()!=null?bufHandler.getWriteBuffer().capacity():0;
+        size += bufHandler.getReadBuffer().capacity();
+        size += bufHandler.getWriteBuffer().capacity();
         return size;
     }
 
@@ -151,7 +146,7 @@ public class NioChannel implements ByteC
         return att;
     }
 
-    public ApplicationBufferHandler getBufHandler() {
+    public SocketBufferHandler getBufHandler() {
         return bufHandler;
     }
 

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?rev=1652003&r1=1652002&r2=1652003&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Thu Jan 15 
09:21:17 2015
@@ -54,7 +54,6 @@ import org.apache.tomcat.util.Introspect
 import org.apache.tomcat.util.collections.SynchronizedQueue;
 import org.apache.tomcat.util.collections.SynchronizedStack;
 import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
-import org.apache.tomcat.util.net.SecureNioChannel.ApplicationBufferHandler;
 import org.apache.tomcat.util.net.jsse.NioX509KeyManager;
 
 /**
@@ -512,16 +511,17 @@ public class NioEndpoint extends Abstrac
                 if (sslContext != null) {
                     SSLEngine engine = createSSLEngine();
                     int appbufsize = 
engine.getSession().getApplicationBufferSize();
-                    NioBufferHandler bufhandler = new 
NioBufferHandler(Math.max(appbufsize,socketProperties.getAppReadBufSize()),
-                                                                       
Math.max(appbufsize,socketProperties.getAppWriteBufSize()),
-                                                                       
socketProperties.getDirectBuffer());
+                    SocketBufferHandler bufhandler = new SocketBufferHandler(
+                            
Math.max(appbufsize,socketProperties.getAppReadBufSize()),
+                            
Math.max(appbufsize,socketProperties.getAppWriteBufSize()),
+                            socketProperties.getDirectBuffer());
                     channel = new SecureNioChannel(socket, engine, bufhandler, 
selectorPool);
                 } else {
                     // normal tcp setup
-                    NioBufferHandler bufhandler = new 
NioBufferHandler(socketProperties.getAppReadBufSize(),
-                                                                       
socketProperties.getAppWriteBufSize(),
-                                                                       
socketProperties.getDirectBuffer());
-
+                    SocketBufferHandler bufhandler = new SocketBufferHandler(
+                            socketProperties.getAppReadBufSize(),
+                            socketProperties.getAppWriteBufSize(),
+                            socketProperties.getDirectBuffer());
                     channel = new NioChannel(socket, bufhandler);
                 }
             } else {
@@ -1339,10 +1339,19 @@ public class NioEndpoint extends Abstrac
             }
             writeLatch = null;
             setWriteTimeout(soTimeout);
-            // Channel will be null when socket is being closed.
-            socketWriteBuffer = (channel == null) ? null : 
channel.getBufHandler().getWriteBuffer();
         }
 
+
+        @Override
+        protected void resetSocketBufferHandler(NioChannel socket) {
+            if (socket == null) {
+                socketBufferHandler = null;
+            } else {
+                socketBufferHandler = socket.getBufHandler();
+            }
+        }
+
+
         public void reset() {
             reset(null,null,-1);
         }
@@ -1392,17 +1401,16 @@ public class NioEndpoint extends Abstrac
 
         @Override
         public boolean isReady() throws IOException {
-            ByteBuffer readBuffer = 
getSocket().getBufHandler().getReadBuffer();
+            socketBufferHandler.configureReadBufferForRead();
 
-            if (readBuffer.remaining() > 0) {
+            if (socketBufferHandler.getReadBuffer().remaining() > 0) {
                 return true;
             }
 
-            readBuffer.clear();
             fillReadBuffer(false);
 
-            boolean isReady = readBuffer.position() > 0;
-            readBuffer.flip();
+
+            boolean isReady = socketBufferHandler.getReadBuffer().position() > 
0;
             return isReady;
         }
 
@@ -1411,7 +1419,8 @@ public class NioEndpoint extends Abstrac
         public int read(boolean block, byte[] b, int off, int len)
                 throws IOException {
 
-            ByteBuffer readBuffer = 
getSocket().getBufHandler().getReadBuffer();
+            socketBufferHandler.configureReadBufferForRead();
+            ByteBuffer readBuffer = socketBufferHandler.getReadBuffer();
             int remaining = readBuffer.remaining();
 
             // Is there enough data in the read buffer to satisfy this request?
@@ -1430,13 +1439,12 @@ public class NioEndpoint extends Abstrac
             }
 
             // Fill the read buffer as best we can
-            readBuffer.clear();
             int nRead = fillReadBuffer(block);
 
-            // Full as much of the remaining byte array as possible with the 
data
-            // that was just read
+            // Full as much of the remaining byte array as possible with the
+            // data that was just read
             if (nRead > 0) {
-                readBuffer.flip();
+                socketBufferHandler.configureReadBufferForRead();
                 if (nRead > leftToWrite) {
                     readBuffer.get(b, newOffset, leftToWrite);
                     leftToWrite = 0;
@@ -1444,8 +1452,6 @@ public class NioEndpoint extends Abstrac
                     readBuffer.get(b, newOffset, nRead);
                     leftToWrite -= nRead;
                 }
-            } else if (nRead == 0) {
-                readBuffer.flip();
             } else if (nRead == -1) {
                 // TODO i18n
                 throw new EOFException();
@@ -1458,14 +1464,8 @@ public class NioEndpoint extends Abstrac
         @Override
         public void unRead(ByteBuffer returnedInput) {
             if (returnedInput != null) {
-                ByteBuffer readBuffer = 
getSocket().getBufHandler().getReadBuffer();
-                if (readBuffer.remaining() > 0) {
-                    readBuffer.flip();
-                } else {
-                    readBuffer.clear();
-                }
-                readBuffer.put(returnedInput);
-                readBuffer.flip();
+                socketBufferHandler.configureReadBufferForWrite();
+                socketBufferHandler.getReadBuffer().put(returnedInput);
             }
         }
 
@@ -1482,6 +1482,7 @@ public class NioEndpoint extends Abstrac
         private int fillReadBuffer(boolean block) throws IOException {
             int nRead;
             NioChannel channel = getSocket();
+            socketBufferHandler.configureReadBufferForWrite();
             if (block) {
                 Selector selector = null;
                 try {
@@ -1495,7 +1496,7 @@ public class NioEndpoint extends Abstrac
                     if (att == null) {
                         throw new IOException("Key must be cancelled.");
                     }
-                    nRead = pool.read(channel.getBufHandler().getReadBuffer(),
+                    nRead = pool.read(socketBufferHandler.getReadBuffer(),
                             channel, selector, att.getTimeout());
                 } catch (EOFException eof) {
                     nRead = -1;
@@ -1505,7 +1506,7 @@ public class NioEndpoint extends Abstrac
                     }
                 }
             } else {
-                nRead = channel.read(channel.getBufHandler().getReadBuffer());
+                nRead = channel.read(socketBufferHandler.getReadBuffer());
             }
             return nRead;
         }
@@ -1513,10 +1514,7 @@ public class NioEndpoint extends Abstrac
 
         @Override
         protected synchronized void doWrite(boolean block) throws IOException {
-            if (!writeBufferFlipped) {
-                socketWriteBuffer.flip();
-                writeBufferFlipped = true;
-            }
+            socketBufferHandler.configureWriteBufferForRead();
 
             long writeTimeout = getWriteTimeout();
             Selector selector = null;
@@ -1526,7 +1524,8 @@ public class NioEndpoint extends Abstrac
                 // Ignore
             }
             try {
-                pool.write(socketWriteBuffer, getSocket(), selector, 
writeTimeout, block);
+                pool.write(socketBufferHandler.getWriteBuffer(), getSocket(),
+                        selector, writeTimeout, block);
                 // Make sure we are flushed
                 do {
                     if (getSocket().flush(true, selector, writeTimeout)) break;
@@ -1536,10 +1535,6 @@ public class NioEndpoint extends Abstrac
                     pool.put(selector);
                 }
             }
-            if (socketWriteBuffer.remaining() == 0) {
-                socketWriteBuffer.clear();
-                writeBufferFlipped = false;
-            }
             // If there is data left in the buffer the socket will be 
registered for
             // write further up the stack. This is to ensure the socket is only
             // registered for write once as both container and user code can 
trigger
@@ -1581,33 +1576,8 @@ public class NioEndpoint extends Abstrac
     }
 
 
-    // ------------------------------------------------ Application Buffer 
Handler
-    public static class NioBufferHandler implements ApplicationBufferHandler {
-        private ByteBuffer readbuf = null;
-        private ByteBuffer writebuf = null;
-
-        public NioBufferHandler(int readsize, int writesize, boolean direct) {
-            if (direct) {
-                readbuf = ByteBuffer.allocateDirect(readsize);
-                writebuf = ByteBuffer.allocateDirect(writesize);
-            } else {
-                readbuf = ByteBuffer.allocate(readsize);
-                writebuf = ByteBuffer.allocate(writesize);
-            }
-            // TODO AJP and HTTPS have different expectations for the state of
-            // the buffer at the start of a read. These need to be reconciled.
-            readbuf.limit(0);
-        }
-
-        @Override
-        public ByteBuffer getReadBuffer() {return readbuf;}
-        @Override
-        public ByteBuffer getWriteBuffer() {return writebuf;}
-    }
-
     // ------------------------------------------------ Handler Inner Interface
 
-
     /**
      * Bare bones interface used for socket processing. Per thread data is to 
be
      * stored in the ThreadWithAttributes extra folders, or alternately in

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java?rev=1652003&r1=1652002&r2=1652003&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java Thu Jan 
15 09:21:17 2015
@@ -61,7 +61,7 @@ public class SecureNio2Channel extends N
     private CompletionHandler<Integer, SocketWrapperBase<Nio2Channel>> 
handshakeReadCompletionHandler;
     private CompletionHandler<Integer, SocketWrapperBase<Nio2Channel>> 
handshakeWriteCompletionHandler;
 
-    public SecureNio2Channel(SSLEngine engine, ApplicationBufferHandler 
bufHandler,
+    public SecureNio2Channel(SSLEngine engine, SocketBufferHandler bufHandler,
             Nio2Endpoint endpoint0) {
         super(bufHandler);
         sslEngine = engine;
@@ -979,20 +979,6 @@ public class SecureNio2Channel extends N
         }
    }
 
-    /**
-     * Callback interface to be able to expand buffers
-     * when buffer overflow exceptions happen
-     */
-    public static interface ApplicationBufferHandler {
-        public ByteBuffer getReadBuffer();
-        public ByteBuffer getWriteBuffer();
-    }
-
-    @Override
-    public ApplicationBufferHandler getBufHandler() {
-        return bufHandler;
-    }
-
     @Override
     public boolean isHandshakeComplete() {
         return handshakeComplete;
@@ -1011,10 +997,6 @@ public class SecureNio2Channel extends N
         return emptyBuf;
     }
 
-    public void setBufHandler(ApplicationBufferHandler bufHandler) {
-        this.bufHandler = bufHandler;
-    }
-
     @Override
     public AsynchronousSocketChannel getIOChannel() {
         return sc;

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java?rev=1652003&r1=1652002&r2=1652003&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java Thu Jan 
15 09:21:17 2015
@@ -50,8 +50,8 @@ public class SecureNioChannel extends Ni
 
     protected NioSelectorPool pool;
 
-    public SecureNioChannel(SocketChannel channel, SSLEngine engine,
-                            ApplicationBufferHandler bufHandler, 
NioSelectorPool pool) throws IOException {
+    public SecureNioChannel(SocketChannel channel, SSLEngine engine, 
SocketBufferHandler bufHandler,
+            NioSelectorPool pool) throws IOException {
         super(channel,bufHandler);
         this.sslEngine = engine;
         int netBufSize = sslEngine.getSession().getPacketBufferSize();
@@ -192,9 +192,7 @@ public class SecureNioChannel extends Ni
                         //read more data, reregister for OP_READ
                         return SelectionKey.OP_READ;
                     } else if (handshake.getStatus() == 
Status.BUFFER_OVERFLOW) {
-                        // TODO AJP and HTTPS have different expectations for 
the state of
-                        // the buffer at the start of a read. These need to be 
reconciled.
-                        bufHandler.getReadBuffer().compact();
+                        bufHandler.configureReadBufferForWrite();
                     } else {
                         throw new 
IOException(sm.getString("channel.nio.ssl.unexpectedStatusDuringWrap", 
handshakeStatus));
                     }//switch
@@ -225,8 +223,8 @@ public class SecureNioChannel extends Ni
         //validate the network buffers are empty
         if (netInBuffer.position() > 0 && 
netInBuffer.position()<netInBuffer.limit()) throw new 
IOException(sm.getString("channel.nio.ssl.netInputNotEmpty"));
         if (netOutBuffer.position() > 0 && 
netOutBuffer.position()<netOutBuffer.limit()) throw new 
IOException(sm.getString("channel.nio.ssl.netOutputNotEmpty"));
-        if (getBufHandler().getReadBuffer().position()>0 && 
getBufHandler().getReadBuffer().position()<getBufHandler().getReadBuffer().limit())
 throw new IOException(sm.getString("channel.nio.ssl.appInputNotEmpty"));
-        if (getBufHandler().getWriteBuffer().position()>0 && 
getBufHandler().getWriteBuffer().position()<getBufHandler().getWriteBuffer().limit())
 throw new IOException(sm.getString("channel.nio.ssl.appOutputNotEmpty"));
+        if (!getBufHandler().isReadBufferEmpty()) throw new 
IOException(sm.getString("channel.nio.ssl.appInputNotEmpty"));
+        if (!getBufHandler().isWriteBufferEmpty()) throw new 
IOException(sm.getString("channel.nio.ssl.appOutputNotEmpty"));
         reset();
         boolean isReadable = true;
         boolean isWriteable = true;
@@ -292,6 +290,7 @@ public class SecureNioChannel extends Ni
         //so we can clear it here.
         netOutBuffer.clear();
         //perform the wrap
+        bufHandler.configureWriteBufferForWrite();
         SSLEngineResult result = sslEngine.wrap(bufHandler.getWriteBuffer(), 
netOutBuffer);
         //prepare the results to be written
         netOutBuffer.flip();
@@ -326,6 +325,7 @@ public class SecureNioChannel extends Ni
             //prepare the buffer with the incoming data
             netInBuffer.flip();
             //call unwrap
+            bufHandler.configureReadBufferForWrite();
             result = sslEngine.unwrap(netInBuffer, bufHandler.getReadBuffer());
             //compact the buffer, this is an optional method, wonder what 
would happen if we didn't
             netInBuffer.compact();
@@ -410,8 +410,10 @@ public class SecureNioChannel extends Ni
      */
     @Override
     public int read(ByteBuffer dst) throws IOException {
-        //if we want to take advantage of the expand function, make sure we 
only use the ApplicationBufferHandler's buffers
-        if ( dst != bufHandler.getReadBuffer() ) throw new 
IllegalArgumentException(sm.getString("channel.nio.ssl.invalidBuffer"));
+        // Make sure we only use the ApplicationBufferHandler's buffers
+        if (dst != bufHandler.getReadBuffer()) {
+            throw new 
IllegalArgumentException(sm.getString("channel.nio.ssl.invalidBuffer"));
+        }
         //are we in the middle of closing or closed?
         if ( closing || closed) return -1;
         //did we finish our handshake?
@@ -473,7 +475,9 @@ public class SecureNioChannel extends Ni
             return written;
         } else {
             //make sure we can handle expand, and that we only use one buffer
-            if ( (!this.isSendFile()) && (src != bufHandler.getWriteBuffer()) 
) throw new 
IllegalArgumentException(sm.getString("channel.nio.ssl.invalidBuffer"));
+            if (!this.isSendFile() && src != bufHandler.getWriteBuffer()) {
+                throw new 
IllegalArgumentException(sm.getString("channel.nio.ssl.invalidBuffer"));
+            }
             //are we closing or closed?
             if ( closing || closed) throw new 
IOException(sm.getString("channel.nio.ssl.closing"));
 
@@ -531,7 +535,7 @@ public class SecureNioChannel extends Ni
     }
 
     @Override
-    public ApplicationBufferHandler getBufHandler() {
+    public SocketBufferHandler getBufHandler() {
         return bufHandler;
     }
 
@@ -553,10 +557,6 @@ public class SecureNioChannel extends Ni
         return emptyBuf;
     }
 
-    public void setBufHandler(ApplicationBufferHandler bufHandler) {
-        this.bufHandler = bufHandler;
-    }
-
     @Override
     public SocketChannel getIOChannel() {
         return sc;

Added: tomcat/trunk/java/org/apache/tomcat/util/net/SocketBufferHandler.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SocketBufferHandler.java?rev=1652003&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SocketBufferHandler.java 
(added)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SocketBufferHandler.java Thu 
Jan 15 09:21:17 2015
@@ -0,0 +1,149 @@
+/*
+ *  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.tomcat.util.net;
+
+import java.nio.ByteBuffer;
+
+public class SocketBufferHandler {
+
+    private volatile boolean readBufferConfiguredForWrite = true;
+    private final ByteBuffer readBuffer;
+
+    private volatile boolean writeBufferConfiguredForWrite = true;
+    private final ByteBuffer writeBuffer;
+
+
+    public SocketBufferHandler(int readBufferSize, int writeBufferSize,
+            boolean direct) {
+        if (direct) {
+            readBuffer = ByteBuffer.allocateDirect(readBufferSize);
+            writeBuffer = ByteBuffer.allocateDirect(writeBufferSize);
+        } else {
+            readBuffer = ByteBuffer.allocate(readBufferSize);
+            writeBuffer = ByteBuffer.allocate(writeBufferSize);
+        }
+    }
+
+
+    public void configureReadBufferForWrite() {
+        setReadBufferConFiguredForWrite(true);
+    }
+
+
+    public void configureReadBufferForRead() {
+        setReadBufferConFiguredForWrite(false);
+    }
+
+
+    private void setReadBufferConFiguredForWrite(boolean 
readBufferConFiguredForWrite) {
+        // NO-OP if buffer is already in correct state
+        if (this.readBufferConfiguredForWrite != readBufferConFiguredForWrite) 
{
+            if (readBufferConFiguredForWrite) {
+                // Switching to write
+                int remaining = readBuffer.remaining();
+                if (remaining == 0) {
+                    readBuffer.clear();
+                } else {
+                    readBuffer.compact();
+                    readBuffer.position(remaining);
+                    readBuffer.limit(readBuffer.capacity());
+                }
+            } else {
+                // Switching to read
+                readBuffer.flip();
+            }
+            this.readBufferConfiguredForWrite = readBufferConFiguredForWrite;
+        }
+    }
+
+
+    public ByteBuffer getReadBuffer() {
+        return readBuffer;
+    }
+
+
+    public boolean isReadBufferEmpty() {
+        if (readBufferConfiguredForWrite) {
+            return readBuffer.position() > 0;
+        } else {
+            return readBuffer.remaining() > 0;
+        }
+    }
+
+
+    public void configureWriteBufferForWrite() {
+        setWriteBufferConfiguredForWrite(true);
+    }
+
+
+    public void configureWriteBufferForRead() {
+        setWriteBufferConfiguredForWrite(false);
+    }
+
+
+    private void setWriteBufferConfiguredForWrite(boolean 
writeBufferConfiguredForWrite) {
+        // NO-OP if buffer is already in correct state
+        if (this.writeBufferConfiguredForWrite != 
writeBufferConfiguredForWrite) {
+            if (writeBufferConfiguredForWrite) {
+                // Switching to write
+                int remaining = writeBuffer.remaining();
+                if (remaining == 0) {
+                    writeBuffer.clear();
+                } else {
+                    writeBuffer.compact();
+                    writeBuffer.position(remaining);
+                    writeBuffer.limit(writeBuffer.capacity());
+                }
+            } else {
+                // Switching to read
+                writeBuffer.flip();
+            }
+            this.writeBufferConfiguredForWrite = writeBufferConfiguredForWrite;
+        }
+    }
+
+
+    public boolean isWriteBufferWritable() {
+        if (writeBufferConfiguredForWrite) {
+            return writeBuffer.hasRemaining();
+        } else {
+            return writeBuffer.remaining() == 0;
+        }
+    }
+
+
+    public ByteBuffer getWriteBuffer() {
+        return writeBuffer;
+    }
+
+
+    public boolean isWriteBufferEmpty() {
+        if (writeBufferConfiguredForWrite) {
+            return writeBuffer.position() == 0;
+        } else {
+            return writeBuffer.remaining() == 0;
+        }
+    }
+
+
+    public void reset() {
+        readBuffer.clear();
+        readBufferConfiguredForWrite = true;
+        writeBuffer.clear();
+        writeBufferConfiguredForWrite = true;
+    }
+}

Propchange: 
tomcat/trunk/java/org/apache/tomcat/util/net/SocketBufferHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapperBase.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapperBase.java?rev=1652003&r1=1652002&r2=1652003&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapperBase.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapperBase.java Thu Jan 
15 09:21:17 2015
@@ -70,8 +70,10 @@ public abstract class SocketWrapperBase<
      */
     private final Object writeThreadLock = new Object();
 
-    protected volatile ByteBuffer socketWriteBuffer;
-    protected volatile boolean writeBufferFlipped;
+    /**
+     * The buffers used for communicating with the socket.
+     */
+    protected volatile SocketBufferHandler socketBufferHandler = null;
 
     /**
      * For "non-blocking" writes use an external set of buffers. Although the
@@ -180,13 +182,8 @@ public abstract class SocketWrapperBase<
 
     public abstract boolean isReadPending();
 
-    protected boolean hasMoreDataToFlush() {
-        return (writeBufferFlipped && socketWriteBuffer.remaining() > 0) ||
-        (!writeBufferFlipped && socketWriteBuffer.position() > 0);
-    }
-
     public boolean hasDataToWrite() {
-        return hasMoreDataToFlush() || bufferedWrites.size() > 0;
+        return !socketBufferHandler.isWriteBufferEmpty() || 
bufferedWrites.size() > 0;
     }
 
     /**
@@ -213,8 +210,7 @@ public abstract class SocketWrapperBase<
 
 
     public boolean canWrite() {
-        return !writeBufferFlipped && socketWriteBuffer.hasRemaining() &&
-                bufferedWrites.size() == 0;
+        return socketBufferHandler.isWriteBufferWritable() && 
bufferedWrites.size() == 0;
     }
 
     public void addDispatch(DispatchType dispatchType) {
@@ -263,8 +259,11 @@ public abstract class SocketWrapperBase<
         this.socket = socket;
         this.timeout = timeout;
         upgraded = false;
+        resetSocketBufferHandler(socket);
     }
 
+    protected abstract void resetSocketBufferHandler(E socket);
+
     /**
      * Overridden for debug purposes. No guarantees are made about the format 
of
      * this message which may vary significantly between point releases.
@@ -346,12 +345,14 @@ public abstract class SocketWrapperBase<
 
         // Keep writing until all the data has been transferred to the socket
         // write buffer and space remains in that buffer
-        int thisTime = transfer(buf, off, len, socketWriteBuffer);
-        while (socketWriteBuffer.remaining() == 0) {
+        socketBufferHandler.configureWriteBufferForWrite();
+        int thisTime = transfer(buf, off, len, 
socketBufferHandler.getWriteBuffer());
+        while (socketBufferHandler.getWriteBuffer().remaining() == 0) {
             len = len - thisTime;
             off = off + thisTime;
             doWrite(true);
-            thisTime = transfer(buf, off, len, socketWriteBuffer);
+            socketBufferHandler.configureWriteBufferForWrite();
+            thisTime = transfer(buf, off, len, 
socketBufferHandler.getWriteBuffer());
         }
     }
 
@@ -369,16 +370,18 @@ public abstract class SocketWrapperBase<
      * @throws IOException If an IO error occurs during the write
      */
     protected void writeNonBlocking(byte[] buf, int off, int len) throws 
IOException {
-        if (!writeBufferFlipped) {
-            int thisTime = transfer(buf, off, len, socketWriteBuffer);
+        if (bufferedWrites.size() == 0 && 
socketBufferHandler.isWriteBufferWritable()) {
+            socketBufferHandler.configureWriteBufferForWrite();
+            int thisTime = transfer(buf, off, len, 
socketBufferHandler.getWriteBuffer());
             len = len - thisTime;
-            while (socketWriteBuffer.remaining() == 0) {
+            while (!socketBufferHandler.isWriteBufferWritable()) {
                 off = off + thisTime;
                 doWrite(false);
-                if (writeBufferFlipped) {
-                    thisTime = 0;
+                if (len > 0 && socketBufferHandler.isWriteBufferWritable()) {
+                    socketBufferHandler.configureWriteBufferForWrite();
+                    thisTime = transfer(buf, off, len, 
socketBufferHandler.getWriteBuffer());
                 } else {
-                    thisTime = transfer(buf, off, len, socketWriteBuffer);
+                    thisTime = 0;
                 }
                 len = len - thisTime;
             }
@@ -432,11 +435,12 @@ public abstract class SocketWrapperBase<
 
         if (bufferedWrites.size() > 0) {
             Iterator<ByteBufferHolder> bufIter = bufferedWrites.iterator();
-            while (!hasMoreDataToFlush() && bufIter.hasNext()) {
+            while (socketBufferHandler.isWriteBufferEmpty() && 
bufIter.hasNext()) {
                 ByteBufferHolder buffer = bufIter.next();
                 buffer.flip();
-                while (!hasMoreDataToFlush() && buffer.getBuf().remaining()>0) 
{
-                    transfer(buffer.getBuf(), socketWriteBuffer);
+                while (socketBufferHandler.isWriteBufferEmpty() && 
buffer.getBuf().remaining()>0) {
+                    socketBufferHandler.configureWriteBufferForWrite();
+                    transfer(buffer.getBuf(), 
socketBufferHandler.getWriteBuffer());
                     if (buffer.getBuf().remaining() == 0) {
                         bufIter.remove();
                     }
@@ -449,22 +453,23 @@ public abstract class SocketWrapperBase<
 
 
     protected boolean flushNonBlocking() throws IOException {
-        boolean dataLeft = hasMoreDataToFlush();
+        boolean dataLeft = !socketBufferHandler.isWriteBufferEmpty();
 
         // Write to the socket, if there is anything to write
         if (dataLeft) {
             doWrite(false);
         }
 
-        dataLeft = hasMoreDataToFlush();
+        dataLeft = !socketBufferHandler.isWriteBufferEmpty();
 
         if (!dataLeft && bufferedWrites.size() > 0) {
             Iterator<ByteBufferHolder> bufIter = bufferedWrites.iterator();
-            while (!hasMoreDataToFlush() && bufIter.hasNext()) {
+            while (socketBufferHandler.isWriteBufferEmpty() && 
bufIter.hasNext()) {
                 ByteBufferHolder buffer = bufIter.next();
                 buffer.flip();
-                while (!hasMoreDataToFlush() && buffer.getBuf().remaining() > 
0) {
-                    transfer(buffer.getBuf(), socketWriteBuffer);
+                while (socketBufferHandler.isWriteBufferEmpty() && 
buffer.getBuf().remaining() > 0) {
+                    socketBufferHandler.configureWriteBufferForWrite();
+                    transfer(buffer.getBuf(), 
socketBufferHandler.getWriteBuffer());
                     if (buffer.getBuf().remaining() == 0) {
                         bufIter.remove();
                     }
@@ -473,7 +478,7 @@ public abstract class SocketWrapperBase<
             }
         }
 
-        return hasMoreDataToFlush();
+        return !socketBufferHandler.isWriteBufferEmpty();
     }
 
 



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to