Author: reschke
Date: Thu Sep 15 15:05:41 2016
New Revision: 1760946

URL: http://svn.apache.org/viewvc?rev=1760946&view=rev
Log:
OAK-4793: RDBDocumentStore: make sure cache is invalidated upon JDBC exceptions

Added:
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBCacheConsistencyTest.java
   (with props)
Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionWrapper.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDataSourceWrapper.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java?rev=1760946&r1=1760945&r2=1760946&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java
 Thu Sep 15 15:05:41 2016
@@ -480,7 +480,7 @@ public class RDBDocumentStore implements
             return result;
         } catch (SQLException ex) {
             this.ch.rollbackConnection(connection);
-            throw new DocumentStoreException(ex);
+            throw handleException("update failed for: " + keysToUpdate, ex, 
collection, keysToUpdate);
         } finally {
             this.ch.closeConnection(connection);
         }
@@ -1515,7 +1515,7 @@ public class RDBDocumentStore implements
             db.delete(connection, tmd, Collections.singletonList(id));
             connection.commit();
         } catch (Exception ex) {
-            throw new DocumentStoreException(ex);
+            throw handleException("removing " + id, ex, collection, id);
         } finally {
             this.ch.closeConnection(connection);
         }
@@ -1531,7 +1531,7 @@ public class RDBDocumentStore implements
                 numDeleted += db.delete(connection, tmd, sublist);
                 connection.commit();
             } catch (Exception ex) {
-                throw new DocumentStoreException(ex);
+                throw handleException("removing " + ids, ex, collection, ids);
             } finally {
                 this.ch.closeConnection(connection);
             }
@@ -1555,7 +1555,8 @@ public class RDBDocumentStore implements
                     numDeleted += db.delete(connection, tmd, subMap);
                     connection.commit();
                 } catch (Exception ex) {
-                    throw DocumentStoreException.convert(ex);
+                    Set<String> ids = subMap.keySet();
+                    throw handleException("deleting " + ids, ex, collection, 
ids);
                 } finally {
                     this.ch.closeConnection(connection);
                 }
@@ -1623,7 +1624,7 @@ public class RDBDocumentStore implements
             }
             String message = String.format("Update for %s failed%s", 
document.getId(), addDiags);
             LOG.debug(message, ex);
-            throw new DocumentStoreException(message, ex);
+            throw handleException(message, ex, collection, document.getId());
         } finally {
             this.ch.closeConnection(connection);
         }
@@ -1721,7 +1722,7 @@ public class RDBDocumentStore implements
                 LOG.debug("additional diagnostics: " + messages);
             }
 
-            throw new DocumentStoreException(message, ex);
+            throw handleException(message, ex, collection, ids);
         } finally {
             this.ch.closeConnection(connection);
         }
@@ -1890,6 +1891,21 @@ public class RDBDocumentStore implements
         return nodesCache;
     }
 
+    private <T extends Document> DocumentStoreException handleException(String 
message, Exception ex, Collection<T> collection,
+            java.util.Collection<String> ids) {
+        if (collection == Collection.NODES) {
+            for (String id : ids) {
+                invalidateCache(collection, id, false);
+            }
+        }
+        return DocumentStoreException.convert(ex, message);
+    }
+
+    private <T extends Document> DocumentStoreException handleException(String 
message, Exception ex, Collection<T> collection,
+            String id) {
+        return handleException(message, ex, collection, 
Collections.singleton(id));
+    }
+
     // slightly extended query support
     protected static class QueryCondition {
 

Added: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBCacheConsistencyTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBCacheConsistencyTest.java?rev=1760946&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBCacheConsistencyTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBCacheConsistencyTest.java
 Thu Sep 15 15:05:41 2016
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.plugins.document.rdb;
+
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javax.sql.DataSource;
+
+import org.apache.jackrabbit.oak.plugins.document.CacheConsistencyTestBase;
+import org.apache.jackrabbit.oak.plugins.document.DocumentStoreFixture;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class RDBCacheConsistencyTest extends CacheConsistencyTestBase {
+
+    @Parameterized.Parameters(name="{0}")
+    public static Collection<Object[]> fixtures() {
+        return fixtures(false);
+    }
+
+    private final DocumentStoreFixture dsf;
+
+    public RDBCacheConsistencyTest(DocumentStoreFixture dsf) {
+        this.dsf = dsf;
+    }
+
+    protected static Collection<Object[]> fixtures(boolean multi) {
+        Collection<Object[]> result = new ArrayList<Object[]>();
+        DocumentStoreFixture candidates[] = new DocumentStoreFixture[] {
+                DocumentStoreFixture.RDB_H2, DocumentStoreFixture.RDB_DERBY,
+                DocumentStoreFixture.RDB_PG, DocumentStoreFixture.RDB_DB2,
+                DocumentStoreFixture.RDB_MYSQL, 
DocumentStoreFixture.RDB_ORACLE,
+                DocumentStoreFixture.RDB_MSSQL };
+
+        for (DocumentStoreFixture dsf : candidates) {
+            if (dsf.isAvailable()) {
+                if (!multi || dsf.hasSinglePersistence()) {
+                    result.add(new Object[] { dsf });
+                }
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public DocumentStoreFixture getFixture() {
+        return dsf;
+    }
+
+    @Override
+    public void setTemporaryUpdateException(String msg) {
+        DataSource ds = dsf.getRDBDataSource();
+        if (ds instanceof RDBDataSourceWrapper) {
+            ((RDBDataSourceWrapper) ds).setTemporaryUpdateException(msg);
+        } else {
+            fail();
+        }
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBCacheConsistencyTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionWrapper.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionWrapper.java?rev=1760946&r1=1760945&r2=1760946&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionWrapper.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionWrapper.java
 Thu Sep 15 15:05:41 2016
@@ -43,6 +43,7 @@ public class RDBConnectionWrapper implem
     private final RDBDataSourceWrapper datasource;
     private final Connection connection;
     private final long constart;
+    private boolean isReadOnly = false;
 
     public RDBConnectionWrapper(RDBDataSourceWrapper datasource, Connection 
connection) {
         this.datasource = datasource;
@@ -85,6 +86,9 @@ public class RDBConnectionWrapper implem
         SQLException x = null;
         try {
             connection.commit();
+            if (this.datasource.getTemporaryUpdateException() != null && 
!isReadOnly) {
+                throw new 
SQLException(this.datasource.getTemporaryUpdateException());
+            }
         } catch (SQLException ex) {
             x = ex;
             throw ex;
@@ -323,8 +327,9 @@ public class RDBConnectionWrapper implem
         throw new SQLFeatureNotSupportedException();
     }
 
-    public void setReadOnly(boolean arg0) throws SQLException {
-        connection.setReadOnly(arg0);
+    public void setReadOnly(boolean readOnly) throws SQLException {
+        this.isReadOnly = readOnly;
+        connection.setReadOnly(readOnly);
     }
 
     public Savepoint setSavepoint() throws SQLException {

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDataSourceWrapper.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDataSourceWrapper.java?rev=1760946&r1=1760945&r2=1760946&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDataSourceWrapper.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDataSourceWrapper.java
 Thu Sep 15 15:05:41 2016
@@ -54,6 +54,7 @@ public class RDBDataSourceWrapper implem
 
     private final DataSource ds;
     private boolean batchResultPrecise = true;
+    private String temporaryUpdateException = null;
 
     // Logging
 
@@ -96,6 +97,14 @@ public class RDBDataSourceWrapper implem
         return this.batchResultPrecise;
     }
 
+    public void setTemporaryUpdateException(String exmsg) {
+        this.temporaryUpdateException = exmsg;
+    }
+
+    public String getTemporaryUpdateException() {
+        return this.temporaryUpdateException;
+    }
+
     // DataSource
 
     public RDBDataSourceWrapper(DataSource ds) {


Reply via email to