Author: tomekr
Date: Mon Aug 28 10:01:59 2017
New Revision: 1806418
URL: http://svn.apache.org/viewvc?rev=1806418&view=rev
Log:
OAK-6560: Sidegrade uses too much memory
Fixed the progress logging.
Modified:
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/PersistingDiff.java
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositorySidegrade.java
Modified:
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/PersistingDiff.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/PersistingDiff.java?rev=1806418&r1=1806417&r2=1806418&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/PersistingDiff.java
(original)
+++
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/PersistingDiff.java
Mon Aug 28 10:01:59 2017
@@ -16,6 +16,7 @@
*/
package org.apache.jackrabbit.oak.upgrade;
+import com.google.common.collect.Lists;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeBuilder;
import org.apache.jackrabbit.oak.segment.RecordId;
@@ -26,11 +27,16 @@ import org.apache.jackrabbit.oak.segment
import org.apache.jackrabbit.oak.spi.blob.BlobStore;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Supplier;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
@@ -38,6 +44,8 @@ import static org.apache.jackrabbit.oak.
public class PersistingDiff implements NodeStateDiff {
+ private static final Logger LOG =
LoggerFactory.getLogger(PersistingDiff.class);
+
/**
* Number of content updates that need to happen before the updates
* are automatically purged to the underlying segments.
@@ -51,6 +59,12 @@ public class PersistingDiff implements N
private final BlobStore blobStore;
+ private final PersistingDiff parent;
+
+ private final String nodeName;
+
+ private final Reporter reporter;
+
@Nonnull
private MemoryNodeBuilder builder;
@@ -62,12 +76,26 @@ public class PersistingDiff implements N
private long modCount;
+ private PersistingDiff(PersistingDiff parent, String nodeName, @Nonnull
NodeState base) {
+ this.writer = parent.writer;
+ this.reader = parent.reader;
+ this.blobStore = parent.blobStore;
+ this.reporter = parent.reporter;
+ this.builder = new MemoryNodeBuilder(checkNotNull(base));
+ this.parent = parent;
+ this.base = base;
+ this.nodeName = nodeName;
+ }
+
private PersistingDiff(SegmentWriter writer, SegmentReader reader,
BlobStore blobStore, @Nonnull NodeState base) {
this.writer = writer;
this.reader = reader;
this.blobStore = blobStore;
+ this.reporter = new Reporter();
this.builder = new MemoryNodeBuilder(checkNotNull(base));
+ this.parent = null;
this.base = base;
+ this.nodeName = null;
}
public static SegmentNodeState applyDiffOnNodeState(
@@ -78,23 +106,32 @@ public class PersistingDiff implements N
return new PersistingDiff(fileStore.getWriter(),
fileStore.getReader(), fileStore.getBlobStore(), onto).diff(before, after);
}
- private SegmentNodeState copyToSegmentNodeState(NodeState state) throws
IOException {
- return applyDiffOnNodeState(EMPTY_NODE, state, EMPTY_NODE);
- }
-
- private SegmentNodeState applyDiffOnNodeState(
- @Nonnull NodeState before,
- @Nonnull NodeState after,
- @Nonnull NodeState onto) throws IOException {
- return new PersistingDiff(writer, reader, blobStore,
onto).diff(before, after);
- }
-
private void updated() throws IOException {
- if (++modCount % UPDATE_LIMIT == 0) {
+ if (modCount % UPDATE_LIMIT == 0) {
RecordId newBaseId = writer.writeNode(builder.getNodeState(),
null);
SegmentNodeState newBase = new SegmentNodeState(reader, writer,
blobStore, newBaseId);
builder = new MemoryNodeBuilder(newBase);
}
+ modCount++;
+ }
+
+ private String getPath() {
+ List<String> segments = new ArrayList<>();
+ PersistingDiff currentDiff = this;
+ while (currentDiff != null) {
+ if (currentDiff.nodeName != null) {
+ segments.add(currentDiff.nodeName);
+ }
+ currentDiff = currentDiff.parent;
+ }
+ segments = Lists.reverse(segments);
+
+ StringBuilder path = new StringBuilder();
+ for (String segment : segments) {
+ path.append("/");
+ path.append(segment);
+ }
+ return path.toString();
}
@CheckForNull
@@ -106,6 +143,7 @@ public class PersistingDiff implements N
NodeState nodeState = builder.getNodeState();
checkState(modCount == 0 || !(nodeState instanceof
SegmentNodeState));
RecordId nodeId = writer.writeNode(nodeState,
getStableIdBytes(after));
+ reporter.reportNode(this::getPath);
return new SegmentNodeState(reader, writer, blobStore, nodeId);
} else {
return null;
@@ -133,7 +171,7 @@ public class PersistingDiff implements N
@Override
public boolean childNodeAdded(@Nonnull String name, @Nonnull NodeState
after) {
try {
- SegmentNodeState segmentNodeState = copyToSegmentNodeState(after);
+ SegmentNodeState segmentNodeState = new PersistingDiff(this, name,
EMPTY_NODE).diff(EMPTY_NODE, after);
if (segmentNodeState != null) {
updated();
builder.setChildNode(name, segmentNodeState);
@@ -150,7 +188,7 @@ public class PersistingDiff implements N
@Override
public boolean childNodeChanged(@Nonnull String name, @Nonnull NodeState
before, @Nonnull NodeState after) {
try {
- SegmentNodeState compacted = applyDiffOnNodeState(before, after,
base.getChildNode(name));
+ SegmentNodeState compacted = new PersistingDiff(this, name,
base.getChildNode(name)).diff(before, after);
if (compacted != null) {
updated();
builder.setChildNode(name, compacted);
@@ -184,4 +222,17 @@ public class PersistingDiff implements N
return null;
}
}
+
+ private static class Reporter {
+
+ private long count = 0;
+
+ public void reportNode(Supplier<String> pathSupplier) {
+ if (count > 0 && count % RepositorySidegrade.LOG_NODE_COPY == 0) {
+ LOG.info("Copying node {}: {}", count, pathSupplier.get());
+ }
+ count++;
+ }
+
+ }
}
Modified:
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositorySidegrade.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositorySidegrade.java?rev=1806418&r1=1806417&r2=1806418&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositorySidegrade.java
(original)
+++
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositorySidegrade.java
Mon Aug 28 10:01:59 2017
@@ -83,7 +83,7 @@ public class RepositorySidegrade {
private static final Logger LOG =
LoggerFactory.getLogger(RepositorySidegrade.class);
- private static final int LOG_NODE_COPY =
Integer.getInteger("oak.upgrade.logNodeCopy", 10000);
+ static final int LOG_NODE_COPY =
Integer.getInteger("oak.upgrade.logNodeCopy", 10000);
private static final String WORKSPACE_NAME_PROP =
"oak.upgrade.workspaceName";
@@ -423,13 +423,17 @@ public class RepositorySidegrade {
}
private NodeState copyDiffToTarget(NodeState before, NodeState after,
NodeState targetRoot, boolean tracePaths) throws IOException,
CommitFailedException {
- NodeState currentRoot = wrapNodeState(after, tracePaths, true);
- NodeState baseRoot = wrapNodeState(before, false, true);
NodeBuilder targetBuilder = targetRoot.builder();
if (targetFileStore == null) {
+ NodeState currentRoot = wrapNodeState(after, tracePaths, true);
+ NodeState baseRoot = wrapNodeState(before, false, true);
+
currentRoot.compareAgainstBaseState(baseRoot, new
ApplyDiff(targetBuilder));
} else {
+ NodeState currentRoot = wrapNodeState(after, false, true);
+ NodeState baseRoot = wrapNodeState(before, false, true);
+
SegmentNodeState state =
PersistingDiff.applyDiffOnNodeState(targetFileStore, baseRoot, currentRoot,
targetRoot);
state.compareAgainstBaseState(targetRoot, new
ApplyDiff(targetBuilder));
}