2013/10/30 <ma...@apache.org>: > Author: markt > Date: Wed Oct 30 11:24:12 2013 > New Revision: 1537046 > > URL: http://svn.apache.org/r1537046 > Log: > Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=55715 > Add a per web application executor to the WebSocket implementation and use it > for calling SendHandler.onResult() when there is a chance that the current > thread also initiated the write > > Modified: > tomcat/tc7.0.x/trunk/ (props changed) > > tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/Constants.java > > tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsContextListener.java > > tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsHttpUpgradeHandler.java > > tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java > > tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java > > tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsWriteTimeout.java > tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml > tomcat/tc7.0.x/trunk/webapps/docs/web-socket-howto.xml > > Propchange: tomcat/tc7.0.x/trunk/ > ------------------------------------------------------------------------------ > Merged /tomcat/trunk:r1537041 >
<skip> > Modified: > tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java > URL: > http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java?rev=1537046&r1=1537045&r2=1537046&view=diff > ============================================================================== > --- > tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java > (original) > +++ > tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java > Wed Oct 30 11:24:12 2013 > @@ -26,6 +26,12 @@ import java.util.Set; > import java.util.SortedSet; > import java.util.TreeSet; > import java.util.concurrent.ConcurrentHashMap; > +import java.util.concurrent.ExecutorService; > +import java.util.concurrent.LinkedBlockingQueue; > +import java.util.concurrent.ThreadFactory; > +import java.util.concurrent.ThreadPoolExecutor; > +import java.util.concurrent.TimeUnit; > +import java.util.concurrent.atomic.AtomicLong; > > import javax.servlet.DispatcherType; > import javax.servlet.FilterRegistration; > @@ -81,6 +87,7 @@ public class WsServerContainer extends W > private volatile boolean addAllowed = true; > private final ConcurrentHashMap<String,Set<WsSession>> > authenticatedSessions = > new ConcurrentHashMap<String, Set<WsSession>>(); > + private final ExecutorService executorService; > > WsServerContainer(ServletContext servletContext) { > > @@ -104,6 +111,25 @@ public class WsServerContainer extends W > if (value != null) { > setEnforceNoAddAfterHandshake(Boolean.parseBoolean(value)); > } > + // Executor config > + int executorCoreSize = 0; > + int executorMaxSize = 10; > + long executorKeepAliveTimeSeconds = 60; > + value = servletContext.getInitParameter( > + Constants.EXECUTOR_CORE_SIZE_INIT_PARAM); > + if (value != null) { > + executorCoreSize = Integer.parseInt(value); > + } > + value = servletContext.getInitParameter( > + Constants.EXECUTOR_MAX_SIZE_INIT_PARAM); > + if (value != null) { > + executorMaxSize = Integer.parseInt(value); > + } > + value = servletContext.getInitParameter( > + Constants.EXECUTOR_KEEPALIVETIME_SECONDS_INIT_PARAM); > + if (value != null) { > + executorKeepAliveTimeSeconds = Long.parseLong(value); > + } > > FilterRegistration.Dynamic fr = servletContext.addFilter( > WsFilter.class.getName(), new WsFilter()); > @@ -113,6 +139,22 @@ public class WsServerContainer extends W > DispatcherType.FORWARD); > > fr.addMappingForUrlPatterns(types, true, "/*"); > + > + // Use a per web application executor for any threads the the > WebSocket > + // server code needs to create. Group all of the threads under a > single > + // ThreadGroup. > + StringBuffer threadGroupName = new StringBuffer("WebSocketServer-"); > + if ("".equals(servletContext.getContextPath())) { > + threadGroupName.append("ROOT"); > + } else { > + threadGroupName.append(servletContext.getContextPath()); > + } > + ThreadGroup threadGroup = new > ThreadGroup(threadGroupName.toString()); > + WsThreadFactory wsThreadFactory = new WsThreadFactory(threadGroup); > + > + executorService = new ThreadPoolExecutor(executorCoreSize, > + executorMaxSize, executorKeepAliveTimeSeconds, > TimeUnit.SECONDS, > + new LinkedBlockingQueue<Runnable>(), wsThreadFactory); > } > This commit broke the test on tomcat-7 buildbot. The only failing test class is org.apache.tomcat.websocket.server.TestWsServerContainer. Apparently it happens because of "servletContext.getContextPath()" call on the lines above. (The call itself is OK, but the method is not implemented in supplementary class used in this test). Citing from http://ci.apache.org/projects/tomcat/tomcat7/logs/1537075/TEST-org.apache.tomcat.websocket.server.TestWsServerContainer.NIO.txt [[[ Testcase: testSpecExample3 took 0.051 sec Caused an ERROR Not implemented java.lang.RuntimeException: Not implemented at org.apache.catalina.filters.TesterServletContext.getContextPath(TesterServletContext.java:47) at org.apache.tomcat.websocket.server.WsServerContainer.<init>(WsServerContainer.java:147) at org.apache.tomcat.websocket.server.TestWsServerContainer.testSpecExample3(TestWsServerContainer.java:80) ]]] Best regards, Konstantin Kolinko --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org