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 re...@apache.org on 2020/03/02 14:09:00 UTC

svn commit: r1874692 - /jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBVersionGCSupport.java

Author: reschke
Date: Mon Mar  2 14:09:00 2020
New Revision: 1874692

URL: http://svn.apache.org/viewvc?rev=1874692&view=rev
Log:
OAK-8932: RDBDocumentStore: allow RDBVersionGC support fallback to simpler algorithm

Modified:
    jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBVersionGCSupport.java

Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBVersionGCSupport.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBVersionGCSupport.java?rev=1874692&r1=1874691&r2=1874692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBVersionGCSupport.java (original)
+++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBVersionGCSupport.java Mon Mar  2 14:09:00 2020
@@ -16,11 +16,14 @@
  */
 package org.apache.jackrabbit.oak.plugins.document.rdb;
 
+import static com.google.common.collect.Iterables.filter;
+
 import java.io.Closeable;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
@@ -40,6 +43,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Predicate;
+import com.google.common.collect.AbstractIterator;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
@@ -53,6 +57,37 @@ public class RDBVersionGCSupport extends
 
     private RDBDocumentStore store;
 
+    // 1: seek using historical, paging mode
+    // 2: use custom single query directly using RDBDocumentStore API
+    private static final int MODE;
+
+    private static final int DEFAULTMODE = 2;
+
+    static {
+        String propName = RDBVersionGCSupport.class.getName() + ".MODE";
+        String value = System.getProperty(propName, "");
+        switch (value) {
+            case "":
+                MODE = DEFAULTMODE;
+                break;
+            case "1":
+                MODE = 1;
+                break;
+            case "2":
+                MODE = 2;
+                break;
+            default:
+                LOG.error("Ignoring unexpected value '" + value + "' for system property " + propName);
+                MODE = DEFAULTMODE;
+                break;
+        }
+
+        if (DEFAULTMODE != MODE) {
+            LOG.info("Strategy for " + RDBVersionGCSupport.class.getName() + " set to " + MODE + " (via system property "
+                    + propName + ")");
+        }
+    }
+
     public RDBVersionGCSupport(RDBDocumentStore store) {
         super(store);
         this.store = store;
@@ -64,13 +99,49 @@ public class RDBVersionGCSupport extends
         conditions.add(new QueryCondition(NodeDocument.DELETED_ONCE, "=", 1));
         conditions.add(new QueryCondition(NodeDocument.MODIFIED_IN_SECS, "<", NodeDocument.getModifiedInSecs(toModified)));
         conditions.add(new QueryCondition(NodeDocument.MODIFIED_IN_SECS, ">=", NodeDocument.getModifiedInSecs(fromModified)));
-        return store.queryAsIterable(Collection.NODES, null, null, RDBDocumentStore.EMPTY_KEY_PATTERN, conditions, Integer.MAX_VALUE, null);
+        if (MODE == 1) {
+            return getIterator(RDBDocumentStore.EMPTY_KEY_PATTERN, conditions);
+        } else {
+            return store.queryAsIterable(Collection.NODES, null, null, RDBDocumentStore.EMPTY_KEY_PATTERN, conditions, Integer.MAX_VALUE, null);
+        }
     }
 
     @Override
-    protected Iterable<NodeDocument> identifyGarbage(final Set<SplitDocType> gcTypes,
-                                                     final RevisionVector sweepRevs,
-                                                     final long oldestRevTimeStamp) {
+    protected Iterable<NodeDocument> identifyGarbage(final Set<SplitDocType> gcTypes, final RevisionVector sweepRevs,
+            final long oldestRevTimeStamp) {
+        if (MODE == 1) {
+            return identifyGarbageMode1(gcTypes, sweepRevs, oldestRevTimeStamp);
+        } else {
+            return identifyGarbageMode2(gcTypes, sweepRevs, oldestRevTimeStamp);
+        }
+    }
+
+    private Iterable<NodeDocument> getSplitDocuments() {
+        List<QueryCondition> conditions = Collections.emptyList();
+        // absent support for SDTYPE as indexed property: exclude those
+        // documents from the query which definitively aren't split documents
+        List<String> excludeKeyPatterns = Arrays.asList("_:/%", "__:/%", "___:/%");
+        return getIterator(excludeKeyPatterns, conditions);
+    }
+
+    private Iterable<NodeDocument> identifyGarbageMode1(final Set<SplitDocType> gcTypes, final RevisionVector sweepRevs,
+            final long oldestRevTimeStamp) {
+        return filter(getSplitDocuments(), getGarbageCheckPredicate(gcTypes, sweepRevs, oldestRevTimeStamp));
+    }
+
+    private Predicate<NodeDocument> getGarbageCheckPredicate(final Set<SplitDocType> gcTypes, final RevisionVector sweepRevs,
+            final long oldestRevTimeStamp) {
+        return new Predicate<NodeDocument>() {
+            @Override
+            public boolean apply(NodeDocument doc) {
+                return gcTypes.contains(doc.getSplitDocType()) && doc.hasAllRevisionLessThan(oldestRevTimeStamp)
+                        && !isDefaultNoBranchSplitNewerThan(doc, sweepRevs);
+            }
+        };
+    }
+
+    private Iterable<NodeDocument> identifyGarbageMode2(final Set<SplitDocType> gcTypes, final RevisionVector sweepRevs,
+            final long oldestRevTimeStamp) {
         Iterable<NodeDocument> it1;
         Iterable<NodeDocument> it2;
         String name1, name2;
@@ -111,13 +182,7 @@ public class RDBVersionGCSupport extends
         final Iterable<NodeDocument> fit1 = it1;
         final Iterable<NodeDocument> fit2 = it2;
 
-        Predicate<NodeDocument> pred =  new Predicate<NodeDocument>() {
-            @Override
-            public boolean apply(NodeDocument doc) {
-                return gcTypes.contains(doc.getSplitDocType()) && doc.hasAllRevisionLessThan(oldestRevTimeStamp)
-                        && !isDefaultNoBranchSplitNewerThan(doc, sweepRevs);
-            }
-        };
+        Predicate<NodeDocument> pred = getGarbageCheckPredicate(gcTypes, sweepRevs, oldestRevTimeStamp);
 
         final CountingPredicate<NodeDocument> cp1 = new CountingPredicate<NodeDocument>(name1, pred);
         final CountingPredicate<NodeDocument> cp2 = new CountingPredicate<NodeDocument>(name2, pred);
@@ -200,4 +265,42 @@ public class RDBVersionGCSupport extends
         return store.queryCount(Collection.NODES, null, null, RDBDocumentStore.EMPTY_KEY_PATTERN,
                 Collections.singletonList(new QueryCondition(NodeDocument.DELETED_ONCE, "=", 1)));
     }
-}
\ No newline at end of file
+
+    private Iterable<NodeDocument> getIterator(final List<String> excludeKeyPatterns, final List<QueryCondition> conditions) {
+        return new Iterable<NodeDocument>() {
+            @Override
+            public Iterator<NodeDocument> iterator() {
+                return new AbstractIterator<NodeDocument>() {
+
+                    private static final int BATCH_SIZE = 100;
+                    private String startId = NodeDocument.MIN_ID_VALUE;
+                    private Iterator<NodeDocument> batch = nextBatch();
+
+                    @Override
+                    protected NodeDocument computeNext() {
+                        // read next batch if necessary
+                        if (!batch.hasNext()) {
+                            batch = nextBatch();
+                        }
+
+                        NodeDocument doc;
+                        if (batch.hasNext()) {
+                            doc = batch.next();
+                            // remember current id
+                            startId = doc.getId();
+                        } else {
+                            doc = endOfData();
+                        }
+                        return doc;
+                    }
+
+                    private Iterator<NodeDocument> nextBatch() {
+                        List<NodeDocument> result = store.query(Collection.NODES, startId, NodeDocument.MAX_ID_VALUE,
+                                excludeKeyPatterns, conditions, BATCH_SIZE);
+                        return result.iterator();
+                    }
+                };
+            }
+        };
+    }
+ }
\ No newline at end of file