summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn O. Pearce <sop@google.com>2009-02-06 16:41:54 -0800
committerShawn O. Pearce <sop@google.com>2009-02-06 16:41:54 -0800
commit11a16f8b59ac8be302c0ef58d9a1eb059f4f530e (patch)
tree379aa9b8d6143a0d3e87f4a5f35cb5a17ca11a02
parentba1f56d15eb3f4f10abe4f08f2466121ebf1c1f8 (diff)
Cleanup c3p0 connection pools if used
Jetty and c3p0 leak all of the connections unless our own application tells c3p0 to cleanup while Jetty is winding down the context in order to load it again. There's some sort of disconnect in the standards, or in the Jetty code, where the c3p0 DataSource pool doesn't get GC'd automatically. In order to close the connections down we need to do a destroy on the pool ourselves. Since we don't want to make c3p0 a hard dependency we invoke destroy via reflection. Signed-off-by: Shawn O. Pearce <sop@google.com>
-rw-r--r--src/main/java/com/google/gerrit/server/GerritJsonServlet.java1
-rw-r--r--src/main/java/com/google/gerrit/server/GerritServer.java26
2 files changed, 23 insertions, 4 deletions
diff --git a/src/main/java/com/google/gerrit/server/GerritJsonServlet.java b/src/main/java/com/google/gerrit/server/GerritJsonServlet.java
index d61219a688..943d2f2525 100644
--- a/src/main/java/com/google/gerrit/server/GerritJsonServlet.java
+++ b/src/main/java/com/google/gerrit/server/GerritJsonServlet.java
@@ -54,6 +54,7 @@ public abstract class GerritJsonServlet extends JsonServlet<GerritCall> {
@Override
public void destroy() {
WorkQueue.terminate();
+ GerritServer.closeDataSource();
super.destroy();
}
diff --git a/src/main/java/com/google/gerrit/server/GerritServer.java b/src/main/java/com/google/gerrit/server/GerritServer.java
index a996287e37..0a0b16adc9 100644
--- a/src/main/java/com/google/gerrit/server/GerritServer.java
+++ b/src/main/java/com/google/gerrit/server/GerritServer.java
@@ -63,8 +63,25 @@ import javax.sql.DataSource;
/** Global server-side state for Gerrit. */
public class GerritServer {
private static final Logger log = LoggerFactory.getLogger(GerritServer.class);
+ private static DataSource datasource;
private static GerritServer impl;
+ static void closeDataSource() {
+ if (datasource != null) {
+ try {
+ try {
+ Class.forName("com.mchange.v2.c3p0.DataSources").getMethod("destroy",
+ DataSource.class).invoke(null, datasource);
+ } catch (Throwable bad) {
+ // Oh well, its not a c3p0 pooled connection. Too bad its
+ // not standardized how "good applications cleanup".
+ }
+ } finally {
+ datasource = null;
+ }
+ }
+ }
+
/**
* Obtain the singleton server instance for this web application.
*
@@ -82,9 +99,11 @@ public class GerritServer {
try {
impl = new GerritServer();
} catch (OrmException e) {
+ closeDataSource();
log.error("GerritServer ORM is unavailable", e);
throw e;
} catch (XsrfException e) {
+ closeDataSource();
log.error("GerritServer XSRF support failed to initailize", e);
throw e;
}
@@ -148,9 +167,8 @@ public class GerritServer {
private Database<ReviewDb> createDatabase() throws OrmException {
final String dsName = "java:comp/env/jdbc/ReviewDb";
- DataSource ds;
try {
- ds = (DataSource) new InitialContext().lookup(dsName);
+ datasource = (DataSource) new InitialContext().lookup(dsName);
} catch (NamingException namingErr) {
final Properties p = readGerritDataSource();
if (p == null) {
@@ -160,12 +178,12 @@ public class GerritServer {
}
try {
- ds = new SimpleDataSource(p);
+ datasource = new SimpleDataSource(p);
} catch (SQLException se) {
throw new OrmException("Database unavailable", se);
}
}
- return new Database<ReviewDb>(ds, ReviewDb.class);
+ return new Database<ReviewDb>(datasource, ReviewDb.class);
}
private Properties readGerritDataSource() throws OrmException {