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 2016/01/07 13:46:36 UTC
svn commit: r1723532 [4/5] - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/
oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/d...
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/RevisionsKey.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/RevisionsKey.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/RevisionsKey.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/RevisionsKey.java Thu Jan 7 12:46:35 2016
@@ -20,7 +20,7 @@ import javax.annotation.Nonnull;
import org.apache.jackrabbit.oak.cache.CacheValue;
import org.apache.jackrabbit.oak.plugins.document.Revision;
-import org.apache.jackrabbit.oak.plugins.document.StableRevisionComparator;
+import org.apache.jackrabbit.oak.plugins.document.RevisionVector;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -29,16 +29,16 @@ import static com.google.common.base.Pre
*/
public final class RevisionsKey implements CacheValue, Comparable<RevisionsKey> {
- private final Revision r1, r2;
+ private final RevisionVector r1, r2;
- public RevisionsKey(Revision r1, Revision r2) {
+ public RevisionsKey(RevisionVector r1, RevisionVector r2) {
this.r1 = checkNotNull(r1);
this.r2 = checkNotNull(r2);
}
@Override
public int getMemory() {
- return 88;
+ return 32 + r1.getMemory() + r2.getMemory();
}
@Override
@@ -65,11 +65,11 @@ public final class RevisionsKey implemen
}
public int compareTo(@Nonnull RevisionsKey k) {
- int c = StableRevisionComparator.INSTANCE.compare(r1, k.r1);
+ int c = r1.compareTo(k.r1);
if (c != 0) {
return c;
}
- return StableRevisionComparator.INSTANCE.compare(r2, k.r2);
+ return r2.compareTo(k.r2);
}
public static RevisionsKey fromString(String s) {
@@ -78,7 +78,7 @@ public final class RevisionsKey implemen
throw new IllegalArgumentException(s);
}
return new RevisionsKey(
- Revision.fromString(s.substring(0, idx)),
- Revision.fromString(s.substring(idx + 1)));
+ RevisionVector.fromString(s.substring(0, idx)),
+ RevisionVector.fromString(s.substring(idx + 1)));
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/Utils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/Utils.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/Utils.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/Utils.java Thu Jan 7 12:46:35 2016
@@ -46,7 +46,7 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.document.DocumentStore;
import org.apache.jackrabbit.oak.plugins.document.NodeDocument;
import org.apache.jackrabbit.oak.plugins.document.Revision;
-import org.apache.jackrabbit.oak.plugins.document.RevisionContext;
+import org.apache.jackrabbit.oak.plugins.document.RevisionVector;
import org.apache.jackrabbit.oak.plugins.document.StableRevisionComparator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -467,19 +467,6 @@ public class Utils {
}
/**
- * Checks that revision x is newer than another revision.
- *
- * @param x the revision to check
- * @param previous the presumed earlier revision
- * @return true if x is newer
- */
- public static boolean isRevisionNewer(@Nonnull RevisionContext context,
- @Nonnull Revision x,
- @Nonnull Revision previous) {
- return context.getRevisionComparator().compare(x, previous) > 0;
- }
-
- /**
* Returns the revision with the newer timestamp or {@code null} if both
* revisions are {@code null}. The implementation will return the first
* revision if both have the same timestamp.
@@ -517,6 +504,43 @@ public class Utils {
}
/**
+ * Returns the revision with the older timestamp or {@code null} if both
+ * revisions are {@code null}. The implementation will return the first
+ * revision if both have the same timestamp.
+ *
+ * @param a the first revision (or {@code null}).
+ * @param b the second revision (or {@code null}).
+ * @return the revision with the older timestamp.
+ */
+ @CheckForNull
+ public static Revision min(@Nullable Revision a, @Nullable Revision b) {
+ return min(a, b, StableRevisionComparator.INSTANCE);
+ }
+
+ /**
+ * Returns the revision which is considered older or {@code null} if
+ * both revisions are {@code null}. The implementation will return the first
+ * revision if both are considered equal. The comparison is done using the
+ * provided comparator.
+ *
+ * @param a the first revision (or {@code null}).
+ * @param b the second revision (or {@code null}).
+ * @param c the comparator.
+ * @return the revision considered more recent.
+ */
+ @CheckForNull
+ public static Revision min(@Nullable Revision a,
+ @Nullable Revision b,
+ @Nonnull Comparator<Revision> c) {
+ if (a == null) {
+ return b;
+ } else if (b == null) {
+ return a;
+ }
+ return c.compare(a, b) <= 0 ? a : b;
+ }
+
+ /**
* Returns an {@link Iterable} over all {@link NodeDocument}s in the given
* store. The returned {@linkplain Iterable} does not guarantee a consistent
* view on the store. it may return documents that have been added to the
@@ -686,4 +710,34 @@ public class Utils {
return n.longValue();
}
}
+
+ /**
+ * Returns the minimum timestamp to use for a query for child documents that
+ * have been modified between {@code fromRev} and {@code toRev}.
+ *
+ * @param fromRev the from revision.
+ * @param toRev the to revision.
+ * @param minRevisions the minimum revisions of foreign cluster nodes. These
+ * are derived from the startTime of a cluster node.
+ * @return the minimum timestamp.
+ */
+ public static long getMinTimestampForDiff(@Nonnull RevisionVector fromRev,
+ @Nonnull RevisionVector toRev,
+ @Nonnull RevisionVector minRevisions) {
+ // make sure we have minimum revisions for all known cluster nodes
+ fromRev = fromRev.pmax(minRevisions);
+ toRev = toRev.pmax(minRevisions);
+ // keep only revision entries that changed
+ RevisionVector from = fromRev.difference(toRev);
+ RevisionVector to = toRev.difference(fromRev);
+ // now calculate minimum timestamp
+ long min = Long.MAX_VALUE;
+ for (Revision r : from) {
+ min = Math.min(r.getTimestamp(), min);
+ }
+ for (Revision r : to) {
+ min = Math.min(r.getTimestamp(), min);
+ }
+ return min;
+ }
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/AmnesiaDiffCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/AmnesiaDiffCache.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/AmnesiaDiffCache.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/AmnesiaDiffCache.java Thu Jan 7 12:46:35 2016
@@ -35,8 +35,8 @@ class AmnesiaDiffCache extends DiffCache
}
@Override
- public String getChanges(@Nonnull Revision from,
- @Nonnull Revision to,
+ public String getChanges(@Nonnull RevisionVector from,
+ @Nonnull RevisionVector to,
@Nonnull String path,
@Nullable Loader loader) {
if (loader != null) {
@@ -47,7 +47,7 @@ class AmnesiaDiffCache extends DiffCache
@Nonnull
@Override
- public Entry newEntry(@Nonnull Revision from, @Nonnull Revision to, boolean local) {
+ public Entry newEntry(@Nonnull RevisionVector from, @Nonnull RevisionVector to, boolean local) {
return new Entry() {
@Override
public void append(@Nonnull String path, @Nonnull String changes) {
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/BranchTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/BranchTest.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/BranchTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/BranchTest.java Thu Jan 7 12:46:35 2016
@@ -28,9 +28,9 @@ public class BranchTest {
@Test
public void getModifiedPathsUntil() {
- UnmergedBranches branches = new UnmergedBranches(StableRevisionComparator.INSTANCE);
+ UnmergedBranches branches = new UnmergedBranches();
- Revision base = Revision.newRevision(1);
+ RevisionVector base = new RevisionVector(Revision.newRevision(1));
Revision c1 = Revision.newRevision(1).asBranchRevision();
Branch b = branches.create(base, c1, null);
@@ -43,7 +43,7 @@ public class BranchTest {
bc2.track("/bar");
Revision c3 = Revision.newRevision(1).asBranchRevision();
- b.rebase(c3, Revision.newRevision(1));
+ b.rebase(c3, new RevisionVector(Revision.newRevision(1)));
Revision c4 = Revision.newRevision(1).asBranchRevision();
b.addCommit(c4);
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CheckpointsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CheckpointsTest.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CheckpointsTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CheckpointsTest.java Thu Jan 7 12:46:35 2016
@@ -22,9 +22,11 @@ import java.util.Collections;
import java.util.Map;
import java.util.concurrent.TimeUnit;
+import org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.stats.Clock;
import org.junit.Before;
import org.junit.Rule;
@@ -33,6 +35,7 @@ import org.junit.Test;
import com.google.common.collect.ImmutableMap;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
@@ -70,7 +73,7 @@ public class CheckpointsTest {
Revision r1 = null;
for(int i = 0; i < Checkpoints.CLEANUP_INTERVAL; i++){
r1 = Revision.fromString(store.checkpoint(expiryTime));
- store.setHeadRevision(Revision.newRevision(0));
+ store.setRoot(new RevisionVector(Revision.newRevision(store.getClusterId())));
}
assertEquals(r1, store.getCheckpoints().getOldestRevisionToKeep());
assertEquals(Checkpoints.CLEANUP_INTERVAL, store.getCheckpoints().size());
@@ -204,4 +207,148 @@ public class CheckpointsTest {
assertNotNull(info);
assertEquals(props, info);
}
+
+ @Test
+ public void parseInfo() {
+ long expires = System.currentTimeMillis();
+ // initial 1.0 format: only expiry time
+ Checkpoints.Info info = Checkpoints.Info.fromString(String.valueOf(expires));
+ assertEquals(expires, info.getExpiryTime());
+ // 1.2 format: json with expiry and info map
+ String infoString = "{\"expires\":\"" + expires + "\",\"foo\":\"bar\"}";
+ info = Checkpoints.Info.fromString(infoString);
+ assertEquals(expires, info.getExpiryTime());
+ assertEquals(Collections.singleton("foo"), info.get().keySet());
+ assertEquals("bar", info.get().get("foo"));
+ // 1.4 format: json with expiry, revision vector and info map
+ Revision r1 = new Revision(1, 0, 1);
+ Revision r2 = new Revision(1, 0, 2);
+ RevisionVector rv = new RevisionVector(r1, r2);
+ infoString = "{\"expires\":\"" + expires +
+ "\",\"rv\":\"" + rv.toString() +
+ "\",\"foo\":\"bar\"}";
+ info = Checkpoints.Info.fromString(infoString);
+ assertEquals(expires, info.getExpiryTime());
+ assertEquals(Collections.singleton("foo"), info.get().keySet());
+ assertEquals("bar", info.get().get("foo"));
+ assertEquals(rv, info.getCheckpoint());
+ assertEquals(infoString, info.toString());
+ }
+
+ @Test
+ public void crossClusterNodeCheckpoint() throws Exception {
+ // use an async delay to ensure DocumentNodeStore.suspendUntil() works
+ // but set it to a high value and control background ops manually in
+ // this test
+ final int asyncDelay = (int) TimeUnit.MINUTES.toMillis(1);
+ DocumentStore store = new MemoryDocumentStore();
+ final DocumentNodeStore ns1 = builderProvider.newBuilder()
+ .setDocumentStore(store).setAsyncDelay(asyncDelay).getNodeStore();
+ final DocumentNodeStore ns2 = builderProvider.newBuilder()
+ .setDocumentStore(store).setAsyncDelay(asyncDelay).getNodeStore();
+
+ // create node on ns1
+ NodeBuilder builder = ns1.getRoot().builder();
+ builder.child("foo");
+ ns1.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+ // make visible on ns2
+ ns1.runBackgroundOperations();
+ ns2.runBackgroundOperations();
+ // create checkpoint on ns1
+ String cp1 = ns1.checkpoint(Long.MAX_VALUE);
+ // retrieve checkpoint on ns2
+ NodeState root = ns2.retrieve(cp1);
+ assertNotNull(root);
+ assertTrue(root.hasChildNode("foo"));
+ ns2.release(cp1);
+
+ // create node on ns1
+ builder = ns1.getRoot().builder();
+ builder.child("bar");
+ ns1.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+ // create checkpoint when 'bar' is not yet visible to ns2
+ final String cp2 = ns1.checkpoint(Long.MAX_VALUE);
+ // retrieve checkpoint on ns2
+ final NodeState state[] = new NodeState[1];
+ Thread t = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ state[0] = ns2.retrieve(cp2);
+ }
+ });
+ t.start();
+ ns1.runBackgroundOperations();
+ ns2.runBackgroundOperations();
+ t.join();
+ assertNotNull(state[0]);
+ assertTrue(state[0].hasChildNode("bar"));
+ }
+
+ @Test
+ public void crossClusterCheckpointNewClusterNode() throws Exception {
+ DocumentStore store = new MemoryDocumentStore();
+ DocumentNodeStore ns1 = builderProvider.newBuilder()
+ .setDocumentStore(store).setAsyncDelay(0).getNodeStore();
+
+ // create 'foo' on ns1
+ NodeBuilder b1 = ns1.getRoot().builder();
+ b1.child("foo");
+ ns1.merge(b1, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+ // checkpoint sees 'foo' but not 'bar'
+ String checkpoint = ns1.checkpoint(Long.MAX_VALUE);
+
+ // create 'bar' on ns1
+ b1 = ns1.getRoot().builder();
+ b1.child("bar");
+ ns1.merge(b1, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+ // make visible
+ ns1.runBackgroundOperations();
+
+ // now start second node store
+ DocumentNodeStore ns2 = builderProvider.newBuilder()
+ .setDocumentStore(store).setAsyncDelay(0).getNodeStore();
+ NodeBuilder b2 = ns2.getRoot().builder();
+ b2.child("baz");
+ ns2.merge(b2, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+ NodeState root = ns2.retrieve(checkpoint);
+ assertNotNull(root);
+ assertTrue(root.hasChildNode("foo"));
+ assertFalse(root.hasChildNode("bar"));
+ assertFalse(root.hasChildNode("baz"));
+ }
+
+ @Test
+ public void crossClusterReadOldCheckpoint() throws Exception {
+ DocumentStore store = new MemoryDocumentStore();
+ DocumentNodeStore ns1 = builderProvider.newBuilder()
+ .setDocumentStore(store).setAsyncDelay(0).getNodeStore();
+
+ NodeBuilder b1 = ns1.getRoot().builder();
+ b1.child("foo");
+ ns1.merge(b1, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+ ns1.runBackgroundOperations();
+
+ // manually create a check point in 1.2 format
+ Revision headRev = Revision.fromString(ns1.getHeadRevision().toString());
+ long expires = Long.MAX_VALUE;
+ String data = "{\"expires\":\"" + expires + "\"}";
+ UpdateOp update = new UpdateOp("checkpoint", false);
+ update.setMapEntry("data", headRev, data);
+ store.createOrUpdate(Collection.SETTINGS, update);
+
+ // now start second node store
+ DocumentNodeStore ns2 = builderProvider.newBuilder()
+ .setDocumentStore(store).setAsyncDelay(0).getNodeStore();
+ NodeBuilder b2 = ns2.getRoot().builder();
+ b2.child("baz");
+ ns2.merge(b2, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+ NodeState root = ns2.retrieve(headRev.toString());
+ assertNotNull(root);
+ assertTrue(root.hasChildNode("foo"));
+ assertFalse(root.hasChildNode("baz"));
+ }
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterRevisionComparisonTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterRevisionComparisonTest.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterRevisionComparisonTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterRevisionComparisonTest.java Thu Jan 7 12:46:35 2016
@@ -92,8 +92,6 @@ public class ClusterRevisionComparisonTe
c1.invalidateNodeCache("/a/c2" , ((DocumentNodeState)c1ns1.getChildNode("a")).getLastRevision());
c1.invalidateNodeCache("/a/c3" , ((DocumentNodeState)c1ns1.getChildNode("a")).getLastRevision());
- //Revision comparator purge by moving in future
- clock.waitUntil(clock.getTime() + DocumentNodeStore.REMEMBER_REVISION_ORDER_MILLIS * 2);
runBgOps(c1);
NodeState a = c1ns1.getChildNode("a");
@@ -139,8 +137,6 @@ public class ClusterRevisionComparisonTe
c1.invalidateNodeCache("/a/c1" , ((DocumentNodeState)a).getLastRevision());
c1.invalidateNodeCache("/a/c2" , ((DocumentNodeState)a).getLastRevision());
- //Revision comparator purge by moving in future
- clock.waitUntil(clock.getTime() + DocumentNodeStore.REMEMBER_REVISION_ORDER_MILLIS * 2);
runBgOps(c1);
assertTrue("/a/c1 disappeared", a.hasChildNode("c1"));
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterTest.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterTest.java Thu Jan 7 12:46:35 2016
@@ -216,9 +216,9 @@ public class ClusterTest {
mk3.runBackgroundOperations(); // pick up changes from mk2
- DocumentNodeState base = ns3.getNode("/", Revision.fromString(base3));
+ DocumentNodeState base = ns3.getNode("/", RevisionVector.fromString(base3));
assertNotNull(base);
- NodeState branchHead = ns3.getNode("/", Revision.fromString(b3));
+ NodeState branchHead = ns3.getNode("/", RevisionVector.fromString(b3));
assertNotNull(branchHead);
TrackingDiff diff = new TrackingDiff();
branchHead.compareAgainstBaseState(base, diff);
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitQueueTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitQueueTest.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitQueueTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitQueueTest.java Thu Jan 7 12:46:35 2016
@@ -68,14 +68,15 @@ public class CommitQueueTest {
AtomicBoolean running = new AtomicBoolean(true);
Closeable observer = store.addObserver(new Observer() {
- private Revision before = new Revision(0, 0, store.getClusterId());
+ private RevisionVector before = new RevisionVector(
+ new Revision(0, 0, store.getClusterId()));
@Override
public void contentChanged(@Nonnull NodeState root, @Nullable CommitInfo info) {
DocumentNodeState after = (DocumentNodeState) root;
- Revision r = after.getRevision();
+ RevisionVector r = after.getRevision();
LOG.debug("seen: {}", r);
- if (r.compareRevisionTime(before) < 0) {
+ if (r.compareTo(before) < 0) {
exceptions.add(new Exception(
"Inconsistent revision sequence. Before: " +
before + ", after: " + r));
@@ -187,7 +188,7 @@ public class CommitQueueTest {
final DocumentNodeStore ds = builderProvider.newBuilder().getNodeStore();
// simulate start of a branch commit
- Commit c = ds.newCommit(ds.getHeadRevision().asBranchRevision(), null);
+ Commit c = ds.newCommit(ds.getHeadRevision().asBranchRevision(ds.getClusterId()), null);
Thread t = new Thread(new Runnable() {
@Override
@@ -212,16 +213,15 @@ public class CommitQueueTest {
@Test
public void suspendUntil() throws Exception {
- final AtomicReference<Revision> headRevision = new AtomicReference<Revision>();
+ final AtomicReference<RevisionVector> headRevision = new AtomicReference<RevisionVector>();
RevisionContext context = new DummyRevisionContext() {
@Nonnull
@Override
- public Revision getHeadRevision() {
+ public RevisionVector getHeadRevision() {
return headRevision.get();
}
};
- headRevision.set(context.newRevision());
-
+ headRevision.set(new RevisionVector(context.newRevision()));
final CommitQueue queue = new CommitQueue(context);
final Revision newHeadRev = context.newRevision();
@@ -247,7 +247,7 @@ public class CommitQueueTest {
// must still be suspended
assertEquals(1, queue.numSuspendedThreads());
- headRevision.set(newHeadRev);
+ headRevision.set(new RevisionVector(newHeadRev));
queue.headRevisionChanged();
// must still be suspended
assertEquals(1, queue.numSuspendedThreads());
@@ -261,15 +261,15 @@ public class CommitQueueTest {
@Test
public void suspendUntilTimeout() throws Exception {
- final AtomicReference<Revision> headRevision = new AtomicReference<Revision>();
+ final AtomicReference<RevisionVector> headRevision = new AtomicReference<RevisionVector>();
RevisionContext context = new DummyRevisionContext() {
@Nonnull
@Override
- public Revision getHeadRevision() {
+ public RevisionVector getHeadRevision() {
return headRevision.get();
}
};
- headRevision.set(context.newRevision());
+ headRevision.set(new RevisionVector(context.newRevision()));
final CommitQueue queue = new CommitQueue(context);
queue.setSuspendTimeoutMillis(0);
@@ -288,15 +288,15 @@ public class CommitQueueTest {
@Test
public void concurrentSuspendUntil() throws Exception {
- final AtomicReference<Revision> headRevision = new AtomicReference<Revision>();
+ final AtomicReference<RevisionVector> headRevision = new AtomicReference<RevisionVector>();
RevisionContext context = new DummyRevisionContext() {
@Nonnull
@Override
- public Revision getHeadRevision() {
+ public RevisionVector getHeadRevision() {
return headRevision.get();
}
};
- headRevision.set(context.newRevision());
+ headRevision.set(new RevisionVector(context.newRevision()));
List<Thread> threads = new ArrayList<Thread>();
List<Revision> allRevisions = new ArrayList<Revision>();
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitTest.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitTest.java Thu Jan 7 12:46:35 2016
@@ -57,7 +57,8 @@ public class CommitTest {
// this commit should fail
Commit c = ns.newCommit(ns.getHeadRevision(), null);
try {
- c.addNode(new DocumentNodeState(ns, "/foo/baz", c.getRevision()));
+ c.addNode(new DocumentNodeState(ns, "/foo/baz",
+ new RevisionVector(c.getRevision())));
UpdateOp op = c.getUpdateOperationForNode("/bar");
op.setMapEntry("p", c.getRevision(), "v");
try {
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CountingTieredDiffCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CountingTieredDiffCache.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CountingTieredDiffCache.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CountingTieredDiffCache.java Thu Jan 7 12:46:35 2016
@@ -56,8 +56,8 @@ public class CountingTieredDiffCache ext
}
@Override
- public String getChanges(@Nonnull Revision from,
- @Nonnull Revision to,
+ public String getChanges(@Nonnull RevisionVector from,
+ @Nonnull RevisionVector to,
@Nonnull String path,
@Nullable Loader loader) {
return super.getChanges(from, to, path, new CountingLoader(loader));
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStateTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStateTest.java?rev=1723532&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStateTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStateTest.java Thu Jan 7 12:46:35 2016
@@ -0,0 +1,36 @@
+/*
+ * 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 org.junit.Rule;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class DocumentNodeStateTest {
+
+ @Rule
+ public DocumentMKBuilderProvider builderProvider = new DocumentMKBuilderProvider();
+
+ @Test
+ public void getMemory() {
+ DocumentNodeStore store = builderProvider.newBuilder().getNodeStore();
+ RevisionVector rv = new RevisionVector(Revision.newRevision(1));
+ DocumentNodeState state = new DocumentNodeState(store, "/foo", rv);
+ assertEquals(232, state.getMemory());
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStateTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java Thu Jan 7 12:46:35 2016
@@ -19,7 +19,6 @@ package org.apache.jackrabbit.oak.plugin
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.jackrabbit.oak.api.CommitFailedException.CONSTRAINT;
import static org.apache.jackrabbit.oak.plugins.document.Collection.NODES;
-import static org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore.REMEMBER_REVISION_ORDER_MILLIS;
import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.MODIFIED_IN_SECS;
import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.MODIFIED_IN_SECS_RESOLUTION;
import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.NUM_REVS_THRESHOLD;
@@ -99,7 +98,6 @@ import org.apache.jackrabbit.oak.spi.sta
import org.apache.jackrabbit.oak.spi.state.NodeStore;
import org.apache.jackrabbit.oak.stats.Clock;
import org.junit.After;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.slf4j.Logger;
@@ -266,7 +264,7 @@ public class DocumentNodeStoreTest {
builder.child("deletedNode").remove();
merge(store, builder);
- final Revision head = store.getHeadRevision();
+ final RevisionVector head = store.getHeadRevision();
Thread writer = new Thread(new Runnable() {
@Override
@@ -274,8 +272,8 @@ public class DocumentNodeStoreTest {
try {
Revision r = store.newRevision();
Commit c = new Commit(store, r, head, null);
- c.addNode(new DocumentNodeState(store, "/newConflictingNode", r));
- c.addNode(new DocumentNodeState(store, "/deletedNode", r));
+ c.addNode(new DocumentNodeState(store, "/newConflictingNode", new RevisionVector(r)));
+ c.addNode(new DocumentNodeState(store, "/deletedNode", new RevisionVector(r)));
c.updateProperty("/updateNode", "foo", "baz");
c.apply();
} catch (DocumentStoreException e) {
@@ -292,8 +290,8 @@ public class DocumentNodeStoreTest {
// commit will succeed and add collision marker to writer commit
Revision r = store.newRevision();
Commit c = new Commit(store, r, head, null);
- c.addNode(new DocumentNodeState(store, "/newConflictingNode", r));
- c.addNode(new DocumentNodeState(store, "/newNonConflictingNode", r));
+ c.addNode(new DocumentNodeState(store, "/newConflictingNode", new RevisionVector(r)));
+ c.addNode(new DocumentNodeState(store, "/newNonConflictingNode", new RevisionVector(r)));
c.apply();
// allow writer to continue
s.release();
@@ -356,7 +354,7 @@ public class DocumentNodeStoreTest {
.setDocumentStore(docStore).setAsyncDelay(0)
.setClusterId(1).getNodeStore();
ns1.getRoot();
- Revision r1 = ns1.getHeadRevision();
+ Revision r1 = ns1.getHeadRevision().getRevision(ns1.getClusterId());
ns1.runBackgroundOperations();
DocumentNodeStore ns2 = builderProvider.newBuilder()
.setDocumentStore(docStore).setAsyncDelay(0)
@@ -434,48 +432,6 @@ public class DocumentNodeStoreTest {
}
}
- // OAK-1814
- @Test
- public void visibilityAfterRevisionComparatorPurge() throws Exception {
- Clock clock = new Clock.Virtual();
- clock.waitUntil(System.currentTimeMillis());
- Revision.setClock(clock);
- MemoryDocumentStore docStore = new MemoryDocumentStore();
- DocumentNodeStore nodeStore1 = builderProvider.newBuilder()
- .setDocumentStore(docStore).setClusterId(1)
- .setAsyncDelay(0).clock(clock).getNodeStore();
- nodeStore1.runBackgroundOperations();
- DocumentNodeStore nodeStore2 = builderProvider.newBuilder()
- .setDocumentStore(docStore).setClusterId(2)
- .setAsyncDelay(0).clock(clock).getNodeStore();
- DocumentNodeStore nodeStore3 = builderProvider.newBuilder()
- .setDocumentStore(docStore).setClusterId(3)
- .setAsyncDelay(0).clock(clock).getNodeStore();
-
- NodeDocument doc = docStore.find(NODES, Utils.getIdFromPath("/"));
- assertNotNull(doc);
- Revision created = doc.getLocalDeleted().firstKey();
- assertEquals(1, created.getClusterId());
-
- clock.waitUntil(System.currentTimeMillis() +
- REMEMBER_REVISION_ORDER_MILLIS / 2);
-
- NodeBuilder builder = nodeStore2.getRoot().builder();
- builder.setProperty("prop", "value");
- nodeStore2.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
- nodeStore2.runBackgroundOperations();
-
- clock.waitUntil(System.currentTimeMillis() +
- REMEMBER_REVISION_ORDER_MILLIS + 1000);
- nodeStore3.runBackgroundOperations();
-
- doc = docStore.find(NODES, Utils.getIdFromPath("/"));
- assertNotNull(doc);
- NodeState state = doc.getNodeAtRevision(nodeStore3,
- nodeStore3.getHeadRevision(), null);
- assertNotNull(state);
- }
-
@Test
public void modifiedReset() throws Exception {
Clock clock = new Clock.Virtual();
@@ -580,7 +536,7 @@ public class DocumentNodeStoreTest {
builder.child("test").setProperty("prop", "value");
ns.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
- Revision rev = ns.getHeadRevision();
+ RevisionVector rev = ns.getHeadRevision();
NodeDocument doc = docStore.find(NODES, Utils.getIdFromPath("/test"));
assertNotNull(doc);
DocumentNodeState state = doc.getNodeAtRevision(ns, rev, null);
@@ -677,28 +633,30 @@ public class DocumentNodeStoreTest {
DocumentNodeStore ns1 = builderProvider.newBuilder().setAsyncDelay(0)
.setClusterId(1).setDocumentStore(docStore)
.getNodeStore();
+ int cId1 = ns1.getClusterId();
DocumentNodeStore ns2 = builderProvider.newBuilder().setAsyncDelay(0)
.setClusterId(2).setDocumentStore(docStore)
.getNodeStore();
+ int cId2 = ns2.getClusterId();
ns1.updateClusterState();
ns2.updateClusterState();
- assertEquals(0, ns1.getInactiveClusterNodes().size());
- assertEquals(0, ns2.getInactiveClusterNodes().size());
- assertEquals(2, ns1.getActiveClusterNodes().size());
- assertEquals(2, ns2.getActiveClusterNodes().size());
+ assertEquals(0, ns1.getMBean().getInactiveClusterNodes().length);
+ assertEquals(0, ns2.getMBean().getInactiveClusterNodes().length);
+ assertEquals(2, ns1.getMBean().getActiveClusterNodes().length);
+ assertEquals(2, ns2.getMBean().getActiveClusterNodes().length);
ns1.dispose();
ns2.updateClusterState();
- Map<Integer, Long> inactive = ns2.getInactiveClusterNodes();
- Map<Integer, Long> active = ns2.getActiveClusterNodes();
- assertEquals(1, inactive.size());
- assertEquals(1, (int) inactive.keySet().iterator().next());
- assertEquals(1, active.size());
- assertEquals(2, (int) active.keySet().iterator().next());
+ String[] inactive = ns2.getMBean().getInactiveClusterNodes();
+ String[] active = ns2.getMBean().getActiveClusterNodes();
+ assertEquals(1, inactive.length);
+ assertTrue(inactive[0].startsWith(cId1 + "="));
+ assertEquals(1, active.length);
+ assertTrue(active[0].startsWith(cId2 + "="));
}
// OAK-2288
@@ -723,7 +681,7 @@ public class DocumentNodeStoreTest {
NodeDocument doc = docStore.find(NODES, id);
assertNotNull(doc);
- Revision rev = doc.getLocalDeleted().firstKey();
+ RevisionVector rev = new RevisionVector(doc.getLocalDeleted().firstKey());
merge(store, builder1);
@@ -829,41 +787,6 @@ public class DocumentNodeStoreTest {
}
}
- // OAK-2345
- @Test
- public void inactiveClusterId() throws Exception {
- Clock clock = new Clock.Virtual();
- clock.waitUntil(System.currentTimeMillis());
- Revision.setClock(clock);
- MemoryDocumentStore docStore = new MemoryDocumentStore();
- DocumentNodeStore ns1 = builderProvider.newBuilder()
- .setDocumentStore(docStore).setClusterId(1)
- .setAsyncDelay(0).clock(clock).getNodeStore();
- NodeBuilder builder = ns1.getRoot().builder();
- builder.child("test");
- merge(ns1, builder);
- Revision r = ns1.getHeadRevision();
- ns1.dispose();
-
- // start other cluster node
- DocumentNodeStore ns2 = builderProvider.newBuilder()
- .setDocumentStore(docStore).setClusterId(2)
- .setAsyncDelay(0).clock(clock).getNodeStore();
- assertNotNull(ns2.getRevisionComparator().getRevisionSeen(r));
- ns2.dispose();
-
- // wait until revision is old
- clock.waitUntil(System.currentTimeMillis()
- + REMEMBER_REVISION_ORDER_MILLIS + 1000);
-
- // start cluster 2 again
- ns2 = builderProvider.newBuilder()
- .setDocumentStore(docStore).setClusterId(2)
- .setAsyncDelay(0).clock(clock).getNodeStore();
- // now r is considered old and revisionSeen is null
- assertNull(ns2.getRevisionComparator().getRevisionSeen(r));
- }
-
// OAK-1782
@Test
public void diffOnce() throws Exception {
@@ -892,9 +815,11 @@ public class DocumentNodeStoreTest {
}
merge(ns, builder);
- final Revision head = ns.getHeadRevision();
- final Revision to = new Revision(
- head.getTimestamp() + 1000, 0, head.getClusterId());
+ final RevisionVector head = ns.getHeadRevision();
+ Revision localHead = head.getRevision(ns.getClusterId());
+ assertNotNull(localHead);
+ final RevisionVector to = new RevisionVector(new Revision(
+ localHead.getTimestamp() + 1000, 0, localHead.getClusterId()));
int numReaders = 10;
final CountDownLatch ready = new CountDownLatch(numReaders);
final CountDownLatch go = new CountDownLatch(1);
@@ -954,7 +879,7 @@ public class DocumentNodeStoreTest {
builder.child("test").remove();
merge(store, builder);
- Revision removedAt = store.getHeadRevision();
+ RevisionVector removedAt = store.getHeadRevision();
String id = Utils.getIdFromPath("/test");
int count = 0;
@@ -973,7 +898,7 @@ public class DocumentNodeStoreTest {
assertNoPreviousDocs(reads);
reads.clear();
- doc.getValueMap("foo").get(removedAt);
+ doc.getValueMap("foo").get(removedAt.getRevision(store.getClusterId()));
assertNoPreviousDocs(reads);
}
@@ -1244,7 +1169,7 @@ public class DocumentNodeStoreTest {
String parentPath = "/:hidden/parent";
NodeDocument parentDoc = docStore.find(Collection.NODES, Utils.getIdFromPath(parentPath));
assertFalse("parent node of unseen children must not get deleted",
- isDocDeleted(parentDoc, store1.getRevisionComparator()));
+ isDocDeleted(parentDoc));
//Test 2 - parent shouldn't be removable if order of operation is:
//# N1 and N2 know about /:hidden
@@ -1262,7 +1187,7 @@ public class DocumentNodeStoreTest {
parentDoc = docStore.find(Collection.NODES, Utils.getIdFromPath(parentPath));
assertFalse("parent node of unseen children must not get deleted",
- isDocDeleted(parentDoc, store2.getRevisionComparator()));
+ isDocDeleted(parentDoc));
store1.runBackgroundOperations();
store2.runBackgroundOperations();
@@ -1296,7 +1221,7 @@ public class DocumentNodeStoreTest {
parentPath = "/:hidden/parent1";
parentDoc = docStore.find(Collection.NODES, Utils.getIdFromPath(parentPath));
assertFalse("parent node of unseen children must not get deleted",
- isDocDeleted(parentDoc, store1.getRevisionComparator()));
+ isDocDeleted(parentDoc));
//Test 4 - parent shouldn't be removable if order of operation is:
//# N1 and N2 know about /:hidden/parent1
@@ -1313,7 +1238,7 @@ public class DocumentNodeStoreTest {
parentDoc = docStore.find(Collection.NODES, Utils.getIdFromPath(parentPath));
assertFalse("parent node of unseen children must not get deleted",
- isDocDeleted(parentDoc, store2.getRevisionComparator()));
+ isDocDeleted(parentDoc));
}
@Test
@@ -1699,7 +1624,6 @@ public class DocumentNodeStoreTest {
}
// OAK-3646
- @Ignore("OAK-3646")
@Test
public void concurrentChildOperations() throws Exception {
Clock clock = new Clock.Virtual();
@@ -1742,7 +1666,7 @@ public class DocumentNodeStoreTest {
// on cluster node 2, remove of child-0 is not yet visible
List<ChildNodeEntry> children = Lists.newArrayList(ns2.getRoot().getChildNode("foo").getChildNode("bar").getChildNodeEntries());
assertEquals(2, Iterables.size(children));
- Revision invalidate = null;
+ RevisionVector invalidate = null;
for (ChildNodeEntry entry : children) {
if (entry.getName().equals("child-0")) {
invalidate = asDocumentNodeState(entry.getNodeState()).getRevision();
@@ -1753,16 +1677,12 @@ public class DocumentNodeStoreTest {
// this will make changes from cluster node 1 visible
ns2.runBackgroundOperations();
- // wait twice the time we remember revision order
- clock.waitUntil(clock.getTime() + 2 * REMEMBER_REVISION_ORDER_MILLIS);
- // collect everything older than one hour (time revision order is remembered)
+ // wait two hours
+ clock.waitUntil(clock.getTime() + TimeUnit.HOURS.toMillis(2));
+ // collect everything older than one hour
// this will remove child-0 and child-1 doc
- ns1.getVersionGarbageCollector().gc(REMEMBER_REVISION_ORDER_MILLIS, TimeUnit.MILLISECONDS);
+ ns1.getVersionGarbageCollector().gc(1, TimeUnit.HOURS);
- // trigger purge of revisions older than one hour in RevisionComparator
- // this is usually done by the background read operation, but we
- // do it explicitly here to make sure it really happens in this test
- ns2.getRevisionComparator().purge(clock.getTime() - REMEMBER_REVISION_ORDER_MILLIS);
// forget cache entry for deleted node
ns2.invalidateNodeCache("/foo/bar/child-0", invalidate);
@@ -1772,7 +1692,6 @@ public class DocumentNodeStoreTest {
// OAK-3646
// similar to previous test but both cluster nodes add a child node
- @Ignore("OAK-3646")
@Test
public void concurrentChildOperations2() throws Exception {
Clock clock = new Clock.Virtual();
@@ -1814,14 +1733,6 @@ public class DocumentNodeStoreTest {
// this will make changes from cluster node 1 visible
ns2.runBackgroundOperations();
- // wait twice the time we remember revision order
- clock.waitUntil(clock.getTime() + 2 * REMEMBER_REVISION_ORDER_MILLIS);
-
- // trigger purge of revisions older than one hour in RevisionComparator
- // this is usually done by the background read operation, but we
- // do it explicitly here to make sure it really happens in this test
- ns2.getRevisionComparator().purge(clock.getTime() - REMEMBER_REVISION_ORDER_MILLIS);
-
children = Lists.newArrayList(ns2.getRoot().getChildNode("foo").getChildNodeEntries());
assertEquals(2, Iterables.size(children));
}
@@ -2156,11 +2067,11 @@ public class DocumentNodeStoreTest {
public void dispatch() throws Exception {
DocumentNodeStore ns = builderProvider.newBuilder().getNodeStore();
- Revision from = ns.getHeadRevision();
+ RevisionVector from = ns.getHeadRevision();
NodeBuilder builder = ns.getRoot().builder();
builder.child("test");
merge(ns, builder);
- Revision to = ns.getHeadRevision();
+ RevisionVector to = ns.getHeadRevision();
DiffCache.Entry entry = ns.getDiffCache().newEntry(from, to, true);
entry.append("/", "-\"foo\"");
@@ -2188,7 +2099,7 @@ public class DocumentNodeStoreTest {
builder.child("foo").child("child").child("node");
merge(ns, builder);
- Revision head = ns.getHeadRevision();
+ RevisionVector head = ns.getHeadRevision();
NodeState child = ns.getRoot().getChildNode("bar").getChildNode("child");
assertTrue(child instanceof DocumentNodeState);
DocumentNodeState state = (DocumentNodeState) child;
@@ -2304,7 +2215,9 @@ public class DocumentNodeStoreTest {
afterTest.compareAgainstBaseState(beforeTest, new DefaultNodeStateDiff());
assertEquals(1, startValues.size());
- long beforeModified = getModifiedInSecs(before.getRevision().getTimestamp());
+ Revision localHead = before.getRevision().getRevision(ns.getClusterId());
+ assertNotNull(localHead);
+ long beforeModified = getModifiedInSecs(localHead.getTimestamp());
// startValue must be based on the revision of the before state
// and not when '/test' was last modified
assertEquals(beforeModified, (long) startValues.get(0));
@@ -2444,7 +2357,7 @@ public class DocumentNodeStoreTest {
final List<Commit> commits = new ArrayList<Commit>();
for (int i = 0; i < 10; i++) {
Revision revision = ds.newRevision();
- Commit commit = ds.newCommit(revision, ds.createBranch(root));
+ Commit commit = ds.newCommit(new RevisionVector(revision), ds.createBranch(root));
commits.add(commit);
revisions.add(revision);
}
@@ -2655,6 +2568,80 @@ public class DocumentNodeStoreTest {
assertTrue(diff.modified.contains("/parent/node-x/child"));
}
+ @Test
+ public void lastRevWithRevisionVector() throws Exception {
+ MemoryDocumentStore store = new MemoryDocumentStore();
+ DocumentNodeStore ns1 = builderProvider.newBuilder()
+ .setDocumentStore(store).setAsyncDelay(0).getNodeStore();
+ DocumentNodeStore ns2 = builderProvider.newBuilder()
+ .setDocumentStore(store).setAsyncDelay(0).getNodeStore();
+
+ NodeBuilder b1 = ns1.getRoot().builder();
+ b1.child("parent");
+ merge(ns1, b1);
+ b1 = ns1.getRoot().builder();
+ NodeBuilder parent = b1.child("parent");
+ parent.setProperty("p", 1);
+ parent.child("child");
+ merge(ns1, b1);
+ ns1.runBackgroundOperations();
+ ns2.runBackgroundOperations();
+
+ NodeBuilder b2 = ns2.getRoot().builder();
+ b2.child("parent").setProperty("p", 2);
+ merge(ns2, b2);
+ ns2.runBackgroundOperations();
+ ns1.runBackgroundOperations();
+
+ assertTrue(ns1.getRoot().getChildNode("parent").hasChildNode("child"));
+ }
+
+ @Test
+ public void branchBaseBeforeClusterJoin() throws Exception {
+ MemoryDocumentStore store = new MemoryDocumentStore();
+ DocumentNodeStore ns1 = builderProvider.newBuilder()
+ .setDocumentStore(store).setAsyncDelay(0).getNodeStore();
+
+ NodeBuilder b1 = ns1.getRoot().builder();
+ b1.child("parent");
+ merge(ns1, b1);
+ ns1.runBackgroundOperations();
+
+ DocumentNodeStore ns2 = builderProvider.newBuilder()
+ .setDocumentStore(store).setAsyncDelay(0).getNodeStore();
+ NodeBuilder b2 = ns2.getRoot().builder();
+ b2.child("parent").child("baz");
+ merge(ns2, b2);
+ ns2.runBackgroundOperations();
+
+ DocumentNodeState root = ns1.getRoot();
+ DocumentNodeStoreBranch b = ns1.createBranch(root);
+ // branch state is now Unmodified
+ NodeBuilder builder = root.builder();
+ builder.child("parent").child("foo");
+ b.setRoot(builder.getNodeState());
+ // branch state is now InMemory
+ builder.child("parent").child("bar");
+ b.setRoot(builder.getNodeState());
+ // branch state is now Persisted
+
+ b.rebase();
+ NodeState parent = b.getHead().getChildNode("parent");
+ assertTrue(parent.exists());
+ assertTrue(parent.hasChildNode("foo"));
+ assertTrue(parent.hasChildNode("bar"));
+ assertFalse(parent.hasChildNode("baz"));
+
+ ns1.runBackgroundOperations();
+
+ b.merge(EmptyHook.INSTANCE, CommitInfo.EMPTY);
+ parent = ns1.getRoot().getChildNode("parent");
+ assertTrue(parent.exists());
+ assertTrue(parent.hasChildNode("foo"));
+ assertTrue(parent.hasChildNode("bar"));
+ assertTrue(parent.hasChildNode("baz"));
+ }
+
private static DocumentNodeState asDocumentNodeState(NodeState state) {
if (!(state instanceof DocumentNodeState)) {
throw new IllegalArgumentException("Not a DocumentNodeState");
@@ -2768,11 +2755,10 @@ public class DocumentNodeStoreTest {
* @param doc the document to be tested
* @return latest committed value of _deleted map
*/
- private boolean isDocDeleted(NodeDocument doc,
- Comparator<Revision> comparator) {
+ private boolean isDocDeleted(NodeDocument doc) {
boolean latestDeleted = false;
- SortedMap<Revision, String> localDeleted = Maps.newTreeMap(
- Collections.reverseOrder(comparator));
+ SortedMap<Revision, String> localDeleted =
+ Maps.newTreeMap(StableRevisionComparator.REVERSE);
localDeleted.putAll(doc.getLocalDeleted());
for (Map.Entry<Revision, String> entry : localDeleted.entrySet()) {
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentSplitTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentSplitTest.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentSplitTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentSplitTest.java Thu Jan 7 12:46:35 2016
@@ -18,7 +18,6 @@ package org.apache.jackrabbit.oak.plugin
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -95,7 +94,7 @@ public class DocumentSplitTest extends B
assertTrue(doc.isCommitted(rev));
}
// check if document is still there
- assertNotNull(ns.getNode("/", Revision.fromString(head)));
+ assertNotNull(ns.getNode("/", RevisionVector.fromString(head)));
NodeDocument prevDoc = Iterators.getOnlyElement(doc.getAllPreviousDocs());
assertEquals(SplitDocType.DEFAULT, prevDoc.getSplitDocType());
@@ -135,7 +134,7 @@ public class DocumentSplitTest extends B
|| doc.getCommitRootPath(rev) != null);
assertTrue(doc.isCommitted(rev));
}
- DocumentNodeState node = ns.getNode("/foo", Revision.fromString(head));
+ DocumentNodeState node = ns.getNode("/foo", RevisionVector.fromString(head));
// check status of node
if (create) {
assertNull(node);
@@ -290,7 +289,7 @@ public class DocumentSplitTest extends B
// read current value
NodeDocument doc = ds.find(NODES, Utils.getIdFromPath("/test"));
assertNotNull(doc);
- Revision head = ns.getHeadRevision();
+ RevisionVector head = ns.getHeadRevision();
Revision lastRev = ns.getPendingModifications().get("/test");
DocumentNodeState n = doc.getNodeAtRevision(mk.getNodeStore(), head, lastRev);
assertNotNull(n);
@@ -326,7 +325,7 @@ public class DocumentSplitTest extends B
doc = store.find(NODES, Utils.getIdFromPath("/test/foo"));
assertNotNull(doc);
DocumentNodeState node = doc.getNodeAtRevision(ns,
- Revision.fromString(rev), null);
+ RevisionVector.fromString(rev), null);
assertNotNull(node);
}
@@ -473,7 +472,7 @@ public class DocumentSplitTest extends B
Map<Revision, String> valueMap = doc.getValueMap("prop");
for (Map.Entry<Revision, String> entry : valueMap.entrySet()) {
if (previous != null) {
- assertTrue(ns.isRevisionNewer(previous, entry.getKey()));
+ assertTrue(previous.compareRevisionTime(entry.getKey()) > 0);
}
previous = entry.getKey();
numValues++;
@@ -482,7 +481,7 @@ public class DocumentSplitTest extends B
assertEquals(revs.size(), numValues);
assertEquals(revs.size(), valueMap.size());
- assertNotNull(doc.getNodeAtRevision(ns, Revision.fromString(rev), null));
+ assertNotNull(doc.getNodeAtRevision(ns, RevisionVector.fromString(rev), null));
}
@Test
@@ -525,7 +524,7 @@ public class DocumentSplitTest extends B
}
// some fake previous doc references to trigger UpdateOp
// for an intermediate document
- TreeSet<Revision> prev = Sets.newTreeSet(mk.getNodeStore().getRevisionComparator());
+ TreeSet<Revision> prev = Sets.newTreeSet(StableRevisionComparator.INSTANCE);
for (int i = 0; i < PREV_SPLIT_FACTOR; i++) {
Revision low = Revision.newRevision(clusterId);
Revision high = Revision.newRevision(clusterId);
@@ -669,7 +668,7 @@ public class DocumentSplitTest extends B
NodeDocument doc = new NodeDocument(mk.getDocumentStore());
doc.put(NodeDocument.ID, Utils.getIdFromPath("/test"));
doc.put(NodeDocument.SD_TYPE, NodeDocument.SplitDocType.DEFAULT.type);
- Revision head = mk.getNodeStore().getHeadRevision();
+ RevisionVector head = mk.getNodeStore().getHeadRevision();
SplitOperations.forDocument(doc, DummyRevisionContext.INSTANCE, head, NUM_REVS_THRESHOLD);
}
@@ -780,7 +779,7 @@ public class DocumentSplitTest extends B
final DocumentStore store = mk.getDocumentStore();
final DocumentNodeStore ns = mk.getNodeStore();
final List<Exception> exceptions = Lists.newArrayList();
- final List<Revision> revisions = Lists.newArrayList();
+ final List<RevisionVector> revisions = Lists.newArrayList();
Thread t = new Thread(new Runnable() {
@Override
@@ -811,7 +810,7 @@ public class DocumentSplitTest extends B
RevisionContext rc = new TestRevisionContext(ns);
while (t.isAlive()) {
for (String id : ns.getSplitCandidates()) {
- Revision head = ns.getHeadRevision();
+ RevisionVector head = ns.getHeadRevision();
NodeDocument doc = store.find(NODES, id);
List<UpdateOp> ops = SplitOperations.forDocument(doc, rc, head, NUM_REVS_THRESHOLD);
Set<Revision> removed = Sets.newHashSet();
@@ -842,7 +841,10 @@ public class DocumentSplitTest extends B
if (doc.isSplitDocument() || Utils.getDepthFromId(doc.getId()) < 2) {
continue;
}
- Set<Revision> revs = Sets.newHashSet(revisions);
+ Set<Revision> revs = Sets.newHashSet();
+ for (RevisionVector rv : revisions) {
+ Iterables.addAll(revs, rv);
+ }
revs.removeAll(doc.getValueMap("_deleted").keySet());
assertTrue("Missing _deleted entries on " + doc.getId() + ": " + revs, revs.isEmpty());
}
@@ -867,18 +869,13 @@ public class DocumentSplitTest extends B
}
@Override
- public Comparator<Revision> getRevisionComparator() {
- return rc.getRevisionComparator();
- }
-
- @Override
public int getClusterId() {
return rc.getClusterId();
}
@Nonnull
@Override
- public Revision getHeadRevision() {
+ public RevisionVector getHeadRevision() {
try {
Thread.sleep((long) (Math.random() * 100));
} catch (InterruptedException e) {
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DummyRevisionContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DummyRevisionContext.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DummyRevisionContext.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DummyRevisionContext.java Thu Jan 7 12:46:35 2016
@@ -16,8 +16,6 @@
*/
package org.apache.jackrabbit.oak.plugins.document;
-import java.util.Comparator;
-
import javax.annotation.Nonnull;
/**
@@ -27,12 +25,9 @@ public class DummyRevisionContext implem
static final RevisionContext INSTANCE = new DummyRevisionContext();
- private final Comparator<Revision> comparator
- = StableRevisionComparator.INSTANCE;
-
@Override
public UnmergedBranches getBranches() {
- return new UnmergedBranches(comparator);
+ return new UnmergedBranches();
}
@Override
@@ -41,24 +36,19 @@ public class DummyRevisionContext implem
}
@Override
- public Comparator<Revision> getRevisionComparator() {
- return comparator;
- }
-
- @Override
public int getClusterId() {
return 1;
}
@Nonnull
@Override
- public Revision getHeadRevision() {
- return Revision.newRevision(1);
+ public RevisionVector getHeadRevision() {
+ return new RevisionVector(Revision.newRevision(getClusterId()));
}
@Nonnull
@Override
public Revision newRevision() {
- return Revision.newRevision(1);
+ return Revision.newRevision(getClusterId());
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalEntryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalEntryTest.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalEntryTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalEntryTest.java Thu Jan 7 12:46:35 2016
@@ -53,8 +53,8 @@ public class JournalEntryTest {
addRandomPaths(paths);
StringSort sort = JournalEntry.newSorter();
add(sort, paths);
- Revision from = new Revision(1, 0, 1);
- Revision to = new Revision(2, 0, 1);
+ RevisionVector from = new RevisionVector(new Revision(1, 0, 1));
+ RevisionVector to = new RevisionVector(new Revision(2, 0, 1));
sort.sort();
JournalEntry.applyTo(sort, cache, from, to);
@@ -72,9 +72,9 @@ public class JournalEntryTest {
@Test
public void useParentDiff() throws Exception {
DiffCache cache = new MemoryDiffCache(new DocumentMK.Builder());
- Revision from = new Revision(1, 0, 1);
- Revision to = new Revision(2, 0, 1);
- Revision unjournalled = new Revision(3, 0, 1);
+ RevisionVector from = new RevisionVector(new Revision(1, 0, 1));
+ RevisionVector to = new RevisionVector(new Revision(2, 0, 1));
+ RevisionVector unjournalled = new RevisionVector(new Revision(3, 0, 1));
//Put one entry for (from, to, "/a/b")->["c1", "c2"] manually
DiffCache.Entry entry = cache.newEntry(from, to, false);
@@ -190,7 +190,11 @@ public class JournalEntryTest {
}
}
- private void validateCacheUsage(DiffCache cache, Revision from, Revision to, String path, boolean cacheExpected) {
+ private void validateCacheUsage(DiffCache cache,
+ RevisionVector from,
+ RevisionVector to,
+ String path,
+ boolean cacheExpected) {
String nonLoaderDiff = cache.getChanges(from, to, path, null);
final AtomicBoolean loaderCalled = new AtomicBoolean(false);
cache.getChanges(from, to, path, new DiffCache.Loader() {
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalTest.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalTest.java Thu Jan 7 12:46:35 2016
@@ -41,6 +41,7 @@ import org.junit.rules.TestRule;
import static java.util.Collections.synchronizedList;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -371,7 +372,7 @@ public class JournalTest extends Abstrac
Revision zlastRev2 = z1.getLastRev().get(c2Id);
// /x/y/z is a new node and does not have a _lastRev
assertNull(zlastRev2);
- Revision head2 = ds2.getHeadRevision();
+ Revision head2 = ds2.getHeadRevision().getRevision(ds2.getClusterId());
//lastRev should not be updated for C #2
assertNull(y1.getLastRev().get(c2Id));
@@ -458,7 +459,8 @@ public class JournalTest extends Abstrac
NodeBuilder b2 = ns2.getRoot().builder();
b2.child("bar");
ns2.merge(b2, EmptyHook.INSTANCE, CommitInfo.EMPTY);
- Revision h2 = ns2.getHeadRevision();
+ Revision h2 = ns2.getHeadRevision().getRevision(ns2.getClusterId());
+ assertNotNull(h2);
ns2.runBackgroundReadOperations();
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgentTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgentTest.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgentTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgentTest.java Thu Jan 7 12:46:35 2016
@@ -139,7 +139,7 @@ public class LastRevRecoveryAgentTest {
b2.child("x").child("y").child("z").setProperty("foo", "bar");
ds2.merge(b2, EmptyHook.INSTANCE, CommitInfo.EMPTY);
- Revision zlastRev2 = ds2.getHeadRevision();
+ Revision zlastRev2 = ds2.getHeadRevision().getRevision(ds2.getClusterId());
long leaseTime = ds1.getClusterInfo().getLeaseTime();
ds1.runBackgroundOperations();
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryTest.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryTest.java Thu Jan 7 12:46:35 2016
@@ -122,7 +122,7 @@ public class LastRevRecoveryTest {
Revision zlastRev2 = z1.getLastRev().get(c2Id);
// /x/y/z is a new node and does not have a _lastRev
assertNull(zlastRev2);
- Revision head2 = ds2.getHeadRevision();
+ Revision head2 = ds2.getHeadRevision().getRevision(c2Id);
//lastRev should not be updated for C #2
assertNull(y1.getLastRev().get(c2Id));
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MeasureMemory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MeasureMemory.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MeasureMemory.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MeasureMemory.java Thu Jan 7 12:46:35 2016
@@ -167,12 +167,50 @@ public class MeasureMemory {
@Override
public Object[] call() {
RevisionsKey k = new RevisionsKey(
- Revision.newRevision(0), Revision.newRevision(0));
+ new RevisionVector(Revision.newRevision(0)),
+ new RevisionVector(Revision.newRevision(0)));
return new Object[]{k, k.getMemory() + OVERHEAD};
}
});
}
+ @Test
+ public void revisionVector() throws Exception {
+ measureMemory(new Callable<Object[]>() {
+ @Override
+ public Object[] call() throws Exception {
+ RevisionVector rv = new RevisionVector(
+ Revision.newRevision(0),
+ Revision.newRevision(1),
+ Revision.newRevision(2),
+ Revision.newRevision(3));
+ return new Object[]{rv, rv.getMemory() + OVERHEAD};
+ }
+ });
+ }
+
+ @Test
+ public void revisionVectorSingle() throws Exception {
+ measureMemory(new Callable<Object[]>() {
+ @Override
+ public Object[] call() throws Exception {
+ RevisionVector rv = new RevisionVector(Revision.newRevision(0));
+ return new Object[]{rv, rv.getMemory() + OVERHEAD};
+ }
+ });
+ }
+
+ @Test
+ public void revision() throws Exception {
+ measureMemory(new Callable<Object[]>() {
+ @Override
+ public Object[] call() throws Exception {
+ Revision r = Revision.newRevision(0);
+ return new Object[]{r, r.getMemory() + OVERHEAD};
+ }
+ });
+ }
+
private static void measureMemory(Callable<Object[]> c) throws Exception {
LinkedList<Object> list = new LinkedList<Object>();
long base = getMemoryUsed();
@@ -201,11 +239,11 @@ public class MeasureMemory {
static DocumentNodeState generateNode(int propertyCount) {
DocumentNodeState n = new DocumentNodeState(STORE, new String("/hello/world"),
- new Revision(1, 2, 3));
+ new RevisionVector(new Revision(1, 2, 3)));
for (int i = 0; i < propertyCount; i++) {
n.setProperty("property" + i, "\"values " + i + "\"");
}
- n.setLastRevision(new Revision(1, 2, 3));
+ n.setLastRevision(new RevisionVector(new Revision(1, 2, 3)));
return n;
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MongoDocumentStoreTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MongoDocumentStoreTest.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MongoDocumentStoreTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MongoDocumentStoreTest.java Thu Jan 7 12:46:35 2016
@@ -228,8 +228,9 @@ public class MongoDocumentStoreTest {
Revision rev = Revision.newRevision(0);
List<UpdateOp> inserts = new ArrayList<UpdateOp>();
for (int i = 0; i < DocumentMK.MANY_CHILDREN_THRESHOLD * 2; i++) {
- DocumentNodeState n = new DocumentNodeState(store, "/node-" + i, rev);
- inserts.add(n.asOperation(true));
+ DocumentNodeState n = new DocumentNodeState(store, "/node-" + i,
+ new RevisionVector(rev));
+ inserts.add(n.asOperation(rev));
}
docStore.create(Collection.NODES, inserts);
List<NodeDocument> docs = docStore.query(Collection.NODES,
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/NodeDocumentTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/NodeDocumentTest.java?rev=1723532&r1=1723531&r2=1723532&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/NodeDocumentTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/NodeDocumentTest.java Thu Jan 7 12:46:35 2016
@@ -17,7 +17,6 @@
package org.apache.jackrabbit.oak.plugins.document;
import java.util.Collections;
-import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -28,7 +27,6 @@ import java.util.Set;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats;
@@ -40,10 +38,9 @@ import org.apache.jackrabbit.oak.spi.sta
import org.apache.jackrabbit.oak.spi.state.NodeStore;
import org.junit.Test;
+import static com.google.common.collect.Sets.newHashSet;
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.NodeDocument.revisionAreAmbiguous;
-import static org.apache.jackrabbit.oak.plugins.document.Revision.RevisionComparator;
import static org.apache.jackrabbit.oak.plugins.document.util.Utils.getRootDocument;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -70,58 +67,20 @@ public class NodeDocumentTest {
NodeDocument.addCollision(op, r, Revision.newRevision(1));
}
UpdateUtils.applyChanges(doc, op);
- Revision head = DummyRevisionContext.INSTANCE.getHeadRevision();
+ RevisionVector head = DummyRevisionContext.INSTANCE.getHeadRevision();
doc.split(DummyRevisionContext.INSTANCE, head);
}
@Test
- public void ambiguousRevisions() {
- // revisions from same cluster node are not ambiguous
- RevisionContext context = DummyRevisionContext.INSTANCE;
- Revision r1 = new Revision(1, 0, 1);
- Revision r2 = new Revision(2, 0, 1);
- assertFalse(revisionAreAmbiguous(context, r1, r1));
- assertFalse(revisionAreAmbiguous(context, r1, r2));
- assertFalse(revisionAreAmbiguous(context, r2, r1));
-
- // revisions from different cluster nodes are not ambiguous
- // if seen with stable revision comparator
- r1 = new Revision(1, 0, 2);
- r2 = new Revision(2, 0, 1);
- assertFalse(revisionAreAmbiguous(context, r1, r1));
- assertFalse(revisionAreAmbiguous(context, r1, r2));
- assertFalse(revisionAreAmbiguous(context, r2, r1));
-
- // now use a revision comparator with seen-at support
- final RevisionComparator comparator = new RevisionComparator(1);
- context = new DummyRevisionContext() {
- @Override
- public Comparator<Revision> getRevisionComparator() {
- return comparator;
- }
- };
- r1 = new Revision(1, 0, 2);
- r2 = new Revision(2, 0, 1);
- // add revision to comparator in reverse time order
- comparator.add(r2, new Revision(2, 0, 0));
- comparator.add(r1, new Revision(3, 0, 0)); // r1 seen after r2
- assertFalse(revisionAreAmbiguous(context, r1, r1));
- assertFalse(revisionAreAmbiguous(context, r2, r2));
- assertTrue(revisionAreAmbiguous(context, r1, r2));
- assertTrue(revisionAreAmbiguous(context, r2, r1));
- }
-
- @Test
- public void getMostRecentConflictFor() {
- RevisionContext context = DummyRevisionContext.INSTANCE;
+ public void getConflictsFor() {
MemoryDocumentStore docStore = new MemoryDocumentStore();
String id = Utils.getPathFromId("/");
NodeDocument doc = new NodeDocument(docStore);
doc.put(Document.ID, id);
Iterable<Revision> branchCommits = Collections.emptyList();
- Revision conflict = doc.getMostRecentConflictFor(branchCommits, context);
- assertNull(conflict);
+ Set<Revision> conflicts = doc.getConflictsFor(branchCommits);
+ assertTrue(conflicts.isEmpty());
// add some collisions
UpdateOp op = new UpdateOp(id, false);
@@ -138,24 +97,24 @@ public class NodeDocumentTest {
UpdateUtils.applyChanges(doc, op);
branchCommits = Collections.singleton(r0);
- conflict = doc.getMostRecentConflictFor(branchCommits, context);
- assertNull(conflict);
+ conflicts = doc.getConflictsFor(branchCommits);
+ assertTrue(conflicts.isEmpty());
branchCommits = Collections.singleton(r1.asBranchRevision());
- conflict = doc.getMostRecentConflictFor(branchCommits, context);
- assertEquals(c1, conflict);
+ conflicts = doc.getConflictsFor(branchCommits);
+ assertEquals(newHashSet(c1), conflicts);
branchCommits = Collections.singleton(r2.asBranchRevision());
- conflict = doc.getMostRecentConflictFor(branchCommits, context);
- assertEquals(c2, conflict);
+ conflicts = doc.getConflictsFor(branchCommits);
+ assertEquals(newHashSet(c2), conflicts);
branchCommits = Lists.newArrayList(r1.asBranchRevision(), r2.asBranchRevision());
- conflict = doc.getMostRecentConflictFor(branchCommits, context);
- assertEquals(c2, conflict);
+ conflicts = doc.getConflictsFor(branchCommits);
+ assertEquals(newHashSet(c1, c2), conflicts);
branchCommits = Lists.newArrayList(r2.asBranchRevision(), r1.asBranchRevision());
- conflict = doc.getMostRecentConflictFor(branchCommits, context);
- assertEquals(c2, conflict);
+ conflicts = doc.getConflictsFor(branchCommits);
+ assertEquals(newHashSet(c1, c2), conflicts);
}
@Test
@@ -240,7 +199,7 @@ public class NodeDocumentTest {
builder.setProperty("p-" + clusterIdx, i);
merge(ns, builder);
if (r.nextFloat() < 0.2) {
- Revision head = ns.getHeadRevision();
+ RevisionVector head = ns.getHeadRevision();
for (UpdateOp op : SplitOperations.forDocument(
getRootDocument(store), ns, head, 2)) {
store.createOrUpdate(NODES, op);
@@ -328,7 +287,7 @@ public class NodeDocumentTest {
@Test
public void getNewestRevisionTooExpensive() throws Exception {
final int NUM_CHANGES = 200;
- final Set<String> prevDocCalls = Sets.newHashSet();
+ final Set<String> prevDocCalls = newHashSet();
DocumentStore store = new MemoryDocumentStore() {
@Override
public <T extends Document> T find(Collection<T> collection,
@@ -354,7 +313,7 @@ public class NodeDocumentTest {
}
merge(ns, builder);
if (Math.random() < 0.2) {
- Revision head = ns.getHeadRevision();
+ RevisionVector head = ns.getHeadRevision();
NodeDocument doc = ns.getDocumentStore().find(
NODES, Utils.getIdFromPath("/test"));
for (UpdateOp op : SplitOperations.forDocument(
@@ -374,7 +333,8 @@ public class NodeDocumentTest {
Revision changeRev = new Revision(baseRev.getTimestamp(), 1000, ns.getClusterId());
// reset calls to previous documents
prevDocCalls.clear();
- doc.getNewestRevision(ns, baseRev, changeRev, null, new HashSet<Revision>());
+ doc.getNewestRevision(ns, new RevisionVector(baseRev), changeRev,
+ null, new HashSet<Revision>());
// must not read all previous docs
assertTrue("too many calls for previous documents: " + prevDocCalls,
prevDocCalls.size() <= 5);
@@ -391,10 +351,11 @@ public class NodeDocumentTest {
NodeBuilder b1 = ns1.getRoot().builder();
b1.child("test");
merge(ns1, b1);
- Revision created = ns1.getHeadRevision();
+ RevisionVector headCreated = ns1.getHeadRevision();
+ Revision created = headCreated.getRevision(ns1.getClusterId());
NodeDocument doc = store.find(NODES, Utils.getIdFromPath("/test"));
- Set<Revision> collisions = Sets.newHashSet();
+ Set<Revision> collisions = newHashSet();
Revision newest = doc.getNewestRevision(ns1, ns1.getHeadRevision(),
ns1.newRevision(), null, collisions);
assertEquals(created, newest);
@@ -444,14 +405,14 @@ public class NodeDocumentTest {
b1 = ns1.getRoot().builder();
b1.child("test").setProperty("q", "v");
merge(ns1, b1);
- Revision committed = ns1.getHeadRevision();
+ Revision committed = ns1.getHeadRevision().getRevision(ns1.getClusterId());
collisions.clear();
// ns1 must now report committed revision as newest
// uncommitted is not considered a collision anymore
// because it is older than the base revision
doc = store.find(NODES, Utils.getIdFromPath("/test"));
- newest = doc.getNewestRevision(ns1, created,
+ newest = doc.getNewestRevision(ns1, headCreated,
ns1.newRevision(), null, collisions);
assertEquals(committed, newest);
assertEquals(0, collisions.size());
@@ -479,9 +440,9 @@ public class NodeDocumentTest {
builder.child("test");
merge(ns, builder);
- Set<Revision> collisions = Sets.newHashSet();
+ Set<Revision> collisions = newHashSet();
NodeDocument doc = store.find(NODES, Utils.getIdFromPath("/test"));
- Revision branchBase = ns.getHeadRevision().asBranchRevision();
+ RevisionVector branchBase = ns.getHeadRevision().asBranchRevision(ns.getClusterId());
try {
doc.getNewestRevision(ns, branchBase, ns.newRevision(), null, collisions);
fail("Must fail with IllegalArgumentException");
@@ -489,7 +450,7 @@ public class NodeDocumentTest {
// expected
}
try {
- Revision head = ns.getHeadRevision();
+ RevisionVector head = ns.getHeadRevision();
Branch b = ns.getBranches().create(head, ns.newRevision(), null);
doc.getNewestRevision(ns, head, ns.newRevision(), b, collisions);
fail("Must fail with IllegalArgumentException");
@@ -510,7 +471,7 @@ public class NodeDocumentTest {
for (int i = 0; i < 10; i++) {
int idx = random.nextInt(numChanges);
Revision r = Iterables.get(doc.getValueMap("p").keySet(), idx);
- Iterable<Revision> revs = doc.getChanges("p", r, ns);
+ Iterable<Revision> revs = doc.getChanges("p", new RevisionVector(r));
assertEquals(idx, Iterables.size(revs));
}
ns.dispose();
@@ -525,15 +486,17 @@ public class NodeDocumentTest {
DocumentNodeStore ns2 = createTestStore(store, 2, 0);
List<DocumentNodeStore> nodeStores = Lists.newArrayList(ns1, ns2);
+ List<RevisionVector> headRevisions = Lists.newArrayList();
for (int i = 0; i < numChanges; i++) {
DocumentNodeStore ns = nodeStores.get(random.nextInt(nodeStores.size()));
ns.runBackgroundOperations();
NodeBuilder builder = ns.getRoot().builder();
builder.setProperty("p", i);
merge(ns, builder);
+ headRevisions.add(ns.getHeadRevision());
ns.runBackgroundOperations();
if (random.nextDouble() < 0.2) {
- Revision head = ns.getHeadRevision();
+ RevisionVector head = ns.getHeadRevision();
for (UpdateOp op : SplitOperations.forDocument(
getRootDocument(store), ns, head, 2)) {
store.createOrUpdate(NODES, op);
@@ -541,12 +504,13 @@ public class NodeDocumentTest {
}
}
+ headRevisions = Lists.reverse(headRevisions);
NodeDocument doc = getRootDocument(store);
for (int i = 0; i < 10; i++) {
int idx = random.nextInt(numChanges);
- Revision r = Iterables.get(doc.getValueMap("p").keySet(), idx);
- Iterable<Revision> revs1 = doc.getChanges("p", r, ns1);
- Iterable<Revision> revs2 = doc.getChanges("p", r, ns2);
+ RevisionVector r = headRevisions.get(idx);
+ Iterable<Revision> revs1 = doc.getChanges("p", r);
+ Iterable<Revision> revs2 = doc.getChanges("p", r);
assertEquals(Iterables.size(revs1), Iterables.size(revs2));
assertEquals(idx, Iterables.size(revs1));
}
@@ -559,7 +523,7 @@ public class NodeDocumentTest {
@Test
public void isConflicting() throws Exception {
final int numChanges = 200;
- final Set<String> prevDocCalls = Sets.newHashSet();
+ final Set<String> prevDocCalls = newHashSet();
MemoryDocumentStore store = new MemoryDocumentStore() {
@Override
public <T extends Document> T find(Collection<T> collection,
@@ -574,13 +538,13 @@ public class NodeDocumentTest {
NodeDocument doc = getRootDocument(store);
Map<Revision, String> valueMap = doc.getValueMap("p");
assertEquals(200, valueMap.size());
- Revision baseRev = valueMap.keySet().iterator().next();
+ RevisionVector baseRev = new RevisionVector(valueMap.keySet().iterator().next());
Revision commitRev = ns.newRevision();
UpdateOp op = new UpdateOp(Utils.getIdFromPath("/"), false);
op.setMapEntry("p", commitRev, "v");
prevDocCalls.clear();
- assertFalse(doc.isConflicting(op, baseRev, commitRev, ns, false));
+ assertFalse(doc.isConflicting(op, baseRev, commitRev, false));
assertTrue("too many calls for previous documents: " + prevDocCalls,
prevDocCalls.size() <= 6);
ns.dispose();
@@ -601,7 +565,7 @@ public class NodeDocumentTest {
builder.setProperty("p", i);
merge(ns, builder);
if (Math.random() < 0.2) {
- Revision head = ns.getHeadRevision();
+ RevisionVector head = ns.getHeadRevision();
for (UpdateOp op : SplitOperations.forDocument(
getRootDocument(store), ns, head, 2)) {
store.createOrUpdate(NODES, op);