--- ../../apache-tomcat-6.0.18-src-stock/java/org/apache/catalina/startup/HostConfig.java +++ ../../apache-tomcat-6.0.18-src-stock/java/org/apache/catalina/startup/HostConfig.java @@ -25,8 +25,12 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.EmptyStackException; +import java.util.Enumeration; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.Stack; +import java.util.Vector; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -1179,26 +1183,81 @@ * Undeploy all deployed applications. */ protected void undeployApps() { - + if (log.isDebugEnabled()) log.debug(sm.getString("hostConfig.undeploying")); // Soft undeploy all contexts we have deployed - DeployedApplication[] apps = - (DeployedApplication[]) deployed.values().toArray(new DeployedApplication[0]); - for (int i = 0; i < apps.length; i++) { - try { - host.removeChild(host.findChild(apps[i].name)); - } catch (Throwable t) { - log.warn(sm.getString - ("hostConfig.context.remove", apps[i].name), t); - } - } - - deployed.clear(); + DeployedApplication[] apps = (DeployedApplication[]) deployed.values().toArray(new DeployedApplication[0]); + //Number of processors affects the number of shutdown worker threads we should spawn + //We spawn 2x# Processors to cover threads getting blocked on IO, Network or internal locking + int numWorkers = Runtime.getRuntime().availableProcessors()*2; + + //Generate a stack for the work. Stacks are synchronized, so we can use the same stack for multiple threads + Stack deployedApplicationStack = new Stack(); + for (int i = 0; i < apps.length; i++) { + deployedApplicationStack.addElement(apps[i]); + } + + //Create the workers and start them + Vector workerThreads = new Vector(numWorkers); + for (int i = 0; i < numWorkers; i++) { + UndeployApplicationWorkerThread uawt = new UndeployApplicationWorkerThread(sm, host, deployedApplicationStack); + uawt.start(); + workerThreads.addElement(uawt); + } + + //Wait for all threads to finish + for (Enumeration e = workerThreads.elements() ; e.hasMoreElements(); ) { + UndeployApplicationWorkerThread uawt = (UndeployApplicationWorkerThread) e.nextElement(); + try { + uawt.join(); + } catch (InterruptedException ie) { + //We're probably getting forcefully killed, so we'll give up waiting on the other threads + log.warn(sm.getString + ("hostConfig.context.remove", "Global Wait"), ie); + } + } + + deployed.clear(); } + /** This inner Thread takes a vector of DeployedApplications. It will iterate through the vector + * undeploying each + */ + class UndeployApplicationWorkerThread extends Thread { + private StringManager sm; + private Host host; + private Stack deployedApplicationStack; + + /** + * @param sm The String Manager + * @param host The Host to undeploy from + * @param deployedApplicationStack The DeployedApplications to undeploy + */ + public UndeployApplicationWorkerThread(StringManager sm, Host host, Stack deployedApplicationStack) { + this.host=host; + this.sm=sm; + this.deployedApplicationStack=deployedApplicationStack; + } + + public void run() { + try { + while (true) { + DeployedApplication da = (DeployedApplication) deployedApplicationStack.pop(); + try { + host.removeChild(host.findChild(da.name)); + } catch (Throwable t) { + log.warn(sm.getString + ("hostConfig.context.remove", da.name), t); + } + } + } catch (EmptyStackException ese) { + //There is no more work to be done. So this is fine, we'll terminate now + } + } + } /** * Check status of all webapps.