This is an automated email from the ASF dual-hosted git repository.

daim pushed a commit to branch OAK-10740
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git

commit b52e82ec5d63e0b6b2bf6f7b34107c4b478a7311
Author: Rishabh Kumar <[email protected]>
AuthorDate: Thu Apr 4 11:08:49 2024 +0530

    OAK-10740 : added metrics for orphan nodes deletion
---
 .../document/DetailedRevisionGCStatsCollector.java |  6 ++
 .../DetailedRevisionGCStatsCollectorImpl.java      | 12 +++
 .../plugins/document/VersionGarbageCollector.java  | 88 +++++++++++++++-------
 .../DetailedRevisionGCStatsCollectorImplTest.java  | 13 ++++
 .../oak/plugins/document/VersionGCStatsTest.java   |  3 +
 5 files changed, 96 insertions(+), 26 deletions(-)

diff --git 
a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DetailedRevisionGCStatsCollector.java
 
b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DetailedRevisionGCStatsCollector.java
index 0a965f44be..a4d0163480 100644
--- 
a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DetailedRevisionGCStatsCollector.java
+++ 
b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DetailedRevisionGCStatsCollector.java
@@ -31,6 +31,12 @@ public interface DetailedRevisionGCStatsCollector {
      */
     void documentRead();
 
+    /**
+     * No. of orphan nodes deleted during DetailedGC
+     * @param numNodes no. of orphan nodes deleted in current cycle
+     */
+    void orphanNodesDeleted(long numNodes);
+
     /**
      * No. of properties deleted during DetailedGC
      * @param numProps no. of properties deleted in current cycle
diff --git 
a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DetailedRevisionGCStatsCollectorImpl.java
 
b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DetailedRevisionGCStatsCollectorImpl.java
index 01f196831f..8055889581 100644
--- 
a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DetailedRevisionGCStatsCollectorImpl.java
+++ 
b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DetailedRevisionGCStatsCollectorImpl.java
@@ -35,6 +35,7 @@ class DetailedRevisionGCStatsCollectorImpl implements 
DetailedRevisionGCStatsCol
 
     static final String DETAILED_GC = "DetailedGC";
     static final String READ_DOC = "READ_DOC";
+    static final String DELETED_ORPHAN_NODE = "DELETED_ORPHAN_NODE";
     static final String DELETED_PROPERTY = "DELETED_PROPERTY";
     static final String DELETED_UNMERGED_BC = "DELETED_UNMERGED_BC";
     static final String UPDATED_DOC = "UPDATED_DOC";
@@ -42,6 +43,7 @@ class DetailedRevisionGCStatsCollectorImpl implements 
DetailedRevisionGCStatsCol
     static final String DETAILED_GC_ACTIVE_TIMER = "DETAILED_GC_ACTIVE_TIMER";
     static final String DETAILED_GC_TIMER = "DETAILED_GC_TIMER";
     static final String COLLECT_DETAILED_GARBAGE_TIMER = 
"COLLECT_DETAILED_GARBAGE_TIMER";
+    static final String COLLECT_ORPHAN_NODES_TIMER = 
"COLLECT_ORPHAN_NODES_TIMER";
     static final String COLLECT_DELETED_PROPS_TIMER = 
"COLLECT_DELETED_PROPS_TIMER";
     static final String COLLECT_DELETED_OLD_REVS_TIMER = 
"COLLECT_DELETED_OLD_REVS_TIMER";
     static final String COLLECT_UNMERGED_BC_TIMER = 
"COLLECT_UNMERGED_BC_TIMER";
@@ -51,6 +53,7 @@ class DetailedRevisionGCStatsCollectorImpl implements 
DetailedRevisionGCStatsCol
     static final String FAILURE_COUNTER = "FAILURE";
 
     private final MeterStats readDoc;
+    private final MeterStats deletedOrphanNode;
     private final MeterStats deletedProperty;
     private final MeterStats deletedUnmergedBC;
     private final MeterStats updatedDoc;
@@ -58,6 +61,7 @@ class DetailedRevisionGCStatsCollectorImpl implements 
DetailedRevisionGCStatsCol
     private final TimerStats detailedGCActiveTimer;
     private final TimerStats detailedGCTimer;
     private final TimerStats collectDetailedGarbageTimer;
+    private final TimerStats collectOrphanNodesTimer;
     private final TimerStats collectDeletedPropsTimer;
     private final TimerStats collectDeletedOldRevsTimer;
     private final TimerStats collectUnmergedBCTimer;
@@ -69,6 +73,7 @@ class DetailedRevisionGCStatsCollectorImpl implements 
DetailedRevisionGCStatsCol
     DetailedRevisionGCStatsCollectorImpl(StatisticsProvider provider) {
 
         readDoc = meter(provider, READ_DOC);
+        deletedOrphanNode = meter(provider, DELETED_ORPHAN_NODE);
         deletedProperty = meter(provider, DELETED_PROPERTY);
         deletedUnmergedBC = meter(provider, DELETED_UNMERGED_BC);
         updatedDoc = meter(provider, UPDATED_DOC);
@@ -77,6 +82,7 @@ class DetailedRevisionGCStatsCollectorImpl implements 
DetailedRevisionGCStatsCol
         detailedGCActiveTimer = timer(provider, DETAILED_GC_ACTIVE_TIMER);
         detailedGCTimer = timer(provider, DETAILED_GC_TIMER);
         collectDetailedGarbageTimer = timer(provider, 
COLLECT_DETAILED_GARBAGE_TIMER);
+        collectOrphanNodesTimer = timer(provider, COLLECT_ORPHAN_NODES_TIMER);
         collectDeletedPropsTimer = timer(provider, 
COLLECT_DELETED_PROPS_TIMER);
         collectDeletedOldRevsTimer = timer(provider, 
COLLECT_DELETED_OLD_REVS_TIMER);
         collectUnmergedBCTimer = timer(provider, COLLECT_UNMERGED_BC_TIMER);
@@ -93,6 +99,11 @@ class DetailedRevisionGCStatsCollectorImpl implements 
DetailedRevisionGCStatsCol
         readDoc.mark();
     }
 
+    @Override
+    public void orphanNodesDeleted(long numNodes) {
+        deletedOrphanNode.mark(numNodes);
+    }
+
     @Override
     public void propertiesDeleted(long numProps) {
         deletedProperty.mark(numProps);
@@ -123,6 +134,7 @@ class DetailedRevisionGCStatsCollectorImpl implements 
DetailedRevisionGCStatsCol
         detailedGCActiveTimer.update(stats.detailedGCActiveElapsed, 
MICROSECONDS);
         detailedGCTimer.update(stats.detailedGCDocsElapsed, MICROSECONDS);
         
collectDetailedGarbageTimer.update(stats.collectDetailedGarbageElapsed, 
MICROSECONDS);
+        collectOrphanNodesTimer.update(stats.collectOrphanNodesElapsed, 
MICROSECONDS);
         collectDeletedPropsTimer.update(stats.collectDeletedPropsElapsed, 
MICROSECONDS);
         collectDeletedOldRevsTimer.update(stats.collectDeletedOldRevsElapsed, 
MICROSECONDS);
         collectUnmergedBCTimer.update(stats.collectUnmergedBCElapsed, 
MICROSECONDS);
diff --git 
a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollector.java
 
b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollector.java
index 82872b92fb..8aece8136d 100644
--- 
a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollector.java
+++ 
b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollector.java
@@ -69,6 +69,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import static java.lang.Math.round;
+import static java.lang.String.join;
 import static java.util.Collections.emptySet;
 import static java.util.Objects.requireNonNull;
 import static java.util.Optional.ofNullable;
@@ -92,6 +93,7 @@ import static 
org.apache.jackrabbit.oak.plugins.document.NodeDocument.MODIFIED_I
 import static 
org.apache.jackrabbit.oak.plugins.document.NodeDocument.SplitDocType.COMMIT_ROOT_ONLY;
 import static 
org.apache.jackrabbit.oak.plugins.document.NodeDocument.SplitDocType.DEFAULT_LEAF;
 import static 
org.apache.jackrabbit.oak.plugins.document.NodeDocument.SplitDocType.DEFAULT_NO_BRANCH;
+import static 
org.apache.jackrabbit.oak.plugins.document.util.Utils.timestampToString;
 import static org.apache.jackrabbit.oak.stats.StatisticsProvider.NOOP;
 import static 
org.apache.jackrabbit.oak.plugins.document.util.Utils.isCommitted;
 import static org.slf4j.helpers.MessageFormatter.arrayFormat;
@@ -364,6 +366,7 @@ public class VersionGarbageCollector {
         int deletedPropRevsCount;
         int deletedInternalPropRevsCount;
         int deletedUnmergedBCCount;
+        int deletedOrphanNodesCount;
         final TimeDurationFormatter df = TimeDurationFormatter.forLogging();
         final Stopwatch active = Stopwatch.createUnstarted();
         final Stopwatch detailedGCActive = Stopwatch.createUnstarted();
@@ -377,18 +380,20 @@ public class VersionGarbageCollector {
         final Stopwatch deleteDeletedDocs = Stopwatch.createUnstarted();
         final Stopwatch collectAndDeleteSplitDocs = 
Stopwatch.createUnstarted();
         final Stopwatch collectDetailedGarbage = Stopwatch.createUnstarted();
+        final Stopwatch collectOrphanNodes = Stopwatch.createUnstarted();
         final Stopwatch collectDeletedProps = Stopwatch.createUnstarted();
         final Stopwatch collectDeletedOldRevs = Stopwatch.createUnstarted();
         final Stopwatch collectUnmergedBC = Stopwatch.createUnstarted();
         long activeElapsed, detailedGCActiveElapsed, 
collectDeletedDocsElapsed, checkDeletedDocsElapsed, deleteDeletedDocsElapsed,
                 collectAndDeleteSplitDocsElapsed, deleteSplitDocsElapsed, 
sortDocIdsElapsed, updateResurrectedDocumentsElapsed,
-                detailedGCDocsElapsed, collectDetailedGarbageElapsed, 
collectDeletedPropsElapsed, deleteDetailedGCDocsElapsed,
-                collectDeletedOldRevsElapsed, collectUnmergedBCElapsed;
+                detailedGCDocsElapsed, collectDetailedGarbageElapsed, 
collectOrphanNodesElapsed, collectDeletedPropsElapsed,
+                deleteDetailedGCDocsElapsed, collectDeletedOldRevsElapsed, 
collectUnmergedBCElapsed;
 
         @Override
         public String toString() {
             String timings;
-            String fmt = "timeToCollectDeletedDocs=%s, 
timeToCheckDeletedDocs=%s, timeToSortDocIds=%s, 
timeTakenToUpdateResurrectedDocs=%s, timeTakenToDeleteDeletedDocs=%s, 
timeTakenToCollectAndDeleteSplitDocs=%s%s";
+            String fmt = "timeToCollectDeletedDocs=%s, 
timeToCheckDeletedDocs=%s, timeToSortDocIds=%s, 
timeTakenToUpdateResurrectedDocs=%s, timeTakenToDeleteDeletedDocs=%s, 
timeTakenToCollectAndDeleteSplitDocs=%s%s, " +
+                    "timeToRunDetailedGC=%s, which includes 
[timeToDeleteDetailedGarbage=%s and timeToCollectDetailedGarbage=%s, (of which 
timeToCollectOrphanNodes=%s timeToCollectDeletedProps=%s, 
timeToCollectOldRevs=%s, timeToCollectUnmergedBranchCommits=%s)]";
 
             // aggregated timings?
             if (iterationCount > 0) {
@@ -402,12 +407,14 @@ public class VersionGarbageCollector {
                         df.format(updateResurrectedDocumentsElapsed, 
MICROSECONDS),
                         df.format(deleteDeletedDocsElapsed, MICROSECONDS),
                         df.format(collectAndDeleteSplitDocsElapsed, 
MICROSECONDS),
+                        timeDeletingSplitDocs,
                         df.format(detailedGCDocsElapsed, MICROSECONDS),
                         df.format(deleteDetailedGCDocsElapsed, MICROSECONDS),
+                        df.format(collectDetailedGarbageElapsed, MICROSECONDS),
+                        df.format(collectOrphanNodesElapsed, MICROSECONDS),
                         df.format(collectDeletedPropsElapsed, MICROSECONDS),
                         df.format(collectDeletedOldRevsElapsed, MICROSECONDS),
-                        df.format(collectUnmergedBCElapsed, MICROSECONDS),
-                        timeDeletingSplitDocs);
+                        df.format(collectUnmergedBCElapsed, MICROSECONDS));
             } else {
                 String timeDeletingSplitDocs = "";
                 if (deleteSplitDocs.elapsed(MICROSECONDS) > 0) {
@@ -420,18 +427,19 @@ public class VersionGarbageCollector {
                         
df.format(updateResurrectedDocuments.elapsed(MICROSECONDS), MICROSECONDS),
                         df.format(deleteDeletedDocs.elapsed(MICROSECONDS), 
MICROSECONDS),
                         
df.format(collectAndDeleteSplitDocs.elapsed(MICROSECONDS), MICROSECONDS),
+                        timeDeletingSplitDocs,
                         df.format(detailedGCDocs.elapsed(MICROSECONDS), 
MICROSECONDS),
                         df.format(deleteDetailedGCDocs.elapsed(MICROSECONDS), 
MICROSECONDS),
                         
df.format(collectDetailedGarbage.elapsed(MICROSECONDS), MICROSECONDS),
+                        df.format(collectOrphanNodes.elapsed(MICROSECONDS), 
MICROSECONDS),
                         df.format(collectDeletedProps.elapsed(MICROSECONDS), 
MICROSECONDS),
                         df.format(collectDeletedOldRevs.elapsed(MICROSECONDS), 
MICROSECONDS),
-                        df.format(collectUnmergedBC.elapsed(MICROSECONDS), 
MICROSECONDS),
-                        timeDeletingSplitDocs);
+                        df.format(collectUnmergedBC.elapsed(MICROSECONDS), 
MICROSECONDS));
             }
 
             return "VersionGCStats{" +
                     "ignoredGCDueToCheckPoint=" + ignoredGCDueToCheckPoint +
-                    "detailedGCDryRunMode=" + detailedGCDryRunMode +
+                    ", detailedGCDryRunMode=" + detailedGCDryRunMode +
                     ", ignoredDetailedGCDueToCheckPoint=" + 
ignoredDetailedGCDueToCheckPoint +
                     ", canceled=" + canceled +
                     ", deletedDocGCCount=" + deletedDocGCCount + " (of which 
leaf: " + deletedLeafDocGCCount + ")" +
@@ -439,7 +447,7 @@ public class VersionGarbageCollector {
                     ", splitDocGCCount=" + splitDocGCCount +
                     ", intermediateSplitDocGCCount=" + 
intermediateSplitDocGCCount +
                     ", oldestModifiedDocId=" + oldestModifiedDocId +
-                    ", oldestModifiedDocTimeStamp=" + 
oldestModifiedDocTimeStamp +
+                    ", oldestModifiedDocTimeStamp=" + 
timestampToString(oldestModifiedDocTimeStamp) +
                     ", updatedDetailedGCDocsCount=" + 
updatedDetailedGCDocsCount +
                     ", skippedDetailedGCDocsCount=" + 
skippedDetailedGCDocsCount +
                     ", deletedPropsCount=" + deletedPropsCount +
@@ -447,6 +455,7 @@ public class VersionGarbageCollector {
                     ", deletedPropRevsCount=" + deletedPropRevsCount +
                     ", deletedInternalPropRevsCount=" + 
deletedInternalPropRevsCount +
                     ", deletedUnmergedBCCount=" + deletedUnmergedBCCount +
+                    ", deletedOrphanNodesCount=" + deletedOrphanNodesCount +
                     ", iterationCount=" + iterationCount +
                     ", timeDetailedGCActive=" + 
df.format(detailedGCActiveElapsed, MICROSECONDS) +
                     ", timeActive=" + df.format(activeElapsed, MICROSECONDS) +
@@ -476,6 +485,7 @@ public class VersionGarbageCollector {
             this.deletedPropRevsCount += run.deletedPropRevsCount;
             this.deletedInternalPropRevsCount += 
run.deletedInternalPropRevsCount;
             this.deletedUnmergedBCCount += run.deletedUnmergedBCCount;
+            this.deletedOrphanNodesCount += run.deletedOrphanNodesCount;
             if (run.iterationCount > 0) {
                 // run is cumulative with times in elapsed fields
                 this.activeElapsed += run.activeElapsed;
@@ -490,6 +500,7 @@ public class VersionGarbageCollector {
                 this.detailedGCDocsElapsed += run.detailedGCDocsElapsed;
                 this.deleteDetailedGCDocsElapsed += 
run.deleteDetailedGCDocsElapsed;
                 this.collectDetailedGarbageElapsed += 
run.collectDetailedGarbageElapsed;
+                this.collectOrphanNodesElapsed += 
run.collectOrphanNodesElapsed;
                 this.collectDeletedPropsElapsed += 
run.collectDeletedPropsElapsed;
                 this.collectDeletedOldRevsElapsed += 
run.collectDeletedOldRevsElapsed;
                 this.collectUnmergedBCElapsed += run.collectUnmergedBCElapsed;
@@ -507,6 +518,7 @@ public class VersionGarbageCollector {
                 this.detailedGCDocsElapsed += 
run.detailedGCDocs.elapsed(MICROSECONDS);
                 this.deleteDetailedGCDocsElapsed += 
run.deleteDetailedGCDocs.elapsed(MICROSECONDS);
                 this.collectDetailedGarbageElapsed += 
run.collectDetailedGarbage.elapsed(MICROSECONDS);
+                this.collectOrphanNodesElapsed += 
run.collectOrphanNodes.elapsed(MICROSECONDS);
                 this.collectDeletedPropsElapsed += 
run.collectDeletedProps.elapsed(MICROSECONDS);
                 this.collectDeletedOldRevsElapsed += 
run.collectDeletedOldRevs.elapsed(MICROSECONDS);
                 this.collectUnmergedBCElapsed += 
run.collectUnmergedBC.elapsed(MICROSECONDS);
@@ -523,6 +535,7 @@ public class VersionGarbageCollector {
         SPLITS_CLEANUP,
         DETAILED_GC,
         DETAILED_GC_COLLECT_GARBAGE,
+        DETAILED_GC_COLLECT_ORPHAN_NODES,
         DETAILED_GC_COLLECT_PROPS,
         DETAILED_GC_COLLECT_OLD_REVS,
         DETAILED_GC_COLLECT_UNMERGED_BC,
@@ -557,6 +570,7 @@ public class VersionGarbageCollector {
             this.watches.put(GCPhase.UPDATING, 
stats.updateResurrectedDocuments);
             this.watches.put(GCPhase.DETAILED_GC, stats.detailedGCDocs);
             this.watches.put(GCPhase.DETAILED_GC_COLLECT_GARBAGE, 
stats.collectDetailedGarbage);
+            this.watches.put(GCPhase.DETAILED_GC_COLLECT_ORPHAN_NODES, 
stats.collectOrphanNodes);
             this.watches.put(GCPhase.DETAILED_GC_COLLECT_PROPS, 
stats.collectDeletedProps);
             this.watches.put(GCPhase.DETAILED_GC_COLLECT_OLD_REVS, 
stats.collectDeletedOldRevs);
             this.watches.put(GCPhase.DETAILED_GC_COLLECT_UNMERGED_BC, 
stats.collectUnmergedBC);
@@ -1001,14 +1015,7 @@ public class VersionGarbageCollector {
                 traversedState = traversedState.getChildNode(name);
             }
 
-            if (isDeletedOrOrphanedNode(traversedState)) {
-                // if this is an orphaned node, all that is needed is its 
removal
-                garbageDocsCount++;
-                totalGarbageDocsCount++;
-                monitor.info("Deleted orphaned or deleted doc [{}]", 
doc.getId());
-                orphanOrDeletedRemovalMap.put(doc.getId(), doc.getModified());
-                orphanOrDeletedRemovalPathMap.put(doc.getId(), doc.getPath());
-            } else {
+            if (!isDeletedOrOrphanedNode(traversedState, phases, doc)) {
                 // here the node is not orphaned which means that we can reach 
the node from root
                 collectDeletedProperties(doc, phases, op, traversedState);
                 switch(revisionDetailedGcType) {
@@ -1086,14 +1093,21 @@ public class VersionGarbageCollector {
          * parent node. But from a GC point of view this also includes regular
          * deletion cases that have not otherwise been deleted already (eg by 
DeletedDocsGC).
          *
-         * @param traversedState
+         * @param traversedState the state of current doc when we start 
traversing from root via lastRef
+         * @param phases GC phases
+         * @param doc current document node to check whether it is orphan or 
not
          * @return true if the node is orphaned (and/or can be removed), false
          *         otherwise
          */
-        private boolean isDeletedOrOrphanedNode(NodeState traversedState) {
-            // several different cases here, but ultimately they all lead back 
to:
-            return !traversedState.exists();
+        private boolean isDeletedOrOrphanedNode(final NodeState 
traversedState, final GCPhases phases, final NodeDocument doc) {
+
+            if (!phases.start(GCPhase.DETAILED_GC_COLLECT_ORPHAN_NODES)) {
+                // gc has been cancelled
+                return false;
+            }
 
+            // several different cases here, but ultimately they all lead back 
to:
+            boolean isOrphan = !traversedState.exists();
             // if the node when reading at current headRevision (rather than 
traversed)
             // does not exist, then this is rather a regular deletion, nothing 
special.
             // that is usually handled in DeletedDocsGC - but if DetailedGC 
sees this,
@@ -1103,6 +1117,22 @@ public class VersionGarbageCollector {
             // does exist, then it could be either due to the parent node 
having
             // been deleted (true orphan) - or the node itself got 
late-write-added.
             // in both of these cases we should now delete it. That's all with 
above return.
+            if (!isOrphan) {
+                // nothing to do here
+                phases.stop(GCPhase.DETAILED_GC_COLLECT_ORPHAN_NODES);
+                return false;
+            }
+
+            // if this is an orphaned node, all that is needed is its removal
+            garbageDocsCount++;
+            totalGarbageDocsCount++;
+            monitor.info("Deleted orphaned or deleted doc [{}]", doc.getId());
+            orphanOrDeletedRemovalMap.put(doc.getId(), doc.getModified());
+            orphanOrDeletedRemovalPathMap.put(doc.getId(), doc.getPath());
+
+            phases.stop(GCPhase.DETAILED_GC_COLLECT_ORPHAN_NODES);
+            return true;
+
         }
 
         private boolean hasGarbage() {
@@ -1728,12 +1758,18 @@ public class VersionGarbageCollector {
                         final int removedSize = ds.remove(NODES, 
orphanOrDeletedRemovalMap);
                         stats.updatedDetailedGCDocsCount += removedSize;
                         stats.deletedDocGCCount += removedSize;
-                        detailedGCStats.documentsUpdated(removedSize);
-                        gcStats.documentsDeleted(removedSize);
+                        stats.deletedOrphanNodesCount += removedSize;
+
                         if (log.isDebugEnabled()) {
-                            log.debug("deleted [{}] documents (from intended 
{})",
-                                    removedSize, 
orphanOrDeletedRemovalMap.size());
+                            log.debug("deleted [{}] documents (from intended 
{})", removedSize, orphanOrDeletedRemovalMap.size());
                         }
+
+                        // save stats
+                        detailedGCStats.documentsUpdated(removedSize);
+                        detailedGCStats.orphanNodesDeleted(removedSize);
+                        gcStats.documentsDeleted(removedSize);
+                        // fix for sonar : converted to long before operation
+                        
detailedGCStats.documentsUpdateSkipped((long)orphanOrDeletedRemovalMap.size() - 
removedSize);
                     }
 
                     if (!updateOpList.isEmpty()) {
@@ -1778,7 +1814,7 @@ public class VersionGarbageCollector {
                     // for orphan nodes.
                     stats.updatedDetailedGCDocsCount += 
orphanOrDeletedRemovalMap.size();
                     stats.deletedDocGCCount += 
orphanOrDeletedRemovalMap.size();
-//                    stats.deletedOrphanNodesCount += 
orphanOrDeletedRemovalMap.size();
+                    stats.deletedOrphanNodesCount += 
orphanOrDeletedRemovalMap.size();
                 }
             } finally {
                 // now reset delete metadata
diff --git 
a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DetailedRevisionGCStatsCollectorImplTest.java
 
b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DetailedRevisionGCStatsCollectorImplTest.java
index 3af5165f5c..d0694fc477 100644
--- 
a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DetailedRevisionGCStatsCollectorImplTest.java
+++ 
b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DetailedRevisionGCStatsCollectorImplTest.java
@@ -37,8 +37,10 @@ import static 
org.apache.commons.lang3.reflect.FieldUtils.readField;
 import static 
org.apache.jackrabbit.oak.plugins.document.DetailedRevisionGCStatsCollectorImpl.COLLECT_DELETED_OLD_REVS_TIMER;
 import static 
org.apache.jackrabbit.oak.plugins.document.DetailedRevisionGCStatsCollectorImpl.COLLECT_DELETED_PROPS_TIMER;
 import static 
org.apache.jackrabbit.oak.plugins.document.DetailedRevisionGCStatsCollectorImpl.COLLECT_DETAILED_GARBAGE_TIMER;
+import static 
org.apache.jackrabbit.oak.plugins.document.DetailedRevisionGCStatsCollectorImpl.COLLECT_ORPHAN_NODES_TIMER;
 import static 
org.apache.jackrabbit.oak.plugins.document.DetailedRevisionGCStatsCollectorImpl.COLLECT_UNMERGED_BC_TIMER;
 import static 
org.apache.jackrabbit.oak.plugins.document.DetailedRevisionGCStatsCollectorImpl.COUNTER;
+import static 
org.apache.jackrabbit.oak.plugins.document.DetailedRevisionGCStatsCollectorImpl.DELETED_ORPHAN_NODE;
 import static 
org.apache.jackrabbit.oak.plugins.document.DetailedRevisionGCStatsCollectorImpl.DELETED_PROPERTY;
 import static 
org.apache.jackrabbit.oak.plugins.document.DetailedRevisionGCStatsCollectorImpl.DELETED_UNMERGED_BC;
 import static 
org.apache.jackrabbit.oak.plugins.document.DetailedRevisionGCStatsCollectorImpl.DELETE_DETAILED_GC_DOCS_TIMER;
@@ -84,6 +86,15 @@ public class DetailedRevisionGCStatsCollectorImplTest {
         assertEquals(count + 17, ((MeterStats) readField(stats, "skippedDoc", 
true)).getCount());
     }
 
+    @Test
+    public void getOrphanNodesDeletedCount() throws IllegalAccessException {
+        Meter m = getMeter(DELETED_ORPHAN_NODE);
+        long count = m.getCount();
+        stats.orphanNodesDeleted(10);
+        assertEquals(count + 10, m.getCount());
+        assertEquals(count + 10, ((MeterStats) readField(stats, 
"deletedOrphanNode", true)).getCount());
+    }
+
     @Test
     public void getPropertiesDeletedCount() throws IllegalAccessException {
         Meter m = getMeter(DELETED_PROPERTY);
@@ -117,6 +128,7 @@ public class DetailedRevisionGCStatsCollectorImplTest {
         vgcs.detailedGCActiveElapsed = MILLISECONDS.toMicros(2);
         vgcs.detailedGCDocsElapsed = MILLISECONDS.toMicros(3);
         vgcs.collectDetailedGarbageElapsed = MILLISECONDS.toMicros(5);
+        vgcs.collectOrphanNodesElapsed = MILLISECONDS.toMicros(6);
         vgcs.collectDeletedPropsElapsed = MILLISECONDS.toMicros(7);
         vgcs.collectDeletedOldRevsElapsed = MILLISECONDS.toMicros(11);
         vgcs.collectUnmergedBCElapsed = MILLISECONDS.toMicros(13);
@@ -127,6 +139,7 @@ public class DetailedRevisionGCStatsCollectorImplTest {
         assertTimer(2, DETAILED_GC_ACTIVE_TIMER);
         assertTimer(3, DETAILED_GC_TIMER);
         assertTimer(5, COLLECT_DETAILED_GARBAGE_TIMER);
+        assertTimer(6, COLLECT_ORPHAN_NODES_TIMER);
         assertTimer(7, COLLECT_DELETED_PROPS_TIMER);
         assertTimer(11, COLLECT_DELETED_OLD_REVS_TIMER);
         assertTimer(13, COLLECT_UNMERGED_BC_TIMER);
diff --git 
a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGCStatsTest.java
 
b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGCStatsTest.java
index a1e889fe18..5243531178 100644
--- 
a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGCStatsTest.java
+++ 
b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGCStatsTest.java
@@ -61,6 +61,7 @@ public class VersionGCStatsTest {
         assertEquals(stats.detailedGCDocs.elapsed(MICROSECONDS), 
cumulative.detailedGCDocsElapsed);
         assertEquals(stats.deleteDetailedGCDocs.elapsed(MICROSECONDS), 
cumulative.deleteDetailedGCDocsElapsed);
         assertEquals(stats.collectDetailedGarbage.elapsed(MICROSECONDS), 
cumulative.collectDetailedGarbageElapsed);
+        assertEquals(stats.collectOrphanNodes.elapsed(MICROSECONDS), 
cumulative.collectOrphanNodesElapsed);
         assertEquals(stats.collectDeletedProps.elapsed(MICROSECONDS), 
cumulative.collectDeletedPropsElapsed);
         assertEquals(stats.collectDeletedOldRevs.elapsed(MICROSECONDS), 
cumulative.collectDeletedOldRevsElapsed);
         assertEquals(stats.collectUnmergedBC.elapsed(MICROSECONDS), 
cumulative.collectUnmergedBCElapsed);
@@ -84,6 +85,7 @@ public class VersionGCStatsTest {
         assertEquals(stats.detailedGCDocs.elapsed(MICROSECONDS) * 2, 
cumulative.detailedGCDocsElapsed);
         assertEquals(stats.deleteDetailedGCDocs.elapsed(MICROSECONDS) * 2, 
cumulative.deleteDetailedGCDocsElapsed);
         assertEquals(stats.collectDetailedGarbage.elapsed(MICROSECONDS) * 2, 
cumulative.collectDetailedGarbageElapsed);
+        assertEquals(stats.collectOrphanNodes.elapsed(MICROSECONDS) * 2, 
cumulative.collectOrphanNodesElapsed);
         assertEquals(stats.collectDeletedProps.elapsed(MICROSECONDS) * 2, 
cumulative.collectDeletedPropsElapsed);
         assertEquals(stats.collectDeletedOldRevs.elapsed(MICROSECONDS) * 2, 
cumulative.collectDeletedOldRevsElapsed);
         assertEquals(stats.collectUnmergedBC.elapsed(MICROSECONDS) * 2, 
cumulative.collectUnmergedBCElapsed);
@@ -101,6 +103,7 @@ public class VersionGCStatsTest {
         c.call(stats.detailedGCDocs);
         c.call(stats.deleteDetailedGCDocs);
         c.call(stats.collectDetailedGarbage);
+        c.call(stats.collectOrphanNodes);
         c.call(stats.collectDeletedProps);
         c.call(stats.collectDeletedOldRevs);
         c.call(stats.collectUnmergedBC);

Reply via email to