### Eclipse Workspace Patch 1.0 #P jackrabbit-core Index: src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java (revision 1539029) +++ src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java (working copy) @@ -35,6 +35,7 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; @@ -87,6 +88,12 @@ */ private static final int NODESATONCE = Integer.getInteger("org.apache.jackrabbit.garbagecollector.nodesatonce", 1024 * 8); + /** + * Set this System Property to true to speed up the node traversing in a binary focused repository. + * See JCR-3708 + */ + private static final boolean NODE_ID_SCAN = Boolean.getBoolean("org.apache.jackrabbit.garbagecollector.node_id.scan"); + private MarkEventListener callback; private long sleepBetweenNodes; @@ -169,7 +176,11 @@ } } else { try { - scanPersistenceManagers(); + if (!NODE_ID_SCAN) { + scanPersistenceManagersByNodeInfos(); + } else { + scanPersistenceManagersByNodeIds(); + } } catch (ItemStateException e) { throw new RepositoryException(e); } @@ -195,12 +206,19 @@ return persistenceManagerScan; } - private void scanPersistenceManagers() throws RepositoryException, ItemStateException { + private void scanPersistenceManagersByNodeInfos() throws RepositoryException, ItemStateException { + int pmCount = 0; for (IterablePersistenceManager pm : pmList) { + pmCount++; + int count = 0; Map batch = pm.getAllNodeInfos(null, NODESATONCE); while (!batch.isEmpty()) { NodeId lastId = null; for (NodeInfo info : batch.values()) { + count++; + if (count % 1000 == 0) { + LOG.debug(pm.toString() + " ("+pmCount + "/" + pmList.length + "): analyzed " + count + " nodes..."); + } lastId = info.getId(); if (callback != null) { callback.beforeScanning(null); @@ -231,6 +249,43 @@ NodeInfo.clearPool(); } + private void scanPersistenceManagersByNodeIds() throws RepositoryException, ItemStateException { + int pmCount = 0; + for (IterablePersistenceManager pm : pmList) { + pmCount++; + List allNodeIds = pm.getAllNodeIds(null, 0); + int overAllCount = allNodeIds.size(); + int count = 0; + for (NodeId id : allNodeIds) { + count++; + if (count % 1000 == 0) { + LOG.debug(pm.toString() + " ("+pmCount + "/" + pmList.length + "): analyzed " + count + " nodes [" + overAllCount + "]..."); + } + if (callback != null) { + callback.beforeScanning(null); + } + try { + NodeState state = pm.load(id); + Set propertyNames = state.getPropertyNames(); + for (Name name : propertyNames) { + PropertyId pid = new PropertyId(id, name); + PropertyState ps = pm.load(pid); + if (ps.getType() == PropertyType.BINARY) { + for (InternalValue v : ps.getValues()) { + // getLength will update the last modified date + // if the persistence manager scan is running + v.getLength(); + } + } + } + } catch (NoSuchItemStateException e) { + // the node may have been deleted or moved in the meantime + // ignore it + } + } + } + } + /** * Reset modifiedDateOnAccess to 0 and stop the observation * listener if any are installed.