You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ma...@apache.org on 2009/09/05 19:55:55 UTC

svn commit: r811689 - in /jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core: persistence/bundle/BundleDbPersistenceManager.java util/db/ConnectionHelper.java

Author: martijnh
Date: Sat Sep  5 17:55:55 2009
New Revision: 811689

URL: http://svn.apache.org/viewvc?rev=811689&view=rev
Log:
JCR-1456 Database connection pooling

* Added retry logic again. Although the DataSource is responsible for lending out good Connections
having 1 retry makes things a bit more robust.

Modified:
    jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java
    jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/ConnectionHelper.java

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java?rev=811689&r1=811688&r2=811689&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java Sat Sep  5 17:55:55 2009
@@ -432,23 +432,31 @@
      * Basically wraps a JDBC transaction around super.store().
      */
     public synchronized void store(ChangeLog changeLog) throws ItemStateException {
-        try {
-            conHelper.startBatch();
-            super.store(changeLog);
-            conHelper.endBatch(true);
-        } catch (SQLException e) {
-            // Either startBatch or stopBatch threw it: either way the
-            // transaction was not persisted and no action needs to be taken.
-            throw new ItemStateException(e.getMessage(), e);
-        } catch (ItemStateException e) {
-            // store call threw it: we need to cancel the transaction
+        int failures = 0;
+        ItemStateException lastException = null;
+        while (failures <= 1) { // retry once
             try {
-                conHelper.endBatch(false);
-            } catch (SQLException e2) {
-                DbUtility.logException("rollback failed", e2);
+                conHelper.startBatch();
+                super.store(changeLog);
+                conHelper.endBatch(true);
+                return;
+            } catch (SQLException e) {
+                // Either startBatch or stopBatch threw it: either way the
+                // transaction was not persisted and no action needs to be taken.
+                failures++;
+                lastException = new ItemStateException(e.getMessage(), e);
+            } catch (ItemStateException e) {
+                // store call threw it: we need to cancel the transaction
+                failures++;
+                lastException = e;
+                try {
+                    conHelper.endBatch(false);
+                } catch (SQLException e2) {
+                    DbUtility.logException("rollback failed", e2);
+                }
             }
-            throw e;
         }
+        throw lastException;
     }
 
     /**

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/ConnectionHelper.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/ConnectionHelper.java?rev=811689&r1=811688&r2=811689&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/ConnectionHelper.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/ConnectionHelper.java Sat Sep  5 17:55:55 2009
@@ -32,6 +32,8 @@
  */
 public class ConnectionHelper {
 
+    private static final int RETRIES = 1;
+
     private final boolean checkTablesWithUserName;
 
     protected final DataSource dataSource;
@@ -210,7 +212,19 @@
      * @param params the parameters for the SQL statement
      * @throws SQLException on error
      */
-    public final void exec(String sql, Object... params) throws SQLException {
+    public final void exec(final String sql, final Object... params) throws SQLException {
+        new RetryManager<Void>() {
+
+            @Override
+            protected Void call() throws SQLException {
+                reallyExec(sql, params);
+                return null;
+            }
+            
+        }.doTry();
+    }
+    
+    private void reallyExec(String sql, Object... params) throws SQLException {
         Connection con = null;
         Statement stmt = null;
         try {
@@ -235,7 +249,18 @@
      * @return the update count
      * @throws SQLException on error
      */
-    public final int update(String sql, Object[] params) throws SQLException {
+    public final int update(final String sql, final Object[] params) throws SQLException {
+        return new RetryManager<Integer>() {
+
+            @Override
+            protected Integer call() throws SQLException {
+                return reallyUpdate(sql, params);
+            }
+            
+        }.doTry();
+    }
+
+    private int reallyUpdate(String sql, Object[] params) throws SQLException {
         Connection con = null;
         PreparedStatement stmt = null;
         try {
@@ -258,7 +283,19 @@
      * @return a {@link ResultSet}
      * @throws SQLException on error
      */
-    public final ResultSet exec(String sql, Object[] params, boolean returnGeneratedKeys, int maxRows)
+    public final ResultSet exec(final String sql, final Object[] params, final boolean returnGeneratedKeys,
+            final int maxRows) throws SQLException {
+        return new RetryManager<ResultSet>() {
+
+            @Override
+            protected ResultSet call() throws SQLException {
+                return reallyExec(sql, params, returnGeneratedKeys, maxRows);
+            }
+            
+        }.doTry();
+    }
+    
+    private ResultSet reallyExec(String sql, Object[] params, boolean returnGeneratedKeys, int maxRows)
             throws SQLException {
         Connection con = null;
         PreparedStatement stmt = null;
@@ -352,4 +389,32 @@
         stmt.execute();
         return stmt;
     }
+    
+    /**
+     * This class encapsulates the logic to retry a method invocation if it threw an SQLException.
+     * 
+     * @param <T> the return type of the method which is retried if it failed
+     */
+    public abstract class RetryManager<T> {
+
+        public final T doTry() throws SQLException {
+            if (inBatchMode) {
+                return call();
+            } else {
+                int failures = 0;
+                SQLException lastException = null;
+                while (failures <= RETRIES) {
+                    try {
+                        return call();
+                    } catch (SQLException e) {
+                        failures++;
+                        lastException = e;
+                    }
+                }
+                throw lastException;
+            }
+        }
+        
+        protected abstract T call() throws SQLException;
+    }
 }