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 2013/08/30 21:06:07 UTC
svn commit: r1519050 -
/tomcat/trunk/java/org/apache/coyote/ajp/AjpAprProcessor.java
Author: markt
Date: Fri Aug 30 19:06:07 2013
New Revision: 1519050
URL: http://svn.apache.org/r1519050
Log:
Add the (as yet unused) plumbing to allow the AJP APR/native processor to perform non-blocking reads and writes.
Modified:
tomcat/trunk/java/org/apache/coyote/ajp/AjpAprProcessor.java
Modified: tomcat/trunk/java/org/apache/coyote/ajp/AjpAprProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/ajp/AjpAprProcessor.java?rev=1519050&r1=1519049&r2=1519050&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/ajp/AjpAprProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/ajp/AjpAprProcessor.java Fri Aug 30 19:06:07 2013
@@ -19,6 +19,8 @@ package org.apache.coyote.ajp;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.nio.ByteBuffer;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import org.apache.coyote.ActionCode;
import org.apache.coyote.RequestInfo;
@@ -280,7 +282,8 @@ public class AjpAprProcessor extends Abs
long socketRef = socketWrapper.getSocket().longValue();
if (outputBuffer.position() > 0) {
- if ((socketRef != 0) && Socket.sendbb(socketRef, 0, outputBuffer.position()) < 0) {
+ if ((socketRef != 0) &&
+ writeSocket(0, outputBuffer.position(), true) < 0) {
// There are no re-tries so clear the buffer to prevent a
// possible overflow if the buffer is used again. BZ53119.
outputBuffer.clear();
@@ -291,6 +294,51 @@ public class AjpAprProcessor extends Abs
}
+ private int writeSocket(int pos, int len, boolean block) {
+
+ Lock readLock = socketWrapper.getBlockingStatusReadLock();
+ WriteLock writeLock = socketWrapper.getBlockingStatusWriteLock();
+ long socket = socketWrapper.getSocket().longValue();
+
+ boolean writeDone = false;
+ int result = 0;
+ try {
+ readLock.lock();
+ if (socketWrapper.getBlockingStatus() == block) {
+ result = Socket.sendbb(socket, pos, len);
+ writeDone = true;
+ }
+ } finally {
+ readLock.unlock();
+ }
+
+ if (!writeDone) {
+ try {
+ writeLock.lock();
+ socketWrapper.setBlockingStatus(block);
+ // Set the current settings for this socket
+ Socket.optSet(socket, Socket.APR_SO_NONBLOCK, (block ? 0 : 1));
+ // Downgrade the lock
+ try {
+ readLock.lock();
+ writeLock.unlock();
+ result = Socket.sendbb(socket, pos, len);
+ } finally {
+ readLock.unlock();
+ }
+ } finally {
+ // Should have been released above but may not have been on some
+ // exception paths
+ if (writeLock.isHeldByCurrentThread()) {
+ writeLock.unlock();
+ }
+ }
+ }
+
+ return result;
+ }
+
+
/**
* Read at least the specified amount of bytes, and place them
* in the input buffer.
@@ -306,9 +354,8 @@ public class AjpAprProcessor extends Abs
}
int nRead;
while (inputBuffer.remaining() < n) {
- nRead = Socket.recvbb
- (socketWrapper.getSocket().longValue(), inputBuffer.limit(),
- inputBuffer.capacity() - inputBuffer.limit());
+ nRead = readSocket(inputBuffer.limit(),
+ inputBuffer.capacity() - inputBuffer.limit(), true);
if (nRead > 0) {
inputBuffer.limit(inputBuffer.limit() + nRead);
} else {
@@ -339,9 +386,8 @@ public class AjpAprProcessor extends Abs
}
int nRead;
while (inputBuffer.remaining() < n) {
- nRead = Socket.recvbb
- (socketWrapper.getSocket().longValue(), inputBuffer.limit(),
- inputBuffer.capacity() - inputBuffer.limit());
+ nRead = readSocket(inputBuffer.limit(),
+ inputBuffer.capacity() - inputBuffer.limit(), true);
if (nRead > 0) {
inputBuffer.limit(inputBuffer.limit() + nRead);
} else {
@@ -358,6 +404,51 @@ public class AjpAprProcessor extends Abs
}
+ private int readSocket(int pos, int len, boolean block) {
+
+ Lock readLock = socketWrapper.getBlockingStatusReadLock();
+ WriteLock writeLock = socketWrapper.getBlockingStatusWriteLock();
+ long socket = socketWrapper.getSocket().longValue();
+
+ boolean readDone = false;
+ int result = 0;
+ try {
+ readLock.lock();
+ if (socketWrapper.getBlockingStatus() == block) {
+ result = Socket.recvbb(socket, pos, len);
+ readDone = true;
+ }
+ } finally {
+ readLock.unlock();
+ }
+
+ if (!readDone) {
+ try {
+ writeLock.lock();
+ socketWrapper.setBlockingStatus(block);
+ // Set the current settings for this socket
+ Socket.optSet(socket, Socket.APR_SO_NONBLOCK, (block ? 0 : 1));
+ // Downgrade the lock
+ try {
+ readLock.lock();
+ writeLock.unlock();
+ result = Socket.recvbb(socket, pos, len);
+ } finally {
+ readLock.unlock();
+ }
+ } finally {
+ // Should have been released above but may not have been on some
+ // exception paths
+ if (writeLock.isHeldByCurrentThread()) {
+ writeLock.unlock();
+ }
+ }
+ }
+
+ return result;
+ }
+
+
/** Receive a chunk of data. Called to implement the
* 'special' packet in ajp13 and to receive the data
* after we send a GET_BODY packet
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org