diff --git oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java index 8aae0dc..c391414 100644 --- oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java +++ oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java @@ -45,14 +45,15 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.jcr.Repository; +import javax.jcr.RepositoryException; import com.google.common.base.Joiner; import com.google.common.collect.Maps; import com.google.common.collect.Queues; import com.google.common.io.Closer; import com.google.common.util.concurrent.AbstractScheduledService; import com.mongodb.MongoClient; @@ -60,14 +61,15 @@ import com.mongodb.MongoClientURI; import com.mongodb.MongoURI; import joptsimple.ArgumentAcceptingOptionSpec; import joptsimple.OptionParser; import joptsimple.OptionSet; import joptsimple.OptionSpec; import org.apache.jackrabbit.core.RepositoryContext; import org.apache.jackrabbit.core.config.RepositoryConfig; +import org.apache.jackrabbit.core.data.FileDataStore; import org.apache.jackrabbit.oak.Oak; import org.apache.jackrabbit.oak.api.ContentRepository; import org.apache.jackrabbit.oak.benchmark.BenchmarkRunner; import org.apache.jackrabbit.oak.checkpoint.Checkpoints; import org.apache.jackrabbit.oak.commons.PathUtils; import org.apache.jackrabbit.oak.commons.json.JsopBuilder; import org.apache.jackrabbit.oak.console.Console; @@ -75,14 +77,15 @@ import org.apache.jackrabbit.oak.explorer.Explorer; import org.apache.jackrabbit.oak.explorer.NodeStoreTree; import org.apache.jackrabbit.oak.fixture.OakFixture; import org.apache.jackrabbit.oak.http.OakServlet; import org.apache.jackrabbit.oak.jcr.Jcr; import org.apache.jackrabbit.oak.json.JsopDiff; import org.apache.jackrabbit.oak.plugins.backup.FileStoreBackup; import org.apache.jackrabbit.oak.plugins.backup.FileStoreRestore; +import org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreBlobStore; import org.apache.jackrabbit.oak.plugins.document.DocumentMK; import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore; import org.apache.jackrabbit.oak.plugins.document.LastRevRecoveryAgent; import org.apache.jackrabbit.oak.plugins.document.NodeDocument; import org.apache.jackrabbit.oak.plugins.document.mongo.MongoDocumentStore; import org.apache.jackrabbit.oak.plugins.document.mongo.MongoDocumentStoreHelper; import org.apache.jackrabbit.oak.plugins.document.mongo.MongoMissingLastRevSeeker; @@ -98,16 +101,18 @@ import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState; import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore; import org.apache.jackrabbit.oak.plugins.segment.compaction.CompactionStrategy; import org.apache.jackrabbit.oak.plugins.segment.compaction.CompactionStrategy.CleanupType; import org.apache.jackrabbit.oak.plugins.segment.file.FileStore; import org.apache.jackrabbit.oak.plugins.segment.standby.client.StandbyClient; import org.apache.jackrabbit.oak.plugins.segment.standby.server.StandbyServer; import org.apache.jackrabbit.oak.scalability.ScalabilityRunner; +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.upgrade.RepositorySidegrade; import org.apache.jackrabbit.oak.upgrade.RepositoryUpgrade; import org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet; import org.apache.jackrabbit.webdav.jcr.JCRWebdavServerServlet; import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet; import org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; @@ -161,14 +166,17 @@ public class Main { break; case COMPACT: compact(args); break; case SERVER: server(URI, args); break; + case COPY: + copy(args); + break; case UPGRADE: upgrade(args); break; case SCALABILITY: ScalabilityRunner.main(args); break; case EXPLORE: @@ -928,14 +936,74 @@ public class Main { if ("journal.log".equals(f)) { return true; } } return false; } + private static void copy(String[] args) throws IOException, RepositoryException { + OptionParser parser = new OptionParser(); + final OptionSpec datastore = parser + .accepts("datastore", "path to shared data store") + .withRequiredArg().ofType(String.class); + OptionSpec nonOption = parser.nonOptions(" "); + OptionSet options = parser.parse(args); + + List argList = nonOption.values(options); + if (argList.size() != 2) { + parser.printHelpOn(System.err); + System.exit(1); + } + + final BlobStore blobStore; + if (options.has(datastore)) { + final String dsPath = datastore.value(options); + final FileDataStore dataStore = new FileDataStore(); + dataStore.setPath(dsPath); + dataStore.init(null); + blobStore = new DataStoreBlobStore(dataStore); + } else { + blobStore = null; + } + + final Closer closer = Closer.create(); + try { + final NodeStore source = initializeNodeStore(argList.get(0), closer, blobStore); + final NodeStore target = initializeNodeStore(argList.get(1), closer, blobStore); + + final RepositorySidegrade sidegrade = new RepositorySidegrade(source, target); + sidegrade.setCopyBinariesByReference(blobStore != null); + sidegrade.copy(); + } finally { + closer.close(); + } + } + + private static NodeStore initializeNodeStore(String pathOrUrl, Closer closer, BlobStore blobStore) + throws IOException { + if (pathOrUrl.startsWith(MongoURI.MONGODB_PREFIX)) { + final MongoClientURI uri = new MongoClientURI(pathOrUrl); + final MongoClient client = new MongoClient(uri); + final DocumentMK.Builder builder = new DocumentMK.Builder(); + builder.setMongoDB(client.getDB(uri.getDatabase())); + builder.setBlobStore(blobStore); + final DocumentNodeStore nodeStore = builder.getNodeStore(); + closer.register(asCloseable(nodeStore)); + return nodeStore; + } else { + final FileStore fileStore = FileStore + .newFileStore(new File(pathOrUrl)) + .withCacheSize(256) + .withBlobStore(blobStore) + .create(); + closer.register(asCloseable(fileStore)); + return new SegmentNodeStore(fileStore); + } + } + private static void upgrade(String[] args) throws Exception { OptionParser parser = new OptionParser(); parser.accepts("datastore", "keep data store"); OptionSpec nonOption = parser.nonOptions(); OptionSet options = parser.parse(args); List argList = nonOption.values(options); @@ -1187,14 +1255,15 @@ public class Main { RESTORE("restore"), BENCHMARK("benchmark"), CONSOLE("console"), DEBUG("debug"), CHECK("check"), COMPACT("compact"), SERVER("server"), + COPY("copy"), UPGRADE("upgrade"), SCALABILITY("scalability"), EXPLORE("explore"), PRIMARY("primary"), STANDBY("standy"), HELP("help"), CHECKPOINTS("checkpoints"),