Author: markt
Date: Sat Sep 8 21:00:32 2012
New Revision: 1382366
URL: http://svn.apache.org/viewvc?rev=1382366&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=52777
Implement optional automatic removal of old applications where parallel
deployment has been used.
Modified:
tomcat/trunk/java/org/apache/catalina/Host.java
tomcat/trunk/java/org/apache/catalina/core/StandardHost.java
tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml
tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java
tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties
tomcat/trunk/java/org/apache/catalina/startup/mbeans-descriptors.xml
tomcat/trunk/webapps/docs/config/context.xml
tomcat/trunk/webapps/docs/config/host.xml
Modified: tomcat/trunk/java/org/apache/catalina/Host.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Host.java?rev=1382366&r1=1382365&r2=1382366&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/Host.java (original)
+++ tomcat/trunk/java/org/apache/catalina/Host.java Sat Sep 8 21:00:32 2012
@@ -210,6 +210,22 @@ public interface Host extends Container
public void setCreateDirs(boolean createDirs);
+ /**
+ * Returns true of the Host is configured to automatically undeploy old
+ * versions of applications deployed using parallel deployment. This only
+ * takes effect is {@link #getAutoDeploy()} also returns true.
+ */
+ public boolean getUndeployOldVersions();
+
+
+ /**
+ * Set to true if the Host should automatically undeploy old versions of
+ * applications deployed using parallel deployment. This only takes effect
+ * if {@link #getAutoDeploy()} returns true.
+ */
+ public void setUndeployOldVersions(boolean undeployOldVersions);
+
+
// --------------------------------------------------------- Public Methods
/**
Modified: tomcat/trunk/java/org/apache/catalina/core/StandardHost.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardHost.java?rev=1382366&r1=1382365&r2=1382366&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardHost.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardHost.java Sat Sep 8
21:00:32 2012
@@ -181,9 +181,24 @@ public class StandardHost extends Contai
private Pattern deployIgnore = null;
+ private boolean undeployOldVersions = false;
+
+
// ------------------------------------------------------------- Properties
@Override
+ public boolean getUndeployOldVersions() {
+ return undeployOldVersions;
+ }
+
+
+ @Override
+ public void setUndeployOldVersions(boolean undeployOldVersions) {
+ this.undeployOldVersions = undeployOldVersions;
+ }
+
+
+ @Override
public ExecutorService getStartStopExecutor() {
return startStopExecutor;
}
Modified: tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml?rev=1382366&r1=1382365&r2=1382366&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml (original)
+++ tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml Sat Sep
8 21:00:32 2012
@@ -1181,6 +1181,10 @@
type="java.lang.String"
writeable="false"/>
+ <attribute name="undeployOldVersions"
+ description="Determines if old versions of applications
deployed using parallel deployment are automatically undeployed when no longer
used. Requires autoDeploy to be enabled."
+ type="boolean"/>
+
<attribute name="unpackWARs"
description="Unpack WARs property"
is="true"
Modified: tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java?rev=1382366&r1=1382365&r2=1382366&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java Sat Sep 8
21:00:32 2012
@@ -27,11 +27,14 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
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.Future;
@@ -48,6 +51,7 @@ import org.apache.catalina.Host;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.Manager;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.util.ContextName;
import org.apache.catalina.util.IOTools;
@@ -1163,43 +1167,7 @@ public class HostConfig
if ((!resource.isDirectory()) &&
resource.lastModified() > lastModified) {
// Undeploy application
- if (log.isInfoEnabled())
- log.info(sm.getString("hostConfig.undeploy",
app.name));
- Container context = host.findChild(app.name);
- try {
- host.removeChild(context);
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(t);
- log.warn(sm.getString
- ("hostConfig.context.remove", app.name), t);
- }
- // Delete other redeploy resources
- for (int j = i + 1; j < resources.length; j++) {
- try {
- File current = new File(resources[j]);
- current = current.getCanonicalFile();
- // Never delete per host context.xml defaults
- if (Constants.HostContextXml.equals(
- current.getName())) {
- continue;
- }
- // Only delete resources in the appBase or the
- // host's configBase
- if ((current.getAbsolutePath().startsWith(
- host.getAppBaseFile().getAbsolutePath() +
- File.separator))
- || (current.getAbsolutePath().startsWith(
-
host.getConfigBaseFile().getAbsolutePath()))) {
- if (log.isDebugEnabled())
- log.debug("Delete " + current);
- ExpandWar.delete(current);
- }
- } catch (IOException e) {
- log.warn(sm.getString
- ("hostConfig.canonicalizing", app.name),
e);
- }
- }
- deployed.remove(app.name);
+ deleteRedeployResources(app, resources, i, false);
return;
}
} else {
@@ -1220,71 +1188,7 @@ public class HostConfig
continue;
}
// Undeploy application
- if (log.isInfoEnabled())
- log.info(sm.getString("hostConfig.undeploy", app.name));
- Container context = host.findChild(app.name);
- try {
- host.removeChild(context);
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(t);
- log.warn(sm.getString
- ("hostConfig.context.remove", app.name), t);
- }
- // Delete all redeploy resources
- for (int j = i + 1; j < resources.length; j++) {
- try {
- File current = new File(resources[j]);
- current = current.getCanonicalFile();
- // Never delete per host context.xml defaults
- if (Constants.HostContextXml.equals(
- current.getName())) {
- continue;
- }
- // Only delete resources in the appBase or the host's
- // configBase
- if ((current.getAbsolutePath().startsWith(
- host.getAppBaseFile().getAbsolutePath() +
File.separator))
- || (current.getAbsolutePath().startsWith(
-
host.getConfigBaseFile().getAbsolutePath()))) {
- if (log.isDebugEnabled())
- log.debug("Delete " + current);
- ExpandWar.delete(current);
- }
- } catch (IOException e) {
- log.warn(sm.getString
- ("hostConfig.canonicalizing", app.name), e);
- }
- }
- // Delete reload resources as well (to remove any remaining
.xml
- // descriptor)
- String[] resources2 =
- app.reloadResources.keySet().toArray(new String[0]);
- for (int j = 0; j < resources2.length; j++) {
- try {
- File current = new File(resources2[j]);
- current = current.getCanonicalFile();
- // Never delete per host context.xml defaults
- if (Constants.HostContextXml.equals(
- current.getName())) {
- continue;
- }
- // Only delete resources in the appBase or the host's
- // configBase
- if ((current.getAbsolutePath().startsWith(
- host.getAppBaseFile().getAbsolutePath() +
File.separator))
- || ((current.getAbsolutePath().startsWith(
- host.getConfigBaseFile().getAbsolutePath())
- &&
(current.getAbsolutePath().endsWith(".xml"))))) {
- if (log.isDebugEnabled())
- log.debug("Delete " + current);
- ExpandWar.delete(current);
- }
- } catch (IOException e) {
- log.warn(sm.getString
- ("hostConfig.canonicalizing", app.name), e);
- }
- }
- deployed.remove(app.name);
+ deleteRedeployResources(app, resources, i, true);
return;
}
}
@@ -1325,6 +1229,81 @@ public class HostConfig
}
+ private void deleteRedeployResources(DeployedApplication app,
+ String[] resources, int i, boolean deleteReloadResources) {
+
+ // Delete redeploy resources
+ if (log.isInfoEnabled())
+ log.info(sm.getString("hostConfig.undeploy", app.name));
+ Container context = host.findChild(app.name);
+ try {
+ host.removeChild(context);
+ } catch (Throwable t) {
+ ExceptionUtils.handleThrowable(t);
+ log.warn(sm.getString
+ ("hostConfig.context.remove", app.name), t);
+ }
+ // Delete other redeploy resources
+ for (int j = i + 1; j < resources.length; j++) {
+ try {
+ File current = new File(resources[j]);
+ current = current.getCanonicalFile();
+ // Never delete per host context.xml defaults
+ if (Constants.HostContextXml.equals(
+ current.getName())) {
+ continue;
+ }
+ // Only delete resources in the appBase or the
+ // host's configBase
+ if ((current.getAbsolutePath().startsWith(
+ host.getAppBaseFile().getAbsolutePath() +
+ File.separator))
+ || (current.getAbsolutePath().startsWith(
+ host.getConfigBaseFile().getAbsolutePath()))) {
+ if (log.isDebugEnabled())
+ log.debug("Delete " + current);
+ ExpandWar.delete(current);
+ }
+ } catch (IOException e) {
+ log.warn(sm.getString
+ ("hostConfig.canonicalizing", app.name), e);
+ }
+ }
+
+ // Delete reload resources (to remove any remaining .xml descriptor)
+ if (deleteReloadResources) {
+ String[] resources2 =
+ app.reloadResources.keySet().toArray(new String[0]);
+ for (int j = 0; j < resources2.length; j++) {
+ try {
+ File current = new File(resources2[j]);
+ current = current.getCanonicalFile();
+ // Never delete per host context.xml defaults
+ if (Constants.HostContextXml.equals(
+ current.getName())) {
+ continue;
+ }
+ // Only delete resources in the appBase or the host's
+ // configBase
+ if ((current.getAbsolutePath().startsWith(
+ host.getAppBaseFile().getAbsolutePath() +
File.separator))
+ || ((current.getAbsolutePath().startsWith(
+ host.getConfigBaseFile().getAbsolutePath())
+ &&
(current.getAbsolutePath().endsWith(".xml"))))) {
+ if (log.isDebugEnabled())
+ log.debug("Delete " + current);
+ ExpandWar.delete(current);
+ }
+ } catch (IOException e) {
+ log.warn(sm.getString
+ ("hostConfig.canonicalizing", app.name), e);
+ }
+ }
+
+ }
+ deployed.remove(app.name);
+ }
+
/**
* Process a "start" event for this Host.
*/
@@ -1397,10 +1376,15 @@ public class HostConfig
if (!isServiced(apps[i].name))
checkResources(apps[i]);
}
+
+ // Check for old versions of applications that can now be
undeployed
+ if (host.getUndeployOldVersions()) {
+ checkUndeploy();
+ }
+
// Hotdeploy applications
deployApps();
}
-
}
@@ -1417,6 +1401,52 @@ public class HostConfig
}
/**
+ * Check for old versions of applications using parallel deployment that
are
+ * now unused (have no active sessions) and undeploy any that are found.
+ */
+ public void checkUndeploy() {
+ // Need ordered set of names
+ SortedSet<String> sortedAppNames = new TreeSet<>();
+ sortedAppNames.addAll(deployed.keySet());
+
+ if (sortedAppNames.size() < 2) {
+ return;
+ }
+ Iterator<String> iter = sortedAppNames.iterator();
+
+ ContextName previous = new ContextName(iter.next());
+ do {
+ ContextName current = new ContextName(iter.next());
+
+ if (current.getPath().equals(previous.getPath())) {
+ // Current and previous are same version - current will always
+ // be a later version
+ Context context = (Context) host.findChild(previous.getName());
+ if (context != null) {
+ Manager manager = context.getManager();
+ if (manager != null && manager.getActiveSessions() == 0) {
+ if (log.isInfoEnabled()) {
+ log.info(sm.getString("hostConfig.undeployVersion",
+ previous.getName()));
+ }
+ DeployedApplication app =
+ deployed.get(previous.getName());
+ String[] resources =
+ app.redeployResources.keySet().toArray(
+ new String[0]);
+ // Version is unused - undeploy it completely
+ // The -1 is a 'trick' to ensure all redeploy resources
+ // are removed
+ deleteRedeployResources(app, resources, -1,
+ true);
+ }
+ }
+ }
+ previous = current;
+ } while (iter.hasNext());
+ }
+
+ /**
* Add a new Context to be managed by us.
* Entry point for the admin webapp, and other JMX Context controllers.
*/
Modified: tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties?rev=1382366&r1=1382365&r2=1382366&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties
(original)
+++ tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties Sat
Sep 8 21:00:32 2012
@@ -104,6 +104,7 @@ hostConfig.reload=Reloading context [{0}
hostConfig.start=HostConfig: Processing START
hostConfig.stop=HostConfig: Processing STOP
hostConfig.undeploy=Undeploying context [{0}]
+hostConfig.undeployVersion=Undeploying old version of context [{0}] which has
no active session
tldConfig.addListeners=Adding {0} listeners from TLD files
tldConfig.cce=Lifecycle event data object {0} is not a Context
tldConfig.dirFail=Failed to process directory [{0}] for TLD files
Modified: tomcat/trunk/java/org/apache/catalina/startup/mbeans-descriptors.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/mbeans-descriptors.xml?rev=1382366&r1=1382365&r2=1382366&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/mbeans-descriptors.xml
(original)
+++ tomcat/trunk/java/org/apache/catalina/startup/mbeans-descriptors.xml Sat
Sep 8 21:00:32 2012
@@ -109,6 +109,12 @@
type="java.lang.String"/>
</operation>
+ <operation name="checkUndeploy"
+ description="Undeploy any old versions of applications deployed
using parallel deployment that have no active sessions"
+ impact="ACTION"
+ returnType="void">
+ </operation>
+
<operation name="getDeploymentTime"
description="Get the instant where an application was deployed"
impact="ACTION"
Modified: tomcat/trunk/webapps/docs/config/context.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/context.xml?rev=1382366&r1=1382365&r2=1382366&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/context.xml (original)
+++ tomcat/trunk/webapps/docs/config/context.xml Sat Sep 8 21:00:32 2012
@@ -82,6 +82,9 @@
<li>If session information is present in the request but no matching session
can be found, use the latest version.</li>
</ul>
+ <p>The <a href="host.html">Host</a> may be configured (via the
+ <code>undeployOldVersions</code>) to remove old versions deployed in this way
+ once they are no longer in use.</p>
</subsection>
<subsection name="Naming">
Modified: tomcat/trunk/webapps/docs/config/host.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/host.xml?rev=1382366&r1=1382365&r2=1382366&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/host.xml (original)
+++ tomcat/trunk/webapps/docs/config/host.xml Sat Sep 8 21:00:32 2012
@@ -201,6 +201,14 @@
not specified, the default value of 1 will be used.</p>
</attribute>
+ <attribute name="undeployOldVersions" required="false">
+ <p>This flag determines if Tomcat, as part of the auto deployment
+ process, will check for old, unused versions of web applications
+ deployed using parallel deployment and, if any are found, remove them.
+ This flag only applies if <code>autoDeploy</code> is true. If not
+ specified the default value of false will be used.</p>
+ </attribute>
+
</attributes>
</subsection>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]