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 2013/09/30 21:50:20 UTC
svn commit: r1527751 - in
/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk:
Document.java MongoDocumentStore.java NodeDocument.java
Author: mreutegg
Date: Mon Sep 30 19:50:20 2013
New Revision: 1527751
URL: http://svn.apache.org/r1527751
Log:
OAK-1044: Reduce traffic between MongoMK and MongoDB
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Document.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoDocumentStore.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/NodeDocument.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Document.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Document.java?rev=1527751&r1=1527750&r2=1527751&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Document.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Document.java Mon Sep 30 19:50:20 2013
@@ -44,6 +44,12 @@ public class Document implements CacheVa
static final String ID = "_id";
/**
+ * The modification count on the document. This is an long value
+ * incremented on every modification.
+ */
+ static final String MOD_COUNT = "_modCount";
+
+ /**
* The data of this document.
*/
protected Map<String, Object> data = Maps.newHashMap();
@@ -62,6 +68,15 @@ public class Document implements CacheVa
}
/**
+ * @return the modification count of this document or <code>null</code> if
+ * none is set.
+ */
+ @CheckForNull
+ public Number getModCount() {
+ return (Number) get(MOD_COUNT);
+ }
+
+ /**
* Gets the data for the given <code>key</code>.
*
* @param key the key.
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoDocumentStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoDocumentStore.java?rev=1527751&r1=1527750&r2=1527751&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoDocumentStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoDocumentStore.java Mon Sep 30 19:50:20 2013
@@ -269,12 +269,15 @@ public class MongoDocumentStore implemen
boolean upsert,
boolean checkConditions) {
DBCollection dbCollection = getDBCollection(collection);
- QueryBuilder query = getByKeyQuery(updateOp.id);
BasicDBObject setUpdates = new BasicDBObject();
BasicDBObject incUpdates = new BasicDBObject();
BasicDBObject unsetUpdates = new BasicDBObject();
+ // always increment modCount
+ updateOp.increment(Document.MOD_COUNT, 1);
+
+ // other updates
for (Entry<Key, Operation> entry : updateOp.changes.entrySet()) {
Key k = entry.getKey();
if (k.getName().equals(Document.ID)) {
@@ -299,12 +302,6 @@ public class MongoDocumentStore implemen
unsetUpdates.append(k.toString(), "1");
break;
}
- case CONTAINS_MAP_ENTRY: {
- if (checkConditions) {
- query.and(k.toString()).exists(op.value);
- }
- break;
- }
}
}
@@ -323,28 +320,49 @@ public class MongoDocumentStore implemen
// WriteConcern.SAFE);
// return null;
+ // get modCount of cached document
+ Number modCount = null;
+ @SuppressWarnings("unchecked")
+ T cachedDoc = (T) nodesCache.getIfPresent(updateOp.getId());
+ if (cachedDoc != null) {
+ modCount = cachedDoc.getModCount();
+ }
+
+
long start = start();
try {
- DBObject oldNode = dbCollection.findAndModify(query.get(), null /*fields*/,
+ // perform a conditional update with limited result
+ // if we have a matching modCount
+ if (modCount != null) {
+ QueryBuilder query = createQueryForUpdate(updateOp, checkConditions);
+ 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) {
+ // success, update cached document
+ // FIXME: ensure consistent cache update
+ applyToCache(collection, cachedDoc, updateOp);
+ // return previously cached document
+ return cachedDoc;
+ }
+ }
+
+ // conditional update failed or not possible
+ // perform operation and get complete document
+ QueryBuilder query = createQueryForUpdate(updateOp, checkConditions);
+ DBObject oldNode = dbCollection.findAndModify(query.get(), null,
null /*sort*/, false /*remove*/, update, false /*returnNew*/,
- upsert /*upsert*/);
+ upsert);
if (checkConditions && oldNode == null) {
return null;
}
T oldDoc = convertFromDBObject(collection, oldNode);
-
- // cache the new document
- if (collection == Collection.NODES) {
- T newDoc = collection.newDocument(this);
- if (oldDoc != null) {
- oldDoc.deepCopy(newDoc);
- oldDoc.seal();
- }
- String key = updateOp.getId();
- MemoryDocumentStore.applyChanges(newDoc, updateOp, comparator);
- newDoc.seal();
- nodesCache.put(key, (NodeDocument) newDoc);
- }
+ applyToCache(collection, oldDoc, updateOp);
return oldDoc;
} catch (Exception e) {
throw new MicroKernelException(e);
@@ -381,6 +399,7 @@ public class MongoDocumentStore implemen
for (int i = 0; i < updateOps.size(); i++) {
inserts[i] = new BasicDBObject();
UpdateOp update = updateOps.get(i);
+ update.increment(Document.MOD_COUNT, 1);
T target = collection.newDocument(this);
MemoryDocumentStore.applyChanges(target, update, comparator);
docs.add(target);
@@ -511,4 +530,42 @@ public class MongoDocumentStore implemen
return nodesCache.getIfPresent(key) != null;
}
+
+ private <T extends Document> void applyToCache(@Nonnull Collection<T> collection,
+ @Nullable T oldDoc,
+ @Nonnull UpdateOp updateOp) {
+ // cache the new document
+ if (collection == Collection.NODES) {
+ T newDoc = collection.newDocument(this);
+ if (oldDoc != null) {
+ oldDoc.deepCopy(newDoc);
+ oldDoc.seal();
+ }
+ String key = updateOp.getId();
+ MemoryDocumentStore.applyChanges(newDoc, updateOp, comparator);
+ newDoc.seal();
+ nodesCache.put(key, (NodeDocument) newDoc);
+ }
+ }
+
+ @Nonnull
+ private QueryBuilder createQueryForUpdate(UpdateOp updateOp,
+ boolean checkConditions) {
+ QueryBuilder query = getByKeyQuery(updateOp.id);
+
+ for (Entry<Key, Operation> entry : updateOp.changes.entrySet()) {
+ Key k = entry.getKey();
+ Operation op = entry.getValue();
+ switch (op.type) {
+ case CONTAINS_MAP_ENTRY: {
+ if (checkConditions) {
+ query.and(k.toString()).exists(op.value);
+ }
+ break;
+ }
+ }
+ }
+ return query;
+ }
+
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/NodeDocument.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/NodeDocument.java?rev=1527751&r1=1527750&r2=1527751&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/NodeDocument.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/NodeDocument.java Mon Sep 30 19:50:20 2013
@@ -129,7 +129,7 @@ public class NodeDocument extends Docume
*/
private static final Set<String> IGNORE_ON_SPLIT =
Collections.unmodifiableSet(new HashSet<String>(
- Arrays.asList(ID, MODIFIED, PREVIOUS, LAST_REV)));
+ Arrays.asList(ID, MOD_COUNT, MODIFIED, PREVIOUS, LAST_REV)));
final DocumentStore store;