From 3c0ccd4645ccd8c84d966573e8b464e59b31a083 Mon Sep 17 00:00:00 2001 From: Vikas Saurabh Date: Tue, 20 Dec 2016 05:01:59 +0530 Subject: [PATCH] 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 --- .../oak/plugins/document/LastRevRecoveryAgent.java | 2 +- .../plugins/document/LastRevRecoveryAgentTest.java | 45 ++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgent.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgent.java index b67c402..0fbc7ff 100644 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgent.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgent.java @@ -446,7 +446,7 @@ public class LastRevRecoveryAgent { new Predicate() { @Override public boolean apply(ClusterNodeInfoDocument input) { - return missingLastRevUtil.isRecoveryNeeded(input); + return nodeStore.getClusterId() != input.getClusterId() && missingLastRevUtil.isRecoveryNeeded(input); } }), new Function() { @Override diff --git a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgentTest.java b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgentTest.java index 79b856d..98bfa8a 100644 --- a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgentTest.java +++ b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgentTest.java @@ -163,6 +163,51 @@ public class LastRevRecoveryAgentTest { assertEquals(zlastRev2, getDocument(ds1, "/").getLastRev().get(c2Id)); } + //OAK-5337 + @Test + public void testSelfRecovery() throws Exception{ + //1. Create base structure /x/y (remove /x first to have genuine new "z" later despite old remnants) + NodeBuilder b1 = ds1.getRoot().builder(); + if (b1.hasChildNode("x")) { + b1.getChildNode("x").remove(); + } + b1.child("x").child("y"); + merge(ds1, b1); + ds1.runBackgroundOperations(); + + //2. Add a new node /x/y/z in C1 + b1 = ds1.getRoot().builder(); + String randomChild = "z"; + b1.child("x").child("y").child(randomChild); + merge(ds1, b1); + + long leaseTime = ds1.getClusterInfo().getLeaseTime(); + + clock.waitUntil(clock.getTime() + leaseTime + 10); + + //Renew the lease for C2 + ds2.getClusterInfo().renewLease(); + assertTrue(ds1.getLastRevRecoveryAgent().isRecoveryNeeded());//C1 needs recovery from lease timeout pov + + Iterable 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(randomChild)); + + // 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(randomChild)); + } + @Test public void testRepeatedRecovery() throws Exception { //1. Create base structure /x/y -- 2.8.3