diff options
author | Shawn O. Pearce <sop@google.com> | 2009-02-06 16:41:54 -0800 |
---|---|---|
committer | Shawn O. Pearce <sop@google.com> | 2009-02-06 16:41:54 -0800 |
commit | 11a16f8b59ac8be302c0ef58d9a1eb059f4f530e (patch) | |
tree | 379aa9b8d6143a0d3e87f4a5f35cb5a17ca11a02 | |
parent | ba1f56d15eb3f4f10abe4f08f2466121ebf1c1f8 (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.java | 1 | ||||
-rw-r--r-- | src/main/java/com/google/gerrit/server/GerritServer.java | 26 |
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 { |