Author: markt Date: Mon Nov 10 16:46:09 2014 New Revision: 1637925 URL: http://svn.apache.org/r1637925 Log: Push down read methods to AprSocketWrapper
Modified: tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprProcessor.java tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Modified: tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprProcessor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprProcessor.java?rev=1637925&r1=1637924&r2=1637925&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprProcessor.java (original) +++ tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprProcessor.java Mon Nov 10 16:46:09 2014 @@ -24,6 +24,7 @@ import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.jni.Socket; import org.apache.tomcat.util.net.AprEndpoint; +import org.apache.tomcat.util.net.AprEndpoint.AprSocketWrapper; import org.apache.tomcat.util.net.SocketWrapperBase; public class AprProcessor extends AbstractProcessor<Long> { @@ -34,13 +35,13 @@ public class AprProcessor extends Abstra private static final int INFINITE_TIMEOUT = -1; - public AprProcessor(SocketWrapperBase<Long> wrapper, ByteBuffer leftoverInput, + public AprProcessor(SocketWrapperBase<Long> wrapper, ByteBuffer leftOverInput, HttpUpgradeHandler httpUpgradeProcessor, AprEndpoint endpoint, int asyncWriteBufferSize) { super(httpUpgradeProcessor, - new AprServletInputStream(wrapper, leftoverInput), + new AprServletInputStream(wrapper), new AprServletOutputStream(wrapper, asyncWriteBufferSize, endpoint)); - + ((AprSocketWrapper) wrapper).setLeftOverInput(leftOverInput); Socket.timeoutSet(wrapper.getSocket().longValue(), INFINITE_TIMEOUT); } } Modified: tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java?rev=1637925&r1=1637924&r2=1637925&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java (original) +++ tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java Mon Nov 10 16:46:09 2014 @@ -16,136 +16,31 @@ */ package org.apache.coyote.http11.upgrade; -import java.io.EOFException; import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; - -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; -import org.apache.tomcat.jni.OS; -import org.apache.tomcat.jni.Socket; -import org.apache.tomcat.jni.Status; + +import org.apache.tomcat.util.net.AprEndpoint.AprSocketWrapper; import org.apache.tomcat.util.net.SocketWrapperBase; public class AprServletInputStream extends AbstractServletInputStream { - private static final Log log = LogFactory.getLog(AprServletInputStream.class); - private final SocketWrapperBase<Long> wrapper; - private final long socket; - private ByteBuffer leftoverInput; - private volatile boolean eagain = false; - private volatile boolean closed = false; - - public AprServletInputStream(SocketWrapperBase<Long> wrapper, ByteBuffer leftoverInput) { + public AprServletInputStream(SocketWrapperBase<Long> wrapper) { this.wrapper = wrapper; - this.socket = wrapper.getSocket().longValue(); - if (leftoverInput != null) { - this.leftoverInput = ByteBuffer.allocate(leftoverInput.remaining()); - this.leftoverInput.put(leftoverInput); - } } - @Override - protected int doRead(boolean block, byte[] b, int off, int len) - throws IOException { - - if (closed) { - throw new IOException(sm.getString("apr.closed", Long.valueOf(socket))); - } - - if (leftoverInput != null) { - if (leftoverInput.remaining() < len) { - len = leftoverInput.remaining(); - } - leftoverInput.get(b, off, len); - if (leftoverInput.remaining() == 0) { - leftoverInput = null; - } - return len; - } - - Lock readLock = wrapper.getBlockingStatusReadLock(); - WriteLock writeLock = wrapper.getBlockingStatusWriteLock(); - - boolean readDone = false; - int result = 0; - readLock.lock(); - try { - if (wrapper.getBlockingStatus() == block) { - result = Socket.recv(socket, b, off, len); - readDone = true; - } - } finally { - readLock.unlock(); - } - - if (!readDone) { - writeLock.lock(); - try { - wrapper.setBlockingStatus(block); - // Set the current settings for this socket - Socket.optSet(socket, Socket.APR_SO_NONBLOCK, (block ? 0 : 1)); - // Downgrade the lock - readLock.lock(); - try { - writeLock.unlock(); - result = Socket.recv(socket, b, off, len); - } finally { - readLock.unlock(); - } - } finally { - // Should have been released above but may not have been on some - // exception paths - if (writeLock.isHeldByCurrentThread()) { - writeLock.unlock(); - } - } - } - - if (result > 0) { - eagain = false; - return result; - } else if (-result == Status.EAGAIN) { - eagain = true; - return 0; - } else if (-result == Status.APR_EGENERAL && wrapper.isSecure()) { - // Not entirely sure why this is necessary. Testing to date has not - // identified any issues with this but log it so it can be tracked - // if it is suspected of causing issues in the future. - if (log.isDebugEnabled()) { - log.debug(sm.getString("apr.read.sslGeneralError", - Long.valueOf(socket), wrapper)); - } - eagain = true; - return 0; - } else if (-result == Status.APR_EOF) { - throw new EOFException(sm.getString("apr.clientAbort")); - } else if ((OS.IS_WIN32 || OS.IS_WIN64) && - (-result == Status.APR_OS_START_SYSERR + 10053)) { - // 10053 on Windows is connection aborted - throw new EOFException(sm.getString("apr.clientAbort")); - } else { - throw new IOException(sm.getString("apr.read.error", - Integer.valueOf(-result), Long.valueOf(socket), wrapper)); - } + protected boolean doIsReady() throws IOException { + return ((AprSocketWrapper) wrapper).doIsReady(); } - @Override - protected boolean doIsReady() { - return !eagain; + protected int doRead(boolean block, byte[] b, int off, int len) throws IOException { + return ((AprSocketWrapper) wrapper).doRead(block, b, off, len); } - @Override protected void doClose() throws IOException { - closed = true; - // AbstractProcessor needs to trigger the close as multiple closes for - // APR/native sockets will cause problems. + ((AprSocketWrapper) wrapper).doClose(); } } 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=1637925&r1=1637924&r2=1637925&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Mon Nov 10 16:46:09 2014 @@ -16,6 +16,9 @@ */ package org.apache.tomcat.util.net; +import java.io.EOFException; +import java.io.IOException; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -23,6 +26,8 @@ import java.util.concurrent.ConcurrentHa import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; @@ -2346,13 +2351,122 @@ public class AprEndpoint extends Abstrac } - private static class AprSocketWrapper extends SocketWrapperBase<Long> { + public static class AprSocketWrapper extends SocketWrapperBase<Long> { + + private ByteBuffer leftOverInput; + private volatile boolean eagain = false; + private volatile boolean closed = false; // This field should only be used by Poller#run() private int pollerFlags = 0; + public AprSocketWrapper(Long socket, AprEndpoint endpoint) { super(socket, endpoint); } + + + public void setLeftOverInput(ByteBuffer leftOverInput) { + if (leftOverInput != null) { + this.leftOverInput = ByteBuffer.allocate(leftOverInput.remaining()); + this.leftOverInput.put(leftOverInput); + } + } + + + public int doRead(boolean block, byte[] b, int off, int len) + throws IOException { + + if (closed) { + throw new IOException(sm.getString("apr.closed", getSocket())); + } + + if (leftOverInput != null) { + if (leftOverInput.remaining() < len) { + len = leftOverInput.remaining(); + } + leftOverInput.get(b, off, len); + if (leftOverInput.remaining() == 0) { + leftOverInput = null; + } + return len; + } + + Lock readLock = getBlockingStatusReadLock(); + WriteLock writeLock = getBlockingStatusWriteLock(); + + boolean readDone = false; + int result = 0; + readLock.lock(); + try { + if (getBlockingStatus() == block) { + result = Socket.recv(getSocket().longValue(), b, off, len); + readDone = true; + } + } finally { + readLock.unlock(); + } + + if (!readDone) { + writeLock.lock(); + try { + setBlockingStatus(block); + // Set the current settings for this socket + Socket.optSet(getSocket().longValue(), Socket.APR_SO_NONBLOCK, (block ? 0 : 1)); + // Downgrade the lock + readLock.lock(); + try { + writeLock.unlock(); + result = Socket.recv(getSocket().longValue(), b, off, len); + } finally { + readLock.unlock(); + } + } finally { + // Should have been released above but may not have been on some + // exception paths + if (writeLock.isHeldByCurrentThread()) { + writeLock.unlock(); + } + } + } + + if (result > 0) { + eagain = false; + return result; + } else if (-result == Status.EAGAIN) { + eagain = true; + return 0; + } else if (-result == Status.APR_EGENERAL && isSecure()) { + // Not entirely sure why this is necessary. Testing to date has not + // identified any issues with this but log it so it can be tracked + // if it is suspected of causing issues in the future. + if (log.isDebugEnabled()) { + log.debug(sm.getString("apr.read.sslGeneralError", getSocket(), this)); + } + eagain = true; + return 0; + } else if (-result == Status.APR_EOF) { + throw new EOFException(sm.getString("apr.clientAbort")); + } else if ((OS.IS_WIN32 || OS.IS_WIN64) && + (-result == Status.APR_OS_START_SYSERR + 10053)) { + // 10053 on Windows is connection aborted + throw new EOFException(sm.getString("apr.clientAbort")); + } else { + throw new IOException(sm.getString("apr.read.error", + Integer.valueOf(-result), getSocket(), this)); + } + } + + + public boolean doIsReady() { + return !eagain; + } + + + public void doClose() { + closed = true; + // AbstractProcessor needs to trigger the close as multiple closes for + // APR/native sockets will cause problems. + } } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org