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/10/29 23:21:13 UTC
svn commit: r1635315 - in /jackrabbit/oak/branches/1.0: ./
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/
oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/
oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/
Author: mreutegg
Date: Wed Oct 29 22:21:12 2014
New Revision: 1635315
URL: http://svn.apache.org/r1635315
Log:
OAK-2232: External events incomplete
Merged revisions 1634841,1635077,1635218 from trunk
Added:
jackrabbit/oak/branches/1.0/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/ObservationTest.java
- copied, changed from r1634841, jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/ObservationTest.java
Modified:
jackrabbit/oak/branches/1.0/ (props changed)
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoDocument.java
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Revision.java
jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/RevisionTest.java
jackrabbit/oak/branches/1.0/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/AbstractClusterTest.java
Propchange: jackrabbit/oak/branches/1.0/
------------------------------------------------------------------------------
Merged /jackrabbit/oak/trunk:r1634841,1635077,1635218
Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java?rev=1635315&r1=1635314&r2=1635315&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java Wed Oct 29 22:21:12 2014
@@ -301,10 +301,7 @@ public class ClusterNodeInfo {
private static ClusterNodeInfo createInstance(DocumentStore store, String machineId,
String instanceId) {
long now = getCurrentTime();
- // keys between "0" and "a" includes all possible numbers
- List<ClusterNodeInfoDocument> list = store.query(Collection.CLUSTER_NODES,
- ClusterNodeInfoDocument.MIN_ID_VALUE, ClusterNodeInfoDocument.MAX_ID_VALUE,
- Integer.MAX_VALUE);
+ List<ClusterNodeInfoDocument> list = ClusterNodeInfoDocument.all(store);
int clusterNodeId = 0;
int maxId = 0;
ClusterNodeState state = ClusterNodeState.NONE;
@@ -365,11 +362,13 @@ public class ClusterNodeInfo {
* to ensure the same cluster id is not re-used by a different instance.
* The lease is only renewed when half of the lease time passed. That is,
* with a lease time of 60 seconds, the lease is renewed every 30 seconds.
+ *
+ * @return {@code true} if the lease was renewed; {@code false} otherwise.
*/
- public void renewLease() {
+ public boolean renewLease() {
long now = getCurrentTime();
if (now + leaseTime / 2 < leaseEndTime) {
- return;
+ return false;
}
UpdateOp update = new UpdateOp("" + id, true);
leaseEndTime = now + leaseTime;
@@ -381,6 +380,7 @@ public class ClusterNodeInfo {
readWriteMode = mode;
store.setReadWriteMode(mode);
}
+ return true;
}
public void setLeaseTime(long leaseTime) {
Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoDocument.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoDocument.java?rev=1635315&r1=1635314&r2=1635315&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoDocument.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoDocument.java Wed Oct 29 22:21:12 2014
@@ -16,6 +16,8 @@
*/
package org.apache.jackrabbit.oak.plugins.document;
+import java.util.List;
+
import static com.google.common.base.Preconditions.checkNotNull;
import static org.apache.jackrabbit.oak.plugins.document.ClusterNodeInfo.ClusterNodeState;
import static org.apache.jackrabbit.oak.plugins.document.ClusterNodeInfo.RecoverLockState;
@@ -29,13 +31,13 @@ public class ClusterNodeInfoDocument ext
* All ClusterNodeInfoDocument ID value would be greater than this value
* It can be used as startKey in DocumentStore#query methods
*/
- public static final String MIN_ID_VALUE = "0";
+ private static final String MIN_ID_VALUE = "0";
/**
* All ClusterNodeInfoDocument ID value would be less than this value
* It can be used as endKey in DocumentStore#query methods
*/
- public static final String MAX_ID_VALUE = "a";
+ private static final String MAX_ID_VALUE = "a";
public long getLeaseEndTime(){
return checkNotNull((Long) get(ClusterNodeInfo.LEASE_END_KEY), "Lease End Time not set");
@@ -49,6 +51,25 @@ public class ClusterNodeInfoDocument ext
return getRecoveryState() == RecoverLockState.ACQUIRED;
}
+ public int getClusterId() {
+ return Integer.parseInt(getId());
+ }
+
+ /**
+ * Returns all cluster node info documents currently available in the given
+ * document store.
+ *
+ * @param store the document store.
+ * @return list of cluster node info documents.
+ */
+ public static List<ClusterNodeInfoDocument> all(DocumentStore store) {
+ // keys between "0" and "a" includes all possible numbers
+ return store.query(Collection.CLUSTER_NODES,
+ MIN_ID_VALUE, MAX_ID_VALUE, Integer.MAX_VALUE);
+ }
+
+ //-----------------------< internal >---------------------------------------
+
private ClusterNodeState getState(){
return ClusterNodeState.fromString((String) get(ClusterNodeInfo.STATE));
}
Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java?rev=1635315&r1=1635314&r2=1635315&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java Wed Oct 29 22:21:12 2014
@@ -30,6 +30,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -37,6 +38,7 @@ import java.util.NavigableSet;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -175,6 +177,14 @@ public final class DocumentNodeStore
private final int clusterId;
/**
+ * Map of inactive cluster nodes and when the cluster node was last seen
+ * as inactive.
+ * Key: clusterId, value: timeInMillis
+ */
+ private final ConcurrentMap<Integer, Long> inactiveClusterNodes
+ = new ConcurrentHashMap<Integer, Long>();
+
+ /**
* The comparator for revisions.
*/
private final Revision.RevisionComparator revisionComparator;
@@ -1432,11 +1442,42 @@ public final class DocumentNodeStore
}
}
- void renewClusterIdLease() {
- if (clusterNodeInfo == null) {
- return;
+ /**
+ * Renews the cluster lease if necessary.
+ *
+ * @return {@code true} if the lease was renewed; {@code false} otherwise.
+ */
+ boolean renewClusterIdLease() {
+ return clusterNodeInfo != null && clusterNodeInfo.renewLease();
+ }
+
+ /**
+ * Updates the info about inactive cluster nodes in
+ * {@link #inactiveClusterNodes}.
+ */
+ void updateClusterState() {
+ long now = clock.getTime();
+ Set<Integer> inactive = Sets.newHashSet();
+ for (ClusterNodeInfoDocument doc : ClusterNodeInfoDocument.all(store)) {
+ int cId = doc.getClusterId();
+ if (cId != this.clusterId && !doc.isActive()) {
+ inactive.add(cId);
+ }
+ }
+ inactiveClusterNodes.keySet().retainAll(inactive);
+ for (Integer clusterId : inactive) {
+ inactiveClusterNodes.putIfAbsent(clusterId, now);
}
- clusterNodeInfo.renewLease();
+ }
+
+ /**
+ * Returns the cluster nodes currently known to be inactive.
+ *
+ * @return a map with the cluster id as key and the time in millis when it
+ * was first seen inactive.
+ */
+ Map<Integer, Long> getInactiveClusterNodes() {
+ return new HashMap<Integer, Long>(inactiveClusterNodes);
}
/**
@@ -1600,7 +1641,9 @@ public final class DocumentNodeStore
}
private void diffManyChildren(JsopWriter w, String path, Revision fromRev, Revision toRev) {
- long minTimestamp = Math.min(fromRev.getTimestamp(), toRev.getTimestamp());
+ long minTimestamp = Math.min(
+ revisionComparator.getMinimumTimestamp(fromRev, inactiveClusterNodes),
+ revisionComparator.getMinimumTimestamp(toRev, inactiveClusterNodes));
long minValue = NodeDocument.getModifiedInSecs(minTimestamp);
String fromKey = Utils.getKeyLowerLimit(path);
String toKey = Utils.getKeyUpperLimit(path);
@@ -1836,7 +1879,9 @@ public final class DocumentNodeStore
@Override
protected void execute(@Nonnull DocumentNodeStore nodeStore) {
- nodeStore.renewClusterIdLease();
+ if (nodeStore.renewClusterIdLease()) {
+ nodeStore.updateClusterState();
+ }
}
}
Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java?rev=1635315&r1=1635314&r2=1635315&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java Wed Oct 29 22:21:12 2014
@@ -45,8 +45,7 @@ public class MissingLastRevSeeker {
* @return the clusters
*/
public Iterable<ClusterNodeInfoDocument> getAllClusters() {
- return store.query(Collection.CLUSTER_NODES, ClusterNodeInfoDocument.MIN_ID_VALUE,
- ClusterNodeInfoDocument.MAX_ID_VALUE, Integer.MAX_VALUE);
+ return ClusterNodeInfoDocument.all(store);
}
/**
Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Revision.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Revision.java?rev=1635315&r1=1635314&r2=1635315&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Revision.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Revision.java Wed Oct 29 22:21:12 2014
@@ -19,10 +19,13 @@ package org.apache.jackrabbit.oak.plugin
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
+import java.util.Map;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import javax.annotation.Nonnull;
+
import org.apache.jackrabbit.oak.plugins.document.util.Utils;
import org.apache.jackrabbit.oak.stats.Clock;
@@ -534,6 +537,47 @@ public class Revision {
}
}
+ /**
+ * Returns the minimum timestamp of the most recent revisions from all
+ * active cluster nodes as seen from the given {@code revision}.
+ *
+ * @param revision a revision.
+ * @param inactive map of cluster nodes considered inactive.
+ * @return the minimum timestamp.
+ */
+ public long getMinimumTimestamp(@Nonnull Revision revision,
+ @Nonnull Map<Integer, Long> inactive) {
+ long timestamp = checkNotNull(revision).getTimestamp();
+ Revision seenAt = getRevisionSeen(revision);
+ if (seenAt == null) {
+ // already purged
+ return timestamp;
+ }
+ // go through all known cluster nodes
+ for (List<RevisionRange> list : map.values()) {
+ RevisionRange range;
+ for (int i = list.size() - 1; i >= 0; i--) {
+ range = list.get(i);
+ if (range.seenAt.compareRevisionTimeThenClusterId(seenAt) <= 0) {
+ // found newest range older or equal the given seenAt
+ // check if the cluster node is still active
+ Long inactiveSince = inactive.get(range.revision.getClusterId());
+ if (inactiveSince != null
+ && revision.getTimestamp() > inactiveSince
+ && range.revision.getTimestamp() < inactiveSince) {
+ // ignore, because the revision is after the
+ // cluster node became inactive and the most recent
+ // range is before it became inactive
+ } else {
+ timestamp = Math.min(timestamp, range.revision.getTimestamp());
+ }
+ break;
+ }
+ }
+ }
+ return timestamp;
+ }
+
@Override
public int compare(Revision o1, Revision o2) {
if (o1.getClusterId() == o2.getClusterId()) {
Modified: jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java?rev=1635315&r1=1635314&r2=1635315&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java Wed Oct 29 22:21:12 2014
@@ -526,6 +526,98 @@ public class DocumentNodeStoreTest {
assertEquals("value", state.getProperty("prop").getValue(Type.STRING));
}
+ // OAK-2232
+ @Test
+ public void diffExternalChanges() throws Exception {
+ long modifiedResMillis = SECONDS.toMillis(MODIFIED_IN_SECS_RESOLUTION);
+ Clock clock = new Clock.Virtual();
+ clock.waitUntil(System.currentTimeMillis());
+ Revision.setClock(clock);
+
+ DocumentStore docStore = new MemoryDocumentStore();
+ DocumentNodeStore ns1 = new DocumentMK.Builder().setAsyncDelay(0)
+ .clock(clock).setDocumentStore(docStore).setClusterId(1)
+ .getNodeStore();
+ DocumentNodeStore ns2 = new DocumentMK.Builder().setAsyncDelay(0)
+ .clock(clock).setDocumentStore(docStore).setClusterId(2)
+ .getNodeStore();
+
+ NodeBuilder builder = ns1.getRoot().builder();
+ NodeBuilder test = builder.child("test");
+ for (int i = 0; i < DocumentMK.MANY_CHILDREN_THRESHOLD * 2; i++) {
+ test.child("node-" + i);
+ }
+ ns1.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+ ns1.runBackgroundOperations();
+ ns2.runBackgroundOperations();
+
+ // make sure next change has a different _modified value
+ clock.waitUntil(clock.getTime() + modifiedResMillis * 2);
+
+ builder = ns2.getRoot().builder();
+ builder.child("test").child("foo");
+ ns2.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+ // 'wait' again for a different _modified value
+ clock.waitUntil(clock.getTime() + modifiedResMillis * 2);
+
+ builder = ns1.getRoot().builder();
+ builder.child("test").child("bar");
+ ns1.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+ // remember current root for diff
+ NodeState r1 = ns1.getRoot();
+
+ ns2.runBackgroundOperations();
+ ns1.runBackgroundOperations();
+
+ NodeState r2 = ns1.getRoot();
+
+ // are we able to see foo?
+ boolean found = false;
+ for (ChildNodeEntry entry : r2.getChildNode("test").getChildNodeEntries()) {
+ if (entry.getName().equals("foo")) {
+ found = true;
+ break;
+ }
+ }
+ assertTrue(found);
+
+ // diff must report '/test' modified and '/test/foo' added
+ ClusterTest.TrackingDiff diff = new ClusterTest.TrackingDiff();
+ r2.compareAgainstBaseState(r1, diff);
+ assertEquals(1, diff.modified.size());
+ assertTrue(diff.modified.contains("/test"));
+ assertEquals(1, diff.added.size());
+ assertTrue(diff.added.contains("/test/foo"));
+
+ ns1.dispose();
+ ns2.dispose();
+ }
+
+ @Test
+ public void updateClusterState() {
+ DocumentStore docStore = new MemoryDocumentStore();
+ DocumentNodeStore ns1 = new DocumentMK.Builder().setAsyncDelay(0)
+ .setDocumentStore(docStore).getNodeStore();
+ DocumentNodeStore ns2 = new DocumentMK.Builder().setAsyncDelay(0)
+ .setDocumentStore(docStore).getNodeStore();
+
+ assertEquals(0, ns1.getInactiveClusterNodes().size());
+ assertEquals(0, ns2.getInactiveClusterNodes().size());
+
+ ns1.dispose();
+
+ ns2.updateClusterState();
+
+ Map<Integer, Long> inactive = ns2.getInactiveClusterNodes();
+ assertEquals(1, inactive.size());
+ assertEquals(1, (int) inactive.keySet().iterator().next());
+
+ ns2.dispose();
+ }
+
private static class TestHook extends EditorHook {
TestHook(final String prefix) {
Modified: jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/RevisionTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/RevisionTest.java?rev=1635315&r1=1635314&r2=1635315&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/RevisionTest.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/RevisionTest.java Wed Oct 29 22:21:12 2014
@@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
@@ -33,6 +34,7 @@ import static org.junit.Assert.assertTru
import static org.junit.Assert.fail;
import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import com.google.common.collect.Queues;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.Uninterruptibles;
@@ -455,4 +457,43 @@ public class RevisionTest {
assertTrue(String.format("Duplicate rev seen %s %n Seen %s", duplicates, seenRevs), duplicates.isEmpty());
}
+ @Test
+ public void getMinimumTimestamp() {
+ Map<Integer, Long> inactive = Maps.newHashMap();
+ RevisionComparator comp = new RevisionComparator(1);
+
+ Revision r11 = new Revision(1, 0, 1);
+ comp.add(r11, new Revision(1, 0, 0));
+
+ assertEquals(1, comp.getMinimumTimestamp(r11, inactive));
+
+ Revision r21 = new Revision(1, 0, 2);
+ comp.add(r21, new Revision(2, 0, 0));
+
+ assertEquals(1, comp.getMinimumTimestamp(r21, inactive));
+
+ Revision r13 = new Revision(3, 0, 1);
+ comp.add(r13, new Revision(3, 0, 0));
+
+ assertEquals(1, comp.getMinimumTimestamp(r13, inactive));
+
+ Revision r24 = new Revision(4, 0, 2);
+ comp.add(r24, new Revision(4, 0, 0));
+
+ assertEquals(3, comp.getMinimumTimestamp(r24, inactive));
+
+ Revision r15 = new Revision(5, 0, 1);
+ comp.add(r15, new Revision(5, 0, 0));
+
+ assertEquals(4, comp.getMinimumTimestamp(r15, inactive));
+
+ // simulate cluster node 2 is stopped
+ inactive.put(2, 6L);
+
+ Revision r17 = new Revision(7, 0, 1);
+ comp.add(r17, new Revision(7, 0, 0));
+
+ assertEquals(7, comp.getMinimumTimestamp(r17, inactive));
+ }
+
}
Modified: jackrabbit/oak/branches/1.0/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/AbstractClusterTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/AbstractClusterTest.java?rev=1635315&r1=1635314&r2=1635315&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/AbstractClusterTest.java (original)
+++ jackrabbit/oak/branches/1.0/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/AbstractClusterTest.java Wed Oct 29 22:21:12 2014
@@ -68,6 +68,9 @@ public class AbstractClusterTest {
}
}
+ protected void prepareTestData(Session s) throws RepositoryException {
+ }
+
@Before
public void login() throws RepositoryException {
ns1 = fixture.createNodeStore(1);
@@ -75,12 +78,13 @@ public class AbstractClusterTest {
return;
}
r1 = new Jcr(ns1).createRepository();
+ s1 = r1.login(new SimpleCredentials("admin", "admin".toCharArray()));
+ prepareTestData(s1);
if (ns1 instanceof DocumentNodeStore) {
// make sure initial repository data is visible to
// other cluster nodes initialized later
((DocumentNodeStore) ns1).runBackgroundOperations();
}
- s1 = r1.login(new SimpleCredentials("admin", "admin".toCharArray()));
ns2 = fixture.createNodeStore(2);
r2 = new Jcr(ns2).createRepository();
s2 = r2.login(new SimpleCredentials("admin", "admin".toCharArray()));
Copied: jackrabbit/oak/branches/1.0/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/ObservationTest.java (from r1634841, jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/ObservationTest.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/ObservationTest.java?p2=jackrabbit/oak/branches/1.0/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/ObservationTest.java&p1=jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/ObservationTest.java&r1=1634841&r2=1635315&rev=1635315&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/ObservationTest.java (original)
+++ jackrabbit/oak/branches/1.0/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/ObservationTest.java Wed Oct 29 22:21:12 2014
@@ -16,7 +16,11 @@
*/
package org.apache.jackrabbit.oak.jcr.cluster;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@@ -38,11 +42,16 @@ import org.junit.Ignore;
import org.junit.Test;
import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+import static java.util.Collections.synchronizedSet;
+import static org.junit.Assert.assertTrue;
/**
* Test for external events from another cluster node.
*/
-@Ignore
+@Ignore("This is a rather long running test and therefore disabled. See " +
+ "DocumentNodeStoreTest.diffExternalChanges() in oak-core for a unit test")
public class ObservationTest extends AbstractClusterTest {
private ScheduledExecutorService executor;
@@ -68,6 +77,7 @@ public class ObservationTest extends Abs
@Test
public void externalEvents() throws Throwable {
+ final Set<String> externallyAdded = synchronizedSet(new LinkedHashSet<String>());
final List<Throwable> exceptions = Lists.newArrayList();
ObservationManager obsMgr = s1.getWorkspace().getObservationManager();
final AtomicLong localEvents = new AtomicLong();
@@ -76,6 +86,7 @@ public class ObservationTest extends Abs
@Override
public void onEvent(EventIterator events) {
try {
+ Set<String> paths = Sets.newHashSet();
while (events.hasNext()) {
Event event = events.nextEvent();
String external = "";
@@ -84,12 +95,19 @@ public class ObservationTest extends Abs
if (((JackrabbitEvent) event).isExternal()) {
external = " (external)";
counter = externalEvents;
+ paths.add(event.getPath());
}
}
System.out.println(event.getPath() + external);
counter.incrementAndGet();
}
- } catch (RepositoryException e) {
+ while (!paths.isEmpty()) {
+ Iterator<String> it = externallyAdded.iterator();
+ String p = it.next();
+ assertTrue("missing event for " + p, paths.remove(p));
+ it.remove();
+ }
+ } catch (Throwable e) {
exceptions.add(e);
}
}
@@ -97,8 +115,8 @@ public class ObservationTest extends Abs
obsMgr.addEventListener(listener, Event.NODE_ADDED, "/",
true, null, null, false);
- Future f1 = executor.submit(new Worker(s1, exceptions));
- Future f2 = executor.submit(new Worker(s2, exceptions));
+ Future f1 = executor.submit(new Worker(s1, exceptions, new HashSet<String>()));
+ Future f2 = executor.submit(new Worker(s2, exceptions, externallyAdded));
f1.get();
f2.get();
@@ -117,18 +135,21 @@ public class ObservationTest extends Abs
private Session s;
private List<Throwable> exceptions;
+ private Set<String> paths;
- Worker(Session s, List<Throwable> exceptions) {
+ Worker(Session s, List<Throwable> exceptions, Set<String> paths) {
this.s = s;
this.exceptions = exceptions;
+ this.paths = paths;
}
@Override
public void run() {
try {
Node test = s.getNode("/test");
- for (int i = 0; i < 500; i++) {
- test.addNode(UUID.randomUUID().toString());
+ for (int i = 0; i < 500 && exceptions.isEmpty(); i++) {
+ Node n = test.addNode(UUID.randomUUID().toString());
+ paths.add(n.getPath());
s.save();
Thread.sleep((long) (Math.random() * 100));
}