Author: catholicon
Date: Thu Dec 22 22:23:25 2016
New Revision: 1775757
URL: http://svn.apache.org/viewvc?rev=1775757&view=rev
Log:
OAK-5337: LastRevRecoveryAgent should avoid recovering documents from its own
cluster id if the instance is running
Skip self-clusterId while filtering cluster candidates that "might" need
recovery
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgent.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgentTest.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/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=1775757&r1=1775756&r2=1775757&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 Dec 22 22:23:25 2016
@@ -437,7 +437,9 @@ public class LastRevRecoveryAgent {
/**
* Gets the _lastRev recovery candidate cluster nodes. This also includes
- * cluster nodes that are currently being recovered.
+ * cluster nodes that are currently being recovered. The method would not
+ * return self as a candidate for recovery even if it has failed to update
+ * lease in time
*
* @return the recovery candidate nodes.
*/
@@ -446,7 +448,7 @@ public class LastRevRecoveryAgent {
new Predicate<ClusterNodeInfoDocument>() {
@Override
public boolean apply(ClusterNodeInfoDocument input) {
- return missingLastRevUtil.isRecoveryNeeded(input);
+ return nodeStore.getClusterId() != input.getClusterId() &&
missingLastRevUtil.isRecoveryNeeded(input);
}
}), new Function<ClusterNodeInfoDocument, Integer>() {
@Override
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=1775757&r1=1775756&r2=1775757&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 Dec 22 22:23:25 2016
@@ -115,10 +115,11 @@ public class LastRevRecoveryAgentTest {
}
@After
- public void tearDown(){
+ public void tearDown() throws Exception {
ds1.dispose();
ds2.dispose();
sharedStore.dispose();
+ fixture.dispose();
ClusterNodeInfo.resetClockToDefault();
Revision.resetClockToDefault();
}
@@ -163,6 +164,48 @@ public class LastRevRecoveryAgentTest {
assertEquals(zlastRev2, getDocument(ds1, "/").getLastRev().get(c2Id));
}
+ //OAK-5337
+ @Test
+ public void testSelfRecovery() throws Exception{
+ //1. Create base structure /x/y
+ NodeBuilder b1 = ds1.getRoot().builder();
+ b1.child("x").child("y");
+ merge(ds1, b1);
+ ds1.runBackgroundOperations();
+
+ //2. Add a new node /x/y/z in C1
+ b1 = ds1.getRoot().builder();
+ b1.child("x").child("y").child("z");
+ merge(ds1, b1);
+
+ long leaseTime = ds1.getClusterInfo().getLeaseTime();
+
+ clock.waitUntil(clock.getTime() + leaseTime + 10);
+
+ //Renew the lease for C2
+ ds2.getClusterInfo().renewLease();
+ //C1 needs recovery from lease timeout pov
+ assertTrue(ds1.getLastRevRecoveryAgent().isRecoveryNeeded());
+
+ Iterable<Integer> cids =
ds1.getLastRevRecoveryAgent().getRecoveryCandidateNodes();
+ //.. but, it won't be returned while we iterate candidate nodes from
self
+ assertEquals(0, Iterables.size(cids));
+
+ cids = ds2.getLastRevRecoveryAgent().getRecoveryCandidateNodes();
+ //... checking that from other node still reports
+ assertEquals(1, Iterables.size(cids));
+ assertEquals(c1Id, Iterables.get(cids, 0).intValue());
+
+ ds2.runBackgroundOperations();
+
assertFalse(ds2.getRoot().getChildNode("x").getChildNode("y").hasChildNode("z"));
+
+ // yet, calling recover with self-cluster-id still works (useful for
startup LRRA)
+ ds1.getLastRevRecoveryAgent().recover(Iterables.get(cids, 0));
+
+ ds2.runBackgroundOperations();
+
assertTrue(ds2.getRoot().getChildNode("x").getChildNode("y").hasChildNode("z"));
+ }
+
@Test
public void testRepeatedRecovery() throws Exception {
//1. Create base structure /x/y
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=1775757&r1=1775756&r2=1775757&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 Dec 22 22:23:25 2016
@@ -20,6 +20,7 @@
package org.apache.jackrabbit.oak.plugins.document;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.Collection;
@@ -173,10 +174,13 @@ public class LastRevSingleNodeRecoveryTe
clock.waitUntil(clock.getTime() + mk.getClusterInfo().getLeaseTime() +
1000);
LastRevRecoveryAgent recoveryAgent =
mk.getNodeStore().getLastRevRecoveryAgent();
- Iterable<Integer> cids = recoveryAgent.getRecoveryCandidateNodes();
- assertEquals(1, Iterables.size(cids));
- assertEquals(Integer.valueOf(1), Iterables.get(cids, 0));
+ // Post OAK-5337, a cluster node won't report itself as a candidate
for recovery
+ // Recovery agent would still detect that recovery is required and
calling
+ // recover on self would recover too (testLastRevRestore)
+ assertTrue(recoveryAgent.isRecoveryNeeded());
+ Iterable<Integer> cids = recoveryAgent.getRecoveryCandidateNodes();
+ assertEquals(0, Iterables.size(cids));
}
private void setupScenario() throws InterruptedException {