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 ch...@apache.org on 2014/04/03 10:53:11 UTC
svn commit: r1584287 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/plugins/document/
main/java/org/apache/jackrabbit/oak/plugins/document/mongo/
test/java/org/apache/jackrabbit/oak/plugins/document/
Author: chetanm
Date: Thu Apr 3 08:53:10 2014
New Revision: 1584287
URL: http://svn.apache.org/r1584287
Log:
OAK-1295 - Recovery for missing _lastRev updates
-- Implemented the check for wether recovery is required by any node as Mongo query
-- Added a scheduled job for running the recovery check every 1 min by default
Also changed Clock handling by adding a resetToDefault method which resets the clock back to simple instead of doing that via passing null
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgentTest.java (with props)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgent.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Revision.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoMissingLastRevSeeker.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterInfoTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevSingleNodeRecoveryTest.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java?rev=1584287&r1=1584286&r2=1584287&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java Thu Apr 3 08:53:10 2014
@@ -16,6 +16,7 @@
*/
package org.apache.jackrabbit.oak.plugins.document;
+import static com.google.common.base.Preconditions.checkNotNull;
import static org.apache.jackrabbit.oak.plugins.document.Document.ID;
import java.lang.management.ManagementFactory;
@@ -58,7 +59,7 @@ public class ClusterNodeInfo {
/**
* The end of the lease.
*/
- protected static final String LEASE_END_KEY = "leaseEnd";
+ public static final String LEASE_END_KEY = "leaseEnd";
/**
* The state of the cluster. On proper shutdown the state should be cleared.
@@ -135,11 +136,14 @@ public class ClusterNodeInfo {
*/
private static Clock clock = Clock.SIMPLE;
+
+ public static final int DEFAULT_LEASE_DURATION_MILLIS = 1000 * 60;
+
/**
* The number of milliseconds for a lease (1 minute by default, and
* initially).
*/
- private long leaseTime = 1000 * 60;
+ private long leaseTime = DEFAULT_LEASE_DURATION_MILLIS;
/**
* The assigned cluster id.
@@ -410,17 +414,21 @@ public class ClusterNodeInfo {
/**
* Specify a custom clock to be used for determining current time.
- * If passed clock is null then clock would be set to the default clock
*
* <b>Only Used For Testing</b>
*/
static void setClock(Clock c) {
- if(c == null){
- c = Clock.SIMPLE;
- }
+ checkNotNull(c);
clock = c;
}
+ /**
+ * Resets the clock to the default
+ */
+ static void resetClockToDefault(){
+ clock = Clock.SIMPLE;
+ }
+
private static long getProcessId() {
try {
String name = ManagementFactory.getRuntimeMXBean().getName();
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java?rev=1584287&r1=1584286&r2=1584287&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java Thu Apr 3 08:53:10 2014
@@ -538,6 +538,7 @@ public final class DocumentNodeStore
return asyncDelay;
}
+ @CheckForNull
public ClusterNodeInfo getClusterInfo() {
return clusterNodeInfo;
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java?rev=1584287&r1=1584286&r2=1584287&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java Thu Apr 3 08:53:10 2014
@@ -59,6 +59,7 @@ import org.apache.jackrabbit.oak.spi.sta
import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardExecutor;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
@@ -138,6 +139,9 @@ public class DocumentNodeStoreService {
*/
private long versionGcMaxAgeInSecs = DEFAULT_VER_GC_MAX_AGE;
+ public static final String PROP_REV_RECOVERY_INTERVAL = "lastRevRecoveryJobIntervalInSecs";
+
+
@Activate
protected void activate(ComponentContext context, Map<String, ?> config) throws Exception {
this.context = context;
@@ -201,6 +205,7 @@ public class DocumentNodeStoreService {
log.info("Connected to database {}", mongoDB);
registerJMXBeans(mk.getNodeStore());
+ registerLastRevRecoveryJob(mk.getNodeStore());
NodeStore store;
if (useMK) {
@@ -220,7 +225,6 @@ public class DocumentNodeStoreService {
reg = context.getBundleContext().registerService(NodeStore.class.getName(), store, props);
}
-
/**
* At runtime DocumentNodeStore only pickup modification of certain properties
*/
@@ -315,8 +319,6 @@ public class DocumentNodeStoreService {
);
}
-
-
if (blobStore instanceof GarbageCollectableBlobStore) {
BlobGarbageCollector gc = new BlobGarbageCollector() {
@Override
@@ -340,6 +342,19 @@ public class DocumentNodeStoreService {
//TODO Register JMX bean for Off Heap Cache stats
}
+ private void registerLastRevRecoveryJob(final DocumentNodeStore nodeStore) {
+ long leaseTime = PropertiesUtil.toLong(context.getProperties().get(PROP_REV_RECOVERY_INTERVAL),
+ ClusterNodeInfo.DEFAULT_LEASE_DURATION_MILLIS);
+ Runnable recoverJob = new Runnable() {
+ @Override
+ public void run() {
+ nodeStore.getLastRevRecoveryAgent().performRecoveryIfNeeded();
+ }
+ };
+ registrations.add(WhiteboardUtils.scheduleWithFixedDelay(whiteboard,
+ recoverJob, TimeUnit.MILLISECONDS.toSeconds(leaseTime)));
+ }
+
private Object prop(String propName) {
return prop(propName, PREFIX + propName);
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgent.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgent.java?rev=1584287&r1=1584286&r2=1584287&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgent.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgent.java Thu Apr 3 08:53:10 2014
@@ -72,6 +72,11 @@ public class LastRevRecoveryAgent {
public int recover(int clusterId) {
ClusterNodeInfoDocument nodeInfo = missingLastRevUtil.getClusterNodeInfo(clusterId);
+ //TODO Currently leaseTime remains same per cluster node. If this
+ //is made configurable then it should be read from DB entry
+ final long leaseTime = ClusterNodeInfo.DEFAULT_LEASE_DURATION_MILLIS;
+ final long asyncDelay = nodeStore.getAsyncDelay();
+
if (nodeInfo != null) {
long leaseEnd = nodeInfo.getLeaseEndTime();
@@ -83,10 +88,17 @@ public class LastRevRecoveryAgent {
Revision lastRev = root.getLastRev().get(clusterId);
// start time is the _lastRev timestamp of this cluster node
- long startTime = lastRev.getTimestamp();
+ final long startTime;
+ //lastRev can be null if other cluster node did not got
+ //chance to perform lastRev rollup even once
+ if (lastRev != null) {
+ startTime = lastRev.getTimestamp();
+ } else {
+ startTime = leaseEnd - leaseTime - asyncDelay;
+ }
// Endtime is the leaseEnd + the asyncDelay
- long endTime = leaseEnd + nodeStore.getAsyncDelay();
+ long endTime = leaseEnd + asyncDelay;
log.info("Recovering candidates modified in time range : [{},{}] for clusterId [{}]",
Utils.timestampToString(startTime),
@@ -260,19 +272,40 @@ public class LastRevRecoveryAgent {
}
return null;
}
+
+ /**
+ * Determines if any of the cluster node failed to renew its lease and
+ * did not properly shutdown. If any such cluster node is found then are potential
+ * candidates for last rev recovery
+ *
+ * @return true if last rev recovery needs to be performed for any of the cluster nodes
+ */
+ public boolean isRecoveryNeeded(){
+ return missingLastRevUtil.isRecoveryNeeded(nodeStore.getClock().getTime());
+ }
+
+ public void performRecoveryIfNeeded(){
+ if(isRecoveryNeeded()){
+ List<Integer> clusterIds = getRecoveryCandidateNodes();
+ log.info("Starting last revision recovery for following clusterId {}", clusterIds);
+ for(int clusterId : clusterIds){
+ recover(clusterId);
+ }
+ }
+ }
/**
* Gets the _lastRev recovery candidate cluster nodes.
*
* @return the recovery candidate nodes
*/
- public List<String> getRecoveryCandidateNodes() {
+ public List<Integer> getRecoveryCandidateNodes() {
Iterable<ClusterNodeInfoDocument> clusters = missingLastRevUtil.getAllClusters();
- List<String> candidateClusterNodes = Lists.newArrayList();
+ List<Integer> candidateClusterNodes = Lists.newArrayList();
for (ClusterNodeInfoDocument nodeInfo : clusters) {
if (isRecoveryNeeded(nodeInfo)) {
- candidateClusterNodes.add(nodeInfo.getId());
+ candidateClusterNodes.add(Integer.valueOf(nodeInfo.getId()));
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java?rev=1584287&r1=1584286&r2=1584287&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java Thu Apr 3 08:53:10 2014
@@ -20,7 +20,6 @@
package org.apache.jackrabbit.oak.plugins.document;
import java.util.List;
-import java.util.concurrent.TimeUnit;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
@@ -77,8 +76,8 @@ public class MissingLastRevSeeker {
public boolean apply(NodeDocument input) {
Long modified = (Long) input.get(NodeDocument.MODIFIED_IN_SECS);
return (modified != null
- && (modified > TimeUnit.MILLISECONDS.toSeconds(startTime))
- && (modified < TimeUnit.MILLISECONDS.toSeconds(endTime)));
+ && (modified >= Commit.getModifiedInSecs(startTime))
+ && (modified <= Commit.getModifiedInSecs(endTime)));
}
});
}
@@ -101,5 +100,18 @@ public class MissingLastRevSeeker {
public NodeDocument getRoot() {
return store.find(Collection.NODES, Utils.getIdFromPath(ROOT_PATH));
}
+
+ public boolean isRecoveryNeeded(long currentTime) {
+ for(ClusterNodeInfoDocument nodeInfo : getAllClusters()){
+ // Check if _lastRev recovery needed for this cluster node
+ // state is Active && currentTime past the leaseEnd time && recoveryLock not held by someone
+ if (nodeInfo.isActive()
+ && currentTime > nodeInfo.getLeaseEndTime()
+ && !nodeInfo.isBeingRecovered()) {
+ return true;
+ }
+ }
+ return false;
+ }
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Revision.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Revision.java?rev=1584287&r1=1584286&r2=1584287&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Revision.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Revision.java Thu Apr 3 08:53:10 2014
@@ -25,6 +25,9 @@ import java.util.concurrent.ConcurrentMa
import org.apache.jackrabbit.oak.plugins.document.util.Utils;
import org.apache.jackrabbit.oak.stats.Clock;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
/**
* A revision.
*/
@@ -71,10 +74,14 @@ public class Revision {
* @param c - the clock
*/
static void setClock(Clock c) {
+ checkNotNull(c);
clock = c;
- if (c == null) {
- lastTimestamp = System.currentTimeMillis();
- }
+ }
+
+ static void resetClockToDefault(){
+ clock = Clock.SIMPLE;
+ lastTimestamp = clock.getTime();
+
}
public Revision(long timestamp, int counter, int clusterId) {
this(timestamp, counter, clusterId, false);
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoMissingLastRevSeeker.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoMissingLastRevSeeker.java?rev=1584287&r1=1584286&r2=1584287&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoMissingLastRevSeeker.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoMissingLastRevSeeker.java Thu Apr 3 08:53:10 2014
@@ -101,6 +101,16 @@ public class MongoMissingLastRevSeeker e
return oldNode != null;
}
+ @Override
+ public boolean isRecoveryNeeded(long currentTime) {
+ QueryBuilder query =
+ start(ClusterNodeInfo.STATE).is(ClusterNodeInfo.ClusterNodeState.ACTIVE.name())
+ .put(ClusterNodeInfo.LEASE_END_KEY).lessThan(currentTime)
+ .put(ClusterNodeInfo.REV_RECOVERY_LOCK).notEquals(RecoverLockState.ACQUIRED.name());
+
+ return getClusterNodeCollection().findOne(query.get()) != null;
+ }
+
private DBCollection getNodeCollection() {
return store.getDBCollection(Collection.NODES);
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterInfoTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterInfoTest.java?rev=1584287&r1=1584286&r2=1584287&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterInfoTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterInfoTest.java Thu Apr 3 08:53:10 2014
@@ -92,6 +92,6 @@ public class ClusterInfoTest {
@After
public void tearDown(){
- ClusterNodeInfo.setClock(null);
+ ClusterNodeInfo.resetClockToDefault();
}
}
Added: 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=1584287&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgentTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgentTest.java Thu Apr 3 08:53:10 2014
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.plugins.document;
+
+import java.io.IOException;
+import java.util.List;
+
+import com.google.common.collect.Lists;
+import org.apache.jackrabbit.oak.plugins.document.util.Utils;
+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.stats.Clock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(Parameterized.class)
+public class LastRevRecoveryAgentTest {
+ private final DocumentStoreFixture fixture;
+
+ private DocumentNodeStore ds1;
+ private DocumentNodeStore ds2;
+ private int c1Id;
+ private int c2Id;
+ private DocumentStore sharedStore;
+ private Clock clock;
+
+ public LastRevRecoveryAgentTest(DocumentStoreFixture fixture) {
+ this.fixture = fixture;
+ }
+
+ //----------------------------------------< Set Up >
+
+ @Parameterized.Parameters
+ public static java.util.Collection<Object[]> fixtures() throws IOException {
+ List<Object[]> fixtures = Lists.newArrayList();
+ fixtures.add(new Object[] {new DocumentStoreFixture.MemoryFixture()});
+
+ DocumentStoreFixture mongo = new DocumentStoreFixture.MongoFixture();
+ if(mongo.isAvailable()){
+ fixtures.add(new Object[] {mongo});
+ }
+ return fixtures;
+ }
+
+ @Before
+ public void setUp() throws InterruptedException {
+ clock = new Clock.Virtual();
+
+ //Quite a bit of logic relies on timestamp converted
+ // to 5 sec resolutions
+ clock.waitUntil(System.currentTimeMillis());
+
+ ClusterNodeInfo.setClock(clock);
+ Revision.setClock(clock);
+ sharedStore = fixture.createDocumentStore();
+ ds1 = new DocumentMK.Builder()
+ .setAsyncDelay(0)
+ .clock(clock)
+ .setDocumentStore(sharedStore)
+ .getNodeStore();
+ c1Id = ds1.getClusterId();
+
+ ds2 = new DocumentMK.Builder()
+ .setAsyncDelay(0)
+ .clock(clock)
+ .setDocumentStore(sharedStore)
+ .getNodeStore();
+ c2Id = ds2.getClusterId();
+ }
+
+ @After
+ public void tearDown(){
+ sharedStore.dispose();
+ ClusterNodeInfo.resetClockToDefault();
+ Revision.resetClockToDefault();
+ }
+
+ //~------------------------------------------< Test Case >
+
+ @Test
+ public void testIsRecoveryRequired() throws Exception{
+ //1. Create base structure /x/y
+ NodeBuilder b1 = ds1.getRoot().builder();
+ b1.child("x").child("y");
+ ds1.merge(b1, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+ ds1.runBackgroundOperations();
+
+ ds2.runBackgroundOperations();
+
+ //2. Add a new node /x/y/z in C2
+ NodeBuilder b2 = ds2.getRoot().builder();
+ b2.child("x").child("y").child("z").setProperty("foo", "bar");
+ ds2.merge(b2, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+ NodeDocument z1 = getDocument(ds1, "/x/y/z");
+ Revision zlastRev2 = z1.getLastRev().get(c2Id);
+
+ long leaseTime = ds1.getClusterInfo().getLeaseTime();
+ ds1.runBackgroundOperations();
+
+ clock.waitUntil(clock.getTime() + leaseTime + 10);
+
+ //Renew the lease for C1
+ ds1.getClusterInfo().renewLease(3*leaseTime);
+
+ assertTrue(ds1.getLastRevRecoveryAgent().isRecoveryNeeded());
+
+ List<Integer> cids = ds1.getLastRevRecoveryAgent().getRecoveryCandidateNodes();
+ assertEquals(1, cids.size());
+ assertEquals(c2Id, cids.get(0).intValue());
+
+ ds1.getLastRevRecoveryAgent().recover(cids.get(0));
+
+ assertEquals(zlastRev2, getDocument(ds1, "/x/y").getLastRev().get(c2Id));
+ assertEquals(zlastRev2, getDocument(ds1, "/x").getLastRev().get(c2Id));
+ assertEquals(zlastRev2, getDocument(ds1, "/").getLastRev().get(c2Id));
+ }
+
+ private NodeDocument getDocument(DocumentNodeStore nodeStore, String path) {
+ return nodeStore.getDocumentStore().find(Collection.NODES, Utils.getIdFromPath(path));
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgentTest.java
------------------------------------------------------------------------------
svn:eol-style = native
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=1584287&r1=1584286&r2=1584287&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 Apr 3 08:53:10 2014
@@ -35,22 +35,24 @@ import static org.junit.Assert.assertNul
public class LastRevRecoveryTest {
private DocumentNodeStore ds1;
private DocumentNodeStore ds2;
+ private int c1Id;
+ private int c2Id;
private MemoryDocumentStore sharedStore;
@Before
public void setUp(){
sharedStore = new MemoryDocumentStore();
ds1 = new DocumentMK.Builder()
- .setClusterId(1)
.setAsyncDelay(0)
.setDocumentStore(sharedStore)
.getNodeStore();
+ c1Id = ds1.getClusterId();
ds2 = new DocumentMK.Builder()
- .setClusterId(2)
.setAsyncDelay(0)
.setDocumentStore(sharedStore)
.getNodeStore();
+ c2Id = ds2.getClusterId();
}
@@ -84,21 +86,21 @@ public class LastRevRecoveryTest {
NodeDocument y1 = getDocument(ds1, "/x/y");
NodeDocument x1 = getDocument(ds1, "/x");
- Revision zlastRev2 = z1.getLastRev().get(2);
+ Revision zlastRev2 = z1.getLastRev().get(c2Id);
assertNotNull(zlastRev2);
//lastRev should not be updated for C #2
- assertNull(y1.getLastRev().get(2));
+ assertNull(y1.getLastRev().get(c2Id));
LastRevRecoveryAgent recovery = new LastRevRecoveryAgent(ds1);
//Do not pass y1 but still y1 should be updated
- recovery.recover(Iterators.forArray(x1,z1), 2);
+ recovery.recover(Iterators.forArray(x1,z1), c2Id);
//Post recovery the lastRev should be updated for /x/y and /x
- assertEquals(zlastRev2, getDocument(ds1, "/x/y").getLastRev().get(2));
- assertEquals(zlastRev2, getDocument(ds1, "/x").getLastRev().get(2));
- assertEquals(zlastRev2, getDocument(ds1, "/").getLastRev().get(2));
+ assertEquals(zlastRev2, getDocument(ds1, "/x/y").getLastRev().get(c2Id));
+ assertEquals(zlastRev2, getDocument(ds1, "/x").getLastRev().get(c2Id));
+ assertEquals(zlastRev2, getDocument(ds1, "/").getLastRev().get(c2Id));
}
private NodeDocument getDocument(DocumentNodeStore nodeStore, String path) {
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevSingleNodeRecoveryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevSingleNodeRecoveryTest.java?rev=1584287&r1=1584286&r2=1584287&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevSingleNodeRecoveryTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevSingleNodeRecoveryTest.java Thu Apr 3 08:53:10 2014
@@ -23,7 +23,6 @@ import static org.junit.Assert.assertEqu
import java.io.IOException;
import java.util.Collection;
-import java.util.Iterator;
import java.util.List;
import com.google.common.collect.Lists;
@@ -54,7 +53,6 @@ public class LastRevSingleNodeRecoveryTe
@Parameterized.Parameters
public static Collection<Object[]> fixtures() throws IOException {
List<Object[]> fixtures = Lists.newArrayList();
-
DocumentStoreFixture mongo = new DocumentStoreFixture.MongoFixture();
if (mongo.isAvailable()) {
fixtures.add(new Object[] {mongo});
@@ -170,9 +168,10 @@ public class LastRevSingleNodeRecoveryTe
clock.waitUntil(clock.getTime() + mk.getClusterInfo().getLeaseTime() + 1000);
LastRevRecoveryAgent recoveryAgent = mk.getNodeStore().getLastRevRecoveryAgent();
- Iterator<String> iter = recoveryAgent.getRecoveryCandidateNodes().iterator();
- assertEquals(String.valueOf(1), iter.next());
- assertEquals(false, iter.hasNext());
+ List<Integer> cids = recoveryAgent.getRecoveryCandidateNodes();
+
+ assertEquals(1, cids.size());
+ assertEquals(Integer.valueOf(1), cids.get(0));
}
private void setupScenario() throws InterruptedException {
@@ -220,8 +219,8 @@ public class LastRevSingleNodeRecoveryTe
@After
public void tearDown() throws Exception {
- Revision.setClock(null);
- ClusterNodeInfo.setClock(null);
+ Revision.resetClockToDefault();
+ ClusterNodeInfo.resetClockToDefault();
mk.dispose();
fixture.dispose();
}