Author: markt
Date: Thu Jan 8 13:10:41 2015
New Revision: 1650277
URL: http://svn.apache.org/r1650277
Log:
Partial NIO2 refactoring
Modified:
tomcat/trunk/java/org/apache/coyote/http11/AbstractOutputBuffer.java
tomcat/trunk/java/org/apache/coyote/http11/InternalAprOutputBuffer.java
tomcat/trunk/java/org/apache/coyote/http11/InternalNio2InputBuffer.java
tomcat/trunk/java/org/apache/coyote/http11/InternalNio2OutputBuffer.java
tomcat/trunk/java/org/apache/coyote/http11/InternalNioOutputBuffer.java
tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java
tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapperBase.java
Modified: tomcat/trunk/java/org/apache/coyote/http11/AbstractOutputBuffer.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/AbstractOutputBuffer.java?rev=1650277&r1=1650276&r2=1650277&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/AbstractOutputBuffer.java
(original)
+++ tomcat/trunk/java/org/apache/coyote/http11/AbstractOutputBuffer.java Thu
Jan 8 13:10:41 2015
@@ -591,7 +591,7 @@ public abstract class AbstractOutputBuff
//------------------------------------------------------ Non-blocking
writes
- protected abstract void registerWriteInterest() throws IOException;
+ protected abstract void registerWriteInterest();
/**
Modified:
tomcat/trunk/java/org/apache/coyote/http11/InternalAprOutputBuffer.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/InternalAprOutputBuffer.java?rev=1650277&r1=1650276&r2=1650277&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/InternalAprOutputBuffer.java
(original)
+++ tomcat/trunk/java/org/apache/coyote/http11/InternalAprOutputBuffer.java Thu
Jan 8 13:10:41 2015
@@ -52,7 +52,7 @@ public class InternalAprOutputBuffer ext
@Override
- protected void registerWriteInterest() throws IOException {
+ protected void registerWriteInterest() {
socketWrapper.registerWriteInterest();
}
}
Modified:
tomcat/trunk/java/org/apache/coyote/http11/InternalNio2InputBuffer.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/InternalNio2InputBuffer.java?rev=1650277&r1=1650276&r2=1650277&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/InternalNio2InputBuffer.java
(original)
+++ tomcat/trunk/java/org/apache/coyote/http11/InternalNio2InputBuffer.java Thu
Jan 8 13:10:41 2015
@@ -172,12 +172,12 @@ public class InternalNio2InputBuffer ext
@Override
public void failed(Throwable exc, SocketWrapperBase<Nio2Channel>
attachment) {
- attachment.setError(true);
if (exc instanceof IOException) {
e = (IOException) exc;
} else {
e = new IOException(exc);
}
+ attachment.setError(e);
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, e);
readPending = false;
endpoint.processSocket(attachment, SocketStatus.OPEN_READ,
true);
Modified:
tomcat/trunk/java/org/apache/coyote/http11/InternalNio2OutputBuffer.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/InternalNio2OutputBuffer.java?rev=1650277&r1=1650276&r2=1650277&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/InternalNio2OutputBuffer.java
(original)
+++ tomcat/trunk/java/org/apache/coyote/http11/InternalNio2OutputBuffer.java
Thu Jan 8 13:10:41 2015
@@ -21,22 +21,16 @@ import java.io.EOFException;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
-import java.nio.channels.CompletionHandler;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import javax.servlet.RequestDispatcher;
-
import org.apache.coyote.Response;
import org.apache.tomcat.util.buf.ByteBufferHolder;
-import org.apache.tomcat.util.net.AbstractEndpoint;
import org.apache.tomcat.util.net.Nio2Channel;
import org.apache.tomcat.util.net.Nio2Endpoint;
-import org.apache.tomcat.util.net.SocketStatus;
-import org.apache.tomcat.util.net.SocketWrapperBase;
+import org.apache.tomcat.util.net.Nio2Endpoint.Nio2SocketWrapper;
/**
* Output buffer implementation for NIO2.
@@ -52,186 +46,9 @@ public class InternalNio2OutputBuffer ex
super(response, headerBufferSize);
}
- private static final ByteBuffer[] EMPTY_BUF_ARRAY = new ByteBuffer[0];
-
- /**
- * Track write interest
- */
- protected volatile boolean interest = false;
-
- /**
- * The completion handler used for asynchronous write operations
- */
- protected CompletionHandler<Integer, ByteBuffer> completionHandler;
-
- /**
- * The completion handler used for asynchronous write operations
- */
- protected CompletionHandler<Long, ByteBuffer[]> gatherCompletionHandler;
-
- /**
- * Write pending flag.
- */
- protected Semaphore writePending = new Semaphore(1);
-
- /**
- * The associated endpoint.
- */
- protected AbstractEndpoint<Nio2Channel> endpoint = null;
-
- /**
- * Exception that occurred during writing.
- */
- protected IOException e = null;
-
- // --------------------------------------------------------- Public Methods
-
- @Override
- public void init(SocketWrapperBase<Nio2Channel> socketWrapper) {
- super.init(socketWrapper);
- this.endpoint = socketWrapper.getEndpoint();
-
- this.completionHandler = new CompletionHandler<Integer, ByteBuffer>() {
- @Override
- public void completed(Integer nBytes, ByteBuffer attachment) {
- boolean notify = false;
- synchronized (completionHandler) {
- if (nBytes.intValue() < 0) {
- failed(new
EOFException(sm.getString("iob.failedwrite")), attachment);
- } else if (socketWrapper.bufferedWrites.size() > 0) {
- // Continue writing data using a gathering write
- ArrayList<ByteBuffer> arrayList = new ArrayList<>();
- if (attachment.hasRemaining()) {
- arrayList.add(attachment);
- }
- for (ByteBufferHolder buffer :
socketWrapper.bufferedWrites) {
- buffer.flip();
- arrayList.add(buffer.getBuf());
- }
- socketWrapper.bufferedWrites.clear();
- ByteBuffer[] array =
arrayList.toArray(EMPTY_BUF_ARRAY);
- socketWrapper.getSocket().write(array, 0, array.length,
- socketWrapper.getTimeout(),
TimeUnit.MILLISECONDS,
- array, gatherCompletionHandler);
- } else if (attachment.hasRemaining()) {
- // Regular write
- socketWrapper.getSocket().write(attachment,
socketWrapper.getTimeout(),
- TimeUnit.MILLISECONDS, attachment,
completionHandler);
- } else {
- // All data has been written
- if (interest && !Nio2Endpoint.isInline()) {
- interest = false;
- notify = true;
- }
- writePending.release();
- }
- }
- if (notify) {
- endpoint.processSocket(socketWrapper,
SocketStatus.OPEN_WRITE, false);
- }
- }
-
- @Override
- public void failed(Throwable exc, ByteBuffer attachment) {
- socketWrapper.setError(true);
- if (exc instanceof IOException) {
- e = (IOException) exc;
- } else {
- e = new IOException(exc);
- }
-
response.getRequest().setAttribute(RequestDispatcher.ERROR_EXCEPTION, e);
- writePending.release();
- endpoint.processSocket(socketWrapper, SocketStatus.OPEN_WRITE,
true);
- }
- };
- this.gatherCompletionHandler = new CompletionHandler<Long,
ByteBuffer[]>() {
- @Override
- public void completed(Long nBytes, ByteBuffer[] attachment) {
- boolean notify = false;
- synchronized (completionHandler) {
- if (nBytes.longValue() < 0) {
- failed(new
EOFException(sm.getString("iob.failedwrite")), attachment);
- } else if (socketWrapper.bufferedWrites.size() > 0 ||
arrayHasData(attachment)) {
- // Continue writing data
- ArrayList<ByteBuffer> arrayList = new ArrayList<>();
- for (ByteBuffer buffer : attachment) {
- if (buffer.hasRemaining()) {
- arrayList.add(buffer);
- }
- }
- for (ByteBufferHolder buffer :
socketWrapper.bufferedWrites) {
- buffer.flip();
- arrayList.add(buffer.getBuf());
- }
- socketWrapper.bufferedWrites.clear();
- ByteBuffer[] array =
arrayList.toArray(EMPTY_BUF_ARRAY);
- socketWrapper.getSocket().write(array, 0, array.length,
- socketWrapper.getTimeout(),
TimeUnit.MILLISECONDS,
- array, gatherCompletionHandler);
- } else {
- // All data has been written
- if (interest && !Nio2Endpoint.isInline()) {
- interest = false;
- notify = true;
- }
- writePending.release();
- }
- }
- if (notify) {
- endpoint.processSocket(socketWrapper,
SocketStatus.OPEN_WRITE, false);
- }
- }
-
- @Override
- public void failed(Throwable exc, ByteBuffer[] attachment) {
- socketWrapper.setError(true);
- if (exc instanceof IOException) {
- e = (IOException) exc;
- } else {
- e = new IOException(exc);
- }
-
response.getRequest().setAttribute(RequestDispatcher.ERROR_EXCEPTION, e);
- writePending.release();
- endpoint.processSocket(socketWrapper, SocketStatus.OPEN_WRITE,
true);
- }
- };
- }
-
-
- /**
- * Recycle the output buffer. This should be called when closing the
- * connection.
- */
- @Override
- public void recycle() {
- super.recycle();
- e = null;
- interest = false;
- if (writePending.availablePermits() != 1) {
- writePending.drainPermits();
- writePending.release();
- }
- }
-
-
- @Override
- public void nextRequest() {
- super.nextRequest();
- interest = false;
- }
-
// ------------------------------------------------------ Protected Methods
- private static boolean arrayHasData(ByteBuffer[] byteBuffers) {
- for (ByteBuffer byteBuffer : byteBuffers) {
- if (byteBuffer.hasRemaining()) {
- return true;
- }
- }
- return false;
- }
-
@Override
protected void addToBB(byte[] buf, int offset, int length)
throws IOException {
@@ -259,8 +76,8 @@ public class InternalNio2OutputBuffer ex
// Could be "smart" with coordination with the main
CoyoteOutputStream to
// indicate the end of a write
// Uses: if (writePending.tryAcquire(socketWrapper.getTimeout(),
TimeUnit.MILLISECONDS))
- if (writePending.tryAcquire()) {
- synchronized (completionHandler) {
+ if (((Nio2SocketWrapper)socketWrapper).writePending.tryAcquire()) {
+ synchronized
(((Nio2SocketWrapper)socketWrapper).writeCompletionHandler) {
// No pending completion handler, so writing to the main
buffer
// is possible
int thisTime = transfer(buf, offset, length,
socketWrapper.socketWriteBuffer);
@@ -273,7 +90,7 @@ public class InternalNio2OutputBuffer ex
flushBufferInternal(false, true);
}
} else {
- synchronized (completionHandler) {
+ synchronized
(((Nio2SocketWrapper)socketWrapper).writeCompletionHandler) {
addToBuffers(buf, offset, length);
}
}
@@ -293,8 +110,8 @@ public class InternalNio2OutputBuffer ex
*/
@Override
protected boolean flushBuffer(boolean block) throws IOException {
- if (e != null) {
- throw e;
+ if (socketWrapper.getError() != null) {
+ throw socketWrapper.getError();
}
return flushBufferInternal(block, false);
}
@@ -308,8 +125,8 @@ public class InternalNio2OutputBuffer ex
// The final flush is blocking, but the processing was using
// non blocking so wait until an async write is done
try {
- if (writePending.tryAcquire(socketWrapper.getTimeout(),
TimeUnit.MILLISECONDS)) {
- writePending.release();
+ if
(((Nio2SocketWrapper)socketWrapper).writePending.tryAcquire(socketWrapper.getTimeout(),
TimeUnit.MILLISECONDS)) {
+
((Nio2SocketWrapper)socketWrapper).writePending.release();
}
} catch (InterruptedException e) {
// Ignore timeout
@@ -352,8 +169,8 @@ public class InternalNio2OutputBuffer ex
socketWrapper.writeBufferFlipped = false;
return false;
} else {
- synchronized (completionHandler) {
- if (hasPermit || writePending.tryAcquire()) {
+ synchronized
(((Nio2SocketWrapper)socketWrapper).writeCompletionHandler) {
+ if (hasPermit ||
((Nio2SocketWrapper)socketWrapper).writePending.tryAcquire()) {
if (!socketWrapper.writeBufferFlipped) {
socketWrapper.socketWriteBuffer.flip();
socketWrapper.writeBufferFlipped = true;
@@ -370,26 +187,26 @@ public class InternalNio2OutputBuffer ex
arrayList.add(buffer.getBuf());
}
socketWrapper.bufferedWrites.clear();
- ByteBuffer[] array =
arrayList.toArray(EMPTY_BUF_ARRAY);
+ ByteBuffer[] array = arrayList.toArray(new
ByteBuffer[arrayList.size()]);
socketWrapper.getSocket().write(array, 0,
array.length, socketWrapper.getTimeout(),
- TimeUnit.MILLISECONDS, array,
gatherCompletionHandler);
+ TimeUnit.MILLISECONDS, array,
((Nio2SocketWrapper)socketWrapper).gatheringWriteCompletionHandler);
} else if (socketWrapper.socketWriteBuffer.hasRemaining())
{
// Regular write
socketWrapper.getSocket().write(socketWrapper.socketWriteBuffer,
socketWrapper.getTimeout(),
- TimeUnit.MILLISECONDS,
socketWrapper.socketWriteBuffer, completionHandler);
+ TimeUnit.MILLISECONDS,
socketWrapper.socketWriteBuffer,
((Nio2SocketWrapper)socketWrapper).writeCompletionHandler);
} else {
// Nothing was written
- writePending.release();
+
((Nio2SocketWrapper)socketWrapper).writePending.release();
}
Nio2Endpoint.endInline();
- if (writePending.availablePermits() > 0) {
+ if
(((Nio2SocketWrapper)socketWrapper).writePending.availablePermits() > 0) {
if (socketWrapper.socketWriteBuffer.remaining() == 0) {
socketWrapper.socketWriteBuffer.clear();
socketWrapper.writeBufferFlipped = false;
}
}
}
- return socketWrapper.hasMoreDataToFlush() || hasBufferedData()
|| e != null;
+ return socketWrapper.hasMoreDataToFlush() || hasBufferedData()
|| socketWrapper.getError() != null;
}
}
}
@@ -397,8 +214,8 @@ public class InternalNio2OutputBuffer ex
@Override
public boolean hasDataToWrite() {
- synchronized (completionHandler) {
- return socketWrapper.hasMoreDataToFlush() || hasBufferedData() ||
e != null;
+ synchronized
(((Nio2SocketWrapper)socketWrapper).writeCompletionHandler) {
+ return socketWrapper.hasMoreDataToFlush() || hasBufferedData() ||
socketWrapper.getError() != null;
}
}
@@ -408,13 +225,6 @@ public class InternalNio2OutputBuffer ex
@Override
protected void registerWriteInterest() {
- synchronized (completionHandler) {
- if (writePending.availablePermits() == 0) {
- interest = true;
- } else {
- // If no write is pending, notify
- endpoint.processSocket(socketWrapper, SocketStatus.OPEN_WRITE,
true);
- }
- }
+ socketWrapper.registerWriteInterest();
}
}
Modified:
tomcat/trunk/java/org/apache/coyote/http11/InternalNioOutputBuffer.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/InternalNioOutputBuffer.java?rev=1650277&r1=1650276&r2=1650277&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/InternalNioOutputBuffer.java
(original)
+++ tomcat/trunk/java/org/apache/coyote/http11/InternalNioOutputBuffer.java Thu
Jan 8 13:10:41 2015
@@ -53,7 +53,7 @@ public class InternalNioOutputBuffer ext
@Override
- protected void registerWriteInterest() throws IOException {
+ protected void registerWriteInterest() {
socketWrapper.registerWriteInterest();
}
}
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=1650277&r1=1650276&r2=1650277&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 8
13:10:41 2015
@@ -2618,7 +2618,7 @@ public class AprEndpoint extends Abstrac
@Override
- public void registerWriteInterest() throws IOException {
+ public void registerWriteInterest() {
((AprEndpoint)
getEndpoint()).getPoller().add(getSocket().longValue(), -1, false, true);
}
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=1650277&r1=1650276&r2=1650277&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 8
13:10:41 2015
@@ -32,6 +32,7 @@ import java.nio.channels.ClosedChannelEx
import java.nio.channels.CompletionHandler;
import java.nio.channels.FileChannel;
import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
@@ -49,6 +50,7 @@ import javax.net.ssl.X509KeyManager;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.ExceptionUtils;
+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;
@@ -721,8 +723,10 @@ public class Nio2Endpoint extends Abstra
private volatile boolean interest = true;
private final int maxWrite;
- private final CompletionHandler<Integer, ByteBuffer>
writeCompletionHandler;
- private final Semaphore writePending = new Semaphore(1);
+ // TODO These are public for now to aid refactoring
+ public final CompletionHandler<Integer, ByteBuffer>
writeCompletionHandler;
+ public final CompletionHandler<Long, ByteBuffer[]>
gatheringWriteCompletionHandler;
+ public final Semaphore writePending = new Semaphore(1);
public Nio2SocketWrapper(Nio2Channel channel, Nio2Endpoint endpoint) {
@@ -753,7 +757,13 @@ public class Nio2Endpoint extends Abstra
}
@Override
public void failed(Throwable exc,
SocketWrapperBase<Nio2Channel> attachment) {
- attachment.setError(true);
+ IOException ioe;
+ if (exc instanceof IOException) {
+ ioe = (IOException) exc;
+ } else {
+ ioe = new IOException(exc);
+ }
+ Nio2SocketWrapper.this.setError(ioe);
readPending = false;
if (exc instanceof AsynchronousCloseException) {
// If already closed, don't call onError and close
again
@@ -766,32 +776,120 @@ public class Nio2Endpoint extends Abstra
this.writeCompletionHandler = new CompletionHandler<Integer,
ByteBuffer>() {
@Override
public void completed(Integer nBytes, ByteBuffer attachment) {
- if (nBytes.intValue() < 0) {
- failed(new EOFException(), attachment);
- } else if (attachment.hasRemaining()) {
- getSocket().write(attachment, getTimeout(),
- TimeUnit.MILLISECONDS, attachment,
writeCompletionHandler);
- } else {
- writePending.release();
- if (!Nio2Endpoint.isInline()) {
-
getEndpoint().processSocket(Nio2SocketWrapper.this, SocketStatus.OPEN_WRITE,
false);
+ boolean notify = false;
+ synchronized (writeCompletionHandler) {
+ if (nBytes.intValue() < 0) {
+ failed(new
EOFException(sm.getString("iob.failedwrite")), attachment);
+ } else if
(Nio2SocketWrapper.this.bufferedWrites.size() > 0) {
+ // Continue writing data using a gathering write
+ ArrayList<ByteBuffer> arrayList = new
ArrayList<>();
+ if (attachment.hasRemaining()) {
+ arrayList.add(attachment);
+ }
+ for (ByteBufferHolder buffer :
Nio2SocketWrapper.this.bufferedWrites) {
+ buffer.flip();
+ arrayList.add(buffer.getBuf());
+ }
+ Nio2SocketWrapper.this.bufferedWrites.clear();
+ ByteBuffer[] array = arrayList.toArray(new
ByteBuffer[arrayList.size()]);
+ Nio2SocketWrapper.this.getSocket().write(array, 0,
array.length,
+ Nio2SocketWrapper.this.getTimeout(),
TimeUnit.MILLISECONDS,
+ array, gatheringWriteCompletionHandler);
+ } else if (attachment.hasRemaining()) {
+ // Regular write
+
Nio2SocketWrapper.this.getSocket().write(attachment,
Nio2SocketWrapper.this.getTimeout(),
+ TimeUnit.MILLISECONDS, attachment,
writeCompletionHandler);
+ } else {
+ // All data has been written
+ if (interest && !Nio2Endpoint.isInline()) {
+ interest = false;
+ notify = true;
+ }
+ writePending.release();
}
}
+ if (notify) {
+ endpoint.processSocket(Nio2SocketWrapper.this,
SocketStatus.OPEN_WRITE, false);
+ }
}
+
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
- setError(true);
+ IOException ioe;
+ if (exc instanceof IOException) {
+ ioe = (IOException) exc;
+ } else {
+ ioe = new IOException(exc);
+ }
+ Nio2SocketWrapper.this.setError(ioe);
writePending.release();
- if (exc instanceof AsynchronousCloseException) {
- // If already closed, don't call onError and close
again
- return;
+ endpoint.processSocket(Nio2SocketWrapper.this,
SocketStatus.OPEN_WRITE, true);
+ }
+ };
+
+ gatheringWriteCompletionHandler = new CompletionHandler<Long,
ByteBuffer[]>() {
+ @Override
+ public void completed(Long nBytes, ByteBuffer[] attachment) {
+ boolean notify = false;
+ synchronized (writeCompletionHandler) {
+ if (nBytes.longValue() < 0) {
+ failed(new
EOFException(sm.getString("iob.failedwrite")), attachment);
+ } else if
(Nio2SocketWrapper.this.bufferedWrites.size() > 0 || arrayHasData(attachment)) {
+ // Continue writing data
+ ArrayList<ByteBuffer> arrayList = new
ArrayList<>();
+ for (ByteBuffer buffer : attachment) {
+ if (buffer.hasRemaining()) {
+ arrayList.add(buffer);
+ }
+ }
+ for (ByteBufferHolder buffer :
Nio2SocketWrapper.this.bufferedWrites) {
+ buffer.flip();
+ arrayList.add(buffer.getBuf());
+ }
+ Nio2SocketWrapper.this.bufferedWrites.clear();
+ ByteBuffer[] array = arrayList.toArray(new
ByteBuffer[arrayList.size()]);
+ Nio2SocketWrapper.this.getSocket().write(array, 0,
array.length,
+ Nio2SocketWrapper.this.getTimeout(),
TimeUnit.MILLISECONDS,
+ array, gatheringWriteCompletionHandler);
+ } else {
+ // All data has been written
+ if (interest && !Nio2Endpoint.isInline()) {
+ interest = false;
+ notify = true;
+ }
+ writePending.release();
+ }
+ }
+ if (notify) {
+ endpoint.processSocket(Nio2SocketWrapper.this,
SocketStatus.OPEN_WRITE, false);
}
- getEndpoint().processSocket(Nio2SocketWrapper.this,
SocketStatus.ERROR, true);
}
+
+ @Override
+ public void failed(Throwable exc, ByteBuffer[] attachment) {
+ IOException ioe;
+ if (exc instanceof IOException) {
+ ioe = (IOException) exc;
+ } else {
+ ioe = new IOException(exc);
+ }
+ Nio2SocketWrapper.this.setError(ioe);
+ writePending.release();
+ endpoint.processSocket(Nio2SocketWrapper.this,
SocketStatus.OPEN_WRITE, true);
+ }
};
}
+ private static boolean arrayHasData(ByteBuffer[] byteBuffers) {
+ for (ByteBuffer byteBuffer : byteBuffers) {
+ if (byteBuffer.hasRemaining()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public void reset(Nio2Channel channel, long soTimeout) {
super.reset(channel, soTimeout);
@@ -1073,8 +1171,15 @@ public class Nio2Endpoint extends Abstra
@Override
- public void registerWriteInterest() throws IOException {
- // TODO Auto-generated method stub
+ public void registerWriteInterest() {
+ synchronized (writeCompletionHandler) {
+ if (writePending.availablePermits() == 0) {
+ interest = true;
+ } else {
+ // If no write is pending, notify
+ getEndpoint().processSocket(this, SocketStatus.OPEN_WRITE,
true);
+ }
+ }
}
@@ -1082,13 +1187,6 @@ public class Nio2Endpoint extends Abstra
public void regsiterForEvent(boolean read, boolean write) {
// NO-OP. Appropriate handlers will already have been registered.
}
-
-
- @Override
- public boolean flush(boolean block) throws IOException {
- // TODO Auto-generated method stub
- return false;
- }
}
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=1650277&r1=1650276&r2=1650277&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 8
13:10:41 2015
@@ -1241,7 +1241,7 @@ public class NioEndpoint extends Abstrac
NioSocketWrapper ka = (NioSocketWrapper) key.attachment();
if ( ka == null ) {
cancelledKey(key); //we don't support any keys without
attachments
- } else if ( ka.getError() ) {
+ } else if ( ka.getError() != null) {
cancelledKey(key);//TODO this is not yet being used
} else if (ka.getCallBackNotify() ) {
ka.setCallBackNotify(false);
@@ -1549,7 +1549,7 @@ public class NioEndpoint extends Abstrac
@Override
- public void registerWriteInterest() throws IOException {
+ public void registerWriteInterest() {
getPoller().add(getSocket(), SelectionKey.OP_WRITE);
}
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=1650277&r1=1650276&r2=1650277&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
8 13:10:41 2015
@@ -37,7 +37,7 @@ public abstract class SocketWrapperBase<
private volatile long lastAsyncStart = 0;
private volatile long asyncTimeout = -1;
private long timeout = -1;
- private boolean error = false;
+ private IOException error = null;
private volatile int keepAliveLeft = 100;
private volatile boolean async = false;
private boolean keptAlive = false;
@@ -152,8 +152,8 @@ public abstract class SocketWrapperBase<
void access(long access) { lastAccess = access; }
public void setTimeout(long timeout) {this.timeout = timeout;}
public long getTimeout() {return this.timeout;}
- public boolean getError() { return error; }
- public void setError(boolean error) { this.error = error; }
+ public IOException getError() { return error; }
+ public void setError(IOException error) { this.error = error; }
public void setKeepAliveLeft(int keepAliveLeft) { this.keepAliveLeft =
keepAliveLeft;}
public int decrementKeepAlive() { return (--keepAliveLeft);}
public boolean isKeptAlive() {return keptAlive;}
@@ -234,7 +234,7 @@ public abstract class SocketWrapperBase<
async = false;
blockingStatus = true;
dispatches.clear();
- error = false;
+ error = null;
keepAliveLeft = 100;
lastAccess = System.currentTimeMillis();
lastAsyncStart = 0;
@@ -407,7 +407,7 @@ public abstract class SocketWrapperBase<
holder.getBuf().put(buf,offset,length);
}
- public abstract void registerWriteInterest() throws IOException;
+ public abstract void registerWriteInterest();
public abstract void regsiterForEvent(boolean read, boolean write);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]