diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java index f12bd56ecf..b97f54f24d 100644 --- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java +++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeeker.java @@ -31,6 +31,7 @@ import com.google.common.collect.Iterables; import static org.apache.jackrabbit.oak.plugins.document.Collection.CLUSTER_NODES; import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.MODIFIED_IN_SECS; +import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.SD_TYPE; import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.getModifiedInSecs; import static org.apache.jackrabbit.oak.plugins.document.util.Utils.getSelectedDocuments; @@ -86,7 +87,8 @@ public class MissingLastRevSeeker { @Override public boolean apply(NodeDocument input) { Long modified = (Long) input.get(MODIFIED_IN_SECS); - return (modified != null && (modified >= getModifiedInSecs(startTime))); + Long sdType = (Long) input.get(SD_TYPE); + return (modified != null && (modified >= getModifiedInSecs(startTime)) && sdType == null); } }); } diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoMissingLastRevSeeker.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoMissingLastRevSeeker.java index 63f71d6cfb..81ed50a4cb 100644 --- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoMissingLastRevSeeker.java +++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoMissingLastRevSeeker.java @@ -54,7 +54,9 @@ public class MongoMissingLastRevSeeker extends MissingLastRevSeeker { @Override @NotNull public CloseableIterable getCandidates(final long startTime) { - Bson query = Filters.gte(NodeDocument.MODIFIED_IN_SECS, NodeDocument.getModifiedInSecs(startTime)); + Bson query = Filters.and( + Filters.gte(NodeDocument.MODIFIED_IN_SECS, NodeDocument.getModifiedInSecs(startTime)), + Filters.exists(NodeDocument.SD_TYPE, false)); Bson sortFields = new BasicDBObject(NodeDocument.MODIFIED_IN_SECS, 1); FindIterable cursor = getNodeCollection() diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBMissingLastRevSeeker.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBMissingLastRevSeeker.java index 8e99645595..844ad1c2a3 100644 --- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBMissingLastRevSeeker.java +++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBMissingLastRevSeeker.java @@ -19,6 +19,7 @@ package org.apache.jackrabbit.oak.plugins.document.rdb; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -63,8 +64,9 @@ public class RDBMissingLastRevSeeker extends MissingLastRevSeeker { if (MODE == 1) { return super.getCandidates(startTime); } else { - List conditions = Collections.singletonList( - new QueryCondition(NodeDocument.MODIFIED_IN_SECS, ">=", NodeDocument.getModifiedInSecs(startTime))); + List conditions = new ArrayList<>(); + conditions.add(new QueryCondition(NodeDocument.MODIFIED_IN_SECS, ">=", NodeDocument.getModifiedInSecs(startTime))); + conditions.add(new QueryCondition(NodeDocument.SD_TYPE, "is null")); return store.queryAsIterable(Collection.NODES, null, null, RDBDocumentStore.EMPTY_KEY_PATTERN, conditions, Integer.MAX_VALUE, null); } diff --git a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/BasicDocumentStoreTest.java b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/BasicDocumentStoreTest.java index de346ffb8b..7608e22730 100644 --- a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/BasicDocumentStoreTest.java +++ b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/BasicDocumentStoreTest.java @@ -1142,11 +1142,13 @@ public class BasicDocumentStoreTest extends AbstractDocumentStoreTest { @Test public void removeInvalidatesCache() throws Exception { - String id = Utils.getIdFromPath("/foo"); + String path = "/foo"; + String id = Utils.getIdFromPath(path); long modified = 1; removeMe.add(id); - ds.create(Collection.NODES, Collections.singletonList(newDocument(id, modified))); - ds.remove(Collection.NODES, Collections.singletonMap(id, modified)); + ds.create(Collection.NODES, Collections.singletonList(newDocument(path, modified))); + int removed = ds.remove(Collection.NODES, Collections.singletonMap(id, modified)); + assertEquals(1, removed); assertNull(ds.getIfCached(Collection.NODES, id)); } diff --git a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeekerTest.java b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeekerTest.java index 607a0b4baf..6280066cbd 100644 --- a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeekerTest.java +++ b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/MissingLastRevSeekerTest.java @@ -24,12 +24,17 @@ import org.apache.jackrabbit.oak.plugins.document.mongo.MongoDocumentStore; import org.apache.jackrabbit.oak.plugins.document.mongo.MongoMissingLastRevSeeker; import org.apache.jackrabbit.oak.plugins.document.rdb.RDBDocumentStore; import org.apache.jackrabbit.oak.plugins.document.rdb.RDBMissingLastRevSeeker; +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 static org.apache.jackrabbit.oak.plugins.document.ClusterNodeInfo.DEFAULT_LEASE_DURATION_MILLIS; +import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.NUM_REVS_THRESHOLD; import static org.apache.jackrabbit.oak.plugins.document.RecoveryHandler.NOOP; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -71,6 +76,12 @@ public class MissingLastRevSeekerTest extends AbstractDocumentStoreTest { Revision.resetClockToDefault(); } + private void markDocumentsForCleanup() { + for (NodeDocument doc : Utils.getAllDocuments(ds)) { + removeMe.add(doc.getId()); + } + } + @Test public void acquireRecoveryLockOnActiveClusterNode() { ClusterNodeInfo.getInstance(store, NOOP, null, null, 1); @@ -216,4 +227,31 @@ public class MissingLastRevSeekerTest extends AbstractDocumentStoreTest { private ClusterNodeInfoDocument getClusterNodeInfo(int clusterId) { return seeker.getClusterNodeInfo(clusterId); } + + @Test + public void getNonSplitDocs() throws Exception { + String nodeName = this.getClass().getName() + "-foo"; + DocumentNodeStore dns = getBuilder().clock(clock).setAsyncDelay(0).setDocumentStore(new DocumentStoreWrapper(store) { + @Override + public void dispose() { + // do not close underlying store, otherwise cleanup + // cannot remove documents after the test + } + }).getNodeStore(); + NodeBuilder b1 = dns.getRoot().builder(); + b1.child(nodeName); + dns.merge(b1, EmptyHook.INSTANCE, CommitInfo.EMPTY); + //Modify and commit changes on this node 100 times to create a split document + for (int i = 0; i < NUM_REVS_THRESHOLD; i++) { + b1 = dns.getRoot().builder(); + b1.child(nodeName).setProperty("prop",i); + dns.merge(b1, EmptyHook.INSTANCE, CommitInfo.EMPTY); + } + dns.runBackgroundOperations(); + //seeker should return only non split documents + int docs = Iterables.size(seeker.getCandidates(0)); + assertEquals(2, docs); + markDocumentsForCleanup(); + dns.dispose(); + } }