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 md...@apache.org on 2019/02/22 09:49:33 UTC

svn commit: r1854125 - in /jackrabbit/oak/branches/1.10: ./ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/DefaultSegmentWriter.java

Author: mduerig
Date: Fri Feb 22 09:49:33 2019
New Revision: 1854125

URL: http://svn.apache.org/viewvc?rev=1854125&view=rev
Log:
OAK-8069: Log warning for too many transient modifications of direct child nodes
Merged r1854058

Modified:
    jackrabbit/oak/branches/1.10/   (props changed)
    jackrabbit/oak/branches/1.10/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/DefaultSegmentWriter.java

Propchange: jackrabbit/oak/branches/1.10/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Feb 22 09:49:33 2019
@@ -1,3 +1,3 @@
 /jackrabbit/oak/branches/1.0:1665962
-/jackrabbit/oak/trunk:1851236,1851253,1851451,1852052,1852084,1852120,1852451,1852492-1852493,1852528,1852582,1852584,1852601,1852920,1853141,1853393,1853429,1853433,1853441,1853866,1853868,1853870,1853893,1853969,1853997,1854034,1854044
+/jackrabbit/oak/trunk:1851236,1851253,1851451,1852052,1852084,1852120,1852451,1852492-1852493,1852528,1852582,1852584,1852601,1852920,1853141,1853393,1853429,1853433,1853441,1853866,1853868,1853870,1853893,1853969,1853997,1854034,1854044,1854058
 /jackrabbit/trunk:1345480

Modified: jackrabbit/oak/branches/1.10/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/DefaultSegmentWriter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.10/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/DefaultSegmentWriter.java?rev=1854125&r1=1854124&r2=1854125&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.10/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/DefaultSegmentWriter.java (original)
+++ jackrabbit/oak/branches/1.10/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/DefaultSegmentWriter.java Fri Feb 22 09:49:33 2019
@@ -33,6 +33,7 @@ import static com.google.common.collect.
 import static com.google.common.collect.Lists.partition;
 import static com.google.common.collect.Maps.newHashMap;
 import static com.google.common.io.ByteStreams.read;
+import static java.lang.Integer.getInteger;
 import static java.lang.Long.numberOfLeadingZeros;
 import static java.lang.Math.min;
 import static java.util.Arrays.asList;
@@ -87,6 +88,19 @@ public class DefaultSegmentWriter implem
 
     private static final Logger LOG = LoggerFactory.getLogger(DefaultSegmentWriter.class);
 
+    /**
+     * Default threshold of the number of modified child nodes of a node after which to
+     * log a warning.
+     */
+    public static final int CHILD_NODE_COUNT_WARN_THRESHOLD_DEFAULT = 1000000;
+
+    /**
+     * Threshold of the number of modified child nodes of a node after which to log
+     * a warning.
+     */
+    private static final int CHILD_NODE_COUNT_WARN_THRESHOLD =
+            getInteger("oak.segment.childNodeCountWarnThreshold", CHILD_NODE_COUNT_WARN_THRESHOLD_DEFAULT);
+
     @NotNull
     private final WriterCacheManager cacheManager;
 
@@ -187,7 +201,7 @@ public class DefaultSegmentWriter implem
     @NotNull
     public RecordId writeNode(@NotNull final NodeState state, @Nullable final Buffer stableIdBytes) throws IOException {
         return new SegmentWriteOperation(writeOperationHandler.getGCGeneration())
-                .writeNode(state, stableIdBytes);
+                .writeNode("/", state, stableIdBytes);
     }
 
     /**
@@ -205,6 +219,8 @@ public class DefaultSegmentWriter implem
 
         private final Cache<String, RecordId> nodeCache;
 
+        private int childNodeCountWarnThreshold = CHILD_NODE_COUNT_WARN_THRESHOLD;
+
         SegmentWriteOperation(@NotNull GCGeneration gcGeneration) {
             int generation = gcGeneration.getGeneration();
             this.gcGeneration = gcGeneration;
@@ -740,7 +756,10 @@ public class DefaultSegmentWriter implem
             return tid;
         }
 
-        private RecordId writeNode(@NotNull NodeState state, @Nullable Buffer stableIdBytes)
+        private RecordId writeNode(
+                @NotNull String path,
+                @NotNull NodeState state,
+                @Nullable Buffer stableIdBytes)
         throws IOException {
             RecordId compactedId = deduplicateNode(state);
 
@@ -751,7 +770,7 @@ public class DefaultSegmentWriter implem
             if (state instanceof SegmentNodeState && stableIdBytes == null) {
                 stableIdBytes = ((SegmentNodeState) state).getStableIdBytes();
             }
-            RecordId recordId = writeNodeUncached(state, stableIdBytes);
+            RecordId recordId = writeNodeUncached(path, state, stableIdBytes);
 
             if (stableIdBytes != null) {
                 // This node state has been rewritten because it is from an older
@@ -767,7 +786,17 @@ public class DefaultSegmentWriter implem
             return (byte) (Byte.MIN_VALUE + 64 - numberOfLeadingZeros(childCount));
         }
 
-        private RecordId writeNodeUncached(@NotNull NodeState state, @Nullable Buffer stableIdBytes)
+        private void warnOnManyChildren(Map<?, ?> map, String path) {
+            if (map.size() >= childNodeCountWarnThreshold) {
+                childNodeCountWarnThreshold += CHILD_NODE_COUNT_WARN_THRESHOLD;
+                LOG.warn("Large number of modified child nodes: {} @ {}", map.size(), path);
+            }
+        }
+
+        private RecordId writeNodeUncached(
+                @NotNull String path,
+                @NotNull NodeState state,
+                @Nullable Buffer stableIdBytes)
         throws IOException {
             ModifiedNodeState after = null;
 
@@ -807,19 +836,20 @@ public class DefaultSegmentWriter implem
                         && before.getChildNodeCount(2) > 1
                         && after.getChildNodeCount(2) > 1) {
                     base = before.getChildNodeMap();
-                    childNodes = new ChildNodeCollectorDiff().diff(before, after);
+                    childNodes = new ChildNodeCollectorDiff(path).diff(before, after);
                 } else {
                     base = null;
                     childNodes = newHashMap();
                     for (ChildNodeEntry entry : state.getChildNodeEntries()) {
                         childNodes.put(
                                 entry.getName(),
-                                writeNode(entry.getNodeState(), null));
+                                writeNode(path + "/" + entry.getName(), entry.getNodeState(), null));
+                        warnOnManyChildren(childNodes, path);
                     }
                 }
                 ids.add(writeMap(base, childNodes));
             } else if (childName != Template.ZERO_CHILD_NODES) {
-                ids.add(writeNode(state.getChildNode(template.getChildName()), null));
+                ids.add(writeNode(path + "/" + template.getChildName(), state.getChildNode(template.getChildName()), null));
             }
 
             List<RecordId> pIds = newArrayList();
@@ -967,8 +997,14 @@ public class DefaultSegmentWriter implem
 
             private final Map<String, RecordId> childNodes = newHashMap();
 
+            private final String path;
+
             private IOException exception;
 
+            public ChildNodeCollectorDiff(String path) {
+                this.path = path;
+            }
+
             public Map<String, RecordId> diff(SegmentNodeState before, ModifiedNodeState after) throws IOException {
                 after.compareAgainstBaseState(before, this);
                 if (exception != null) {
@@ -981,7 +1017,7 @@ public class DefaultSegmentWriter implem
             @Override
             public boolean childNodeAdded(String name, NodeState after) {
                 try {
-                    childNodes.put(name, writeNode(after, null));
+                    addChild(name, writeNode(path + "/" + name, after, null));
                 } catch (IOException e) {
                     exception = e;
                     return false;
@@ -994,7 +1030,7 @@ public class DefaultSegmentWriter implem
                     String name, NodeState before, NodeState after
             ) {
                 try {
-                    childNodes.put(name, writeNode(after, null));
+                    addChild(name, writeNode(path + "/" + name, after, null));
                 } catch (IOException e) {
                     exception = e;
                     return false;
@@ -1004,9 +1040,14 @@ public class DefaultSegmentWriter implem
 
             @Override
             public boolean childNodeDeleted(String name, NodeState before) {
-                childNodes.put(name, null);
+                addChild(name, null);
                 return true;
             }
+
+            private void addChild(String name, @Nullable RecordId recordId) {
+                childNodes.put(name, recordId);
+                warnOnManyChildren(childNodes, path);
+            }
         }
     }