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 2016/06/21 13:40:32 UTC

svn commit: r1749506 - in /tomcat/trunk: java/org/apache/tomcat/websocket/server/ webapps/docs/

Author: markt
Date: Tue Jun 21 13:40:32 2016
New Revision: 1749506

URL: http://svn.apache.org/viewvc?rev=1749506&view=rev
Log:
Now the WebSocket implementation is not built directly on top of the Servlet API and can use Tomcat internals, there is no need for the dedicated WebSocket executor.

Modified:
    tomcat/trunk/java/org/apache/tomcat/websocket/server/Constants.java
    tomcat/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties
    tomcat/trunk/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java
    tomcat/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java
    tomcat/trunk/webapps/docs/web-socket-howto.xml

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/server/Constants.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/server/Constants.java?rev=1749506&r1=1749505&r2=1749506&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/server/Constants.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/server/Constants.java Tue Jun 21 13:40:32 2016
@@ -28,12 +28,6 @@ public class Constants {
     public static final String ENFORCE_NO_ADD_AFTER_HANDSHAKE_CONTEXT_INIT_PARAM =
             "org.apache.tomcat.websocket.noAddAfterHandshake";
 
-    // Executor configuration
-    public static final String EXECUTOR_CORE_SIZE_INIT_PARAM =
-            "org.apache.tomcat.websocket.executorCoreSize";
-    public static final String EXECUTOR_KEEPALIVETIME_SECONDS_INIT_PARAM =
-            "org.apache.tomcat.websocket.executorKeepAliveTimeSeconds";
-
     public static final String SERVER_CONTAINER_SERVLET_CONTEXT_ATTRIBUTE =
             "javax.websocket.server.ServerContainer";
 

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties?rev=1749506&r1=1749505&r2=1749506&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties Tue Jun 21 13:40:32 2016
@@ -22,7 +22,6 @@ serverContainer.missingEndpoint=An Endpo
 serverContainer.pojoDeploy=POJO class [{0}] deploying to path [{1}] in ServletContext [{2}]
 serverContainer.servletContextMismatch=Attempted to register a POJO annotated for WebSocket at path [{0}] in the ServletContext with context path [{1}] when the WebSocket ServerContainer is allocated to the ServletContext with context path [{2}]
 serverContainer.servletContextMissing=No ServletContext was specified
-serverContainer.threadGroupNotDestroyed=Unable to destroy WebSocket thread group [{0}] as [{1}] threads were still running when the web application was stopped. The thread group will be destroyed once the threads terminate.
 
 upgradeUtil.incompatibleRsv=Extensions were specified that have incompatible RSV bit usage
 

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java?rev=1749506&r1=1749505&r2=1749506&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java Tue Jun 21 13:40:32 2016
@@ -20,13 +20,13 @@ import java.io.EOFException;
 import java.io.IOException;
 import java.net.SocketTimeoutException;
 import java.nio.ByteBuffer;
-import java.util.concurrent.ExecutorService;
-
+import java.util.concurrent.Executor;
 import javax.websocket.SendHandler;
 import javax.websocket.SendResult;
 
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.net.AbstractEndpoint;
 import org.apache.tomcat.util.net.SocketWrapperBase;
 import org.apache.tomcat.util.res.StringManager;
 import org.apache.tomcat.websocket.Transformation;
@@ -44,7 +44,6 @@ public class WsRemoteEndpointImplServer
 
     private final SocketWrapperBase<?> socketWrapper;
     private final WsWriteTimeout wsWriteTimeout;
-    private final ExecutorService executorService;
     private volatile SendHandler handler = null;
     private volatile ByteBuffer[] buffers = null;
 
@@ -55,7 +54,6 @@ public class WsRemoteEndpointImplServer
             WsServerContainer serverContainer) {
         this.socketWrapper = socketWrapper;
         this.wsWriteTimeout = serverContainer.getTimeout();
-        this.executorService = serverContainer.getExecutorService();
     }
 
 
@@ -227,7 +225,11 @@ public class WsRemoteEndpointImplServer
         if (sh != null) {
             if (useDispatch) {
                 OnResultRunnable r = new OnResultRunnable(sh, t);
-                if (executorService == null || executorService.isShutdown()) {
+                AbstractEndpoint<?> endpoint = socketWrapper.getEndpoint();
+                Executor containerExecutor = endpoint.getExecutor();
+                if (endpoint.isRunning() && containerExecutor != null) {
+                    containerExecutor.execute(r);
+                } else {
                     // Can't use the executor so call the runnable directly.
                     // This may not be strictly specification compliant in all
                     // cases but during shutdown only close messages are going
@@ -236,8 +238,6 @@ public class WsRemoteEndpointImplServer
                     // 55715. The issues with nested calls was the reason for
                     // the separate thread requirement in the specification.
                     r.run();
-                } else {
-                    executorService.execute(r);
                 }
             } else {
                 if (t == null) {

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java?rev=1749506&r1=1749505&r2=1749506&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java Tue Jun 21 13:40:32 2016
@@ -26,13 +26,6 @@ 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.SynchronousQueue;
-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;
 import javax.servlet.ServletContext;
@@ -49,8 +42,6 @@ import javax.websocket.server.ServerEndp
 import javax.websocket.server.ServerEndpointConfig;
 import javax.websocket.server.ServerEndpointConfig.Configurator;
 
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.InstanceManager;
 import org.apache.tomcat.util.res.StringManager;
 import org.apache.tomcat.websocket.WsSession;
@@ -71,7 +62,6 @@ public class WsServerContainer extends W
         implements ServerContainer {
 
     private static final StringManager sm = StringManager.getManager(WsServerContainer.class);
-    private static final Log log = LogFactory.getLog(WsServerContainer.class);
 
     private static final CloseReason AUTHENTICATED_HTTP_SESSION_CLOSED =
             new CloseReason(CloseCodes.VIOLATED_POLICY,
@@ -89,8 +79,6 @@ public class WsServerContainer extends W
             org.apache.tomcat.websocket.Constants.STRICT_SPEC_COMPLIANCE;
     private volatile boolean addAllowed = true;
     private final Map<String,Set<WsSession>> authenticatedSessions = new ConcurrentHashMap<>();
-    private final ExecutorService executorService;
-    private final ThreadGroup threadGroup;
     private volatile boolean endpointsRegistered = false;
 
     WsServerContainer(ServletContext servletContext) {
@@ -116,19 +104,6 @@ public class WsServerContainer extends W
         if (value != null) {
             setEnforceNoAddAfterHandshake(Boolean.parseBoolean(value));
         }
-        // Executor config
-        int executorCoreSize = 0;
-        long executorKeepAliveTimeSeconds = 60;
-        value = servletContext.getInitParameter(
-                Constants.EXECUTOR_CORE_SIZE_INIT_PARAM);
-        if (value != null) {
-            executorCoreSize = Integer.parseInt(value);
-        }
-        value = servletContext.getInitParameter(
-                Constants.EXECUTOR_KEEPALIVETIME_SECONDS_INIT_PARAM);
-        if (value != null) {
-            executorKeepAliveTimeSeconds = Long.parseLong(value);
-        }
 
         FilterRegistration.Dynamic fr = servletContext.addFilter(
                 "Tomcat WebSocket (JSR356) Filter", new WsFilter());
@@ -138,24 +113,6 @@ public class WsServerContainer extends W
                 DispatcherType.FORWARD);
 
         fr.addMappingForUrlPatterns(types, true, "/*");
-
-        // Use a per web application executor for any threads that the WebSocket
-        // server code needs to create. Group all of the threads under a single
-        // ThreadGroup.
-        StringBuffer threadGroupName = new StringBuffer("WebSocketServer-");
-        threadGroupName.append(servletContext.getVirtualServerName());
-        threadGroupName.append('-');
-        if ("".equals(servletContext.getContextPath())) {
-            threadGroupName.append("ROOT");
-        } else {
-            threadGroupName.append(servletContext.getContextPath());
-        }
-        threadGroup = new ThreadGroup(threadGroupName.toString());
-        WsThreadFactory wsThreadFactory = new WsThreadFactory(threadGroup);
-
-        executorService = new ThreadPoolExecutor(executorCoreSize,
-                Integer.MAX_VALUE, executorKeepAliveTimeSeconds, TimeUnit.SECONDS,
-                new SynchronousQueue<Runnable>(), wsThreadFactory);
     }
 
 
@@ -275,50 +232,6 @@ public class WsServerContainer extends W
     }
 
 
-    @Override
-    public void destroy() {
-        shutdownExecutor();
-        super.destroy();
-        // If the executor hasn't fully shutdown it won't be possible to
-        // destroy this thread group as there will still be threads running.
-        // Mark the thread group as daemon one, so that it destroys itself
-        // when thread count reaches zero.
-        // Synchronization on threadGroup is needed, as there is a race between
-        // destroy() call from termination of the last thread in thread group
-        // marked as daemon versus the explicit destroy() call.
-        int threadCount = threadGroup.activeCount();
-        boolean success = false;
-        try {
-            while (true) {
-                int oldThreadCount = threadCount;
-                synchronized (threadGroup) {
-                    if (threadCount > 0) {
-                        Thread.yield();
-                        threadCount = threadGroup.activeCount();
-                    }
-                    if (threadCount > 0 && threadCount != oldThreadCount) {
-                        // Value not stabilized. Retry.
-                        continue;
-                    }
-                    if (threadCount > 0) {
-                        threadGroup.setDaemon(true);
-                    } else {
-                        threadGroup.destroy();
-                        success = true;
-                    }
-                    break;
-                }
-            }
-        } catch (IllegalThreadStateException exception) {
-            // Fall-through
-        }
-        if (!success) {
-            log.warn(sm.getString("serverContainer.threadGroupNotDestroyed",
-                    threadGroup.getName(), Integer.valueOf(threadCount)));
-        }
-    }
-
-
     boolean areEndpointsRegistered() {
         return endpointsRegistered;
     }
@@ -493,23 +406,6 @@ public class WsServerContainer extends W
     }
 
 
-    ExecutorService getExecutorService() {
-        return executorService;
-    }
-
-
-    private void shutdownExecutor() {
-        if (executorService == null) {
-            return;
-        }
-        executorService.shutdown();
-        try {
-            executorService.awaitTermination(10, TimeUnit.SECONDS);
-        } catch (InterruptedException e) {
-            // Ignore the interruption and carry on
-        }
-    }
-
     private static void validateEncoders(Class<? extends Encoder>[] encoders)
             throws DeploymentException {
 
@@ -574,22 +470,4 @@ public class WsServerContainer extends W
                     tpm2.getUriTemplate().getNormalizedPath());
         }
     }
-
-
-    private static class WsThreadFactory implements ThreadFactory {
-
-        private final ThreadGroup tg;
-        private final AtomicLong count = new AtomicLong(0);
-
-        private WsThreadFactory(ThreadGroup tg) {
-            this.tg = tg;
-        }
-
-        @Override
-        public Thread newThread(Runnable r) {
-            Thread t = new Thread(tg, r);
-            t.setName(tg.getName() + "-" + count.incrementAndGet());
-            return t;
-        }
-    }
 }

Modified: tomcat/trunk/webapps/docs/web-socket-howto.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/web-socket-howto.xml?rev=1749506&r1=1749505&r2=1749506&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/web-socket-howto.xml (original)
+++ tomcat/trunk/webapps/docs/web-socket-howto.xml Tue Jun 21 13:40:32 2016
@@ -91,24 +91,6 @@
    property to <code>true</code> but any explicit setting on the servlet context
    will always take priority.</p>
 
-<p>The Java WebSocket 1.0 specification requires that callbacks for
-   asynchronous writes are performed on a different thread to the thread that
-   initiated the write. Since the container thread pool is not exposed via the
-   Servlet API, the WebSocket implementation has to provide its own thread pool.
-   This thread pool is controlled by the following servlet context
-   initialization parameters:</p>
-   <ul>
-     <li><code>org.apache.tomcat.websocket.executorCoreSize</code>: The core
-         size of the executor thread pool. If not set, the default of 0 (zero)
-         is used. Note that the maximum permitted size of the executor thread
-         pool is hard coded to <code>Integer.MAX_VALUE</code> which effectively
-         means it is unlimited.</li>
-     <li><code>org.apache.tomcat.websocket.executorKeepAliveTimeSeconds</code>:
-         The maximum time an idle thread will remain in the executor thread pool
-         until it is terminated. If not specified, the default of 60 seconds is
-         used.</li>
-   </ul>
-
 <p>When using the WebSocket client to connect to server endpoints, the timeout
    for IO operations while establishing the connection is controlled by the
    <code>userProperties</code> of the provided



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org