Modified the web server to use a dedicated thread to handle socket management. It now will setup new sockets, and pass request and response handling for each socket needing it to a runnable run through the thread service. This may impact performance (not sure which direction) and will ensure that socket listening is never dropped in favor of message processing.
This commit is contained in:
@@ -1796,12 +1796,11 @@ public class WebServer {
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
public void run() {
|
||||
boolean loop = true;
|
||||
// boolean loop = true;
|
||||
|
||||
//Looping only occurs when we are at the maximum allowed number of threads handling messages.//
|
||||
while(!stop && loop) {
|
||||
while(!stop /*&& loop*/) {
|
||||
SelectionKey key = null;
|
||||
boolean isWrite = false;
|
||||
|
||||
try {
|
||||
//Synchronize so that we ensure thread safe access to the activeThreadCount variable.//
|
||||
@@ -1834,12 +1833,9 @@ public class WebServer {
|
||||
selectedKeys.remove();
|
||||
|
||||
//Weed out invalid (cancelled) keys.//
|
||||
if(key.isValid()) {
|
||||
isWrite = key.isWritable();
|
||||
}//if//
|
||||
else {
|
||||
if(!key.isValid()) {
|
||||
key = null;
|
||||
}//else//
|
||||
}//if//
|
||||
|
||||
if(!selectedKeys.hasNext()) {
|
||||
selectedKeys = null;
|
||||
@@ -1856,8 +1852,9 @@ public class WebServer {
|
||||
}//catch//
|
||||
|
||||
if(key != null) {
|
||||
ChannelContext context = (ChannelContext) key.attachment();
|
||||
SelectableChannel channel = key.channel();
|
||||
final boolean isWrite = key.isWritable();
|
||||
final ChannelContext context = (ChannelContext) key.attachment();
|
||||
final SelectableChannel channel = key.channel();
|
||||
|
||||
if(channel instanceof ServerSocketChannel) {
|
||||
try {
|
||||
@@ -1888,7 +1885,7 @@ public class WebServer {
|
||||
}//catch//
|
||||
}//if//
|
||||
else if(channel instanceof SocketChannel) {
|
||||
boolean socketClosed = false;
|
||||
// boolean socketClosed = false;
|
||||
|
||||
//Toggle the write or read flag.//
|
||||
synchronized(key) {
|
||||
@@ -1904,8 +1901,51 @@ public class WebServer {
|
||||
// key.interestOps(0);
|
||||
}//synchronized//
|
||||
|
||||
try {
|
||||
if(((SocketChannel) channel).isOpen()) {
|
||||
ThreadService.run(new Runnable() {
|
||||
public void run() {
|
||||
boolean socketClosed = false;
|
||||
|
||||
try {
|
||||
if(isWrite) {
|
||||
//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 {
|
||||
//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//
|
||||
}//try//
|
||||
catch(TlsFailureException e) {
|
||||
//Allow the failure to be ignored. This occurs when the client fails to use TLS or fails to send the host name as part of the TLS handshake.//
|
||||
try {((SocketChannel) channel).close();}catch(Throwable e2) {} //Release the socket so the message doesn't continue to be processed.//
|
||||
}//catch//
|
||||
catch(Throwable e) {
|
||||
if(debug) Debug.log(e);
|
||||
|
||||
//Force the socket to be closed (for sure).//
|
||||
try {((SocketChannel) channel).close();} catch(Throwable e2) {}
|
||||
//Debug.log(e);
|
||||
socketClosed = true;
|
||||
}//catch//
|
||||
finally {
|
||||
if(channel != null && !socketClosed && channel.isOpen() && context != null) {
|
||||
selector.wakeup();
|
||||
}//if//
|
||||
else if(channel != null && (!channel.isOpen() || socketClosed) && channel instanceof SocketChannel && context instanceof SocketContext) {
|
||||
cleanupClientChannel((SocketContext) context, (SocketChannel) channel);
|
||||
}//else if//
|
||||
}//finally//
|
||||
}//run()//
|
||||
});
|
||||
/*
|
||||
try {
|
||||
synchronized(this) {
|
||||
// if(++activeThreadCount != maxThreadCount) {
|
||||
//Start another thread to take this thread's place.//
|
||||
@@ -1937,7 +1977,6 @@ public class WebServer {
|
||||
((AbstractSocketContext) context).processRequest();
|
||||
}//synchronized//
|
||||
}//else//
|
||||
}//if//
|
||||
}//try//
|
||||
catch(TlsFailureException e) {
|
||||
//Allow the failure to be ignored. This occurs when the client fails to use TLS or fails to send the host name as part of the TLS handshake.//
|
||||
@@ -1956,7 +1995,6 @@ public class WebServer {
|
||||
|
||||
if(channel != null && !socketClosed && channel.isOpen() && key != null && context != null) {
|
||||
requiresWakeup = true;
|
||||
|
||||
}//if//
|
||||
else if(channel != null && (!channel.isOpen() || socketClosed) && channel instanceof SocketChannel && context instanceof SocketContext) {
|
||||
cleanupClientChannel((SocketContext) context, (SocketChannel) channel);
|
||||
@@ -1964,15 +2002,17 @@ public class WebServer {
|
||||
|
||||
//Loop if the last thread to wait for a message couldn't start another thread due to the max number of threads allowed.//
|
||||
synchronized(this) {
|
||||
// if(activeThreadCount-- != maxThreadCount) {
|
||||
// if(activeThreadCount-- != maxThreadCount) {
|
||||
loop = false;
|
||||
|
||||
if(requiresWakeup) {
|
||||
selector.wakeup();
|
||||
}//if//
|
||||
// }//if//
|
||||
// }//if//
|
||||
}//synchronized//
|
||||
}//finally//
|
||||
*/
|
||||
}//if//
|
||||
}//else if//
|
||||
}//if//
|
||||
}//while//
|
||||
|
||||
Reference in New Issue
Block a user