Author: tomekr Date: Sun Aug 27 16:58:21 2017 New Revision: 1806378 URL: http://svn.apache.org/viewvc?rev=1806378&view=rev Log: OAK-6560: Sidegrade uses too much memory
Added: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/segment/ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/segment/CheckpointAccessor.java - copied, changed from r1806367, jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/TarNodeStore.java jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/segment/ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/segment/CheckpointAccessor.java - copied, changed from r1806367, jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/TarNodeStore.java jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/PersistingDiff.java Removed: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/TarNodeStore.java Modified: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositorySidegrade.java jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/checkpoint/CheckpointRetriever.java jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentFactory.java jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentTarFactory.java Copied: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/segment/CheckpointAccessor.java (from r1806367, jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/TarNodeStore.java) URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/segment/CheckpointAccessor.java?p2=jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/segment/CheckpointAccessor.java&p1=jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/TarNodeStore.java&r1=1806367&r2=1806378&rev=1806378&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/TarNodeStore.java (original) +++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/segment/CheckpointAccessor.java Sun Aug 27 16:58:21 2017 @@ -14,35 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.jackrabbit.oak.upgrade.cli.node; +package org.apache.jackrabbit.oak.plugins.segment; +import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore; import org.apache.jackrabbit.oak.spi.state.NodeState; -import org.apache.jackrabbit.oak.spi.state.NodeStore; -import org.apache.jackrabbit.oak.spi.state.ProxyNodeStore; -public class TarNodeStore extends ProxyNodeStore { +public final class CheckpointAccessor { - private final NodeStore ns; - - private final SuperRootProvider superRootProvider; - - public TarNodeStore(NodeStore ns, SuperRootProvider superRootProvider) { - this.ns = ns; - this.superRootProvider = superRootProvider; - } - - public NodeState getSuperRoot() { - return superRootProvider.getSuperRoot(); + private CheckpointAccessor() { } - @Override - protected NodeStore getNodeStore() { - return ns; + public static NodeState getCheckpointsRoot(SegmentNodeStore segmentNodeStore) { + return segmentNodeStore.getCheckpoints(); } - interface SuperRootProvider { - - NodeState getSuperRoot(); - - } } Copied: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/segment/CheckpointAccessor.java (from r1806367, jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/TarNodeStore.java) URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/segment/CheckpointAccessor.java?p2=jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/segment/CheckpointAccessor.java&p1=jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/TarNodeStore.java&r1=1806367&r2=1806378&rev=1806378&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/TarNodeStore.java (original) +++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/segment/CheckpointAccessor.java Sun Aug 27 16:58:21 2017 @@ -14,35 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.jackrabbit.oak.upgrade.cli.node; +package org.apache.jackrabbit.oak.segment; import org.apache.jackrabbit.oak.spi.state.NodeState; -import org.apache.jackrabbit.oak.spi.state.NodeStore; -import org.apache.jackrabbit.oak.spi.state.ProxyNodeStore; -public class TarNodeStore extends ProxyNodeStore { +public final class CheckpointAccessor { - private final NodeStore ns; - - private final SuperRootProvider superRootProvider; - - public TarNodeStore(NodeStore ns, SuperRootProvider superRootProvider) { - this.ns = ns; - this.superRootProvider = superRootProvider; - } - - public NodeState getSuperRoot() { - return superRootProvider.getSuperRoot(); + private CheckpointAccessor() { } - @Override - protected NodeStore getNodeStore() { - return ns; + public static NodeState getCheckpointsRoot(SegmentNodeStore segmentNodeStore) { + return segmentNodeStore.getCheckpoints(); } - interface SuperRootProvider { - - NodeState getSuperRoot(); - - } } Added: 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=1806378&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/PersistingDiff.java (added) +++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/PersistingDiff.java Sun Aug 27 16:58:21 2017 @@ -0,0 +1,187 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.oak.upgrade; + +import org.apache.jackrabbit.oak.api.PropertyState; +import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeBuilder; +import org.apache.jackrabbit.oak.segment.RecordId; +import org.apache.jackrabbit.oak.segment.SegmentNodeState; +import org.apache.jackrabbit.oak.segment.SegmentReader; +import org.apache.jackrabbit.oak.segment.SegmentWriter; +import org.apache.jackrabbit.oak.segment.file.FileStore; +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 javax.annotation.CheckForNull; +import javax.annotation.Nonnull; +import java.io.IOException; +import java.nio.ByteBuffer; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE; + +public class PersistingDiff implements NodeStateDiff { + + /** + * Number of content updates that need to happen before the updates + * are automatically purged to the underlying segments. + */ + private static final int UPDATE_LIMIT = + Integer.getInteger("upgrade.update.limit", 10000); + + private final SegmentWriter writer; + + private final SegmentReader reader; + + private final BlobStore blobStore; + + @Nonnull + private MemoryNodeBuilder builder; + + @Nonnull + private final NodeState base; + + @CheckForNull + private IOException exception; + + private long modCount; + + private PersistingDiff(SegmentWriter writer, SegmentReader reader, BlobStore blobStore, @Nonnull NodeState base) { + this.writer = writer; + this.reader = reader; + this.blobStore = blobStore; + this.builder = new MemoryNodeBuilder(checkNotNull(base)); + this.base = base; + } + + public static SegmentNodeState applyDiffOnNodeState( + FileStore fileStore, + @Nonnull NodeState before, + @Nonnull NodeState after, + @Nonnull NodeState onto) throws IOException { + 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) { + RecordId newBaseId = writer.writeNode(builder.getNodeState(), null); + SegmentNodeState newBase = new SegmentNodeState(reader, writer, blobStore, newBaseId); + builder = new MemoryNodeBuilder(newBase); + } + } + + @CheckForNull + SegmentNodeState diff(@Nonnull NodeState before, @Nonnull NodeState after) throws IOException { + boolean success = after.compareAgainstBaseState(before, this); + if (exception != null) { + throw new IOException(exception); + } else if (success) { + NodeState nodeState = builder.getNodeState(); + checkState(modCount == 0 || !(nodeState instanceof SegmentNodeState)); + RecordId nodeId = writer.writeNode(nodeState, getStableIdBytes(after)); + return new SegmentNodeState(reader, writer, blobStore, nodeId); + } else { + return null; + } + } + + @Override + public boolean propertyAdded(@Nonnull PropertyState after) { + builder.setProperty(after); + return true; + } + + @Override + public boolean propertyChanged(@Nonnull PropertyState before, @Nonnull PropertyState after) { + builder.setProperty(after); + return true; + } + + @Override + public boolean propertyDeleted(PropertyState before) { + builder.removeProperty(before.getName()); + return true; + } + + @Override + public boolean childNodeAdded(@Nonnull String name, @Nonnull NodeState after) { + try { + SegmentNodeState segmentNodeState = copyToSegmentNodeState(after); + if (segmentNodeState != null) { + updated(); + builder.setChildNode(name, segmentNodeState); + return true; + } else { + return false; + } + } catch (IOException e) { + exception = e; + return false; + } + } + + @Override + public boolean childNodeChanged(@Nonnull String name, @Nonnull NodeState before, @Nonnull NodeState after) { + try { + SegmentNodeState compacted = applyDiffOnNodeState(before, after, base.getChildNode(name)); + if (compacted != null) { + updated(); + builder.setChildNode(name, compacted); + return true; + } else { + return false; + } + } catch (IOException e) { + exception = e; + return false; + } + } + + @Override + public boolean childNodeDeleted(String name, NodeState before) { + try { + updated(); + builder.getChildNode(name).remove(); + return true; + } catch (IOException e) { + exception = e; + return false; + } + } + + @CheckForNull + private static ByteBuffer getStableIdBytes(NodeState state) { + if (state instanceof SegmentNodeState) { + return ((SegmentNodeState) state).getStableIdBytes(); + } else { + return null; + } + } +} 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=1806378&r1=1806377&r2=1806378&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 Sun Aug 27 16:58:21 2017 @@ -16,6 +16,7 @@ */ package org.apache.jackrabbit.oak.upgrade; +import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; import java.util.LinkedHashMap; @@ -31,6 +32,8 @@ import org.apache.commons.lang.StringUti import org.apache.jackrabbit.oak.api.CommitFailedException; import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.api.Type; +import org.apache.jackrabbit.oak.segment.SegmentNodeState; +import org.apache.jackrabbit.oak.segment.file.FileStore; import org.apache.jackrabbit.oak.spi.commit.CommitHook; import org.apache.jackrabbit.oak.spi.commit.CommitInfo; import org.apache.jackrabbit.oak.spi.commit.CompositeEditorProvider; @@ -43,7 +46,7 @@ import org.apache.jackrabbit.oak.spi.sta import org.apache.jackrabbit.oak.spi.state.NodeStore; import org.apache.jackrabbit.oak.upgrade.RepositoryUpgrade.LoggingCompositeHook; import org.apache.jackrabbit.oak.upgrade.checkpoint.CheckpointRetriever; -import org.apache.jackrabbit.oak.upgrade.cli.node.TarNodeStore; +import org.apache.jackrabbit.oak.upgrade.cli.node.SegmentTarFactory; import org.apache.jackrabbit.oak.upgrade.nodestate.FilteringNodeState; import org.apache.jackrabbit.oak.upgrade.nodestate.MetadataExposingNodeState; import org.apache.jackrabbit.oak.upgrade.nodestate.NameFilteringNodeState; @@ -89,6 +92,8 @@ public class RepositorySidegrade { */ private final NodeStore target; + private final FileStore targetFileStore; + private final NodeStore source; /** @@ -180,6 +185,12 @@ public class RepositorySidegrade { public RepositorySidegrade(NodeStore source, NodeStore target) { this.source = source; this.target = target; + + FileStore fs = null; + if (target instanceof SegmentTarFactory.NodeStoreWithFileStore) { + fs = ((SegmentTarFactory.NodeStoreWithFileStore) target).getFileStore(); + } + this.targetFileStore = fs; } /** @@ -315,7 +326,7 @@ public class RepositorySidegrade { builder.setChildNode(":async"); } - private void copyState() throws CommitFailedException, RepositoryException { + private void copyState() throws CommitFailedException, RepositoryException, IOException { boolean migrateCheckpoints = true; if (!isCompleteMigration() && !forceCheckpoints) { LOG.info("Checkpoints won't be migrated because of the specified paths"); @@ -341,7 +352,7 @@ public class RepositorySidegrade { } } - private boolean migrateWithCheckpoints() throws CommitFailedException { + private boolean migrateWithCheckpoints() throws CommitFailedException, IOException { List<CheckpointRetriever.Checkpoint> checkpoints = CheckpointRetriever.getCheckpoints(source); if (checkpoints == null) { return false; @@ -351,8 +362,8 @@ public class RepositorySidegrade { Map<String, String> checkpointSegmentToDoc = new LinkedHashMap<>(); NodeState initialRoot = target.getRoot(); + NodeState targetRoot = initialRoot; NodeState previousRoot = initialRoot; - NodeBuilder targetRoot = previousRoot.builder(); for (CheckpointRetriever.Checkpoint checkpoint : checkpoints) { NodeState checkpointRoot = source.retrieve(checkpoint.getName()); Map<String, String> checkpointInfo = source.checkpointInfo(checkpoint.getName()); @@ -367,11 +378,7 @@ public class RepositorySidegrade { } LOG.info("Checkpoint expiry time: {}, metadata: {}", checkpoint.getExpiryTime(), checkpointInfo); - NodeState currentRoot = wrapNodeState(checkpointRoot, tracePaths, true); - NodeState baseRoot = wrapNodeState(previousRoot, false, true); - currentRoot.compareAgainstBaseState(baseRoot, new ApplyDiff(targetRoot)); - - target.merge(targetRoot, EmptyHook.INSTANCE, CommitInfo.EMPTY); + targetRoot = copyDiffToTarget(previousRoot, checkpointRoot, targetRoot, tracePaths); previousRoot = checkpointRoot; String newCheckpointName = target.checkpoint(checkpoint.getExpiryTime() - System.currentTimeMillis(), checkpointInfo); @@ -390,13 +397,12 @@ public class RepositorySidegrade { LOG.info("Applying diff to head"); tracePaths = false; } - - NodeState currentRoot = wrapNodeState(sourceRoot, tracePaths, true); - NodeState baseRoot = wrapNodeState(previousRoot, false, true); - currentRoot.compareAgainstBaseState(baseRoot, new ApplyDiff(targetRoot)); + + targetRoot = copyDiffToTarget(previousRoot, sourceRoot, targetRoot, tracePaths); LOG.info("Rewriting checkpoint names in /:async {}", nameToRevision); - NodeBuilder async = targetRoot.getChildNode(":async"); + NodeBuilder targetBuilder = targetRoot.builder(); + NodeBuilder async = targetBuilder.getChildNode(":async"); for (Map.Entry<String, String> e : nameToRevision.entrySet()) { async.setProperty(e.getKey(), e.getValue(), Type.STRING); @@ -412,11 +418,24 @@ public class RepositorySidegrade { } async.setProperty(e.getKey() + "-temp", tempValues, Type.STRINGS); } - - target.merge(targetRoot, EmptyHook.INSTANCE, CommitInfo.EMPTY); + target.merge(targetBuilder, EmptyHook.INSTANCE, CommitInfo.EMPTY); return true; } + 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) { + currentRoot.compareAgainstBaseState(baseRoot, new ApplyDiff(targetBuilder)); + } else { + SegmentNodeState state = PersistingDiff.applyDiffOnNodeState(targetFileStore, baseRoot, currentRoot, targetRoot); + state.compareAgainstBaseState(targetRoot, new ApplyDiff(targetBuilder)); + } + return target.merge(targetBuilder, EmptyHook.INSTANCE, CommitInfo.EMPTY); + } + private void migrateWithoutCheckpoints() throws CommitFailedException, RepositoryException { final List<CommitHook> hooks = new ArrayList<>(); if (customCommitHooks != null) { @@ -512,16 +531,8 @@ public class RepositorySidegrade { } private void verify() { - final NodeState sourceRoot; - final NodeState targetRoot; - - if (source instanceof TarNodeStore && target instanceof TarNodeStore) { - sourceRoot = ((TarNodeStore) source).getSuperRoot(); - targetRoot = ((TarNodeStore) target).getSuperRoot(); - } else { - sourceRoot = source.getRoot(); - targetRoot = target.getRoot(); - } + final NodeState sourceRoot = source.getRoot(); + final NodeState targetRoot = target.getRoot(); final NodeState reportingSource = ReportingNodeState.wrap(sourceRoot, new LoggingReporter(LOG, "Verifying", LOG_NODE_COPY, -1)); @@ -553,4 +564,5 @@ public class RepositorySidegrade { private boolean targetExists() { return target.getRoot().getChildNodeEntries().iterator().hasNext(); } + } Modified: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/checkpoint/CheckpointRetriever.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/checkpoint/CheckpointRetriever.java?rev=1806378&r1=1806377&r2=1806378&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/checkpoint/CheckpointRetriever.java (original) +++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/checkpoint/CheckpointRetriever.java Sun Aug 27 16:58:21 2017 @@ -23,10 +23,12 @@ import com.google.common.collect.Iterabl import com.google.common.collect.Lists; import org.apache.jackrabbit.oak.plugins.document.DocumentCheckpointRetriever; import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore; +import org.apache.jackrabbit.oak.segment.CheckpointAccessor; +import org.apache.jackrabbit.oak.segment.SegmentNodeStore; import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry; import org.apache.jackrabbit.oak.spi.state.NodeState; import org.apache.jackrabbit.oak.spi.state.NodeStore; -import org.apache.jackrabbit.oak.upgrade.cli.node.TarNodeStore; +import org.apache.jackrabbit.oak.upgrade.cli.node.SegmentTarFactory; import javax.annotation.Nullable; import java.util.Collections; @@ -71,10 +73,14 @@ public final class CheckpointRetriever { public static List<Checkpoint> getCheckpoints(NodeStore nodeStore) { List<Checkpoint> result; - if (nodeStore instanceof TarNodeStore) { - result = getCheckpoints((TarNodeStore) nodeStore); + if (nodeStore instanceof SegmentNodeStore) { + result = getCheckpoints(CheckpointAccessor.getCheckpointsRoot((SegmentNodeStore) nodeStore)); + } else if (nodeStore instanceof org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore) { + result = getCheckpoints(org.apache.jackrabbit.oak.plugins.segment.CheckpointAccessor.getCheckpointsRoot((org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore) nodeStore)); } else if (nodeStore instanceof DocumentNodeStore) { result = DocumentCheckpointRetriever.getCheckpoints((DocumentNodeStore) nodeStore); + } else if (nodeStore instanceof SegmentTarFactory.NodeStoreWithFileStore) { + result = getCheckpoints(CheckpointAccessor.getCheckpointsRoot(((SegmentTarFactory.NodeStoreWithFileStore) nodeStore).getNodeStore())); } else { return null; } @@ -82,8 +88,8 @@ public final class CheckpointRetriever { return result; } - private static List<Checkpoint> getCheckpoints(TarNodeStore nodeStore) { - return Lists.newArrayList(Iterables.transform(nodeStore.getSuperRoot().getChildNode("checkpoints").getChildNodeEntries(), new Function<ChildNodeEntry, Checkpoint>() { + private static List<Checkpoint> getCheckpoints(NodeState checkpointRoot) { + return Lists.newArrayList(Iterables.transform(checkpointRoot.getChildNodeEntries(), new Function<ChildNodeEntry, Checkpoint>() { @Nullable @Override public Checkpoint apply(@Nullable ChildNodeEntry input) { @@ -91,4 +97,4 @@ public final class CheckpointRetriever { } })); } -} +} \ No newline at end of file Modified: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentFactory.java?rev=1806378&r1=1806377&r2=1806378&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentFactory.java (original) +++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentFactory.java Sun Aug 27 16:58:21 2017 @@ -26,7 +26,6 @@ import org.apache.jackrabbit.oak.plugins import org.apache.jackrabbit.oak.plugins.segment.file.FileStore.Builder; import org.apache.jackrabbit.oak.plugins.segment.file.InvalidFileStoreVersionException; import org.apache.jackrabbit.oak.spi.blob.BlobStore; -import org.apache.jackrabbit.oak.spi.state.NodeState; import org.apache.jackrabbit.oak.spi.state.NodeStore; import com.google.common.io.Closer; @@ -82,12 +81,7 @@ public class SegmentFactory implements N } closer.register(asCloseable(fs)); - return new TarNodeStore(SegmentNodeStore.builder(fs).build(), new TarNodeStore.SuperRootProvider() { - @Override - public NodeState getSuperRoot() { - return fs.getHead(); - } - }); + return SegmentNodeStore.builder(fs).build(); } @Override Modified: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentTarFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentTarFactory.java?rev=1806378&r1=1806377&r2=1806378&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentTarFactory.java (original) +++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentTarFactory.java Sun Aug 27 16:58:21 2017 @@ -26,14 +26,15 @@ import com.google.common.io.Closer; import org.apache.jackrabbit.oak.segment.RecordType; import org.apache.jackrabbit.oak.segment.Segment; import org.apache.jackrabbit.oak.segment.SegmentId; +import org.apache.jackrabbit.oak.segment.SegmentNodeStore; import org.apache.jackrabbit.oak.segment.SegmentNodeStoreBuilders; import org.apache.jackrabbit.oak.segment.file.FileStore; import org.apache.jackrabbit.oak.segment.file.FileStoreBuilder; import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException; import org.apache.jackrabbit.oak.segment.file.ReadOnlyFileStore; import org.apache.jackrabbit.oak.spi.blob.BlobStore; -import org.apache.jackrabbit.oak.spi.state.NodeState; import org.apache.jackrabbit.oak.spi.state.NodeStore; +import org.apache.jackrabbit.oak.spi.state.ProxyNodeStore; public class SegmentTarFactory implements NodeStoreFactory { @@ -77,12 +78,12 @@ public class SegmentTarFactory implement final ReadOnlyFileStore fs; fs = builder.buildReadOnly(); closer.register(asCloseable(fs)); - return new TarNodeStore(SegmentNodeStoreBuilders.builder(fs).build(), new SegmentTarSuperRootProvider(fs)); + return SegmentNodeStoreBuilders.builder(fs).build(); } else { final FileStore fs; fs = builder.build(); closer.register(asCloseable(fs)); - return new TarNodeStore(SegmentNodeStoreBuilders.builder(fs).build(), new SegmentTarSuperRootProvider(fs)); + return new NodeStoreWithFileStore(SegmentNodeStoreBuilders.builder(fs).build(), fs); } } catch (InvalidFileStoreVersionException e) { throw new IllegalStateException(e); @@ -154,25 +155,24 @@ public class SegmentTarFactory implement private static class ExternalBlobFound extends RuntimeException { } - private static class SegmentTarSuperRootProvider implements TarNodeStore.SuperRootProvider { + public static class NodeStoreWithFileStore extends ProxyNodeStore { - private final ReadOnlyFileStore readOnlyFileStore; + private final SegmentNodeStore segmentNodeStore; private final FileStore fileStore; - public SegmentTarSuperRootProvider(ReadOnlyFileStore readOnlyFileStore) { - this.readOnlyFileStore = readOnlyFileStore; - this.fileStore = null; + public NodeStoreWithFileStore(SegmentNodeStore segmentNodeStore, FileStore fileStore) { + this.segmentNodeStore = segmentNodeStore; + this.fileStore = fileStore; } - public SegmentTarSuperRootProvider(FileStore fileStore) { - this.readOnlyFileStore = null; - this.fileStore = fileStore; + public FileStore getFileStore() { + return fileStore; } @Override - public NodeState getSuperRoot() { - return fileStore == null ? readOnlyFileStore.getHead() : fileStore.getHead(); + public SegmentNodeStore getNodeStore() { + return segmentNodeStore; } } }