Author: chetanm
Date: Sat Mar 29 10:00:59 2014
New Revision: 1582971

URL: http://svn.apache.org/r1582971
Log:
OAK-1344 - HierarchicalInvalidator hits query size limit

-- Performing in query in batches
-- Close the cursor properly

Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/CacheInvalidator.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/CacheInvalidator.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/CacheInvalidator.java?rev=1582971&r1=1582970&r2=1582971&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/CacheInvalidator.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/CacheInvalidator.java
 Sat Mar 29 10:00:59 2014
@@ -27,6 +27,7 @@ import java.util.Map;
 
 import com.google.common.base.Objects;
 import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.PeekingIterator;
 import com.google.common.collect.TreeTraverser;
@@ -163,6 +164,7 @@ abstract class CacheInvalidator {
                 return root.children();
             }
         };
+        public static final int IN_QUERY_BATCH_SIZE = 250;
 
         private final DBCollection nodes;
         private final MongoDocumentStore documentStore;
@@ -209,41 +211,48 @@ abstract class CacheInvalidator {
 
                 final boolean hasMore = pitr.hasNext();
 
-                // Change in level or last element
+                // Change in level of last element
                 if (!sameLevelNodes.isEmpty() &&
                         ((hasMore && tn.level() != pitr.peek().level()) || 
!hasMore)) {
+                    List<String> sameLevelNodeIds = new 
ArrayList<String>(sameLevelNodes.keySet());
+                    for(List<String> idBatch : 
Lists.partition(sameLevelNodeIds, IN_QUERY_BATCH_SIZE)) {
 
-                    QueryBuilder query = QueryBuilder.start(Document.ID)
-                            .in(sameLevelNodes.keySet());
+                        QueryBuilder query = QueryBuilder.start(Document.ID)
+                                .in(idBatch);
 
-                    // Fetch lastRev and modCount for each such nodes
-                    DBCursor cursor = nodes.find(query.get(), keys);
-                    LOG.debug(
-                            "Checking for changed nodes at level {} with {} 
paths",
-                            tn.level(), sameLevelNodes.size());
-                    result.queryCount++;
-                    for (DBObject obj : cursor) {
-
-                        result.cacheEntriesProcessedCount++;
-
-                        Number latestModCount = (Number) 
obj.get(Document.MOD_COUNT);
-                        String id = (String) obj.get(Document.ID);
-
-                        final TreeNode tn2 = sameLevelNodes.get(id);
-                        CachedNodeDocument cachedDoc = tn2.getDocument();
-                        if (cachedDoc != null) {
-                            boolean noChangeInModCount = 
Objects.equal(latestModCount, cachedDoc.getModCount());
-                            if (noChangeInModCount) {
-                                result.upToDateCount++;
-                                tn2.markUptodate(startTime);
-                            } else {
-                                result.invalidationCount++;
-                                tn2.invalidate();
+                        // Fetch lastRev and modCount for each such nodes
+                        DBCursor cursor = nodes.find(query.get(), keys);
+                        LOG.debug(
+                                "Checking for changed nodes at level {} with 
{} paths",
+                                tn.level(), sameLevelNodes.size());
+                        result.queryCount++;
+                        try {
+                            for (DBObject obj : cursor) {
+
+                                result.cacheEntriesProcessedCount++;
+
+                                Number latestModCount = (Number) 
obj.get(Document.MOD_COUNT);
+                                String id = (String) obj.get(Document.ID);
+
+                                final TreeNode tn2 = sameLevelNodes.get(id);
+                                CachedNodeDocument cachedDoc = 
tn2.getDocument();
+                                if (cachedDoc != null) {
+                                    boolean noChangeInModCount = 
Objects.equal(latestModCount, cachedDoc.getModCount());
+                                    if (noChangeInModCount) {
+                                        result.upToDateCount++;
+                                        tn2.markUptodate(startTime);
+                                    } else {
+                                        result.invalidationCount++;
+                                        tn2.invalidate();
+                                    }
+                                }
+
+                                // Remove the processed nodes
+                                sameLevelNodes.remove(tn2.getId());
                             }
+                        } finally {
+                            cursor.close();
                         }
-
-                        // Remove the processed nodes
-                        sameLevelNodes.remove(tn2.getId());
                     }
 
                     // NodeDocument present in cache but not in database


Reply via email to