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) {