Removed double lock requirement for pass through sockets.
This commit is contained in:
@@ -291,10 +291,10 @@ public class WebServer {
|
||||
protected AbstractSocketContext relatedSocketContext = null;
|
||||
|
||||
/**
|
||||
* Whether this socket context should be synchronized on before the related socket context (if one exists). This simply allows locking to always occur in the same order, preventing deadlocking in the case of related sockets and bad behavior (or SPEEDY like pipelining).
|
||||
* @return Whether this context is to be locked before the related context (if it exists).
|
||||
* Gets the lockable (synchronizable) object for this context. For contexts with a related context, only one of the two will be returned, such that a single synchronize block covers both contexts.
|
||||
* @return The object to synchronize on such that two threads don't attempt to interact with the context at the same time (AsynchronousSocketChannel required for that).
|
||||
*/
|
||||
protected abstract boolean lockFirst();
|
||||
protected abstract Object getLock();
|
||||
/**
|
||||
* Processes the next response in the sequence.
|
||||
* @throws IOException
|
||||
@@ -483,11 +483,11 @@ public class WebServer {
|
||||
flagReadOnly();
|
||||
}//PassThroughSocketContext()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.foundation.web.server.WebServer.AbstractSocketContext#lockFirst()
|
||||
* @see com.foundation.web.server.WebServer.AbstractSocketContext#getLock()
|
||||
*/
|
||||
protected boolean lockFirst() {
|
||||
return false;
|
||||
}//lockFirst()//
|
||||
protected Object getLock() {
|
||||
return getRelatedSocketContext();
|
||||
}//getLock()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.foundation.web.server.WebServer.AbstractSocketContext#processResponses()
|
||||
*/
|
||||
@@ -561,7 +561,6 @@ public class WebServer {
|
||||
//Note: We are throddling this for active connections to prevent a single connection from hogging all the resources.//
|
||||
while(loopCount < 10 && result && count > 0) {
|
||||
loopCount++;
|
||||
socketReadBuffer.clear();
|
||||
count = channel.read(socketReadBuffer);
|
||||
socketReadBuffer.flip();
|
||||
|
||||
@@ -698,11 +697,11 @@ public class WebServer {
|
||||
return (PassThroughSocketContext) getRelatedSocketContext();
|
||||
}//getPassThroughSocketContext()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.foundation.web.server.WebServer.AbstractSocketContext#lockFirst()
|
||||
* @see com.foundation.web.server.WebServer.AbstractSocketContext#getLock()
|
||||
*/
|
||||
protected boolean lockFirst() {
|
||||
return true;
|
||||
}//lockFirst()//
|
||||
protected Object getLock() {
|
||||
return this;
|
||||
}//getLock()//
|
||||
protected synchronized void close() {
|
||||
try {
|
||||
if(applicationDataMap != null) {
|
||||
@@ -1916,26 +1915,11 @@ public class WebServer {
|
||||
// Debug.log("Socket is write available: " + ((SocketChannel) channel).socket().getInetAddress() + ":" + ((SocketChannel) channel).socket().getPort());
|
||||
// }//if//
|
||||
|
||||
//Lock on both contexts if there is a related socket - do it deadlock safe.//
|
||||
if(((AbstractSocketContext) context).getRelatedSocketContext() == null) {
|
||||
//Prevent another thread from reading/writing on the same socket at the same time (safety). This would have to be removed if SPEEDY (or similar pipelining) were allowed, and AsynchronousSocketChannel/AsynchronousServerSocketChannel would have to be used (requiring jdk7).//
|
||||
synchronized(context) {
|
||||
//Process the pending write to the socket as much as is possible, then return.//
|
||||
((AbstractSocketContext) context).processResponses();
|
||||
}//synchronized//
|
||||
}//if//
|
||||
else {
|
||||
Object lockFirst = ((AbstractSocketContext) context).lockFirst() ? context : ((AbstractSocketContext) context).getRelatedSocketContext();
|
||||
Object lockSecond = ((AbstractSocketContext) context).lockFirst() ? ((AbstractSocketContext) context).getRelatedSocketContext() : context;
|
||||
|
||||
//Prevent another thread from reading/writing on the same socket at the same time (safety). This would have to be removed if SPEEDY (or similar pipelining) were allowed, and AsynchronousSocketChannel/AsynchronousServerSocketChannel would have to be used (requiring jdk7).//
|
||||
synchronized(lockFirst) {
|
||||
synchronized(lockSecond) {
|
||||
//Process the pending write to the socket as much as is possible, then return.//
|
||||
((AbstractSocketContext) context).processResponses();
|
||||
}//synchronized//
|
||||
}//synchronized//
|
||||
}//else//
|
||||
//Prevent another thread from reading/writing on the same socket at the same time (safety). This would have to be removed if SPEEDY (or similar pipelining) were allowed, and AsynchronousSocketChannel/AsynchronousServerSocketChannel would have to be used (requiring jdk7).//
|
||||
synchronized(((AbstractSocketContext) context).getLock()) {
|
||||
//Process the pending write to the socket as much as is possible, then return.//
|
||||
((AbstractSocketContext) context).processResponses();
|
||||
}//synchronized//
|
||||
}//if//
|
||||
else {
|
||||
// if(debug) {
|
||||
@@ -1943,26 +1927,11 @@ public class WebServer {
|
||||
// Debug.log("Socket is read available: " + ((SocketChannel) channel).socket().getInetAddress() + ":" + ((SocketChannel) channel).socket().getPort());
|
||||
// }//if//
|
||||
|
||||
//Lock on both contexts if there is a related socket - do it deadlock safe.//
|
||||
if(((AbstractSocketContext) context).getRelatedSocketContext() == null) {
|
||||
//Prevent another thread from reading/writing on the same socket at the same time (safety). This would have to be removed if SPEEDY (or similar pipelining) were allowed, and AsynchronousSocketChannel/AsynchronousServerSocketChannel would have to be used (requiring jdk7).//
|
||||
synchronized(context) {
|
||||
//Process the incoming request and send the response (a partial response may be sent in which case the socket will be set to wait for a write opportunity and not a read opportunity).//
|
||||
((AbstractSocketContext) context).processRequest();
|
||||
}//synchronized//
|
||||
}//if//
|
||||
else {
|
||||
Object lockFirst = ((AbstractSocketContext) context).lockFirst() ? context : ((AbstractSocketContext) context).getRelatedSocketContext();
|
||||
Object lockSecond = ((AbstractSocketContext) context).lockFirst() ? ((AbstractSocketContext) context).getRelatedSocketContext() : context;
|
||||
|
||||
//Prevent another thread from reading/writing on the same socket at the same time (safety). This would have to be removed if SPEEDY (or similar pipelining) were allowed, and AsynchronousSocketChannel/AsynchronousServerSocketChannel would have to be used (requiring jdk7).//
|
||||
synchronized(lockFirst) {
|
||||
synchronized(lockSecond) {
|
||||
//Process the incoming request and send the response (a partial response may be sent in which case the socket will be set to wait for a write opportunity and not a read opportunity).//
|
||||
((AbstractSocketContext) context).processRequest();
|
||||
}//synchronized//
|
||||
}//synchronized//
|
||||
}//else//
|
||||
//Prevent another thread from reading/writing on the same socket at the same time (safety). This would have to be removed if SPEEDY (or similar pipelining) were allowed, and AsynchronousSocketChannel/AsynchronousServerSocketChannel would have to be used (requiring jdk7).//
|
||||
synchronized(((AbstractSocketContext) context).getLock()) {
|
||||
//Process the incoming request and send the response (a partial response may be sent in which case the socket will be set to wait for a write opportunity and not a read opportunity).//
|
||||
((AbstractSocketContext) context).processRequest();
|
||||
}//synchronized//
|
||||
}//else//
|
||||
}//if//
|
||||
}//try//
|
||||
|
||||
Reference in New Issue
Block a user