Author: reschke
Date: Fri Jun 24 10:50:35 2016
New Revision: 1750075

URL: http://svn.apache.org/viewvc?rev=1750075&view=rev
Log:
OAK-4497: RDBDocumentStore: potential race condition between update and 
invalidate can cause stale cache entries

Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocumentCache.java
    
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/ConcurrentQueryAndInvalidateIT.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocumentCache.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocumentCache.java?rev=1750075&r1=1750074&r2=1750075&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocumentCache.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocumentCache.java
 Fri Jun 24 10:50:35 2016
@@ -96,9 +96,21 @@ public class NodeDocumentCache implement
                 nodeDocumentsCache.invalidate(new StringValue(key));
             }
 
-            for (CacheChangesTracker tracker : changeTrackers) {
-                tracker.invalidateDocument(key);
-            }
+            internalMarkChanged(key);
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Mark that the document with the given key is being changed.
+     *
+     * @param key to mark
+     */
+    public void markChanged(@Nonnull String key) {
+        Lock lock = locks.acquire(key);
+        try {
+            internalMarkChanged(key);
         } finally {
             lock.unlock();
         }
@@ -447,6 +459,17 @@ public class NodeDocumentCache implement
     //----------------------------< internal 
>----------------------------------
 
     /**
+     * Marks the document as potentially changed.
+     * 
+     * @param key the document to be marked
+     */
+    private void internalMarkChanged(String key) {
+        for (CacheChangesTracker tracker : changeTrackers) {
+            tracker.invalidateDocument(key);
+        }
+    }
+
+    /**
      * Puts a document into the cache without acquiring a lock.
      *
      * @param doc the document to put into the cache.

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=1750075&r1=1750074&r2=1750075&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
 Fri Jun 24 10:50:35 2016
@@ -524,6 +524,7 @@ public class RDBDocumentStore implements
             if (remove) {
                 nodesCache.invalidate(id);
             } else {
+                nodesCache.markChanged(id);
                 NodeDocument entry = nodesCache.getIfPresent(id);
                 if (entry != null) {
                     entry.markUpToDate(0);
@@ -1416,8 +1417,17 @@ public class RDBDocumentStore implements
                     // already in the cache
                     doc = convertFromDBObject(collection, row);
                 } else {
-                    // otherwise mark it as fresh
-                    ((NodeDocument) doc).markUpToDate(now);
+                    // we got a document from the cache, thus collection is 
NODES
+                    // and a tracker is present
+                    Lock lock = locks.acquire(row.getId());
+                    try {
+                        if (!tracker.mightBeenAffected(row.getId())) {
+                            // otherwise mark it as fresh
+                            ((NodeDocument) doc).markUpToDate(now);
+                        }
+                    } finally {
+                        lock.unlock();
+                    }
                 }
                 result.add(doc);
             }

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ConcurrentQueryAndInvalidateIT.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ConcurrentQueryAndInvalidateIT.java?rev=1750075&r1=1750074&r2=1750075&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ConcurrentQueryAndInvalidateIT.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ConcurrentQueryAndInvalidateIT.java
 Fri Jun 24 10:50:35 2016
@@ -29,13 +29,11 @@ import static org.apache.jackrabbit.oak.
 import static 
org.apache.jackrabbit.oak.plugins.document.util.Utils.getKeyUpperLimit;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assume.assumeFalse;
 
 public class ConcurrentQueryAndInvalidateIT extends 
AbstractMultiDocumentStoreTest {
 
     public ConcurrentQueryAndInvalidateIT(DocumentStoreFixture dsf) {
         super(dsf);
-        assumeFalse(dsf instanceof DocumentStoreFixture.RDBFixture);
     }
 
     protected static final int NUM_NODES = 50;


Reply via email to