VIVO-987 Properly shutdown the TripleSource instances.

When shutting down a ContentTripleSourceSDB instance, attempt to deregister the JDBC driver.
Also, attempt to shut down the AbandonedConnectionCleanupThread.
Each of these produce warning messages if not shut down.
This commit is contained in:
Jim Blake 2015-03-09 16:01:48 -04:00
parent 3b57db938f
commit 32979536e6
3 changed files with 64 additions and 9 deletions

View file

@ -280,9 +280,11 @@ public class ApplicationImpl implements Application {
@Override
public void contextDestroyed(ServletContextEvent sce) {
Application app = ApplicationUtils.instance();
app.getSearchEngine().shutdown(app);
app.getImageProcessor().shutdown(app);
app.getConfigurationTripleSource().shutdown(app);
app.getContentTripleSource().shutdown(app);
app.getFileStorage().shutdown(app);
app.getImageProcessor().shutdown(app);
app.getSearchEngine().shutdown(app);
}
}

View file

@ -16,6 +16,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.query.Dataset;
import com.hp.hpl.jena.shared.JenaException;
import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.tdb.TDB;
import com.hp.hpl.jena.tdb.TDBFactory;
@ -94,12 +95,7 @@ public class RDFServiceTDB extends RDFServiceJena {
@Override
public void close() {
if (this.dataset != null) {
dataset.getLock().enterCriticalSection(Lock.WRITE);
try {
dataset.close();
} finally {
dataset.getLock().leaveCriticalSection();
}
dataset.close();
}
}

View file

@ -4,8 +4,12 @@ package edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb;
import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.BasicCombinedTripleSource.CONTENT_UNIONS;
import java.lang.reflect.Method;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Enumeration;
import javax.servlet.ServletContext;
import javax.sql.DataSource;
@ -212,9 +216,62 @@ public class ContentTripleSourceSDB extends ContentTripleSource {
@Override
public void shutdown(Application application) {
if (this.modelMaker != null) {
this.modelMaker.close();
}
if (this.dataset != null) {
this.dataset.close();
}
if (this.rdfService != null) {
this.rdfService.close();
}
if (ds != null) {
String driverClassName = ds.getDriverClass();
ds.close();
attemptToDeregisterJdbcDriver(driverClassName);
cleanupAbandonedConnectionThread(driverClassName);
}
}
private void attemptToDeregisterJdbcDriver(String driverClassName) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
for (Enumeration<Driver> drivers = DriverManager.getDrivers(); drivers
.hasMoreElements();) {
Driver driver = drivers.nextElement();
if (driver.getClass().getClassLoader() == cl) {
// This driver was registered by the webapp's ClassLoader, so
// deregister it:
try {
DriverManager.deregisterDriver(driver);
} catch (SQLException ex) {
log.error("Error deregistering JDBC driver {" + driver
+ "}", ex);
}
} else {
// driver was not registered by the webapp's ClassLoader and may
// be in use elsewhere
}
}
}
/**
* The MySQL driver leaves a thread running after it is deregistered.
* Versions after 5.1.23 provide AbandonedConnectionCleanupThread.shutdown()
* to stop this thread.
*
* Using reflection to invoke this method means that we don't have a
* hard-coded dependency to MySQL.
*/
private void cleanupAbandonedConnectionThread(String driverClassName) {
if (!driverClassName.contains("mysql")) {
return;
}
try {
Class.forName("com.mysql.jdbc.AbandonedConnectionCleanupThread")
.getMethod("shutdown").invoke(null);
} catch (Exception e) {
log.info("Failed to shutdown MySQL connection cleanup thread: " + e);
}
}
}