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 2014/12/10 18:04:37 UTC
svn commit: r1644479 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/
oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/
oak-run/src/main/js/
Author: mreutegg
Date: Wed Dec 10 17:04:37 2014
New Revision: 1644479
URL: http://svn.apache.org/r1644479
Log:
OAK-2342: Clean up collision markers
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CollisionTest.java (with props)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnmergedBranches.java
jackrabbit/oak/trunk/oak-run/src/main/js/oak-mongo.js
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java?rev=1644479&r1=1644478&r2=1644479&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java Wed Dec 10 17:04:37 2014
@@ -583,7 +583,7 @@ public final class NodeDocument extends
* @param context the revision context.
* @return count of the revision entries purged
*/
- public int purgeUncommittedRevisions(RevisionContext context) {
+ int purgeUncommittedRevisions(RevisionContext context) {
// only look at revisions in this document.
// uncommitted revisions are not split off
Map<Revision, String> valueMap = getLocalRevisions();
@@ -599,6 +599,31 @@ public final class NodeDocument extends
}
}
+ if (op.hasChanges()) {
+ store.findAndUpdate(Collection.NODES, op);
+ }
+ return purgeCount;
+ }
+
+ /**
+ * Purge collision markers with the local clusterId on this document. Use
+ * only on start when there are no ongoing or pending commits.
+ *
+ * @param context the revision context.
+ * @return the number of removed collision markers.
+ */
+ int purgeCollisionMarkers(RevisionContext context) {
+ Map<Revision, String> valueMap = getLocalMap(COLLISIONS);
+ UpdateOp op = new UpdateOp(getId(), false);
+ int purgeCount = 0;
+ for (Map.Entry<Revision, String> commit : valueMap.entrySet()) {
+ Revision r = commit.getKey();
+ if (r.getClusterId() == context.getClusterId()) {
+ purgeCount++;
+ removeCollision(op, r);
+ }
+ }
+
if (op.hasChanges()) {
store.findAndUpdate(Collection.NODES, op);
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnmergedBranches.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnmergedBranches.java?rev=1644479&r1=1644478&r2=1644479&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnmergedBranches.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnmergedBranches.java Wed Dec 10 17:04:37 2014
@@ -80,6 +80,10 @@ class UnmergedBranches {
if (purgeCount > 0) {
log.info("Purged [{}] uncommitted branch revision entries", purgeCount);
}
+ purgeCount = doc.purgeCollisionMarkers(context);
+ if (purgeCount > 0) {
+ log.info("Purged [{}] collision markers", purgeCount);
+ }
}
/**
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CollisionTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CollisionTest.java?rev=1644479&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CollisionTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CollisionTest.java Wed Dec 10 17:04:37 2014
@@ -0,0 +1,81 @@
+/*
+ * 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;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.jackrabbit.oak.plugins.document.util.Utils;
+import org.junit.Test;
+
+import static org.apache.jackrabbit.oak.plugins.document.Collection.NODES;
+import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.COLLISIONS;
+import static org.apache.jackrabbit.oak.plugins.document.util.Utils.getIdFromPath;
+import static org.junit.Assert.assertEquals;
+
+public class CollisionTest {
+
+ private static final AtomicInteger COUNTER = new AtomicInteger();
+
+ // OAK-2342
+ @Test
+ public void purge() throws Exception {
+ DocumentMK mk1 = new DocumentMK.Builder().setClusterId(1).open();
+ DocumentNodeStore ns1 = mk1.getNodeStore();
+ DocumentStore store = ns1.getDocumentStore();
+
+ DocumentMK mk2 = new DocumentMK.Builder().setClusterId(2)
+ .setDocumentStore(store).open();
+ DocumentNodeStore ns2 = mk2.getNodeStore();
+
+ createCollision(mk1);
+ createCollision(mk2);
+
+ String id = getIdFromPath("/");
+ assertEquals(2, store.find(NODES, id).getLocalMap(COLLISIONS).size());
+
+ // restart node store
+ ns1.dispose();
+ mk1 = new DocumentMK.Builder().setClusterId(1)
+ .setDocumentStore(store).open();
+ ns1 = mk1.getNodeStore();
+
+ // must purge collision for clusterId 1
+ assertEquals(1, store.find(NODES, id).getLocalMap(COLLISIONS).size());
+ ns1.dispose();
+
+ // restart other node store
+ ns2.dispose();
+ mk2 = new DocumentMK.Builder().setClusterId(2)
+ .setDocumentStore(store).open();
+ ns2 = mk2.getNodeStore();
+
+ // must purge collision for clusterId 2
+ assertEquals(0, store.find(NODES, id).getLocalMap(COLLISIONS).size());
+ ns2.dispose();
+ }
+
+ private void createCollision(DocumentMK mk) throws Exception {
+ String nodeName = "test-" + COUNTER.getAndIncrement();
+ // create branch
+ String b = mk.branch(null);
+ mk.commit("/", "+\"" + nodeName + "\":{\"p\":\"a\"}", b, null);
+
+ // commit a change resulting in a collision on branch
+ mk.commit("/", "+\"" + nodeName + "\":{\"p\":\"b\"}", null, null);
+ }
+
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CollisionTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/trunk/oak-run/src/main/js/oak-mongo.js
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/js/oak-mongo.js?rev=1644479&r1=1644478&r2=1644479&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/js/oak-mongo.js (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/js/oak-mongo.js Wed Dec 10 17:04:37 2014
@@ -262,6 +262,51 @@ var oak = (function(global){
}
}
+ /**
+ * Removes all collision markers on the document with the given path and
+ * clusterId.
+ */
+ api.removeCollisions = function(path, clusterId) {
+ if (path === undefined) {
+ print("No path specified");
+ return;
+ }
+ if (clusterId === undefined) {
+ print("No clusterId specified");
+ return;
+ }
+ // refuse to remove when clusterId is marked active
+ var clusterNode = db.clusterNodes.findOne({_id: clusterId.toString()});
+ if (clusterNode && clusterNode.state == "ACTIVE") {
+ print("Cluster node with id " + clusterId + " is active!");
+ print("Can only remove collisions for inactive cluster node.");
+ return;
+ }
+
+ var doc = db.nodes.findOne({_id: pathDepth(path) + ":" + path});
+ if (!doc) {
+ print("No document for path: " + path);
+ return;
+ }
+ var unset = {};
+ var r;
+ var num = 0;
+ for (r in doc._collisions) {
+ if (new Revision(r).getClusterId() == clusterId) {
+ unset["_collisions." + r] = "";
+ num++;
+ }
+ }
+ if (num > 0) {
+ var update = {};
+ update["$inc"] = {_modCount: 1};
+ update["$unset"] = unset;
+ return db.nodes.update({_id: pathDepth(path) + ":" + path}, update);
+ } else {
+ print("No collisions found for clusterId " + clusterId);
+ }
+ }
+
//~--------------------------------------------------< internal >
var checkOrFixLastRevs = function(path, clusterId, dryRun) {
@@ -341,6 +386,10 @@ var oak = (function(global){
return new Date(this.timestamp);
}
+ Revision.prototype.getClusterId = function() {
+ return this.clusterId;
+ }
+
var pathDepth = function(path){
if(path === '/'){
return 0;