Repository: cayenne Updated Branches: refs/heads/master 30e892c68 -> 99b282838
CAY-2009 Non-blocking connection pool * ensure consistent auto-commit state (this was the real cause of H2 failures) Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/e784c105 Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/e784c105 Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/e784c105 Branch: refs/heads/master Commit: e784c10537e0d268fe9d41e3bbd62a2d2ec1301a Parents: 30e892c Author: aadamchik <[email protected]> Authored: Sun May 3 07:24:54 2015 -0400 Committer: aadamchik <[email protected]> Committed: Sun May 3 07:27:41 2015 -0400 ---------------------------------------------------------------------- .../cayenne/datasource/PoolAwareConnection.java | 24 ++--------- .../cayenne/datasource/PoolingDataSource.java | 42 +++++++++++++++++++- .../cayenne/datasource/PoolingDataSourceIT.java | 12 ++++++ 3 files changed, 57 insertions(+), 21 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/e784c105/cayenne-server/src/main/java/org/apache/cayenne/datasource/PoolAwareConnection.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/datasource/PoolAwareConnection.java b/cayenne-server/src/main/java/org/apache/cayenne/datasource/PoolAwareConnection.java index 6b90504..da1e3d9 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/datasource/PoolAwareConnection.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/datasource/PoolAwareConnection.java @@ -51,24 +51,7 @@ public class PoolAwareConnection implements Connection { private Connection connection; private String validationQuery; - // An old hack that fixes Sybase problems with autocommit. Used idea from - // Jonas org.objectweb.jonas.jdbc_xa.ConnectionImpl - // (http://www.objectweb.org/jonas/). - // - // If problem is not the one that can be fixed by this patch, original - // exception is rethrown. If exception occurs when fixing the problem, new - // exception is thrown. - // - static void sybaseAutoCommitPatch(Connection c, SQLException e, boolean autoCommit) throws SQLException { - - String s = e.getMessage().toLowerCase(); - if (s.contains("set chained command not allowed")) { - c.commit(); - c.setAutoCommit(autoCommit); // Shouldn't fail now. - } else { - throw e; - } - } + public PoolAwareConnection(PoolingDataSource parent, Connection connection, String validationQuery) { this.parent = parent; @@ -118,6 +101,8 @@ public class PoolAwareConnection implements Connection { // state } + // TODO: autocommit, tx isolation, and other connection settings may + // change when resetting connection and need to be restored... try { connection = parent.createUnwrapped(); } catch (SQLException e) { @@ -312,8 +297,7 @@ public class PoolAwareConnection implements Connection { } catch (SQLException sqlEx) { try { - // apply Sybase patch - sybaseAutoCommitPatch(connection, sqlEx, autoCommit); + PoolingDataSource.sybaseAutoCommitPatch(connection, sqlEx, autoCommit); } catch (SQLException patchEx) { parent.retire(this); throw sqlEx; http://git-wip-us.apache.org/repos/asf/cayenne/blob/e784c105/cayenne-server/src/main/java/org/apache/cayenne/datasource/PoolingDataSource.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/datasource/PoolingDataSource.java b/cayenne-server/src/main/java/org/apache/cayenne/datasource/PoolingDataSource.java index 83bf2f2..bb7f732 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/datasource/PoolingDataSource.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/datasource/PoolingDataSource.java @@ -44,6 +44,26 @@ import org.apache.commons.logging.LogFactory; */ public class PoolingDataSource implements DataSource { + // An old hack that fixes Sybase problems with autocommit. Used idea from + // Jonas org.objectweb.jonas.jdbc_xa.ConnectionImpl + // (http://www.objectweb.org/jonas/). + // + // If problem is not the one that can be fixed by this patch, original + // exception is rethrown. If exception occurs when fixing the problem, new + // exception is thrown. + // + static void sybaseAutoCommitPatch(Connection c, SQLException e, boolean autoCommit) throws SQLException { + + String s = e.getMessage().toLowerCase(); + if (s.contains("set chained command not allowed")) { + // TODO: the hack is ugly... should we rollback instead here? + c.commit(); + c.setAutoCommit(autoCommit); // Shouldn't fail now. + } else { + throw e; + } + } + /** * Defines a maximum time in milliseconds that a connection request could * wait in the connection queue. After this period expires, an exception @@ -238,8 +258,28 @@ public class PoolingDataSource implements DataSource { return new PoolAwareConnection(this, createUnwrapped(), validationQuery); } + /** + * Creates a new connection in a consistent state. + */ Connection createUnwrapped() throws SQLException { - return nonPoolingDataSource.getConnection(); + Connection c = nonPoolingDataSource.getConnection(); + + // set default connection state... + + // TODO: tx isolation level? + + if (!c.getAutoCommit()) { + + try { + c.setAutoCommit(true); + } catch (SQLException e) { + PoolingDataSource.sybaseAutoCommitPatch(c, e, true); + } + } + + c.clearWarnings(); + + return c; } @Override http://git-wip-us.apache.org/repos/asf/cayenne/blob/e784c105/cayenne-server/src/test/java/org/apache/cayenne/datasource/PoolingDataSourceIT.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/datasource/PoolingDataSourceIT.java b/cayenne-server/src/test/java/org/apache/cayenne/datasource/PoolingDataSourceIT.java index e9b0746..7052281 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/datasource/PoolingDataSourceIT.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/datasource/PoolingDataSourceIT.java @@ -20,6 +20,7 @@ package org.apache.cayenne.datasource; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.sql.Connection; @@ -44,6 +45,17 @@ public class PoolingDataSourceIT extends BasePoolingDataSourceIT { } @Test + public void testGetConnectionAutoCommit() throws Exception { + + Connection c1 = dataSource.getConnection(); + try { + assertTrue("Failed to reset connection state", c1.getAutoCommit()); + } finally { + c1.close(); + } + } + + @Test public void testGetConnection() throws Exception { assertEquals(2, dataSource.poolSize());
