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 2019/07/18 09:12:18 UTC
svn commit: r1863260 - in /jackrabbit/oak/trunk/oak-store-document/src:
main/java/org/apache/jackrabbit/oak/plugins/document/
test/java/org/apache/jackrabbit/oak/plugins/document/
Author: mreutegg
Date: Thu Jul 18 09:12:18 2019
New Revision: 1863260
URL: http://svn.apache.org/viewvc?rev=1863260&view=rev
Log:
OAK-8466: Old inactive clusterIds may trigger expensive recovery
Patch provided by Vinod Holani with some modifications from Marcel Reutegger
Modified:
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreStatsCollectorIT.java
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/SimpleTest.java
Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java?rev=1863260&r1=1863259&r2=1863260&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java (original)
+++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java Thu Jul 18 09:12:18 2019
@@ -789,6 +789,18 @@ public class Commit {
cacheEntry.done();
}
+ void markChanged(Path path) {
+ while (true) {
+ if (!modifiedNodes.add(path)) {
+ break;
+ }
+ path = path.getParent();
+ if (path == null) {
+ break;
+ }
+ }
+ }
+
/**
* Apply the changes of a node to the cache.
*
@@ -817,18 +829,6 @@ public class Commit {
cacheEntry.append(path, w.toString());
}
- private void markChanged(Path path) {
- while (true) {
- if (!modifiedNodes.add(path)) {
- break;
- }
- path = path.getParent();
- if (path == null) {
- break;
- }
- }
- }
-
private boolean isBundled(Path path) {
return bundledNodes.containsKey(path);
}
Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java?rev=1863260&r1=1863259&r2=1863260&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java Thu Jul 18 09:12:18 2019
@@ -689,6 +689,15 @@ public final class DocumentNodeStore
clusterUpdateThread.start();
backgroundReadThread.start();
if (!readOnlyMode) {
+ // OAK-8466 - background sweep may take a long time if there is no
+ // sweep revision for this clusterId. When this process is suddenly
+ // stopped while performing the sweep, a recovery will be needed
+ // starting at the timestamp of _lastRev for this clusterId, which
+ // is potentially old and the recovery will be expensive. Hence
+ // triggering below function to update _lastRev, just before
+ // triggering sweep
+ runBackgroundUpdateOperations();
+
// perform an initial document sweep if needed
// this may be long running if there is no sweep revision
// for this clusterId (upgrade from Oak <= 1.6).
@@ -2453,16 +2462,21 @@ public final class DocumentNodeStore
if (isDisposed.get() || isDisableBranches()) {
return;
}
+ DocumentNodeState rootState = getRoot();
// check if local head revision is outdated and needs an update
// this ensures the head and sweep revisions are recent and the
// revision garbage collector can remove old documents
- Revision head = getHeadRevision().getRevision(clusterId);
- if (head != null && head.getTimestamp() + ONE_MINUTE_MS < clock.getTime()) {
+ Revision head = rootState.getRootRevision().getRevision(clusterId);
+ Revision lastRev = rootState.getLastRevision().getRevision(clusterId);
+ long oneMinuteAgo = clock.getTime() - ONE_MINUTE_MS;
+ if ((head != null && head.getTimestamp() < oneMinuteAgo) ||
+ (lastRev != null && lastRev.getTimestamp() < oneMinuteAgo)) {
// head was not updated for more than a minute
// create an empty commit that updates the head
boolean success = false;
Commit c = newTrunkCommit(nop -> {}, getHeadRevision());
try {
+ c.markChanged(ROOT);
done(c, false, CommitInfo.EMPTY);
success = true;
} finally {
Modified: jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreStatsCollectorIT.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreStatsCollectorIT.java?rev=1863260&r1=1863259&r2=1863260&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreStatsCollectorIT.java (original)
+++ jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreStatsCollectorIT.java Thu Jul 18 09:12:18 2019
@@ -88,6 +88,7 @@ public class DocumentNodeStoreStatsColle
@Test
public void doneBackgroundUpdate() {
+ Mockito.clearInvocations(statsCollector);
nodeStore.runBackgroundUpdateOperations();
verify(statsCollector).doneBackgroundUpdate(any(BackgroundWriteStats.class));
}
Modified: jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java?rev=1863260&r1=1863259&r2=1863260&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java (original)
+++ jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java Thu Jul 18 09:12:18 2019
@@ -31,6 +31,7 @@ import static org.apache.jackrabbit.oak.
import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.NUM_REVS_THRESHOLD;
import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.PREV_SPLIT_FACTOR;
import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.getModifiedInSecs;
+import static org.apache.jackrabbit.oak.plugins.document.Path.ROOT;
import static org.apache.jackrabbit.oak.plugins.document.util.Utils.isCommitted;
import static org.hamcrest.CoreMatchers.everyItem;
import static org.hamcrest.CoreMatchers.is;
@@ -117,6 +118,7 @@ import org.apache.jackrabbit.oak.spi.sta
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.spi.state.NodeStore;
import org.apache.jackrabbit.oak.stats.Clock;
+import org.hamcrest.number.OrderingComparison;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.AfterClass;
@@ -751,6 +753,47 @@ public class DocumentNodeStoreTest {
} catch (DocumentStoreException expected) {}
}
+ //OAK-8466
+ @Test
+ public void lastRevisionUpdateOnNodeRestart() throws Exception {
+ MemoryDocumentStore store = new MemoryDocumentStore();
+
+ int clusterId = 1;
+ DocumentNodeStore dns1 = builderProvider.newBuilder()
+ .setDocumentStore(store)
+ .setAsyncDelay(0).setClusterId(clusterId)
+ .getNodeStore();
+ dns1.dispose();
+
+ NodeDocument beforeRootDoc = store.find(NODES, Utils.getIdFromPath(ROOT));
+ assertNotNull(beforeRootDoc);
+ Revision beforeLastRev = beforeRootDoc.getLastRev().get(clusterId);
+
+ Clock clock = new Clock.Virtual();
+ long now = System.currentTimeMillis();
+ // DocumentNodeStore refreshes the head revision and _lastRev
+ // when there was no commit for one minute
+ clock.waitUntil( now + TimeUnit.MINUTES.toMillis(1));
+ long timeBeforeStartup = clock.getTime();
+ ClusterNodeInfo.setClock(clock);
+ Revision.setClock(clock);
+
+ builderProvider.newBuilder()
+ .setDocumentStore(store).clock(clock)
+ .setAsyncDelay(0).setClusterId(clusterId)
+ .getNodeStore();
+
+ NodeDocument afterRootDoc = store.find(NODES, Utils.getIdFromPath(ROOT));
+ assertNotNull(afterRootDoc);
+ Revision afterLastRev = afterRootDoc.getLastRev().get(clusterId);
+
+ assertThat("lastRev must be greater or equal '" + Utils.timestampToString(timeBeforeStartup) + "', but was '"
+ + Utils.timestampToString(afterLastRev.getTimestamp()) + "'", afterLastRev.getTimestamp(),
+ OrderingComparison.greaterThanOrEqualTo(timeBeforeStartup));
+ assertNotEquals("Last revision should be updated after 1 minute even if background thread is not running",
+ beforeLastRev, afterLastRev);
+ }
+
// OAK-2288
@Test
public void mergedBranchVisibility() throws Exception {
Modified: jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/SimpleTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/SimpleTest.java?rev=1863260&r1=1863259&r2=1863260&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/SimpleTest.java (original)
+++ jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/SimpleTest.java Thu Jul 18 09:12:18 2019
@@ -105,25 +105,25 @@ public class SimpleTest {
String rev4 = mk.commit("/test", "^\"a/x\":1", null, null);
String r0 = mk.getNodes("/", rev0, 0, 0, Integer.MAX_VALUE, ":id");
- assertEquals("{\":id\":\"/@r0-0-1\",\":childNodeCount\":0}", r0);
+ assertEquals("{\":id\":\"/@r1-0-1\",\":childNodeCount\":0}", r0);
String r1 = mk.getNodes("/", rev1, 0, 0, Integer.MAX_VALUE, ":id");
- assertEquals("{\":id\":\"/@r1-0-1\",\"test\":{},\":childNodeCount\":1}", r1);
+ assertEquals("{\":id\":\"/@r2-0-1\",\"test\":{},\":childNodeCount\":1}", r1);
String r2 = mk.getNodes("/", rev2, 0, 0, Integer.MAX_VALUE, ":id");
- assertEquals("{\":id\":\"/@r2-0-1\",\"test\":{},\":childNodeCount\":1}", r2);
+ assertEquals("{\":id\":\"/@r3-0-1\",\"test\":{},\":childNodeCount\":1}", r2);
String r3;
r3 = mk.getNodes("/", rev3, 0, 0, Integer.MAX_VALUE, ":id");
- assertEquals("{\":id\":\"/@r3-0-1\",\"test\":{},\":childNodeCount\":1}", r3);
+ assertEquals("{\":id\":\"/@r4-0-1\",\"test\":{},\":childNodeCount\":1}", r3);
r3 = mk.getNodes("/test", rev3, 0, 0, Integer.MAX_VALUE, ":id");
- assertEquals("{\":id\":\"/test@r3-0-1\",\"a\":{},\"b\":{},\":childNodeCount\":2}", r3);
+ assertEquals("{\":id\":\"/test@r4-0-1\",\"a\":{},\"b\":{},\":childNodeCount\":2}", r3);
String r4;
r4 = mk.getNodes("/", rev4, 0, 0, Integer.MAX_VALUE, ":id");
- assertEquals("{\":id\":\"/@r4-0-1\",\"test\":{},\":childNodeCount\":1}", r4);
+ assertEquals("{\":id\":\"/@r5-0-1\",\"test\":{},\":childNodeCount\":1}", r4);
r4 = mk.getNodes("/test", rev4, 0, 0, Integer.MAX_VALUE, ":id");
- assertEquals("{\":id\":\"/test@r4-0-1\",\"a\":{},\"b\":{},\":childNodeCount\":2}", r4);
+ assertEquals("{\":id\":\"/test@r5-0-1\",\"a\":{},\"b\":{},\":childNodeCount\":2}", r4);
r4 = mk.getNodes("/test/a", rev4, 0, 0, Integer.MAX_VALUE, ":id");
- assertEquals("{\":id\":\"/test/a@r4-0-1\",\"x\":1,\":childNodeCount\":0}", r4);
+ assertEquals("{\":id\":\"/test/a@r5-0-1\",\"x\":1,\":childNodeCount\":0}", r4);
r4 = mk.getNodes("/test/b", rev4, 0, 0, Integer.MAX_VALUE, ":id");
- assertEquals("{\":id\":\"/test/b@r3-0-1\",\":childNodeCount\":0}", r4);
+ assertEquals("{\":id\":\"/test/b@r4-0-1\",\":childNodeCount\":0}", r4);
}
@Test