Author: catholicon
Date: Wed Nov 16 04:07:12 2016
New Revision: 1769922

URL: http://svn.apache.org/viewvc?rev=1769922&view=rev
Log:
OAK-3001: Simplify JournalGarbageCollector using a dedicated timestamp property
----Sub-tasks-----
OAK-3982: DocumentStore: add method to remove with a condition on an indexed 
property
OAK-3985: MongoDocumentStore: implement new conditional remove method
OAK-3984: RDBDocumentStore: implement new conditional remove method
OAK-3983: JournalGarbageCollector: use new DocumentStore remove() method

Added interface method and implemented in Mem/Mongo/RDBDocStore as well as in 
DocStoreWrappers.
Added test in BasicDocumentStoreTest against the new method. JournalGC tests 
pass, so no new one added there.

Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentStore.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalGarbageCollector.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/memory/MemoryDocumentStore.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/LeaseCheckDocumentStoreWrapper.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/LoggingDocumentStoreWrapper.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/SynchronizingDocumentStoreWrapper.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/TimingDocumentStoreWrapper.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/BasicDocumentStoreTest.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CountingDocumentStore.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentStoreWrapper.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentStore.java?rev=1769922&r1=1769921&r2=1769922&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentStore.java
 Wed Nov 16 04:07:12 2016
@@ -202,6 +202,34 @@ public interface DocumentStore {
                                     Map<String, Map<UpdateOp.Key, 
UpdateOp.Condition>> toRemove)
             throws DocumentStoreException;
 
+
+    /**
+     * Batch remove documents where the given "indexed property" is within the 
given
+     * range (inclusive) - {@code [startValue, endValue]}.
+     * <p>
+     * The indexed property is a {@link Long} value and numeric comparison 
applies.
+     * <p>
+     * In case of a {@code DocumentStoreException}, the documents with the 
given
+     * keys may or may not have been removed from the store. It may also be
+     * possible that only some have been removed from the store. It is the
+     * responsibility of the caller to check which documents still exist. The
+     * implementation however ensures that the result of the operation is
+     * properly reflected in the document cache. That is, an implementation
+     * could simply evict documents with the given keys from the cache.
+     *
+     * @param <T> the document type
+     * @param collection the collection.
+     * @param indexedProperty the name of the indexed property
+     * @param startValue the minimum value of the indexed property
+     * @param endValue the maximum value of the indexed property
+     * @return the number of removed documents.
+     * @throws DocumentStoreException if the operation failed. E.g. because of
+     *          an I/O error.
+     */
+    <T extends Document> int remove(Collection<T> collection,
+                                    String indexedProperty, long startValue, 
long endValue)
+            throws DocumentStoreException;
+
     /**
      * Try to create a list of documents. This method returns {@code true} iff
      * none of the documents existed before and the create was successful. This

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalGarbageCollector.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalGarbageCollector.java?rev=1769922&r1=1769921&r2=1769922&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalGarbageCollector.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalGarbageCollector.java
 Wed Nov 16 04:07:12 2016
@@ -90,68 +90,11 @@ public class JournalGarbageCollector {
         }
         Stopwatch sw = Stopwatch.createStarted();
 
-        // the journal has ids of the following format:
-        // 1-0000014db9aaf710-00000001
-        // whereas the first number is the cluster node id.
-        // now, this format prevents from doing a generic
-        // query to get all 'old' entries, as the documentstore
-        // can only query for a sequential list of entries.
-        // (and the cluster node id here partitions the set
-        // of entries that we have to delete)
-        // To account for that, we simply iterate over all 
-        // cluster node ids and clean them up individually.
-        // Note that there are possible alternatives, such
-        // as: let each node clean up its own old entries
-        // but the chosen path is also quite simple: it can
-        // be started on any instance - but best on only one.
-        // if it's run on multiple concurrently, then they
-        // will compete at deletion, which is not optimal
-        // due to performance, but does not harm.
-
         // update the tail timestamp in the journalGC document
         // of the settings collection
         updateTailTimestamp(gcOlderThan);
 
-        // 1. get the list of cluster node ids
-        final List<ClusterNodeInfoDocument> clusterNodeInfos = 
ClusterNodeInfoDocument.all(ds);
-        int numDeleted = 0;
-        for (ClusterNodeInfoDocument clusterNodeInfoDocument : 
clusterNodeInfos) {
-            // current algorithm is to simply look at all cluster nodes
-            // irrespective of whether they are active or inactive etc.
-            // this could be optimized for inactive ones: at some point, all
-            // journal entries of inactive ones would have been cleaned up
-            // and at that point we could stop including those 
long-time-inactive ones.
-            // that 'long time' aspect would have to be tracked though, to be 
sure
-            // we don't leave garbage.
-            // so simpler is to quickly do a query even for long-time inactive 
ones
-            final int clusterNodeId = clusterNodeInfoDocument.getClusterId();
-
-            // 2. iterate over that list and do a query with
-            //    a limit of 'batch size'
-            boolean branch = false;
-            long startPointer = 0;
-            while (true) {
-                String fromKey = JournalEntry.asId(new Revision(startPointer, 
0, clusterNodeId, branch));
-                String toKey = JournalEntry.asId(new Revision(gcOlderThan, 0, 
clusterNodeId, branch));
-                List<JournalEntry> deletionBatch = 
ds.query(Collection.JOURNAL, fromKey, toKey, batchSize);
-                if (deletionBatch.size() > 0) {
-                    ds.remove(Collection.JOURNAL, asKeys(deletionBatch));
-                    numDeleted += deletionBatch.size();
-                }
-                if (deletionBatch.size() < batchSize) {
-                    if (!branch) {
-                        // do the same for branches:
-                        // this will start at the beginning again with branch 
set to true
-                        // and eventually finish too
-                        startPointer = 0;
-                        branch = true;
-                        continue;
-                    }
-                    break;
-                }
-                startPointer = deletionBatch.get(deletionBatch.size() - 
1).getRevisionTimestamp();
-            }
-        }
+        int numDeleted = ds.remove(Collection.JOURNAL, JournalEntry.MODIFIED, 
0, gcOlderThan);
 
         sw.stop();
 

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/memory/MemoryDocumentStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/memory/MemoryDocumentStore.java?rev=1769922&r1=1769921&r2=1769922&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/memory/MemoryDocumentStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/memory/MemoryDocumentStore.java
 Wed Nov 16 04:07:12 2016
@@ -27,8 +27,11 @@ import java.util.concurrent.locks.Reentr
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
+import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
 import org.apache.jackrabbit.oak.cache.CacheStats;
 import org.apache.jackrabbit.oak.plugins.document.Collection;
 import org.apache.jackrabbit.oak.plugins.document.Document;
@@ -44,6 +47,7 @@ import com.google.common.base.Splitter;
 import com.mongodb.ReadPreference;
 import com.mongodb.WriteConcern;
 import org.apache.jackrabbit.oak.plugins.document.cache.CacheInvalidationStats;
+import org.apache.jackrabbit.oak.plugins.document.util.Utils;
 
 import static 
org.apache.jackrabbit.oak.plugins.document.UpdateUtils.assertUnconditional;
 import static 
org.apache.jackrabbit.oak.plugins.document.UpdateUtils.checkConditions;
@@ -202,6 +206,31 @@ public class MemoryDocumentStore impleme
         return num;
     }
 
+    @Override
+    public <T extends Document> int remove(Collection<T> collection,
+                                    final String indexedProperty, final long 
startValue, final long endValue)
+            throws DocumentStoreException {
+        ConcurrentSkipListMap<String, T> map = getMap(collection);
+        int num = map.size();
+
+        Lock lock = rwLock.writeLock();
+        lock.lock();
+        try {
+            Maps.filterValues(map, new Predicate<T>() {
+                @Override
+                public boolean apply(@Nullable T doc) {
+                    Long modified = Utils.asLong((Number) 
doc.get(indexedProperty));
+                    return startValue <= modified && modified <= endValue;
+                }
+            }).clear();
+        } finally {
+            lock.unlock();
+        }
+
+        num -= map.size();
+        return num;
+    }
+
     @CheckForNull
     @Override
     public <T extends Document> T createOrUpdate(Collection<T> collection, 
UpdateOp update) {

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java?rev=1769922&r1=1769921&r2=1769922&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
 Wed Nov 16 04:07:12 2016
@@ -764,6 +764,39 @@ public class MongoDocumentStore implemen
         return num;
     }
 
+    @Override
+    public <T extends Document> int remove(Collection<T> collection,
+                                    String indexedProperty, long startValue, 
long endValue)
+            throws DocumentStoreException {
+        log("remove", collection, indexedProperty, startValue, endValue);
+        int num = 0;
+        DBCollection dbCollection = getDBCollection(collection);
+        long start = PERFLOG.start();
+        try {
+            QueryBuilder queryBuilder = QueryBuilder.start(indexedProperty);
+            queryBuilder.greaterThanEquals(startValue);
+            queryBuilder.lessThanEquals(endValue);
+            try {
+                num = dbCollection.remove(queryBuilder.get()).getN();
+            } catch (Exception e) {
+                throw DocumentStoreException.convert(e, "Remove failed for " + 
collection + ": " +
+                    indexedProperty + " in [" + startValue + ", " + endValue + 
"]");
+            } finally {
+                if (num > 0 && collection == Collection.NODES) {
+                    // this method is currently being used only for Journal 
collection while GC.
+                    // But, to keep sanctity of the API, we need to 
acknowledge that Nodes collection
+                    // could've been used. But, in this signature, there's no 
useful way to invalidate
+                    // cache.
+                    // So, we use the hammer for this task
+                    invalidateCache();
+                }
+            }
+        } finally {
+            PERFLOG.end(start, 1, "remove from {}: {} in [{}, {}]", 
collection, indexedProperty, startValue, endValue);
+        }
+        return num;
+    }
+
     @SuppressWarnings("unchecked")
     @CheckForNull
     private <T extends Document> T findAndModify(Collection<T> collection,

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java?rev=1769922&r1=1769921&r2=1769922&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java
 Wed Nov 16 04:07:12 2016
@@ -279,6 +279,27 @@ public class RDBDocumentStore implements
     }
 
     @Override
+    public <T extends Document> int remove(Collection<T> collection,
+                                    String indexedProperty, long startValue, 
long endValue)
+            throws DocumentStoreException {
+        int num = 0;
+        try {
+            num = delete(collection, indexedProperty, startValue, endValue);
+        } finally {
+            if (num > 0 && collection == Collection.NODES) {
+                // this method is currently being used only for Journal 
collection while GC.
+                // But, to keep sanctity of the API, we need to acknowledge 
that Nodes collection
+                // could've been used. But, in this signature, there's no 
useful way to invalidate
+                // cache.
+                // So, we use the hammer for this task
+                invalidateCache();
+            }
+        }
+        return num;
+    }
+
+
+    @Override
     public <T extends Document> boolean create(Collection<T> collection, 
List<UpdateOp> updateOps) {
         return internalCreate(collection, updateOps);
     }
@@ -1565,6 +1586,23 @@ public class RDBDocumentStore implements
         }
         return numDeleted;
     }
+
+    private <T extends Document> int delete(Collection<T> collection,
+                                            String indexedProperty, long 
startVal, long endVal) {
+        int numDeleted = 0;
+        RDBTableMetaData tmd = getTable(collection);
+        Connection connection = null;
+        try {
+            connection = this.ch.getRWConnection();
+            numDeleted = db.delete(connection, tmd, indexedProperty, startVal, 
endVal);
+            connection.commit();
+        } catch (Exception ex) {
+            throw DocumentStoreException.convert(ex, "deleting " + collection 
+ ": " + indexedProperty + " in [" + startVal + ", " + endVal + "]");
+        } finally {
+            this.ch.closeConnection(connection);
+        }
+        return numDeleted;
+    }
 
     private <T extends Document> boolean updateDocument(@Nonnull Collection<T> 
collection, @Nonnull T document,
             @Nonnull UpdateOp update, Long oldmodcount) {

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java?rev=1769922&r1=1769921&r2=1769922&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java
 Wed Nov 16 04:07:12 2016
@@ -225,6 +225,23 @@ public class RDBDocumentStoreJDBC {
         }
     }
 
+    public int delete(Connection connection, RDBTableMetaData tmd, String 
property, long startVal, long endVal)
+            throws SQLException, DocumentStoreException {
+        if (!MODIFIED.equals(property)) {
+            throw new DocumentStoreException("Unsupported condition: " + 
property + " in [" + startVal + ", " + endVal + "]");
+        }
+        PreparedStatement stmt = connection.prepareStatement("delete from " + 
tmd.getName() +
+                " where MODIFIED >= ? AND MODIFIED <= ?");
+        try {
+            int i = 1;
+            stmt.setLong(i++, startVal);
+            stmt.setLong(i++, endVal);
+            return stmt.executeUpdate();
+        } finally {
+            stmt.close();
+        }
+    }
+
     public long determineServerTimeDifferenceMillis(Connection connection) {
         String sql = this.dbInfo.getCurrentTimeStampInSecondsSyntax();
 

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/LeaseCheckDocumentStoreWrapper.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/LeaseCheckDocumentStoreWrapper.java?rev=1769922&r1=1769921&r2=1769922&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/LeaseCheckDocumentStoreWrapper.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/LeaseCheckDocumentStoreWrapper.java
 Wed Nov 16 04:07:12 2016
@@ -26,6 +26,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.document.Collection;
 import org.apache.jackrabbit.oak.plugins.document.Document;
 import org.apache.jackrabbit.oak.plugins.document.DocumentStore;
+import org.apache.jackrabbit.oak.plugins.document.DocumentStoreException;
 import org.apache.jackrabbit.oak.plugins.document.RevisionListener;
 import org.apache.jackrabbit.oak.plugins.document.RevisionVector;
 import org.apache.jackrabbit.oak.plugins.document.UpdateOp;
@@ -108,6 +109,14 @@ public final class LeaseCheckDocumentSto
     }
 
     @Override
+    public<T extends Document> int remove(Collection<T> collection,
+                                          String indexedProperty, long 
startValue, long endValue)
+            throws DocumentStoreException {
+        performLeaseCheck();
+        return delegate.remove(collection, indexedProperty, startValue, 
endValue);
+    }
+
+    @Override
     public final <T extends Document> boolean create(Collection<T> collection,
             List<UpdateOp> updateOps) {
         performLeaseCheck();

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/LoggingDocumentStoreWrapper.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/LoggingDocumentStoreWrapper.java?rev=1769922&r1=1769921&r2=1769922&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/LoggingDocumentStoreWrapper.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/LoggingDocumentStoreWrapper.java
 Wed Nov 16 04:07:12 2016
@@ -173,6 +173,24 @@ public class LoggingDocumentStoreWrapper
     }
 
     @Override
+    public <T extends Document> int remove(final Collection<T> collection,
+                                           final String indexedProperty, final 
long startValue, final long endValue)
+            throws DocumentStoreException {
+        try {
+            logMethod("remove", collection, indexedProperty, startValue, 
endValue);
+            return logResult(new Callable<Integer>() {
+                @Override
+                public Integer call() throws Exception {
+                    return store.remove(collection, indexedProperty, 
startValue, endValue);
+                }
+            });
+        } catch (Exception e) {
+            logException(e);
+            throw convert(e);
+        }
+    }
+
+    @Override
     public <T extends Document> boolean create(final Collection<T> collection,
                                                final List<UpdateOp> updateOps) 
{
         try {

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/SynchronizingDocumentStoreWrapper.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/SynchronizingDocumentStoreWrapper.java?rev=1769922&r1=1769921&r2=1769922&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/SynchronizingDocumentStoreWrapper.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/SynchronizingDocumentStoreWrapper.java
 Wed Nov 16 04:07:12 2016
@@ -25,6 +25,7 @@ import org.apache.jackrabbit.oak.cache.C
 import org.apache.jackrabbit.oak.plugins.document.Collection;
 import org.apache.jackrabbit.oak.plugins.document.Document;
 import org.apache.jackrabbit.oak.plugins.document.DocumentStore;
+import org.apache.jackrabbit.oak.plugins.document.DocumentStoreException;
 import org.apache.jackrabbit.oak.plugins.document.RevisionListener;
 import org.apache.jackrabbit.oak.plugins.document.RevisionVector;
 import org.apache.jackrabbit.oak.plugins.document.UpdateOp;
@@ -83,6 +84,13 @@ public class SynchronizingDocumentStoreW
     }
 
     @Override
+    public <T extends Document> int remove(Collection<T> collection,
+                                           String indexedProperty, long 
startValue, long endValue)
+            throws DocumentStoreException {
+        return store.remove(collection, indexedProperty, startValue, endValue);
+    }
+
+    @Override
     public synchronized <T extends Document> boolean create(final 
Collection<T> collection, final List<UpdateOp> updateOps) {
         return store.create(collection, updateOps);
     }

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/TimingDocumentStoreWrapper.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/TimingDocumentStoreWrapper.java?rev=1769922&r1=1769921&r2=1769922&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/TimingDocumentStoreWrapper.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/TimingDocumentStoreWrapper.java
 Wed Nov 16 04:07:12 2016
@@ -212,6 +212,25 @@ public class TimingDocumentStoreWrapper
     }
 
     @Override
+    public <T extends Document> int remove(Collection<T> collection,
+                                               String indexedProperty, long 
startValue, long endValue)
+            throws DocumentStoreException {
+        try {
+            long start = now();
+            int result = base.remove(collection, indexedProperty, startValue, 
endValue);
+            updateAndLogTimes("remove", start, 0, 0);
+            if (logCommonCall()) {
+                logCommonCall(start, "remove " + collection + "; 
indexedProperty" + indexedProperty +
+                    "; range - [" + startValue + ", " + endValue + "]");
+            }
+            return result;
+        } catch (Exception e) {
+            throw convert(e);
+        }
+    }
+
+
+    @Override
     public <T extends Document> boolean create(Collection<T> collection, 
List<UpdateOp> updateOps) {
         try {
             long start = now();

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/BasicDocumentStoreTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/BasicDocumentStoreTest.java?rev=1769922&r1=1769921&r2=1769922&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/BasicDocumentStoreTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/BasicDocumentStoreTest.java
 Wed Nov 16 04:07:12 2016
@@ -41,8 +41,11 @@ import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.ContiguousSet;
+import com.google.common.collect.DiscreteDomain;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.common.collect.Range;
 
 public class BasicDocumentStoreTest extends AbstractDocumentStoreTest {
 
@@ -357,6 +360,50 @@ public class BasicDocumentStoreTest exte
         }
     }
 
+    //OAK-3001
+    @Test
+    public void testRangeRemove() {
+        String idPrefix = this.getClass().getName() + ".testRangeRemove";
+
+        com.google.common.collect.Range<Long> modTimes = Range.closed(1L, 30L);
+        for (Long modTime : ContiguousSet.create(modTimes, 
DiscreteDomain.longs())) {
+            String id = idPrefix + modTime;
+            // remove if present
+            Document d = super.ds.find(Collection.JOURNAL, id);
+            if (d != null) {
+                super.ds.remove(Collection.JOURNAL, id);
+            }
+
+            // add
+            UpdateOp up = new UpdateOp(id, true);
+            up.set("_id", id);
+            up.set("_modified", modTime);
+            super.ds.create(Collection.JOURNAL, Collections.singletonList(up));
+        }
+
+        assertEquals("Number of entries removed didn't match", 5,
+                ds.remove(Collection.JOURNAL, "_modified", 20, 24));
+
+        assertEquals("Number of entries removed didn't match", 0,
+                ds.remove(Collection.JOURNAL, "_modified", 20, 24));
+
+        assertEquals("Number of entries removed didn't match", 5,
+                ds.remove(Collection.JOURNAL, "_modified", -1, 5));
+
+        assertEquals("Number of entries removed didn't match", 5,
+                ds.remove(Collection.JOURNAL, "_modified", 0, 10));
+
+        // interesting cases
+        assertEquals("Number of entries removed didn't match", 0,
+                ds.remove(Collection.JOURNAL, "_modified", 20, 19));
+
+        assertEquals("Number of entries removed didn't match", 0,
+                ds.remove(Collection.JOURNAL, "_modified", 31, 40));
+
+        assertEquals("Number of entries removed didn't match", 3,
+                ds.remove(Collection.JOURNAL, "_modified", 28, 40));
+    }
+
     private int testMaxId(boolean ascii) {
         int min = 0;
         int max = 32768;

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CountingDocumentStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CountingDocumentStore.java?rev=1769922&r1=1769921&r2=1769922&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CountingDocumentStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CountingDocumentStore.java
 Wed Nov 16 04:07:12 2016
@@ -149,6 +149,14 @@ public class CountingDocumentStore imple
     }
 
     @Override
+    public <T extends Document> int remove(Collection<T> collection,
+                                           String indexedProperty, long 
startValue, long endValue)
+            throws DocumentStoreException {
+        getStats(collection).numRemoveCalls++;
+        return delegate.remove(collection, indexedProperty, startValue, 
endValue);
+    }
+
+    @Override
     public <T extends Document> boolean create(Collection<T> collection,
                                                List<UpdateOp> updateOps) {
         getStats(collection).numCreateOrUpdateCalls++;

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentStoreWrapper.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentStoreWrapper.java?rev=1769922&r1=1769921&r2=1769922&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentStoreWrapper.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentStoreWrapper.java
 Wed Nov 16 04:07:12 2016
@@ -88,6 +88,13 @@ public class DocumentStoreWrapper implem
     }
 
     @Override
+    public <T extends Document> int remove(Collection<T> collection,
+                                           String indexedProperty, long 
startValue, long endValue)
+            throws DocumentStoreException {
+        return store.remove(collection, indexedProperty, startValue, endValue);
+    }
+
+    @Override
     public <T extends Document> boolean create(Collection<T> collection,
                                                List<UpdateOp> updateOps) {
         return store.create(collection, updateOps);


Reply via email to