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 to...@apache.org on 2017/03/30 07:37:42 UTC

svn commit: r1789440 - in /jackrabbit/oak/trunk/oak-upgrade/src: main/java/org/apache/jackrabbit/oak/plugins/ main/java/org/apache/jackrabbit/oak/plugins/document/ main/java/org/apache/jackrabbit/oak/upgrade/ main/java/org/apache/jackrabbit/oak/upgrade...

Author: tomekr
Date: Thu Mar 30 07:37:42 2017
New Revision: 1789440

URL: http://svn.apache.org/viewvc?rev=1789440&view=rev
Log:
OAK-6003: Allow to migrate checkpoints for all type of sidegrades

Added:
    jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/
    jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/document/
    jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointRetriever.java
    jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/checkpoint/
    jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/checkpoint/CheckpointRetriever.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/cli/node/SegmentFactory.java
    jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentTarFactory.java
    jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/TarNodeStore.java
    jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistorySidegradeTest.java
    jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepeatedRepositorySidegradeTest.java
    jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/AbstractOak2OakTest.java
    jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/JdbcToSegmentTest.java
    jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFbsTest.java
    jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFdsTest.java
    jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToSegmentTest.java
    jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToJdbcTest.java
    jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToMongoTest.java

Added: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointRetriever.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointRetriever.java?rev=1789440&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointRetriever.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointRetriever.java Thu Mar 30 07:37:42 2017
@@ -0,0 +1,40 @@
+/*
+ * 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.plugins.document;
+
+import org.apache.jackrabbit.oak.upgrade.checkpoint.CheckpointRetriever;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class DocumentCheckpointRetriever {
+
+    public static List<CheckpointRetriever.Checkpoint> getCheckpoints(DocumentNodeStore nodeStore) {
+        List<CheckpointRetriever.Checkpoint> result = new ArrayList<>();
+        for (Map.Entry<Revision, Checkpoints.Info> e : nodeStore.getCheckpoints().getCheckpoints().entrySet()) {
+            long created = e.getKey().getTimestamp();
+            long expiryTime = e.getValue().getExpiryTime();
+            String name = e.getKey().toString();
+            result.add(new CheckpointRetriever.Checkpoint(name, created, expiryTime));
+        }
+        return result;
+    }
+
+}
\ No newline at end of file

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=1789440&r1=1789439&r2=1789440&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 Thu Mar 30 07:37:42 2017
@@ -18,28 +18,31 @@ package org.apache.jackrabbit.oak.upgrad
 
 import java.util.ArrayList;
 import java.util.Calendar;
-import java.util.Comparator;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
 import javax.jcr.RepositoryException;
 
-import com.google.common.base.Function;
+import com.google.common.collect.Lists;
 import org.apache.commons.lang.StringUtils;
 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.spi.commit.CommitHook;
 import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.apache.jackrabbit.oak.spi.commit.CompositeEditorProvider;
 import org.apache.jackrabbit.oak.spi.commit.EditorHook;
-import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
+import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
 import org.apache.jackrabbit.oak.spi.state.ApplyDiff;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 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.nodestate.NameFilteringNodeState;
 import org.apache.jackrabbit.oak.upgrade.nodestate.report.LoggingReporter;
@@ -54,10 +57,7 @@ import org.slf4j.LoggerFactory;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.collect.ImmutableSet.copyOf;
 import static com.google.common.collect.ImmutableSet.of;
-import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Lists.transform;
 import static com.google.common.collect.Sets.union;
-import static java.util.Collections.sort;
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
 import static org.apache.jackrabbit.JcrConstants.JCR_SYSTEM;
 import static org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionConstants.NT_REP_PERMISSION_STORE;
@@ -219,10 +219,6 @@ public class RepositorySidegrade {
         this.mergePaths = copyOf(checkNotNull(merges));
     }
 
-    public boolean isFilterLongNames() {
-        return filterLongNames;
-    }
-
     public void setFilterLongNames(boolean filterLongNames) {
         this.filterLongNames = filterLongNames;
     }
@@ -240,15 +236,6 @@ public class RepositorySidegrade {
     }
 
     /**
-     * Same as {@link #copy(RepositoryInitializer)}, but with no custom initializer.
-     *
-     * @throws RepositoryException if the copy operation fails
-     */
-    public void copy() throws RepositoryException {
-        copy(null);
-    }
-
-    /**
      * Copies the full content from the source to the target repository.
      * <p>
      * The source repository <strong>must not be modified</strong> while
@@ -257,32 +244,17 @@ public class RepositorySidegrade {
      * Note that both the source and the target repository must be closed
      * during the copy operation as this method requires exclusive access
      * to the repositories.
-     * 
-     * @param initializer optional repository initializer to use
      *
      * @throws RepositoryException if the copy operation fails
      */
-    public void copy(RepositoryInitializer initializer) throws RepositoryException {
+    public void copy() throws RepositoryException {
         try {
             if (!onlyVerify) {
-                NodeBuilder targetRoot = target.getRoot().builder();
-                if (VersionHistoryUtil.getVersionStorage(targetRoot).exists() && !versionCopyConfiguration.skipOrphanedVersionsCopy()) {
+                if (VersionHistoryUtil.getVersionStorage(target.getRoot()).exists() && !versionCopyConfiguration.skipOrphanedVersionsCopy()) {
                     LOG.warn("The version storage on destination already exists. Orphaned version histories will be skipped.");
                     versionCopyConfiguration.setCopyOrphanedVersions(null);
                 }
-
-                if (initializer != null) {
-                    initializer.initialize(targetRoot);
-                }
-
-                final NodeState reportingSourceRoot = ReportingNodeState.wrap(source.getRoot(), new LoggingReporter(LOG, "Copying", LOG_NODE_COPY, -1));
-                final NodeState sourceRoot;
-                if (filterLongNames) {
-                    sourceRoot = NameFilteringNodeState.wrap(reportingSourceRoot);
-                } else {
-                    sourceRoot = reportingSourceRoot;
-                }
-                copyState(sourceRoot, targetRoot);
+                copyState();
             }
             if (verify || onlyVerify) {
                 verify();
@@ -299,64 +271,124 @@ public class RepositorySidegrade {
         builder.setChildNode(":async");
     }
 
-    private void copyState(NodeState sourceRoot, NodeBuilder targetRoot) throws CommitFailedException, RepositoryException {
-        copyWorkspace(sourceRoot, targetRoot);
-
-        if (includeIndex) {
-            IndexCopier.copy(sourceRoot, targetRoot, includePaths);
+    private void copyState() throws CommitFailedException, RepositoryException {
+        final List<CommitHook> hooks = new ArrayList<>();
+        if (customCommitHooks != null) {
+            hooks.addAll(customCommitHooks);
         }
 
-        boolean isRemoveCheckpointReferences = false;
+        boolean migrateCheckpoints = true;
         if (!isCompleteMigration()) {
-            LOG.info("Custom paths have been specified, checkpoints won't be migrated");
-            isRemoveCheckpointReferences = true;
-        } else if (skipCheckpoints) {
-            LOG.info("Checkpoints won't be migrated because of the --skip-checkpoints option");
-            isRemoveCheckpointReferences = true;
-        } else {
-            boolean checkpointsCopied;
-            try {
-                checkpointsCopied = copyCheckpoints(targetRoot);
-            } catch(UnsupportedOperationException e) {
-                removeCheckpoints();
-                throw new RepositoryException("Checkpoints won't be copied, because no external datastore has been specified. This will result in the full repository reindexing on the first start. Use --skip-checkpoints to force the migration or see https://jackrabbit.apache.org/oak/docs/migration.html#Checkpoints_migration for more info.");
+            LOG.info("Checkpoints won't be migrated because of the specified paths");
+            migrateCheckpoints = false;
+        }
+        if (!versionCopyConfiguration.isCopyAll()) {
+            LOG.info("Checkpoints won't be migrated because of the specified version settings");
+            migrateCheckpoints = false;
+        }
+        if (skipCheckpoints) {
+            LOG.info("Checkpoints won't be migrated because of the --skip-checkpoints options");
+            migrateCheckpoints = false;
+        }
+        if (migrateCheckpoints) {
+            migrateCheckpoints = migrateWithCheckpoints();
+        }
+        if (!migrateCheckpoints) {
+            NodeState sourceRoot = wrapSource(source.getRoot());
+            NodeBuilder targetRoot = target.getRoot().builder();
+            copyWorkspace(sourceRoot, targetRoot);
+            removeCheckpointReferences(targetRoot);
+            if (includeIndex) {
+                IndexCopier.copy(sourceRoot, targetRoot, includePaths);
             }
-            if (!checkpointsCopied) {
-                LOG.info("Copying checkpoints is not supported for this combination of node stores");
-                isRemoveCheckpointReferences = true;
+            if (!versionCopyConfiguration.isCopyAll()) {
+                NodeBuilder versionStorage = VersionHistoryUtil.getVersionStorage(targetRoot);
+                if (!versionStorage.exists()) { // it's possible that this is a new repository and the version storage
+                                                // hasn't been created/copied yet
+                    versionStorage = VersionHistoryUtil.createVersionStorage(targetRoot);
+                }
+                if (!versionCopyConfiguration.skipOrphanedVersionsCopy()) {
+                    copyVersionStorage(targetRoot, getVersionStorage(sourceRoot), versionStorage, versionCopyConfiguration);
+                }
+                hooks.add(new EditorHook(new VersionableEditor.Provider(sourceRoot, getWorkspaceName(), versionCopyConfiguration)));
             }
+            markIndexesToBeRebuilt(targetRoot);
+            // type validation, reference and indexing hooks
+            hooks.add(new EditorHook(new CompositeEditorProvider(
+                    createTypeEditorProvider(),
+                    createIndexEditorProvider()
+            )));
+            target.merge(targetRoot, new LoggingCompositeHook(hooks, null, false), CommitInfo.EMPTY);
         }
-        if (isRemoveCheckpointReferences) {
-            removeCheckpointReferences(targetRoot);
+    }
+
+    private boolean migrateWithCheckpoints() throws CommitFailedException {
+        List<CheckpointRetriever.Checkpoint> checkpoints = CheckpointRetriever.getCheckpoints(source);
+        if (checkpoints == null) {
+            return false;
         }
 
-        final List<CommitHook> hooks = new ArrayList<CommitHook>();
-        if (!versionCopyConfiguration.isCopyAll()) {
-            NodeBuilder versionStorage = VersionHistoryUtil.getVersionStorage(targetRoot);
-            if (!versionStorage.exists()) { // it's possible that this is a new repository and the version storage
-                                            // hasn't been created/copied yet
-                versionStorage = VersionHistoryUtil.createVersionStorage(targetRoot);
+        Map<String, String> nameToRevision = new LinkedHashMap<>();
+        Map<String, String> checkpointSegmentToDoc = new LinkedHashMap<>();
+        NodeState previousRoot = null;
+        NodeBuilder targetRoot = target.getRoot().builder();
+        for (CheckpointRetriever.Checkpoint checkpoint : checkpoints) {
+            NodeState checkpointRoot = source.retrieve(checkpoint.getName());
+            if (previousRoot == null) {
+                LOG.info("Migrating first checkpoint: {}", checkpoint.getName());
+                NodeStateCopier.builder()
+                        .include(calculateEffectiveIncludePaths(DEFAULT_INCLUDE_PATHS, checkpointRoot))
+                        .merge(of("/jcr:system"))
+                        .copy(wrapSource(checkpointRoot), targetRoot);
+                copyProperties(checkpointRoot, targetRoot);
+            } else {
+                LOG.info("Applying diff to {}", checkpoint.getName());
+                checkpointRoot.compareAgainstBaseState(wrapSource(previousRoot), new ApplyDiff(targetRoot));
             }
-            if (!versionCopyConfiguration.skipOrphanedVersionsCopy()) {
-                copyVersionStorage(targetRoot, getVersionStorage(sourceRoot), versionStorage, versionCopyConfiguration);
+            target.merge(targetRoot, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+            previousRoot = checkpointRoot;
+
+            Map<String, String> checkpointInfo = source.checkpointInfo(checkpoint.getName());
+            String newCheckpointName = target.checkpoint(checkpoint.getExpiryTime() - System.currentTimeMillis(), checkpointInfo);
+            if (checkpointInfo.containsKey("name")) {
+                nameToRevision.put(checkpointInfo.get("name"), newCheckpointName);
             }
-            hooks.add(new EditorHook(new VersionableEditor.Provider(sourceRoot, getWorkspaceName(), versionCopyConfiguration)));
+            checkpointSegmentToDoc.put(checkpoint.getName(), newCheckpointName);
         }
 
-        if (customCommitHooks != null) {
-            hooks.addAll(customCommitHooks);
+        NodeState sourceRoot = source.getRoot();
+        if (previousRoot == null) {
+            LOG.info("No checkpoints found; migrating head");
+            NodeStateCopier.builder()
+                    .include(calculateEffectiveIncludePaths(DEFAULT_INCLUDE_PATHS, sourceRoot))
+                    .merge(of("/jcr:system"))
+                    .copy(wrapSource(sourceRoot), targetRoot);
+            copyProperties(sourceRoot, targetRoot);
+        } else {
+            LOG.info("Applying diff to head");
+            sourceRoot.compareAgainstBaseState(wrapSource(previousRoot), new ApplyDiff(targetRoot));
         }
 
-        if (!isCompleteMigration()) {
-            markIndexesToBeRebuilt(targetRoot);
-            // type validation, reference and indexing hooks
-            hooks.add(new EditorHook(new CompositeEditorProvider(
-                    createTypeEditorProvider(),
-                    createIndexEditorProvider()
-            )));
+        LOG.info("Rewriting checkpoint names in /:async {}", nameToRevision);
+        NodeBuilder async = targetRoot.getChildNode(":async");
+        for (Map.Entry<String, String> e : nameToRevision.entrySet()) {
+            async.setProperty(e.getKey(), e.getValue(), Type.STRING);
+
+            PropertyState temp = async.getProperty(e.getKey() + "-temp");
+            if (temp == null) {
+                continue;
+            }
+            List<String> tempValues = Lists.newArrayList(temp.getValue(Type.STRINGS));
+            for (Map.Entry<String, String> sToD : checkpointSegmentToDoc.entrySet()) {
+                if (tempValues.contains(sToD.getKey())) {
+                    tempValues.set(tempValues.indexOf(sToD.getKey()), sToD.getValue());
+                }
+            }
+            async.setProperty(e.getKey() + "-temp", tempValues, Type.STRINGS);
         }
 
-        target.merge(targetRoot, new LoggingCompositeHook(hooks, null, false), CommitInfo.EMPTY);
+        target.merge(targetRoot, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        return true;
     }
 
     private boolean isCompleteMigration() {
@@ -384,93 +416,6 @@ public class RepositorySidegrade {
         }
     }
 
-    private boolean copyCheckpoints(NodeBuilder targetRoot) {
-        if (!(source instanceof TarNodeStore && target instanceof TarNodeStore)) {
-            return false;
-        }
-
-        TarNodeStore sourceTarNS = (TarNodeStore) source;
-        TarNodeStore targetTarNS = (TarNodeStore) target;
-
-        NodeState sourceSuperRoot = sourceTarNS.getSuperRoot();
-        NodeBuilder targetSuperRoot = targetTarNS.getSuperRoot().builder();
-
-        String previousCheckpoint = null;
-        for (String checkpoint : getCheckpointNames(sourceSuperRoot)) {
-            NodeState targetPreviousRoot, sourcePreviousRoot;
-            if (previousCheckpoint == null) {
-                sourcePreviousRoot = source.getRoot();
-                targetPreviousRoot = targetRoot.getNodeState();
-            } else {
-                sourcePreviousRoot = getCheckpointRoot(sourceSuperRoot, previousCheckpoint);
-                targetPreviousRoot = getCheckpointRoot(targetSuperRoot.getNodeState(), previousCheckpoint);
-            }
-            NodeState sourceCheckpoint = getCheckpoint(sourceSuperRoot, checkpoint);
-            NodeBuilder targetCheckpoint = getCheckpoint(targetSuperRoot, checkpoint);
-
-            // copy checkpoint metadata
-            NodeStateCopier.copyProperties(sourceCheckpoint, targetCheckpoint);
-            targetCheckpoint.setChildNode("properties", sourceCheckpoint.getChildNode("properties"));
-
-            // create the checkpoint root
-            NodeState sourceCheckpointRoot = sourceCheckpoint.getChildNode("root");
-            NodeBuilder targetCheckpointRoot = targetCheckpoint.setChildNode("root", targetPreviousRoot);
-            sourceCheckpointRoot.compareAgainstBaseState(sourcePreviousRoot, new ApplyDiff(targetCheckpointRoot));
-
-            previousCheckpoint = checkpoint;
-        }
-
-        targetTarNS.setSuperRoot(targetSuperRoot);
-        return true;
-   }
-
-    private void removeCheckpoints() {
-        if (!(target instanceof TarNodeStore)) {
-            return;
-        }
-        TarNodeStore targetTarNS = (TarNodeStore) target;
-        NodeBuilder targetSuperRoot = ((TarNodeStore) target).getSuperRoot().builder();
-        targetSuperRoot.setChildNode("checkpoints");
-        targetTarNS.setSuperRoot(targetSuperRoot);
-    }
-
-    /**
-     * Return all checkpoint paths, sorted by their "created" property, descending.
-     *
-     * @param superRoot
-     * @return
-     */
-    private static List<String> getCheckpointNames(NodeState superRoot) {
-        List<ChildNodeEntry> checkpoints = newArrayList(superRoot.getChildNode("checkpoints").getChildNodeEntries().iterator());
-        sort(checkpoints, new Comparator<ChildNodeEntry>() {
-            @Override
-            public int compare(ChildNodeEntry o1, ChildNodeEntry o2) {
-                long c1 = o1.getNodeState().getLong("created");
-                long c2 = o2.getNodeState().getLong("created");
-                return -Long.compare(c1, c2);
-            }
-        });
-        return transform(checkpoints, new Function<ChildNodeEntry, String>() {
-            @Nullable
-            @Override
-            public String apply(@Nullable ChildNodeEntry input) {
-                return input.getName();
-            }
-        });
-    }
-
-    private static NodeState getCheckpointRoot(NodeState superRoot, String name) {
-        return getCheckpoint(superRoot, name).getChildNode("root");
-    }
-
-    private static NodeState getCheckpoint(NodeState superRoot, String name) {
-        return superRoot.getChildNode("checkpoints").getChildNode(name);
-    }
-
-    private static NodeBuilder getCheckpoint(NodeBuilder superRoot, String name) {
-        return superRoot.child("checkpoints").child(name);
-    }
-
     private String getWorkspaceName() throws RepositoryException {
         String definedName = System.getProperty(WORKSPACE_NAME_PROP);
         String detectedName = deriveWorkspaceName();
@@ -527,4 +472,15 @@ public class RepositorySidegrade {
             LOG.warn("Verification result: repositories are not identical");
         }
     }
+
+    private NodeState wrapSource(NodeState source) {
+        final NodeState reportingSourceRoot = ReportingNodeState.wrap(source, new LoggingReporter(LOG, "Copying", LOG_NODE_COPY, -1));
+        final NodeState sourceRoot;
+        if (filterLongNames) {
+            sourceRoot = NameFilteringNodeState.wrap(reportingSourceRoot);
+        } else {
+            sourceRoot = reportingSourceRoot;
+        }
+        return sourceRoot;
+    }
 }

Added: 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=1789440&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/checkpoint/CheckpointRetriever.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/checkpoint/CheckpointRetriever.java Thu Mar 30 07:37:42 2017
@@ -0,0 +1,94 @@
+/*
+ * 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.checkpoint;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+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.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 javax.annotation.Nullable;
+import java.util.Collections;
+import java.util.List;
+
+public final class CheckpointRetriever {
+
+    public static class Checkpoint implements Comparable<Checkpoint> {
+
+        private final String name;
+
+        private final long created;
+
+        private final long expiryTime;
+
+        public Checkpoint(String name, long created, long expiryTime) {
+            this.name = name;
+            this.created = created;
+            this.expiryTime = expiryTime;
+        }
+
+        public static Checkpoint createFromSegmentNode(String name, NodeState node) {
+            return new Checkpoint(name, node.getLong("created"), node.getLong("timestamp"));
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public long getExpiryTime() {
+            return expiryTime;
+        }
+
+        @Override
+        public int compareTo(Checkpoint o) {
+            return Long.compare(this.created, o.created);
+        }
+    }
+
+    private CheckpointRetriever() {
+    }
+
+    public static List<Checkpoint> getCheckpoints(NodeStore nodeStore) {
+        List<Checkpoint> result;
+        if (nodeStore instanceof TarNodeStore) {
+            result = getCheckpoints((TarNodeStore) nodeStore);
+        } else if (nodeStore instanceof DocumentNodeStore) {
+            result = DocumentCheckpointRetriever.getCheckpoints((DocumentNodeStore) nodeStore);
+        } else {
+            return null;
+        }
+        Collections.sort(result);
+        return result;
+    }
+
+    private static List<Checkpoint> getCheckpoints(TarNodeStore nodeStore) {
+        return Lists.newArrayList(Iterables.transform(nodeStore.getSuperRoot().getChildNode("checkpoints").getChildNodeEntries(), new Function<ChildNodeEntry, Checkpoint>() {
+            @Nullable
+            @Override
+            public Checkpoint apply(@Nullable ChildNodeEntry input) {
+                return Checkpoint.createFromSegmentNode(input.getName(), input.getNodeState());
+            }
+        }));
+    }
+}

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=1789440&r1=1789439&r2=1789440&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 Thu Mar 30 07:37:42 2017
@@ -21,14 +21,11 @@ import java.io.File;
 import java.io.IOException;
 
 import org.apache.jackrabbit.oak.plugins.blob.ReferenceCollector;
-import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeBuilder;
-import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState;
 import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore;
 import org.apache.jackrabbit.oak.plugins.segment.file.FileStore;
 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.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
 
@@ -36,8 +33,6 @@ import com.google.common.io.Closer;
 
 import javax.annotation.Nullable;
 
-import static com.google.common.base.Preconditions.checkArgument;
-
 public class SegmentFactory implements NodeStoreFactory {
 
     private final File dir;
@@ -89,19 +84,6 @@ public class SegmentFactory implements N
 
         return new TarNodeStore(SegmentNodeStore.builder(fs).build(), new TarNodeStore.SuperRootProvider() {
             @Override
-            public void setSuperRoot(NodeBuilder builder) {
-                checkArgument(builder instanceof SegmentNodeBuilder);
-                SegmentNodeBuilder segmentBuilder = (SegmentNodeBuilder) builder;
-                SegmentNodeState lastRoot = (SegmentNodeState) getSuperRoot();
-
-                if (!lastRoot.getRecordId().equals(((SegmentNodeState) segmentBuilder.getBaseState()).getRecordId())) {
-                    throw new IllegalArgumentException("The new head is out of date");
-                }
-
-                fs.setHead(lastRoot, ((SegmentNodeBuilder) builder).getNodeState());
-            }
-
-            @Override
             public NodeState getSuperRoot() {
                 return fs.getHead();
             }

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=1789440&r1=1789439&r2=1789440&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 Thu Mar 30 07:37:42 2017
@@ -16,7 +16,6 @@
  */
 package org.apache.jackrabbit.oak.upgrade.cli.node;
 
-import static com.google.common.base.Preconditions.checkArgument;
 import static org.apache.jackrabbit.oak.segment.file.FileStoreBuilder.fileStoreBuilder;
 
 import java.io.Closeable;
@@ -27,15 +26,12 @@ 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.SegmentNodeBuilder;
-import org.apache.jackrabbit.oak.segment.SegmentNodeState;
 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.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
 
@@ -175,21 +171,6 @@ public class SegmentTarFactory implement
         }
 
         @Override
-        public void setSuperRoot(NodeBuilder builder) {
-            if (fileStore == null) {
-                throw new IllegalStateException("setSuperRoot is not supported for read-only segment-tar");
-            }
-            checkArgument(builder instanceof SegmentNodeBuilder);
-            SegmentNodeBuilder segmentBuilder = (SegmentNodeBuilder) builder;
-            SegmentNodeState lastRoot = (SegmentNodeState) getSuperRoot();
-
-            if (!lastRoot.getRecordId().equals(((SegmentNodeState) segmentBuilder.getBaseState()).getRecordId())) {
-                throw new IllegalArgumentException("The new head is out of date");
-            }
-            fileStore.getRevisions().setHead(lastRoot.getRecordId(), segmentBuilder.getNodeState().getRecordId());
-        }
-
-        @Override
         public NodeState getSuperRoot() {
             return fileStore == null ? readOnlyFileStore.getHead() : fileStore.getHead();
         }

Modified: 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/upgrade/cli/node/TarNodeStore.java?rev=1789440&r1=1789439&r2=1789440&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/upgrade/cli/node/TarNodeStore.java Thu Mar 30 07:37:42 2017
@@ -16,7 +16,6 @@
  */
 package org.apache.jackrabbit.oak.upgrade.cli.node;
 
-import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
 import org.apache.jackrabbit.oak.spi.state.ProxyNodeStore;
@@ -32,10 +31,6 @@ public class TarNodeStore extends ProxyN
         this.superRootProvider = superRootProvider;
     }
 
-    public void setSuperRoot(NodeBuilder builder) {
-        superRootProvider.setSuperRoot(builder);
-    }
-
     public NodeState getSuperRoot() {
         return superRootProvider.getSuperRoot();
     }
@@ -47,8 +42,6 @@ public class TarNodeStore extends ProxyN
 
     interface SuperRootProvider {
 
-        void setSuperRoot(NodeBuilder builder);
-
         NodeState getSuperRoot();
 
     }

Modified: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistorySidegradeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistorySidegradeTest.java?rev=1789440&r1=1789439&r2=1789440&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistorySidegradeTest.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistorySidegradeTest.java Thu Mar 30 07:37:42 2017
@@ -54,7 +54,7 @@ public class CopyVersionHistorySidegrade
         final NodeStore targetNodeStore = new MemoryNodeStore();
         final RepositorySidegrade sidegrade = new RepositorySidegrade(sourceNodeStore, targetNodeStore);
         setup.setup(sidegrade.versionCopyConfiguration);
-        sidegrade.copy(null);
+        sidegrade.copy();
 
         repository = (RepositoryImpl) new Jcr(new Oak(targetNodeStore)).createRepository();
         Session s = repository.login(AbstractRepositoryUpgradeTest.CREDENTIALS);

Modified: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepeatedRepositorySidegradeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepeatedRepositorySidegradeTest.java?rev=1789440&r1=1789439&r2=1789440&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepeatedRepositorySidegradeTest.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepeatedRepositorySidegradeTest.java Thu Mar 30 07:37:42 2017
@@ -28,12 +28,15 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
 import org.apache.jackrabbit.oak.Oak;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.jcr.Jcr;
 import org.apache.jackrabbit.oak.jcr.repository.RepositoryImpl;
 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.InvalidFileStoreVersionException;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
 import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
@@ -96,12 +99,14 @@ public class RepeatedRepositorySidegrade
         SegmentNodeStore segmentNodeStore = SegmentNodeStoreBuilders.builder(fileStore).build();
         try {
             final RepositorySidegrade repositoryUpgrade = new RepositorySidegrade(segmentNodeStore, target);
-            repositoryUpgrade.copy(new RepositoryInitializer() {
-                @Override
-                public void initialize(@Nonnull NodeBuilder builder) {
-                    builder.child("foo").child("bar");
-                }
-            });
+
+            NodeBuilder builder = target.getRoot().builder();
+            builder.child("foo").child("bar");
+            target.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+            repositoryUpgrade.copy();
+        } catch (CommitFailedException e) {
+            throw new RepositoryException(e);
         } finally {
             fileStore.close();
         }

Modified: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/AbstractOak2OakTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/AbstractOak2OakTest.java?rev=1789440&r1=1789439&r2=1789440&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/AbstractOak2OakTest.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/AbstractOak2OakTest.java Thu Mar 30 07:37:42 2017
@@ -49,6 +49,7 @@ import org.apache.jackrabbit.oak.api.Typ
 import org.apache.jackrabbit.oak.commons.IOUtils;
 import org.apache.jackrabbit.oak.jcr.Jcr;
 import org.apache.jackrabbit.oak.jcr.repository.RepositoryImpl;
+import org.apache.jackrabbit.oak.plugins.document.DocumentNodeState;
 import org.apache.jackrabbit.oak.plugins.index.reference.ReferenceIndexProvider;
 import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState;
 import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
@@ -82,8 +83,6 @@ public abstract class AbstractOak2OakTes
 
     private RepositoryImpl repository;
 
-    private String checkpointReference;
-
     protected abstract NodeStoreContainer getSourceContainer();
 
     protected abstract NodeStoreContainer getDestinationContainer();
@@ -149,7 +148,7 @@ public abstract class AbstractOak2OakTes
         builder.setProperty("binary-prop", getRandomBlob(target));
         builder.setProperty("checkpoint-state", "before");
         target.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
-        checkpointReference = target.checkpoint(60000, singletonMap("key", "123"));
+        target.checkpoint(60000, singletonMap("key", "123"));
 
         builder.setProperty("checkpoint-state", "after");
         builder.setProperty("binary-prop", getRandomBlob(target));
@@ -219,6 +218,17 @@ public abstract class AbstractOak2OakTes
     protected void verifyCheckpoint() {
         assertEquals("after", destination.getRoot().getString("checkpoint-state"));
 
+        String checkpointReference = null;
+
+        for (String c : destination.checkpoints()) {
+            if (destination.checkpointInfo(c).containsKey("key")) {
+                checkpointReference = c;
+                break;
+            }
+        }
+
+        assertNotNull(checkpointReference);
+
         Map<String, String> info = destination.checkpointInfo(checkpointReference);
         assertEquals("123", info.get("key"));
 
@@ -244,6 +254,8 @@ public abstract class AbstractOak2OakTes
             return ((SegmentNodeState) node).getRecordId().toString();
         } else if (node instanceof org.apache.jackrabbit.oak.segment.SegmentNodeState) {
             return ((org.apache.jackrabbit.oak.segment.SegmentNodeState) node).getRecordId().toString();
+        } else if (node instanceof DocumentNodeState) {
+            return ((DocumentNodeState) node).getLastRevision().toString();
         } else {
             return null;
         }

Modified: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/JdbcToSegmentTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/JdbcToSegmentTest.java?rev=1789440&r1=1789439&r2=1789440&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/JdbcToSegmentTest.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/JdbcToSegmentTest.java Thu Mar 30 07:37:42 2017
@@ -48,4 +48,9 @@ public class JdbcToSegmentTest extends A
         return new String[] { "--src-user", "sa", "--src-password", "sa", source.getDescription(),
                 destination.getDescription() };
     }
+
+    @Override
+    protected boolean supportsCheckpointMigration() {
+        return true;
+    }
 }

Modified: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFbsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFbsTest.java?rev=1789440&r1=1789439&r2=1789440&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFbsTest.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFbsTest.java Thu Mar 30 07:37:42 2017
@@ -59,4 +59,9 @@ public class MongoToMongoFbsTest extends
         return new String[] { "--copy-binaries", "--fileblobstore", destinationBlob.getDescription(),
                 source.getDescription(), destination.getDescription() };
     }
+
+    @Override
+    protected boolean supportsCheckpointMigration() {
+        return true;
+    }
 }

Modified: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFdsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFdsTest.java?rev=1789440&r1=1789439&r2=1789440&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFdsTest.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFdsTest.java Thu Mar 30 07:37:42 2017
@@ -56,4 +56,9 @@ public class MongoToMongoFdsTest extends
         return new String[] { "--copy-binaries", "--datastore", destinationBlob.getDescription(),
                 source.getDescription(), destination.getDescription() };
     }
+
+    @Override
+    protected boolean supportsCheckpointMigration() {
+        return true;
+    }
 }

Modified: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToSegmentTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToSegmentTest.java?rev=1789440&r1=1789439&r2=1789440&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToSegmentTest.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToSegmentTest.java Thu Mar 30 07:37:42 2017
@@ -51,4 +51,9 @@ public class MongoToSegmentTest extends
     protected String[] getArgs() {
         return new String[] { source.getDescription(), destination.getDescription() };
     }
+
+    @Override
+    protected boolean supportsCheckpointMigration() {
+        return true;
+    }
 }

Modified: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToJdbcTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToJdbcTest.java?rev=1789440&r1=1789439&r2=1789440&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToJdbcTest.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToJdbcTest.java Thu Mar 30 07:37:42 2017
@@ -49,4 +49,9 @@ public class SegmentToJdbcTest extends A
         return new String[] { "--disable-mmap", "--user", "sa", "--password", "sa", source.getDescription(),
                 destination.getDescription() };
     }
+
+    @Override
+    protected boolean supportsCheckpointMigration() {
+        return true;
+    }
 }

Modified: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToMongoTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToMongoTest.java?rev=1789440&r1=1789439&r2=1789440&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToMongoTest.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToMongoTest.java Thu Mar 30 07:37:42 2017
@@ -51,4 +51,9 @@ public class SegmentToMongoTest extends
     protected String[] getArgs() {
         return new String[] { source.getDescription(), destination.getDescription() };
     }
+
+    @Override
+    protected boolean supportsCheckpointMigration() {
+        return true;
+    }
 }