You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by mr...@apache.org on 2015/07/15 11:57:31 UTC

svn commit: r1691159 - /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java

Author: mreutegg
Date: Wed Jul 15 09:57:31 2015
New Revision: 1691159

URL: http://svn.apache.org/r1691159
Log:
OAK-3103: Stale document in MongoDocumentStore cache

- Use update operation instead of findAndModify for conditional update
- Unconditional update the cache when the before document is known

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java?rev=1691159&r1=1691158&r2=1691159&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java Wed Jul 15 09:57:31 2015
@@ -798,16 +798,11 @@ public class MongoDocumentStore implemen
                 QueryBuilder query = createQueryForUpdate(updateOp.getId(),
                         updateOp.getConditions());
                 query.and(Document.MOD_COUNT).is(modCount);
-                DBObject fields = new BasicDBObject();
-                // return _id only
-                fields.put("_id", 1);
-
-                DBObject oldNode = dbCollection.findAndModify(query.get(), fields,
-                        null /*sort*/, false /*remove*/, update, false /*returnNew*/,
-                        false /*upsert*/);
-                if (oldNode != null) {
+
+                WriteResult result = dbCollection.update(query.get(), update);
+                if (result.getN() > 0) {
                     // success, update cached document
-                    applyToCache(collection, cachedDoc, updateOp);
+                    putToCache(collection, cachedDoc, updateOp);
                     // return previously cached document
                     return cachedDoc;
                 }
@@ -821,9 +816,11 @@ public class MongoDocumentStore implemen
                 return null;
             }
             T oldDoc = convertFromDBObject(collection, oldNode);
-            applyToCache(collection, oldDoc, updateOp);
             if (oldDoc != null) {
+                putToCache(collection, oldDoc, updateOp);
                 oldDoc.seal();
+            } else {
+                applyToCache(collection, null, updateOp);
             }
             return oldDoc;
         } catch (Exception e) {
@@ -1258,6 +1255,30 @@ public class MongoDocumentStore implemen
         }
     }
 
+    /**
+     * Unconditionally puts a document into the cache if {@code collection} is
+     * {@link Collection#NODES}. The document put into the cache is
+     * {@code oldDoc} with the {@code updateOp} applied. This method does not
+     * acquire a lock from {@link #locks}! The caller must ensure a lock is held
+     * for the given document.
+     *
+     * @param collection the collection where oldDoc belongs to.
+     * @param oldDoc how the document looked before the update.
+     * @param updateOp the update just applied to the document.
+     */
+    private <T extends Document> void putToCache(@Nonnull Collection<T> collection,
+                                                 @Nonnull T oldDoc,
+                                                 @Nonnull UpdateOp updateOp) {
+        if (collection == Collection.NODES) {
+            CacheValue key = new StringValue(oldDoc.getId());
+            NodeDocument newDoc = (NodeDocument) collection.newDocument(this);
+            oldDoc.deepCopy(newDoc);
+            UpdateUtils.applyChanges(newDoc, updateOp, comparator);
+            newDoc.seal();
+            nodesCache.put(key, newDoc);
+        }
+    }
+
     @Nonnull
     private static QueryBuilder createQueryForUpdate(String key,
                                                      Map<Key, Condition> conditions) {