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 2011/10/28 09:59:17 UTC
svn commit: r1190190 - in /tomcat/tc7.0.x/trunk: ./
java/org/apache/catalina/ java/org/apache/catalina/core/
java/org/apache/catalina/startup/ java/org/apache/coyote/
java/org/apache/tomcat/util/threads/ test/org/apache/tomcat/util/threads/
webapps/doc...
Author: markt
Date: Fri Oct 28 07:59:16 2011
New Revision: 1190190
URL: http://svn.apache.org/viewvc?rev=1190190&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=46264
Implement threaded container start/stop
Removed:
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/threads/DedicatedThreadExecutor.java
tomcat/tc7.0.x/trunk/test/org/apache/tomcat/util/threads/DedicatedThreadExecutorTest.java
Modified:
tomcat/tc7.0.x/trunk/ (props changed)
tomcat/tc7.0.x/trunk/java/org/apache/catalina/Container.java
tomcat/tc7.0.x/trunk/java/org/apache/catalina/Host.java
tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/ContainerBase.java
tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/LocalStrings.properties
tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/StandardContext.java
tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/StandardHost.java
tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml
tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/ContextConfig.java
tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/HostConfig.java
tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/LocalStrings.properties
tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java
tomcat/tc7.0.x/trunk/webapps/docs/config/engine.xml
tomcat/tc7.0.x/trunk/webapps/docs/config/host.xml
Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Oct 28 07:59:16 2011
@@ -1 +1 @@
-/tomcat/trunk:1156115,1156171,1156276,1156304,1156519,1156530,1156602,1157015,1157018,1157151,1157198,1157204,1157810,1157832,1157834,1157847,1157908,1157939,1158155,1158160,1158176,1158195,1158198-1158199,1158227,1158331,1158334-1158335,1158426,1160347,1160592,1160611,1160619,1160626,1160639,1160652,1160720-1160721,1160772,1160774,1160776,1161303,1161310,1161322,1161339,1161486,1161540,1161549,1161584,1162082,1162149,1162169,1162721,1162769,1162836,1162932,1163630,1164419,1164438,1164469,1164480,1164567,1165234,1165247-1165248,1165253,1165273,1165282,1165309,1165331,1165338,1165347,1165360-1165361,1165367-1165368,1165602,1165608,1165677,1165693,1165721,1165723,1165728,1165730,1165738,1165746,1165765,1165777,1165918,1165921,1166077,1166150-1166151,1166290,1166366,1166620,1166686,1166693,1166752,1166757,1167368,1167394,1169447,1170647,1171692,1172233-1172234,1172236,1172269,1172278,1172282,1172556,1172610,1172664,1172689,1172711,1173020-1173021,1173082,1173088,1173090,1173096
,1173241,1173256,1173288,1173333,1173342,1173461,1173614,1173630,1173659,1173722,1174061,1174239,1174322,1174325,1174329-1174330,1174337-1174339,1174343,1174353,1174799,1174882,1174884,1174983,1175155,1175158,1175167,1175182,1175190,1175201,1175272,1175275,1175283,1175582,1175589-1175590,1175594,1175602,1175613,1175633,1175690,1175713,1175889,1175896,1175907,1176584,1176590,1176799,1177050,1177060,1177125,1177152,1177160,1177245,1177850,1177862,1177978,1178209,1178228,1178233,1178449,1178542,1178681,1178684,1178721,1179268,1179274,1180261,1180865,1180891,1180894,1180907,1181028,1181123,1181125,1181136,1181291,1181743,1182796,1183078,1183105,1183142,1183328,1183339-1183340,1183492-1183494,1183605,1184917,1184919,1185018,1185020,1185200,1185588,1185626,1185756,1185758,1186011,1186042-1186045,1186104,1186123,1186137,1186153,1186254,1186257,1186377-1186379,1186479-1186480,1186712,1186743,1186750,1186763,1186890-1186892,1186894,1186949,1187018,1187027-1187028,1187381,1187755,1187
775,1187827,1188301,1188303-1188305,1188399,1188822,1188930-1188931,1189116,1189129,1189183,1189240,1189256,1189386,1189413-1189414,1189477,1189685,1189805,1189857,1189864,1189882,1190034
+/tomcat/trunk:1156115,1156171,1156276,1156304,1156519,1156530,1156602,1157015,1157018,1157151,1157198,1157204,1157810,1157832,1157834,1157847,1157908,1157939,1158155,1158160,1158176,1158195,1158198-1158199,1158227,1158331,1158334-1158335,1158426,1160347,1160592,1160611,1160619,1160626,1160639,1160652,1160720-1160721,1160772,1160774,1160776,1161303,1161310,1161322,1161339,1161486,1161540,1161549,1161584,1162082,1162149,1162169,1162721,1162769,1162836,1162932,1163630,1164419,1164438,1164469,1164480,1164567,1165234,1165247-1165248,1165253,1165273,1165282,1165309,1165331,1165338,1165347,1165360-1165361,1165367-1165368,1165602,1165608,1165677,1165693,1165721,1165723,1165728,1165730,1165738,1165746,1165765,1165777,1165918,1165921,1166077,1166150-1166151,1166290,1166366,1166620,1166686,1166693,1166752,1166757,1167368,1167394,1169447,1170647,1171692,1172233-1172234,1172236,1172269,1172278,1172282,1172556,1172610,1172664,1172689,1172711,1173020-1173021,1173082,1173088,1173090,1173096
,1173241,1173256,1173288,1173333,1173342,1173461,1173614,1173630,1173659,1173722,1174061,1174239,1174322,1174325,1174329-1174330,1174337-1174339,1174343,1174353,1174799,1174882,1174884,1174983,1175155,1175158,1175167,1175182,1175190,1175201,1175272,1175275,1175283,1175582,1175589-1175590,1175594,1175602,1175613,1175633,1175690,1175713,1175889,1175896,1175907,1176584,1176590,1176799,1177050,1177060,1177125,1177152,1177160,1177245,1177850,1177862,1177978,1178209,1178228,1178233,1178449,1178542,1178681,1178684,1178721,1179268,1179274,1180261,1180865,1180891,1180894,1180907,1181028,1181123,1181125,1181136,1181291,1181743,1182796,1183078,1183105,1183142,1183328,1183339-1183340,1183492-1183494,1183605,1184917,1184919,1185018,1185020,1185200,1185588,1185626,1185756,1185758,1186011,1186042-1186045,1186104,1186123,1186137,1186153,1186254,1186257,1186377-1186379,1186479-1186480,1186712,1186743,1186750,1186763,1186890-1186892,1186894,1186949,1187018,1187027-1187028,1187381,1187755,1187
775,1187827,1188301,1188303-1188305,1188399,1188822,1188930-1188931,1189116,1189129,1189183,1189240,1189256,1189386,1189413-1189414,1189477,1189685,1189805,1189857,1189864,1189882,1190034,1190185
Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/Container.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/Container.java?rev=1190190&r1=1190189&r2=1190190&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/Container.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/Container.java Fri Oct 28 07:59:16 2011
@@ -477,4 +477,21 @@ public interface Container extends Lifec
* that the request/response still appears in the correct access logs.
*/
public AccessLog getAccessLog();
+
+
+ /**
+ * Returns the number of threads available for starting and stopping any
+ * children associated with this container. This allows start/stop calls to
+ * children to be processed in parallel.
+ */
+ public int getStartStopThreads();
+
+
+ /**
+ * Sets the number of threads available for starting and stopping any
+ * children associated with this container. This allows start/stop calls to
+ * children to be processed in parallel.
+ * @param startStopThreads The new number of threads to be used
+ */
+ public void setStartStopThreads(int startStopThreads);
}
Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/Host.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/Host.java?rev=1190190&r1=1190189&r2=1190190&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/Host.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/Host.java Fri Oct 28 07:59:16 2011
@@ -16,6 +16,7 @@
*/
package org.apache.catalina;
+import java.util.concurrent.ExecutorService;
import java.util.regex.Pattern;
@@ -171,9 +172,16 @@ public interface Host extends Container
public void setDeployIgnore(String deployIgnore);
- // --------------------------------------------------------- Public Methods
+ /**
+ * Return the executor that is used for starting and stopping contexts. This
+ * is primarily for use by components deploying contexts that want to do
+ * this in a multi-threaded manner.
+ */
+ public ExecutorService getStartStopExecutor();
+ // --------------------------------------------------------- Public Methods
+
/**
* Add an alias name that should be mapped to this same Host.
*
Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/ContainerBase.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/ContainerBase.java?rev=1190190&r1=1190189&r2=1190190&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/ContainerBase.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/ContainerBase.java Fri Oct 28 07:59:16 2011
@@ -26,6 +26,13 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
import javax.management.ObjectName;
import javax.naming.directory.DirContext;
@@ -274,8 +281,55 @@ public abstract class ContainerBase exte
protected volatile AccessLog accessLog = null;
private volatile boolean accessLogScanComplete = false;
+
+ /**
+ * The number of threads available to process start and stop events for any
+ * children associated with this container.
+ */
+ private int startStopThreads = 1;
+ protected ThreadPoolExecutor startStopExecutor;
+
// ------------------------------------------------------------- Properties
+ @Override
+ public int getStartStopThreads() {
+ return startStopThreads;
+ }
+
+ /**
+ * Handles the special values.
+ */
+ private int getStartStopThreadsInternal() {
+ int result = getStartStopThreads();
+
+ // Positive values are unchanged
+ if (result > 0) {
+ return result;
+ }
+
+ // Zero == Runtime.getRuntime().availableProcessors()
+ // -ve == Runtime.getRuntime().availableProcessors() + value
+ // These two are the same
+ result = Runtime.getRuntime().availableProcessors() + result;
+ if (result < 1) {
+ result = 1;
+ }
+ return result;
+ }
+
+ @Override
+ public void setStartStopThreads(int startStopThreads) {
+ this.startStopThreads = startStopThreads;
+
+ // Use local copies to ensure thread safety
+ ThreadPoolExecutor executor = startStopExecutor;
+ if (executor != null) {
+ int newThreads = getStartStopThreadsInternal();
+ executor.setMaximumPoolSize(newThreads);
+ executor.setCorePoolSize(newThreads);
+ }
+ }
+
/**
* Get the delay between the invocation of the backgroundProcess method on
@@ -1002,6 +1056,19 @@ public abstract class ContainerBase exte
}
+ @Override
+ protected void initInternal() throws LifecycleException {
+ BlockingQueue<Runnable> startStopQueue =
+ new LinkedBlockingQueue<Runnable>();
+ startStopExecutor = new ThreadPoolExecutor(
+ getStartStopThreadsInternal(),
+ getStartStopThreadsInternal(), 10, TimeUnit.SECONDS,
+ startStopQueue);
+ startStopExecutor.allowCoreThreadTimeOut(true);
+ super.initInternal();
+ }
+
+
/**
* Start this component and implement the requirements
* of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
@@ -1030,8 +1097,24 @@ public abstract class ContainerBase exte
// Start our child containers, if any
Container children[] = findChildren();
+ List<Future<Void>> results = new ArrayList<Future<Void>>();
for (int i = 0; i < children.length; i++) {
- children[i].start();
+ results.add(startStopExecutor.submit(new StartChild(children[i])));
+ }
+
+ boolean fail = false;
+ for (Future<Void> result : results) {
+ try {
+ result.get();
+ } catch (Exception e) {
+ log.error(sm.getString("containerBase.threadedStartFailed"), e);
+ fail = true;
+ }
+
+ }
+ if (fail) {
+ throw new LifecycleException(
+ sm.getString("containerBase.threadedStartFailed"));
}
// Start the Valves in our pipeline (including the basic), if any
@@ -1070,8 +1153,23 @@ public abstract class ContainerBase exte
// Stop our child containers, if any
Container children[] = findChildren();
+ List<Future<Void>> results = new ArrayList<Future<Void>>();
for (int i = 0; i < children.length; i++) {
- children[i].stop();
+ results.add(startStopExecutor.submit(new StopChild(children[i])));
+ }
+
+ boolean fail = false;
+ for (Future<Void> result : results) {
+ try {
+ result.get();
+ } catch (Exception e) {
+ log.error(sm.getString("containerBase.threadedStopFailed"), e);
+ fail = true;
+ }
+ }
+ if (fail) {
+ throw new LifecycleException(
+ sm.getString("containerBase.threadedStopFailed"));
}
// Stop our subordinate components, if any
@@ -1114,6 +1212,8 @@ public abstract class ContainerBase exte
parent.removeChild(this);
}
+ startStopExecutor.shutdownNow();
+
super.destroyInternal();
}
@@ -1413,4 +1513,37 @@ public abstract class ContainerBase exte
}
}
}
+
+
+ // ----------------------------- Inner classes used with start/stop Executor
+
+ private static class StartChild implements Callable<Void> {
+
+ private Container child;
+
+ public StartChild(Container child) {
+ this.child = child;
+ }
+
+ @Override
+ public Void call() throws LifecycleException {
+ child.start();
+ return null;
+ }
+ }
+
+ private static class StopChild implements Callable<Void> {
+
+ private Container child;
+
+ public StopChild(Container child) {
+ this.child = child;
+ }
+
+ @Override
+ public Void call() throws LifecycleException {
+ child.stop();
+ return null;
+ }
+ }
}
Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/LocalStrings.properties?rev=1190190&r1=1190189&r2=1190190&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/LocalStrings.properties (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/LocalStrings.properties Fri Oct 28 07:59:16 2011
@@ -60,9 +60,8 @@ aprListener.sslInit=Failed to initialize
aprListener.tcnValid=Loaded APR based Apache Tomcat Native library {0}.
aprListener.flags=APR capabilities: IPv6 [{0}], sendfile [{1}], accept filters [{2}], random [{3}].
asyncContextImpl.requestEnded=The request associated with the AsyncContext has already completed processing.
-containerBase.alreadyStarted=Container {0} has already been started
-containerBase.notConfigured=No basic Valve has been configured
-containerBase.notStarted=Container {0} has not been started
+containerBase.threadedStartFailed=A child container failed during start
+containerBase.threadedStopFailed=A child container failed during stop
containerBase.backgroundProcess.cluster=Exception processing cluster {0} background process
containerBase.backgroundProcess.loader=Exception processing loader {0} background process
containerBase.backgroundProcess.manager=Exception processing manager {0} background process
Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/StandardContext.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/StandardContext.java?rev=1190190&r1=1190189&r2=1190190&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/StandardContext.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/StandardContext.java Fri Oct 28 07:59:16 2011
@@ -37,7 +37,6 @@ import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.TreeMap;
-import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicLong;
import javax.management.ListenerNotFoundException;
@@ -118,7 +117,6 @@ import org.apache.tomcat.JarScanner;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.modeler.Registry;
import org.apache.tomcat.util.scan.StandardJarScanner;
-import org.apache.tomcat.util.threads.DedicatedThreadExecutor;
/**
* Standard implementation of the <b>Context</b> interface. Each
@@ -5208,9 +5206,7 @@ public class StandardContext extends Con
}
}
- DedicatedThreadExecutor temporaryExecutor = new DedicatedThreadExecutor();
try {
-
// Create context attributes that will be required
if (ok) {
getServletContext().setAttribute(
@@ -5235,22 +5231,7 @@ public class StandardContext extends Con
// Configure and call application event listeners
if (ok) {
- // we do it in a dedicated thread for memory leak protection, in
- // case the Listeners registers some ThreadLocals that they
- // forget to cleanup
- Boolean listenerStarted =
- temporaryExecutor.execute(new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- ClassLoader old = bindThread();
- try {
- return Boolean.valueOf(listenerStart());
- } finally {
- unbindThread(old);
- }
- }
- });
- if (!listenerStarted.booleanValue()) {
+ if (!listenerStart()) {
log.error( "Error listenerStart");
ok = false;
}
@@ -5271,22 +5252,7 @@ public class StandardContext extends Con
// Configure and call application filters
if (ok) {
- // we do it in a dedicated thread for memory leak protection, in
- // case the Filters register some ThreadLocals that they forget
- // to cleanup
- Boolean filterStarted =
- temporaryExecutor.execute(new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- ClassLoader old = bindThread();
- try {
- return Boolean.valueOf(filterStart());
- } finally {
- unbindThread(old);
- }
- }
- });
- if (!filterStarted.booleanValue()) {
+ if (!filterStart()) {
log.error("Error filterStart");
ok = false;
}
@@ -5294,27 +5260,12 @@ public class StandardContext extends Con
// Load and initialize all "load on startup" servlets
if (ok) {
- // we do it in a dedicated thread for memory leak protection, in
- // case the Servlets register some ThreadLocals that they forget
- // to cleanup
- temporaryExecutor.execute(new Callable<Void>() {
- @Override
- public Void call() throws Exception {
- ClassLoader old = bindThread();
- try {
- loadOnStartup(findChildren());
- return null;
- } finally {
- unbindThread(old);
- }
- }
- });
+ loadOnStartup(findChildren());
}
} finally {
// Unbinding thread
unbindThread(oldCCL);
- temporaryExecutor.shutdown();
}
// Set available status depending upon startup success
@@ -5454,61 +5405,28 @@ public class StandardContext extends Con
// Stop our child containers, if any
final Container[] children = findChildren();
- // we do it in a dedicated thread for memory leak protection, in
- // case some webapp code registers some ThreadLocals that they
- // forget to cleanup
- // TODO Figure out why DedicatedThreadExecutor hangs randomly in the
- // unit tests if used here
- RunnableWithLifecycleException stop =
- new RunnableWithLifecycleException() {
- @Override
- public void run() {
- ClassLoader old = bindThread();
- try {
- for (int i = 0; i < children.length; i++) {
- try {
- children[i].stop();
- } catch (LifecycleException e) {
- le = e;
- return;
- }
- }
- // Stop our filters
- filterStop();
+ ClassLoader old = bindThread();
+ try {
+ for (int i = 0; i < children.length; i++) {
+ children[i].stop();
+ }
- // Stop ContainerBackgroundProcessor thread
- threadStop();
+ // Stop our filters
+ filterStop();
- if (manager != null && manager instanceof Lifecycle &&
- ((Lifecycle) manager).getState().isAvailable()) {
- try {
- ((Lifecycle) manager).stop();
- } catch (LifecycleException e) {
- le = e;
- return;
- }
- }
+ // Stop ContainerBackgroundProcessor thread
+ threadStop();
- // Stop our application listeners
- listenerStop();
- }finally{
- unbindThread(old);
- }
+ if (manager != null && manager instanceof Lifecycle &&
+ ((Lifecycle) manager).getState().isAvailable()) {
+ ((Lifecycle) manager).stop();
}
- };
- Thread t = new Thread(stop);
- t.setName("stop children - " + getObjectName().toString());
- t.start();
- try {
- t.join();
- } catch (InterruptedException e) {
- // Shouldn't happen
- throw new LifecycleException(e);
- }
- if (stop.getLifecycleException() != null) {
- throw stop.getLifecycleException();
+ // Stop our application listeners
+ listenerStop();
+ } finally{
+ unbindThread(old);
}
// Finalize our character set mapper
@@ -6564,14 +6482,4 @@ public class StandardContext extends Con
public boolean isStatisticsProvider() {
return false;
}
-
- private abstract static class RunnableWithLifecycleException
- implements Runnable {
-
- protected LifecycleException le = null;
-
- public LifecycleException getLifecycleException() {
- return le;
- }
- }
}
Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/StandardHost.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/StandardHost.java?rev=1190190&r1=1190189&r2=1190190&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/StandardHost.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/StandardHost.java Fri Oct 28 07:59:16 2011
@@ -22,6 +22,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.WeakHashMap;
+import java.util.concurrent.ExecutorService;
import java.util.regex.Pattern;
import org.apache.catalina.Container;
@@ -179,6 +180,11 @@ public class StandardHost extends Contai
// ------------------------------------------------------------- Properties
+ @Override
+ public ExecutorService getStartStopExecutor() {
+ return startStopExecutor;
+ }
+
/**
* Return the application root for this Host. This can be an absolute
Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml?rev=1190190&r1=1190189&r2=1190190&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml Fri Oct 28 07:59:16 2011
@@ -1011,6 +1011,10 @@
description="Will children be started automatically when they are added."
type="boolean"/>
+ <attribute name="startStopThreads"
+ description="The number of threads to use when starting and stopping child Hosts"
+ type="int"/>
+
<attribute name="stateName"
description="The name of the LifecycleState that this component is currently in"
type="java.lang.String"
@@ -1198,6 +1202,10 @@
description="Will children be started automatically when they are added?"
type="boolean"/>
+ <attribute name="startStopThreads"
+ description="The number of threads to use when starting, stopping and deploying child Contexts"
+ type="int"/>
+
<attribute name="stateName"
description="The name of the LifecycleState that this component is currently in"
type="java.lang.String"
Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/ContextConfig.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/ContextConfig.java?rev=1190190&r1=1190189&r2=1190190&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/ContextConfig.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/ContextConfig.java Fri Oct 28 07:59:16 2011
@@ -127,11 +127,6 @@ public class ContextConfig
protected static final LoginConfig DUMMY_LOGIN_CONFIG =
new LoginConfig("NONE", null, null, null);
- /**
- * The <code>Digester</code> we will use to process web application
- * context files.
- */
- protected static Digester contextDigester = null;
/**
@@ -143,32 +138,6 @@ public class ContextConfig
/**
- * The <code>Digester</code>s available to process web deployment descriptor
- * files.
- */
- protected static Digester[] webDigesters = new Digester[4];
-
-
- /**
- * The <code>Digester</code>s available to process web fragment deployment
- * descriptor files.
- */
- protected static Digester[] webFragmentDigesters = new Digester[4];
-
-
- /**
- * The <code>Rule</code>s used to parse the web.xml
- */
- protected static WebRuleSet webRuleSet = new WebRuleSet(false);
-
-
- /**
- * The <code>Rule</code>s used to parse the web-fragment.xml
- */
- protected static WebRuleSet webFragmentRuleSet = new WebRuleSet(true);
-
-
- /**
* Deployment count.
*/
protected static long deploymentCount = 0L;
@@ -236,12 +205,14 @@ public class ContextConfig
* deployment descriptor files.
*/
protected Digester webDigester = null;
+ protected WebRuleSet webRuleSet = null;
/**
* The <code>Digester</code> we will use to process web fragment
* deployment descriptor files.
*/
protected Digester webFragmentDigester = null;
+ protected WebRuleSet webFragmentRuleSet = null;
// ------------------------------------------------------------- Properties
@@ -485,60 +456,21 @@ public class ContextConfig
/**
- * Create (if necessary) and return a Digester configured to process the
+ * Create and return a Digester configured to process the
* web application deployment descriptor (web.xml).
*/
public void createWebXmlDigester(boolean namespaceAware,
boolean validation) {
- if (!namespaceAware && !validation) {
- if (webDigesters[0] == null) {
- webDigesters[0] = DigesterFactory.newDigester(validation,
- namespaceAware, webRuleSet);
- webFragmentDigesters[0] = DigesterFactory.newDigester(validation,
- namespaceAware, webFragmentRuleSet);
- webDigesters[0].getParser();
- webFragmentDigesters[0].getParser();
- }
- webDigester = webDigesters[0];
- webFragmentDigester = webFragmentDigesters[0];
-
- } else if (!namespaceAware && validation) {
- if (webDigesters[1] == null) {
- webDigesters[1] = DigesterFactory.newDigester(validation,
- namespaceAware, webRuleSet);
- webFragmentDigesters[1] = DigesterFactory.newDigester(validation,
- namespaceAware, webFragmentRuleSet);
- webDigesters[1].getParser();
- webFragmentDigesters[1].getParser();
- }
- webDigester = webDigesters[1];
- webFragmentDigester = webFragmentDigesters[1];
-
- } else if (namespaceAware && !validation) {
- if (webDigesters[2] == null) {
- webDigesters[2] = DigesterFactory.newDigester(validation,
- namespaceAware, webRuleSet);
- webFragmentDigesters[2] = DigesterFactory.newDigester(validation,
- namespaceAware, webFragmentRuleSet);
- webDigesters[2].getParser();
- webFragmentDigesters[2].getParser();
- }
- webDigester = webDigesters[2];
- webFragmentDigester = webFragmentDigesters[2];
-
- } else {
- if (webDigesters[3] == null) {
- webDigesters[3] = DigesterFactory.newDigester(validation,
- namespaceAware, webRuleSet);
- webFragmentDigesters[3] = DigesterFactory.newDigester(validation,
- namespaceAware, webFragmentRuleSet);
- webDigesters[3].getParser();
- webFragmentDigesters[3].getParser();
- }
- webDigester = webDigesters[3];
- webFragmentDigester = webFragmentDigesters[3];
- }
+ webRuleSet = new WebRuleSet(false);
+ webDigester = DigesterFactory.newDigester(validation,
+ namespaceAware, webRuleSet);
+ webDigester.getParser();
+
+ webFragmentRuleSet = new WebRuleSet(true);
+ webFragmentDigester = DigesterFactory.newDigester(validation,
+ namespaceAware, webFragmentRuleSet);
+ webFragmentDigester.getParser();
}
@@ -576,7 +508,7 @@ public class ContextConfig
/**
* Process the default configuration file, if it exists.
*/
- protected void contextConfig() {
+ protected void contextConfig(Digester digester) {
// Open the default context.xml file, if it exists
if( defaultContextXml==null && context instanceof StandardContext ) {
@@ -593,7 +525,7 @@ public class ContextConfig
if (defaultContextFile.exists()) {
try {
URL defaultContextUrl = defaultContextFile.toURI().toURL();
- processContextConfig(defaultContextUrl);
+ processContextConfig(digester, defaultContextUrl);
} catch (MalformedURLException e) {
log.error(sm.getString(
"contextConfig.badUrl", defaultContextFile), e);
@@ -605,7 +537,7 @@ public class ContextConfig
if (hostContextFile.exists()) {
try {
URL hostContextUrl = hostContextFile.toURI().toURL();
- processContextConfig(hostContextUrl);
+ processContextConfig(digester, hostContextUrl);
} catch (MalformedURLException e) {
log.error(sm.getString(
"contextConfig.badUrl", hostContextFile), e);
@@ -613,7 +545,7 @@ public class ContextConfig
}
}
if (context.getConfigFile() != null)
- processContextConfig(context.getConfigFile());
+ processContextConfig(digester, context.getConfigFile());
}
@@ -621,7 +553,7 @@ public class ContextConfig
/**
* Process a context.xml.
*/
- protected void processContextConfig(URL contextXml) {
+ protected void processContextConfig(Digester digester, URL contextXml) {
if (log.isDebugEnabled())
log.debug("Processing context [" + context.getName()
@@ -647,44 +579,43 @@ public class ContextConfig
if (source == null)
return;
- synchronized (contextDigester) {
- try {
- source.setByteStream(stream);
- contextDigester.setClassLoader(this.getClass().getClassLoader());
- contextDigester.setUseContextClassLoader(false);
- contextDigester.push(context.getParent());
- contextDigester.push(context);
- XmlErrorHandler errorHandler = new XmlErrorHandler();
- contextDigester.setErrorHandler(errorHandler);
- contextDigester.parse(source);
- if (errorHandler.getWarnings().size() > 0 ||
- errorHandler.getErrors().size() > 0) {
- errorHandler.logFindings(log, contextXml.toString());
- ok = false;
- }
- if (log.isDebugEnabled())
- log.debug("Successfully processed context [" + context.getName()
- + "] configuration file [" + contextXml + "]");
- } catch (SAXParseException e) {
- log.error(sm.getString("contextConfig.contextParse",
- context.getName()), e);
- log.error(sm.getString("contextConfig.defaultPosition",
- "" + e.getLineNumber(),
- "" + e.getColumnNumber()));
- ok = false;
- } catch (Exception e) {
- log.error(sm.getString("contextConfig.contextParse",
- context.getName()), e);
+
+ try {
+ source.setByteStream(stream);
+ digester.setClassLoader(this.getClass().getClassLoader());
+ digester.setUseContextClassLoader(false);
+ digester.push(context.getParent());
+ digester.push(context);
+ XmlErrorHandler errorHandler = new XmlErrorHandler();
+ digester.setErrorHandler(errorHandler);
+ digester.parse(source);
+ if (errorHandler.getWarnings().size() > 0 ||
+ errorHandler.getErrors().size() > 0) {
+ errorHandler.logFindings(log, contextXml.toString());
ok = false;
- } finally {
- contextDigester.reset();
- try {
- if (stream != null) {
- stream.close();
- }
- } catch (IOException e) {
- log.error(sm.getString("contextConfig.contextClose"), e);
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("Successfully processed context [" + context.getName()
+ + "] configuration file [" + contextXml + "]");
+ }
+ } catch (SAXParseException e) {
+ log.error(sm.getString("contextConfig.contextParse",
+ context.getName()), e);
+ log.error(sm.getString("contextConfig.defaultPosition",
+ "" + e.getLineNumber(),
+ "" + e.getColumnNumber()));
+ ok = false;
+ } catch (Exception e) {
+ log.error(sm.getString("contextConfig.contextParse",
+ context.getName()), e);
+ ok = false;
+ } finally {
+ try {
+ if (stream != null) {
+ stream.close();
}
+ } catch (IOException e) {
+ log.error(sm.getString("contextConfig.contextClose"), e);
}
}
}
@@ -851,17 +782,15 @@ public class ContextConfig
protected void init() {
// Called from StandardContext.init()
- if (contextDigester == null){
- contextDigester = createContextDigester();
- contextDigester.getParser();
- }
+ Digester contextDigester = createContextDigester();
+ contextDigester.getParser();
if (log.isDebugEnabled())
log.debug(sm.getString("contextConfig.init"));
context.setConfigured(false);
ok = true;
- contextConfig();
+ contextConfig(contextDigester);
createWebXmlDigester(context.getXmlNamespaceAware(),
context.getXmlValidation());
@@ -1413,8 +1342,9 @@ public class ContextConfig
}
// Parsing global web.xml is relatively expensive. Use a sync block to
- // make sure it only happens once
- synchronized (host) {
+ // make sure it only happens once. Use the pipeline since a lock will
+ // already be held on the host by another thread
+ synchronized (host.getPipeline()) {
entry = hostWebXmlCache.get(host);
if (entry != null && entry.getGlobalTimeStamp() == globalTimeStamp &&
entry.getHostTimeStamp() == hostTimeStamp) {
@@ -1672,8 +1602,8 @@ public class ContextConfig
}
return getWebXmlSource(defaultWebXml, getBaseDir());
}
-
-
+
+
/**
* Identify the host web.xml to be used and obtain an input source for
* it.
@@ -1797,9 +1727,6 @@ public class ContextConfig
XmlErrorHandler handler = new XmlErrorHandler();
- // Web digesters and rulesets are shared between contexts but are not
- // thread safe. Whilst there should only be one thread at a time
- // processing a config, play safe and sync.
Digester digester;
WebRuleSet ruleSet;
if (fragment) {
@@ -1810,41 +1737,36 @@ public class ContextConfig
ruleSet = webRuleSet;
}
- // Sync on the ruleSet since the same ruleSet is shared across all four
- // digesters
- synchronized(ruleSet) {
-
- digester.push(dest);
- digester.setErrorHandler(handler);
-
- if(log.isDebugEnabled()) {
- log.debug(sm.getString("contextConfig.applicationStart",
- source.getSystemId()));
- }
-
- try {
- digester.parse(source);
+ digester.push(dest);
+ digester.setErrorHandler(handler);
+
+ if(log.isDebugEnabled()) {
+ log.debug(sm.getString("contextConfig.applicationStart",
+ source.getSystemId()));
+ }
+
+ try {
+ digester.parse(source);
- if (handler.getWarnings().size() > 0 ||
- handler.getErrors().size() > 0) {
- ok = false;
- handler.logFindings(log, source.getSystemId());
- }
- } catch (SAXParseException e) {
- log.error(sm.getString("contextConfig.applicationParse",
- source.getSystemId()), e);
- log.error(sm.getString("contextConfig.applicationPosition",
- "" + e.getLineNumber(),
- "" + e.getColumnNumber()));
+ if (handler.getWarnings().size() > 0 ||
+ handler.getErrors().size() > 0) {
ok = false;
- } catch (Exception e) {
- log.error(sm.getString("contextConfig.applicationParse",
- source.getSystemId()), e);
- ok = false;
- } finally {
- digester.reset();
- ruleSet.recycle();
+ handler.logFindings(log, source.getSystemId());
}
+ } catch (SAXParseException e) {
+ log.error(sm.getString("contextConfig.applicationParse",
+ source.getSystemId()), e);
+ log.error(sm.getString("contextConfig.applicationPosition",
+ "" + e.getLineNumber(),
+ "" + e.getColumnNumber()));
+ ok = false;
+ } catch (Exception e) {
+ log.error(sm.getString("contextConfig.applicationParse",
+ source.getSystemId()), e);
+ ok = false;
+ } finally {
+ digester.reset();
+ ruleSet.recycle();
}
}
@@ -2234,7 +2156,8 @@ public class ContextConfig
/**
* process filter annotation and merge with existing one!
- * FIXME: refactoring method to long and has redundant subroutines with processAnnotationWebServlet!
+ * FIXME: refactoring method too long and has redundant subroutines with
+ * processAnnotationWebServlet!
* @param className
* @param ae
* @param fragment
Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/HostConfig.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/HostConfig.java?rev=1190190&r1=1190189&r2=1190190&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/HostConfig.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/HostConfig.java Fri Oct 28 07:59:16 2011
@@ -14,8 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-
package org.apache.catalina.startup;
@@ -33,7 +31,11 @@ import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
@@ -144,8 +146,8 @@ public class HostConfig
/**
* Map of deployed applications.
*/
- protected HashMap<String, DeployedApplication> deployed =
- new HashMap<String, DeployedApplication>();
+ protected Map<String, DeployedApplication> deployed =
+ new ConcurrentHashMap<String, DeployedApplication>();
/**
@@ -519,6 +521,10 @@ public class HostConfig
ContextName cn = new ContextName(name);
String baseName = cn.getBaseName();
+ if (deploymentExists(baseName)) {
+ return;
+ }
+
// Deploy XML descriptors from configBase
File xml = new File(configBase, baseName + ".xml");
if (xml.exists())
@@ -542,17 +548,29 @@ public class HostConfig
if (files == null)
return;
+ ExecutorService es = host.getStartStopExecutor();
+ List<Future<?>> results = new ArrayList<Future<?>>();
+
for (int i = 0; i < files.length; i++) {
File contextXml = new File(configBase, files[i]);
if (files[i].toLowerCase(Locale.ENGLISH).endsWith(".xml")) {
ContextName cn = new ContextName(files[i]);
- String name = cn.getName();
- if (isServiced(name))
+ if (isServiced(cn.getName()) || deploymentExists(cn.getName()))
continue;
- deployDescriptor(cn, contextXml);
+ results.add(
+ es.submit(new DeployDescriptor(this, cn, contextXml)));
+ }
+ }
+
+ for (Future<?> result : results) {
+ try {
+ result.get();
+ } catch (Exception e) {
+ log.error(sm.getString(
+ "hostConfig.deployDescriptor.threaded.error"), e);
}
}
}
@@ -563,9 +581,6 @@ public class HostConfig
* @param contextXml
*/
protected void deployDescriptor(ContextName cn, File contextXml) {
- if (deploymentExists(cn.getName())) {
- return;
- }
DeployedApplication deployedApp = new DeployedApplication(cn.getName());
@@ -692,6 +707,9 @@ public class HostConfig
if (files == null)
return;
+ ExecutorService es = host.getStartStopExecutor();
+ List<Future<?>> results = new ArrayList<Future<?>>();
+
for (int i = 0; i < files.length; i++) {
if (files[i].equalsIgnoreCase("META-INF"))
@@ -712,10 +730,19 @@ public class HostConfig
continue;
}
- if (isServiced(cn.getName()))
+ if (isServiced(cn.getName()) || deploymentExists(cn.getName()))
continue;
- deployWAR(cn, war);
+ results.add(es.submit(new DeployWar(this, cn, war)));
+ }
+ }
+
+ for (Future<?> result : results) {
+ try {
+ result.get();
+ } catch (Exception e) {
+ log.error(sm.getString(
+ "hostConfig.deployWar.threaded.error"), e);
}
}
}
@@ -763,9 +790,6 @@ public class HostConfig
*/
protected void deployWAR(ContextName cn, File war) {
- if (deploymentExists(cn.getName()))
- return;
-
// Checking for a nested /META-INF/context.xml
JarFile jar = null;
JarEntry entry = null;
@@ -957,6 +981,9 @@ public class HostConfig
if (files == null)
return;
+ ExecutorService es = host.getStartStopExecutor();
+ List<Future<?>> results = new ArrayList<Future<?>>();
+
for (int i = 0; i < files.length; i++) {
if (files[i].equalsIgnoreCase("META-INF"))
@@ -967,10 +994,19 @@ public class HostConfig
if (dir.isDirectory()) {
ContextName cn = new ContextName(files[i]);
- if (isServiced(cn.getName()))
+ if (isServiced(cn.getName()) || deploymentExists(cn.getName()))
continue;
- deployDirectory(cn, dir);
+ results.add(es.submit(new DeployDirectory(this, cn, dir)));
+ }
+ }
+
+ for (Future<?> result : results) {
+ try {
+ result.get();
+ } catch (Exception e) {
+ log.error(sm.getString(
+ "hostConfig.deployDir.threaded.error"), e);
}
}
}
@@ -982,9 +1018,6 @@ public class HostConfig
*/
protected void deployDirectory(ContextName cn, File dir) {
- if (deploymentExists(cn.getName()))
- return;
-
DeployedApplication deployedApp = new DeployedApplication(cn.getName());
// Deploy the application in this directory
@@ -1473,7 +1506,61 @@ public class HostConfig
/**
* Instant where the application was last put in service.
*/
- public long timestamp = System.currentTimeMillis();
+ public long timestamp = System.currentTimeMillis();
+ }
+
+ private static class DeployDescriptor implements Runnable {
+
+ private HostConfig config;
+ private ContextName cn;
+ private File descriptor;
+
+ public DeployDescriptor(HostConfig config, ContextName cn,
+ File descriptor) {
+ this.config = config;
+ this.cn = cn;
+ this.descriptor= descriptor;
+ }
+
+ @Override
+ public void run() {
+ config.deployDescriptor(cn, descriptor);
+ }
+ }
+
+ private static class DeployWar implements Runnable {
+
+ private HostConfig config;
+ private ContextName cn;
+ private File war;
+
+ public DeployWar(HostConfig config, ContextName cn, File war) {
+ this.config = config;
+ this.cn = cn;
+ this.war = war;
+ }
+
+ @Override
+ public void run() {
+ config.deployWAR(cn, war);
+ }
}
+ private static class DeployDirectory implements Runnable {
+
+ private HostConfig config;
+ private ContextName cn;
+ private File dir;
+
+ public DeployDirectory(HostConfig config, ContextName cn, File dir) {
+ this.config = config;
+ this.cn = cn;
+ this.dir = dir;
+ }
+
+ @Override
+ public void run() {
+ config.deployDirectory(cn, dir);
+ }
+ }
}
Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/LocalStrings.properties?rev=1190190&r1=1190189&r2=1190190&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/LocalStrings.properties (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/LocalStrings.properties Fri Oct 28 07:59:16 2011
@@ -83,11 +83,14 @@ hostConfig.createDirs=Unable to create d
hostConfig.deploy=Deploying web application directory {0}
hostConfig.deployDescriptor=Deploying configuration descriptor {0}
hostConfig.deployDescriptor.error=Error deploying configuration descriptor {0}
+hostConfig.deployDescriptor.threaded.error=Error waiting for multi-thread deployment of context descriptors to complete
hostConfig.deployDescriptor.localDocBaseSpecified=A docBase {0} inside the host appBase has been specified, and will be ignored
hostConfig.deployDir=Deploying web application directory {0}
hostConfig.deployDir.error=Error deploying web application directory {0}
+hostConfig.deployDir.threaded.error=Error waiting for multi-thread deployment of directories to completehostConfig.deployWar=Deploying web application archive {0}
hostConfig.deployWar=Deploying web application archive {0}
hostConfig.deployWar.error=Error deploying web application archive {0}
+hostConfig.deployWar.threaded.error=Error waiting for multi-thread deployment of WAR files to complete
hostConfig.deploy.error=Exception while deploying web application directory {0}
hostConfig.deploying=Deploying discovered web applications
hostConfig.expand=Expanding web application archive {0}
Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java?rev=1190190&r1=1190189&r2=1190190&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java Fri Oct 28 07:59:16 2011
@@ -493,6 +493,12 @@ public abstract class AbstractProtocol i
SocketStatus status) {
P processor = connections.remove(socket.getSocket());
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("process() entry " +
+ "Socket: [" + logHashcode(socket.getSocket()) + "], " +
+ "Processor [" + logHashcode(processor) + "]");
+ }
+
socket.setAsync(false);
try {
@@ -503,20 +509,51 @@ public abstract class AbstractProtocol i
processor = createProcessor();
}
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("process() gotProcessor " +
+ "Socket: [" + logHashcode(socket.getSocket()) + "], " +
+ "Processor [" + logHashcode(processor) + "]");
+ }
+
initSsl(socket, processor);
SocketState state = SocketState.CLOSED;
do {
if (processor.isAsync() || state == SocketState.ASYNC_END) {
state = processor.asyncDispatch(status);
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("process() asyncDispatch " +
+ "Socket: [" + logHashcode(socket.getSocket()) + "], " +
+ "Processor: [" + logHashcode(processor) + "], " +
+ "State: [" + state.toString() + "]");
+ }
} else if (processor.isComet()) {
state = processor.event(status);
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("process() event " +
+ "Socket: [" + logHashcode(socket.getSocket()) + "], " +
+ "Processor: [" + logHashcode(processor) + "], " +
+ "State: [" + state.toString() + "]");
+ }
} else {
state = processor.process(socket);
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("process() process " +
+ "Socket: [" + logHashcode(socket.getSocket()) + "], " +
+ "Processor: [" + logHashcode(processor) + "], " +
+ "State: [" + state.toString() + "]");
+ }
}
if (state != SocketState.CLOSED && processor.isAsync()) {
state = processor.asyncPostProcess();
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("process() asyncPostProcess " +
+ "Socket: [" + logHashcode(socket.getSocket()) + "], " +
+ "Processor: [" + logHashcode(processor) + "], " +
+ "State: [" + state.toString() + "]");
+ }
+
}
} while (state == SocketState.ASYNC_END);
@@ -562,6 +599,14 @@ public abstract class AbstractProtocol i
return SocketState.CLOSED;
}
+ private String logHashcode (Object o) {
+ if (o == null) {
+ return "null";
+ } else {
+ return Integer.toString(o.hashCode());
+ }
+ }
+
protected abstract P createProcessor();
protected abstract void initSsl(SocketWrapper<S> socket, P processor);
protected abstract void longPoll(SocketWrapper<S> socket, P processor);
Modified: tomcat/tc7.0.x/trunk/webapps/docs/config/engine.xml
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/config/engine.xml?rev=1190190&r1=1190189&r2=1190190&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/config/engine.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/config/engine.xml Fri Oct 28 07:59:16 2011
@@ -102,6 +102,17 @@
name.</em></p>
</attribute>
+ <attribute name="startStopThreads" required="false">
+ <p>The number of threads this <strong>Engine</strong> will use to start
+ child <a href="host.html">Host</a> elements in parallel. The special
+ value of 0 will result in the value of
+ <code>Runtime.getRuntime().availableProcessors()</code> being used.
+ Negative values will result in
+ <code>Runtime.getRuntime().availableProcessors() + value</code> being
+ used unless this is less than 1 in which case 1 thread will be used. If
+ not specified, the default value of 1 will be used. </p>
+ </attribute>
+
</attributes>
</subsection>
Modified: tomcat/tc7.0.x/trunk/webapps/docs/config/host.xml
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/config/host.xml?rev=1190190&r1=1190189&r2=1190190&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/config/host.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/config/host.xml Fri Oct 28 07:59:16 2011
@@ -188,6 +188,19 @@
virtual host.</p>
</attribute>
+ <attribute name="startStopThreads" required="false">
+ <p>The number of threads this <strong>Host</strong> will use to start
+ child <a href="context.html">Context</a> elements in parallel. The same
+ thread pool will be used to deploy new
+ <a href="context.html">Context</a>s if automatic deployment is being
+ used. The special value of 0 will result in the value of
+ <code>Runtime.getRuntime().availableProcessors()</code> being used.
+ Negative values will result in
+ <code>Runtime.getRuntime().availableProcessors() + value</code> being
+ used unless this is less than 1 in which case 1 thread will be used. If
+ not specified, the default value of 1 will be used.</p>
+ </attribute>
+
</attributes>
</subsection>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org