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 fr...@apache.org on 2016/01/29 16:17:44 UTC

svn commit: r1727599 [1/3] - in /jackrabbit/oak/trunk/oak-run/src: main/java/org/apache/jackrabbit/oak/run/ test/java/org/apache/jackrabbit/oak/run/

Author: frm
Date: Fri Jan 29 15:17:44 2016
New Revision: 1727599

URL: http://svn.apache.org/viewvc?rev=1727599&view=rev
Log:
OAK-3957 - Move the commands of oak-run in independent units

Added:
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/BackupCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckpointsCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Command.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CompactCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ConsoleCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DebugCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DumpDataStoreReferencesCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ExploreCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreDiffCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreRevisionRecoveryCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/GarbageCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/GraphCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HelpCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HistoryCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HttpServer.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Mode.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/PrimaryCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RecoveryCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RepairCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RestoreCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ScalabilityCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ServerCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/StandbyCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/TikaCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/UpgradeCommand.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Utils.java   (with props)
Modified:
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
    jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/run/BasicServerTest.java

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/BackupCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/BackupCommand.java?rev=1727599&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/BackupCommand.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/BackupCommand.java Fri Jan 29 15:17:44 2016
@@ -0,0 +1,56 @@
+/*
+ * 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.run;
+
+import static org.apache.jackrabbit.oak.plugins.segment.FileStoreHelper.newBasicReadOnlyBlobStore;
+import static org.apache.jackrabbit.oak.plugins.segment.FileStoreHelper.openReadOnlyFileStore;
+import static org.apache.jackrabbit.oak.run.Utils.asCloseable;
+
+import java.io.File;
+
+import com.google.common.io.Closer;
+import org.apache.jackrabbit.oak.plugins.backup.FileStoreBackup;
+import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore;
+import org.apache.jackrabbit.oak.plugins.segment.file.FileStore;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+
+class BackupCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        boolean fakeBlobStore = FileStoreBackup.USE_FAKE_BLOBSTORE;
+        Closer closer = Closer.create();
+        try {
+            FileStore fs;
+            if (fakeBlobStore) {
+                fs = openReadOnlyFileStore(new File(args[0]),
+                        newBasicReadOnlyBlobStore());
+            } else {
+                fs = openReadOnlyFileStore(new File(args[0]));
+            }
+            closer.register(asCloseable(fs));
+            NodeStore store = SegmentNodeStore.newSegmentNodeStore(fs).create();
+            FileStoreBackup.backup(store, new File(args[1]));
+        } catch (Throwable e) {
+            throw closer.rethrow(e);
+        } finally {
+            closer.close();
+        }
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/BackupCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkCommand.java?rev=1727599&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkCommand.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkCommand.java Fri Jan 29 15:17:44 2016
@@ -0,0 +1,29 @@
+/*
+ * 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.run;
+
+import org.apache.jackrabbit.oak.benchmark.BenchmarkRunner;
+
+class BenchmarkCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        BenchmarkRunner.main(args);
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckCommand.java?rev=1727599&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckCommand.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckCommand.java Fri Jan 29 15:17:44 2016
@@ -0,0 +1,64 @@
+/*
+ * 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.run;
+
+import static org.apache.jackrabbit.oak.plugins.segment.FileStoreHelper.isValidFileStoreOrFail;
+import static org.apache.jackrabbit.oak.plugins.segment.file.tooling.ConsistencyChecker.checkConsistency;
+
+import java.io.File;
+
+import joptsimple.ArgumentAcceptingOptionSpec;
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+
+class CheckCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        OptionParser parser = new OptionParser();
+        ArgumentAcceptingOptionSpec<String> path = parser.accepts(
+                "path", "path to the segment store (required)")
+                .withRequiredArg().ofType(String.class);
+        ArgumentAcceptingOptionSpec<String> journal = parser.accepts(
+                "journal", "journal file")
+                .withRequiredArg().ofType(String.class).defaultsTo("journal.log");
+        ArgumentAcceptingOptionSpec<Long> deep = parser.accepts(
+                "deep", "enable deep consistency checking. An optional long " +
+                        "specifies the number of seconds between progress notifications")
+                .withOptionalArg().ofType(Long.class).defaultsTo(Long.MAX_VALUE);
+        ArgumentAcceptingOptionSpec<Long> bin = parser.accepts(
+                "bin", "read the n first bytes from binary properties. -1 for all bytes.")
+                .withOptionalArg().ofType(Long.class).defaultsTo(0L);
+
+        OptionSet options = parser.parse(args);
+
+        if (!options.has(path)) {
+            System.err.println("usage: check <options>");
+            parser.printHelpOn(System.err);
+            System.exit(1);
+        }
+
+        File dir = isValidFileStoreOrFail(new File(path.value(options)));
+        String journalFileName = journal.value(options);
+        boolean fullTraversal = options.has(deep);
+        long debugLevel = deep.value(options);
+        long binLen = bin.value(options);
+        checkConsistency(dir, journalFileName, fullTraversal, debugLevel, binLen);
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckpointsCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckpointsCommand.java?rev=1727599&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckpointsCommand.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckpointsCommand.java Fri Jan 29 15:17:44 2016
@@ -0,0 +1,132 @@
+/*
+ * 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.run;
+
+import static org.apache.jackrabbit.oak.plugins.segment.FileStoreHelper.openFileStore;
+
+import java.sql.Timestamp;
+
+import com.google.common.io.Closer;
+import com.mongodb.MongoClient;
+import com.mongodb.MongoClientURI;
+import com.mongodb.MongoURI;
+import org.apache.jackrabbit.oak.checkpoint.Checkpoints;
+import org.apache.jackrabbit.oak.plugins.document.DocumentMK;
+import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore;
+import org.apache.jackrabbit.oak.plugins.segment.file.FileStore;
+
+class CheckpointsCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        if (args.length == 0) {
+            System.out
+                    .println("usage: checkpoints {<path>|<mongo-uri>} [list|rm-all|rm-unreferenced|rm <checkpoint>]");
+            System.exit(1);
+        }
+        boolean success = false;
+        Checkpoints cps;
+        Closer closer = Closer.create();
+        try {
+            String op = "list";
+            if (args.length >= 2) {
+                op = args[1];
+                if (!"list".equals(op) && !"rm-all".equals(op) && !"rm-unreferenced".equals(op) && !"rm".equals(op)) {
+                    failWith("Unknown command.");
+                }
+            }
+
+            if (args[0].startsWith(MongoURI.MONGODB_PREFIX)) {
+                MongoClientURI uri = new MongoClientURI(args[0]);
+                MongoClient client = new MongoClient(uri);
+                final DocumentNodeStore store = new DocumentMK.Builder()
+                        .setMongoDB(client.getDB(uri.getDatabase()))
+                        .getNodeStore();
+                closer.register(Utils.asCloseable(store));
+                cps = Checkpoints.onDocumentMK(store);
+            } else {
+                FileStore store = openFileStore(args[0]);
+                closer.register(Utils.asCloseable(store));
+                cps = Checkpoints.onTarMK(store);
+            }
+
+            System.out.println("Checkpoints " + args[0]);
+            if ("list".equals(op)) {
+                int cnt = 0;
+                for (Checkpoints.CP cp : cps.list()) {
+                    System.out.printf("- %s created %s expires %s%n",
+                            cp.id,
+                            new Timestamp(cp.created),
+                            new Timestamp(cp.expires));
+                    cnt++;
+                }
+                System.out.println("Found " + cnt + " checkpoints");
+            } else if ("rm-all".equals(op)) {
+                long time = System.currentTimeMillis();
+                long cnt = cps.removeAll();
+                time = System.currentTimeMillis() - time;
+                if (cnt != -1) {
+                    System.out.println("Removed " + cnt + " checkpoints in " + time + "ms.");
+                } else {
+                    failWith("Failed to remove all checkpoints.");
+                }
+            } else if ("rm-unreferenced".equals(op)) {
+                long time = System.currentTimeMillis();
+                long cnt = cps.removeUnreferenced();
+                time = System.currentTimeMillis() - time;
+                if (cnt != -1) {
+                    System.out.println("Removed " + cnt + " checkpoints in " + time + "ms.");
+                } else {
+                    failWith("Failed to remove unreferenced checkpoints.");
+                }
+            } else if ("rm".equals(op)) {
+                if (args.length != 3) {
+                    failWith("Missing checkpoint id");
+                } else {
+                    String cp = args[2];
+                    long time = System.currentTimeMillis();
+                    int cnt = cps.remove(cp);
+                    time = System.currentTimeMillis() - time;
+                    if (cnt != 0) {
+                        if (cnt == 1) {
+                            System.out.println("Removed checkpoint " + cp + " in "
+                                    + time + "ms.");
+                        } else {
+                            failWith("Failed to remove checkpoint " + cp);
+                        }
+                    } else {
+                        failWith("Checkpoint '" + cp + "' not found.");
+                    }
+                }
+            }
+            success = true;
+        } catch (Throwable t) {
+            System.err.println(t.getMessage());
+        } finally {
+            closer.close();
+        }
+        if (!success) {
+            System.exit(1);
+        }
+    }
+
+    private static void failWith(String message) {
+        throw new RuntimeException(message);
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckpointsCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Command.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Command.java?rev=1727599&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Command.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Command.java Fri Jan 29 15:17:44 2016
@@ -0,0 +1,24 @@
+/*
+ * 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.run;
+
+interface Command {
+
+    void execute(String... args) throws Exception;
+
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Command.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CompactCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CompactCommand.java?rev=1727599&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CompactCommand.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CompactCommand.java Fri Jan 29 15:17:44 2016
@@ -0,0 +1,133 @@
+/*
+ * 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.run;
+
+import static org.apache.jackrabbit.oak.plugins.segment.FileStoreHelper.openFileStore;
+
+import java.io.File;
+import java.io.RandomAccessFile;
+import java.util.Arrays;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+import com.google.common.base.Stopwatch;
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
+import org.apache.commons.io.FileUtils;
+import org.apache.jackrabbit.oak.commons.IOUtils;
+import org.apache.jackrabbit.oak.plugins.segment.compaction.CompactionStrategy;
+import org.apache.jackrabbit.oak.plugins.segment.file.FileStore;
+import org.apache.jackrabbit.oak.plugins.segment.file.JournalReader;
+
+class CompactCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        OptionParser parser = new OptionParser();
+        OptionSpec<String> directoryArg = parser.nonOptions(
+                "Path to segment store (required)").ofType(String.class);
+        OptionSpec<Void> forceFlag = parser.accepts(
+                "force", "Force compaction and ignore non matching segment version");
+        OptionSet options = parser.parse(args);
+
+        String path = directoryArg.value(options);
+        if (path == null) {
+            System.err.println("Compact a file store. Usage: compact [path] <options>");
+            parser.printHelpOn(System.err);
+            System.exit(-1);
+        }
+        Stopwatch watch = Stopwatch.createStarted();
+        FileStore store = openFileStore(path, options.has(forceFlag));
+        File directory = new File(path);
+        try {
+            boolean persistCM = Boolean.getBoolean("tar.PersistCompactionMap");
+            System.out.println("Compacting " + directory);
+            System.out.println("    before " + Arrays.toString(directory.list()));
+            long sizeBefore = FileUtils.sizeOfDirectory(directory);
+            System.out.println("    size "
+                    + IOUtils.humanReadableByteCount(sizeBefore) + " (" + sizeBefore
+                    + " bytes)");
+
+            System.out.println("    -> compacting");
+
+            CompactionStrategy compactionStrategy = new CompactionStrategy(
+                    false, CompactionStrategy.CLONE_BINARIES_DEFAULT,
+                    CompactionStrategy.CleanupType.CLEAN_ALL, 0,
+                    CompactionStrategy.MEMORY_THRESHOLD_DEFAULT) {
+                @Override
+                public boolean compacted(Callable<Boolean> setHead)
+                        throws Exception {
+                    // oak-run is doing compaction single-threaded
+                    // hence no guarding needed - go straight ahead
+                    // and call setHead
+                    return setHead.call();
+                }
+            };
+            compactionStrategy.setOfflineCompaction(true);
+            compactionStrategy.setPersistCompactionMap(persistCM);
+            store.setCompactionStrategy(compactionStrategy);
+            store.compact();
+        } finally {
+            store.close();
+        }
+
+        System.out.println("    -> cleaning up");
+        store = openFileStore(path, false);
+        try {
+            for (File file : store.cleanup()) {
+                if (!file.exists() || file.delete()) {
+                    System.out.println("    -> removed old file " + file.getName());
+                } else {
+                    System.out.println("    -> failed to remove old file " + file.getName());
+                }
+            }
+
+            String head;
+            File journal = new File(directory, "journal.log");
+            JournalReader journalReader = new JournalReader(journal);
+            try {
+                head = journalReader.iterator().next() + " root\n";
+            } finally {
+                journalReader.close();
+            }
+
+            RandomAccessFile journalFile = new RandomAccessFile(journal, "rw");
+            try {
+                System.out.println("    -> writing new " + journal.getName() + ": " + head);
+                journalFile.setLength(0);
+                journalFile.writeBytes(head);
+                journalFile.getChannel().force(false);
+            } finally {
+                journalFile.close();
+            }
+        } finally {
+            store.close();
+        }
+        watch.stop();
+        System.out.println("    after  "
+                + Arrays.toString(directory.list()));
+        long sizeAfter = FileUtils.sizeOfDirectory(directory);
+        System.out.println("    size "
+                + IOUtils.humanReadableByteCount(sizeAfter) + " (" + sizeAfter
+                + " bytes)");
+        System.out.println("    duration  " + watch.toString() + " ("
+                + watch.elapsed(TimeUnit.SECONDS) + "s).");
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CompactCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ConsoleCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ConsoleCommand.java?rev=1727599&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ConsoleCommand.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ConsoleCommand.java Fri Jan 29 15:17:44 2016
@@ -0,0 +1,29 @@
+/*
+ * 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.run;
+
+import org.apache.jackrabbit.oak.console.Console;
+
+class ConsoleCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        Console.main(args);
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ConsoleCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DebugCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DebugCommand.java?rev=1727599&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DebugCommand.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DebugCommand.java Fri Jan 29 15:17:44 2016
@@ -0,0 +1,265 @@
+/*
+ * 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.run;
+
+import static com.google.common.collect.Sets.newHashSet;
+import static org.apache.commons.io.FileUtils.byteCountToDisplaySize;
+import static org.apache.jackrabbit.oak.plugins.segment.FileStoreHelper.openReadOnlyFileStore;
+import static org.apache.jackrabbit.oak.plugins.segment.RecordType.NODE;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Queues;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.commons.json.JsopBuilder;
+import org.apache.jackrabbit.oak.explorer.NodeStoreTree;
+import org.apache.jackrabbit.oak.json.JsopDiff;
+import org.apache.jackrabbit.oak.plugins.segment.PCMAnalyser;
+import org.apache.jackrabbit.oak.plugins.segment.RecordId;
+import org.apache.jackrabbit.oak.plugins.segment.RecordUsageAnalyser;
+import org.apache.jackrabbit.oak.plugins.segment.Segment;
+import org.apache.jackrabbit.oak.plugins.segment.SegmentId;
+import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState;
+import org.apache.jackrabbit.oak.plugins.segment.SegmentTracker;
+import org.apache.jackrabbit.oak.plugins.segment.file.FileStore;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+class DebugCommand implements Command {
+
+    private static void debugFileStore(FileStore store) {
+        Map<SegmentId, List<SegmentId>> idmap = Maps.newHashMap();
+        int dataCount = 0;
+        long dataSize = 0;
+        int bulkCount = 0;
+        long bulkSize = 0;
+
+        ((Logger) getLogger(SegmentTracker.class)).setLevel(Level.OFF);
+        RecordUsageAnalyser analyser = new RecordUsageAnalyser();
+
+        for (SegmentId id : store.getSegmentIds()) {
+            if (id.isDataSegmentId()) {
+                Segment segment = id.getSegment();
+                dataCount++;
+                dataSize += segment.size();
+                idmap.put(id, segment.getReferencedIds());
+                analyseSegment(segment, analyser);
+            } else if (id.isBulkSegmentId()) {
+                bulkCount++;
+                bulkSize += id.getSegment().size();
+                idmap.put(id, Collections.<SegmentId>emptyList());
+            }
+        }
+        System.out.println("Total size:");
+        System.out.format(
+                "%s in %6d data segments%n",
+                byteCountToDisplaySize(dataSize), dataCount);
+        System.out.format(
+                "%s in %6d bulk segments%n",
+                byteCountToDisplaySize(bulkSize), bulkCount);
+        System.out.println(analyser.toString());
+
+        Set<SegmentId> garbage = newHashSet(idmap.keySet());
+        Queue<SegmentId> queue = Queues.newArrayDeque();
+        queue.add(store.getHead().getRecordId().getSegmentId());
+        while (!queue.isEmpty()) {
+            SegmentId id = queue.remove();
+            if (garbage.remove(id)) {
+                queue.addAll(idmap.get(id));
+            }
+        }
+        dataCount = 0;
+        dataSize = 0;
+        bulkCount = 0;
+        bulkSize = 0;
+        for (SegmentId id : garbage) {
+            if (id.isDataSegmentId()) {
+                dataCount++;
+                dataSize += id.getSegment().size();
+            } else if (id.isBulkSegmentId()) {
+                bulkCount++;
+                bulkSize += id.getSegment().size();
+            }
+        }
+        System.out.format("%nAvailable for garbage collection:%n");
+        System.out.format("%s in %6d data segments%n",
+                byteCountToDisplaySize(dataSize), dataCount);
+        System.out.format("%s in %6d bulk segments%n",
+                byteCountToDisplaySize(bulkSize), bulkCount);
+        System.out.format("%n%s", new PCMAnalyser(store).toString());
+    }
+
+    private static void analyseSegment(Segment segment, RecordUsageAnalyser analyser) {
+        for (int k = 0; k < segment.getRootCount(); k++) {
+            if (segment.getRootType(k) == NODE) {
+                RecordId nodeId = new RecordId(segment.getSegmentId(), segment.getRootOffset(k));
+                try {
+                    analyser.analyseNode(nodeId);
+                } catch (Exception e) {
+                    System.err.format("Error while processing node at %s", nodeId);
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    private static void debugTarFile(FileStore store, String[] args) {
+        File root = new File(args[0]);
+        for (int i = 1; i < args.length; i++) {
+            String f = args[i];
+            if (!f.endsWith(".tar")) {
+                System.out.println("skipping " + f);
+                continue;
+            }
+            File tar = new File(root, f);
+            if (!tar.exists()) {
+                System.out.println("file doesn't exist, skipping " + f);
+                continue;
+            }
+            System.out.println("Debug file " + tar + "(" + tar.length() + ")");
+            Set<UUID> uuids = new HashSet<UUID>();
+            boolean hasrefs = false;
+            for (Map.Entry<String, Set<UUID>> e : store.getTarReaderIndex()
+                    .entrySet()) {
+                if (e.getKey().endsWith(f)) {
+                    hasrefs = true;
+                    uuids = e.getValue();
+                }
+            }
+            if (hasrefs) {
+                System.out.println("SegmentNodeState references to " + f);
+                List<String> paths = new ArrayList<String>();
+                NodeStoreTree.filterNodeStates(uuids, paths, store.getHead(),
+                        "/");
+                for (String p : paths) {
+                    System.out.println("  " + p);
+                }
+            } else {
+                System.out.println("No references to " + f);
+            }
+
+            try {
+                Map<UUID, List<UUID>> graph = store.getTarGraph(f);
+                System.out.println();
+                System.out.println("Tar graph:");
+                for (Map.Entry<UUID, List<UUID>> entry : graph.entrySet()) {
+                    System.out.println("" + entry.getKey() + '=' + entry.getValue());
+                }
+            } catch (IOException e) {
+                System.out.println("Error getting tar graph:");
+            }
+
+        }
+    }
+
+    private static void debugSegment(FileStore store, String[] args) {
+        Pattern pattern = Pattern
+                .compile("([0-9a-f-]+)|(([0-9a-f-]+:[0-9a-f]+)(-([0-9a-f-]+:[0-9a-f]+))?)?(/.*)?");
+        for (int i = 1; i < args.length; i++) {
+            Matcher matcher = pattern.matcher(args[i]);
+            if (!matcher.matches()) {
+                System.err.println("Unknown argument: " + args[i]);
+            } else if (matcher.group(1) != null) {
+                UUID uuid = UUID.fromString(matcher.group(1));
+                SegmentId id = store.getTracker().getSegmentId(
+                        uuid.getMostSignificantBits(),
+                        uuid.getLeastSignificantBits());
+                System.out.println(id.getSegment());
+            } else {
+                RecordId id1 = store.getHead().getRecordId();
+                RecordId id2 = null;
+                if (matcher.group(2) != null) {
+                    id1 = RecordId.fromString(store.getTracker(),
+                            matcher.group(3));
+                    if (matcher.group(4) != null) {
+                        id2 = RecordId.fromString(store.getTracker(),
+                                matcher.group(5));
+                    }
+                }
+                String path = "/";
+                if (matcher.group(6) != null) {
+                    path = matcher.group(6);
+                }
+
+                if (id2 == null) {
+                    NodeState node = new SegmentNodeState(id1);
+                    System.out.println("/ (" + id1 + ") -> " + node);
+                    for (String name : PathUtils.elements(path)) {
+                        node = node.getChildNode(name);
+                        RecordId nid = null;
+                        if (node instanceof SegmentNodeState) {
+                            nid = ((SegmentNodeState) node).getRecordId();
+                        }
+                        System.out.println("  " + name + " (" + nid + ") -> "
+                                + node);
+                    }
+                } else {
+                    NodeState node1 = new SegmentNodeState(id1);
+                    NodeState node2 = new SegmentNodeState(id2);
+                    for (String name : PathUtils.elements(path)) {
+                        node1 = node1.getChildNode(name);
+                        node2 = node2.getChildNode(name);
+                    }
+                    System.out.println(JsopBuilder.prettyPrint(JsopDiff
+                            .diffToJsop(node1, node2)));
+                }
+            }
+        }
+    }
+
+    @Override
+    public void execute(String... args) throws Exception {
+        if (args.length == 0) {
+            System.err.println("usage: debug <path> [id...]");
+            System.exit(1);
+        } else {
+            // TODO: enable debug information for other node store implementations
+            File file = new File(args[0]);
+            System.out.println("Debug " + file);
+            FileStore store = openReadOnlyFileStore(file);
+            try {
+                if (args.length == 1) {
+                    debugFileStore(store);
+                } else {
+                    if (args[1].endsWith(".tar")) {
+                        debugTarFile(store, args);
+                    } else {
+                        debugSegment(store, args);
+                    }
+                }
+            } finally {
+                store.close();
+            }
+        }
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DebugCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DumpDataStoreReferencesCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DumpDataStoreReferencesCommand.java?rev=1727599&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DumpDataStoreReferencesCommand.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DumpDataStoreReferencesCommand.java Fri Jan 29 15:17:44 2016
@@ -0,0 +1,137 @@
+/*
+ * 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.run;
+
+import static org.apache.jackrabbit.oak.plugins.segment.FileStoreHelper.openFileStore;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Joiner;
+import com.google.common.base.StandardSystemProperty;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
+import com.google.common.io.Closer;
+import com.google.common.io.Files;
+import com.mongodb.MongoClient;
+import com.mongodb.MongoClientURI;
+import com.mongodb.MongoURI;
+import org.apache.jackrabbit.oak.commons.IOUtils;
+import org.apache.jackrabbit.oak.plugins.blob.BlobReferenceRetriever;
+import org.apache.jackrabbit.oak.plugins.blob.ReferenceCollector;
+import org.apache.jackrabbit.oak.plugins.document.DocumentBlobReferenceRetriever;
+import org.apache.jackrabbit.oak.plugins.document.DocumentMK;
+import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore;
+import org.apache.jackrabbit.oak.plugins.segment.SegmentBlobReferenceRetriever;
+import org.apache.jackrabbit.oak.plugins.segment.file.FileStore;
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+import org.apache.jackrabbit.oak.spi.blob.GarbageCollectableBlobStore;
+
+class DumpDataStoreReferencesCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        if (args.length == 0) {
+            System.out
+                    .println("usage: dumpdatastorerefs {<path>|<mongo-uri>} <dump_path>]");
+            System.exit(1);
+        }
+
+        Closer closer = Closer.create();
+        try {
+            BlobReferenceRetriever marker = null;
+            BlobStore blobStore = null;
+
+            if (args[0].startsWith(MongoURI.MONGODB_PREFIX)) {
+                MongoClientURI uri = new MongoClientURI(args[0]);
+                MongoClient client = new MongoClient(uri);
+                final DocumentNodeStore store = new DocumentMK.Builder().setMongoDB(client.getDB(uri.getDatabase())).getNodeStore();
+                blobStore = store.getBlobStore();
+                closer.register(Utils.asCloseable(store));
+                marker = new DocumentBlobReferenceRetriever(store);
+            } else {
+                FileStore store = openFileStore(args[0]);
+                closer.register(Utils.asCloseable(store));
+                marker = new SegmentBlobReferenceRetriever(store.getTracker());
+            }
+
+            String dumpPath = StandardSystemProperty.JAVA_IO_TMPDIR.value();
+            if (args.length == 2) {
+                dumpPath = args[1];
+            }
+            File dumpFile = new File(dumpPath, "marked-" + System.currentTimeMillis());
+            final BufferedWriter writer = Files.newWriter(dumpFile, Charsets.UTF_8);
+            final AtomicInteger count = new AtomicInteger();
+            try {
+                final List<String> idBatch = Lists.newArrayListWithCapacity(1024);
+                final Joiner delimJoiner = Joiner.on(",").skipNulls();
+                final GarbageCollectableBlobStore gcBlobStore =
+                        (blobStore != null && blobStore instanceof GarbageCollectableBlobStore
+                                ? (GarbageCollectableBlobStore) blobStore
+                                : null);
+                marker.collectReferences(
+                        new ReferenceCollector() {
+                            @Override
+                            public void addReference(String blobId, String nodeId) {
+                                try {
+                                    Iterator<String> idIter = null;
+                                    if (gcBlobStore != null) {
+                                        idIter = gcBlobStore.resolveChunks(blobId);
+                                    } else{
+                                        idIter = Iterators.singletonIterator(blobId);
+                                    }
+
+                                    while (idIter.hasNext()) {
+                                        String id = idIter.next();
+                                        idBatch.add(delimJoiner.join(id, nodeId));
+                                        count.getAndIncrement();
+                                        if (idBatch.size() >= 1024) {
+                                            writer.append(Joiner.on(StandardSystemProperty.LINE_SEPARATOR.value()).join(idBatch));
+                                            writer.append(StandardSystemProperty.LINE_SEPARATOR.value());
+                                            writer.flush();
+                                            idBatch.clear();
+                                        }
+                                    }
+                                } catch (Exception e) {
+                                    throw new RuntimeException("Error in retrieving references", e);
+                                }
+                            }
+                        }
+                );
+                if (!idBatch.isEmpty()) {
+                    writer.append(Joiner.on(StandardSystemProperty.LINE_SEPARATOR.value()).join(idBatch));
+                    writer.append(StandardSystemProperty.LINE_SEPARATOR.value());
+                    writer.flush();
+                    idBatch.clear();
+                }
+                System.out.println(count.get() + " DataStore references dumped in " + dumpFile);
+            } finally {
+                IOUtils.closeQuietly(writer);
+            }
+        } catch (Throwable t) {
+            System.err.println(t.getMessage());
+        } finally {
+            closer.close();
+        }
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DumpDataStoreReferencesCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ExploreCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ExploreCommand.java?rev=1727599&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ExploreCommand.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ExploreCommand.java Fri Jan 29 15:17:44 2016
@@ -0,0 +1,29 @@
+/*
+ * 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.run;
+
+import org.apache.jackrabbit.oak.explorer.Explorer;
+
+class ExploreCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        Explorer.main(args);
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ExploreCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreDiffCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreDiffCommand.java?rev=1727599&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreDiffCommand.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreDiffCommand.java Fri Jan 29 15:17:44 2016
@@ -0,0 +1,29 @@
+/*
+ * 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.run;
+
+import org.apache.jackrabbit.oak.plugins.segment.FileStoreDiff;
+
+class FileStoreDiffCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        FileStoreDiff.main(args);
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreDiffCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreRevisionRecoveryCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreRevisionRecoveryCommand.java?rev=1727599&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreRevisionRecoveryCommand.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreRevisionRecoveryCommand.java Fri Jan 29 15:17:44 2016
@@ -0,0 +1,29 @@
+/*
+ * 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.run;
+
+import org.apache.jackrabbit.oak.plugins.segment.file.FileStoreRevisionRecovery;
+
+class FileStoreRevisionRecoveryCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        FileStoreRevisionRecovery.main(args);
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreRevisionRecoveryCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/GarbageCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/GarbageCommand.java?rev=1727599&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/GarbageCommand.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/GarbageCommand.java Fri Jan 29 15:17:44 2016
@@ -0,0 +1,47 @@
+/*
+ * 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.run;
+
+import com.google.common.io.Closer;
+import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore;
+import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreHelper;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+
+class GarbageCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        Closer closer = Closer.create();
+        String h = "garbage mongodb://host:port/database";
+        try {
+            NodeStore store = Utils.bootstrapNodeStore(args, closer, h);
+            if (!(store instanceof DocumentNodeStore)) {
+                System.err.println("Garbage mode only available for DocumentNodeStore");
+                System.exit(1);
+            }
+            DocumentNodeStore dns = (DocumentNodeStore) store;
+
+            DocumentNodeStoreHelper.garbageReport(dns);
+        } catch (Throwable e) {
+            throw closer.rethrow(e);
+        } finally {
+            closer.close();
+        }
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/GarbageCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/GraphCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/GraphCommand.java?rev=1727599&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/GraphCommand.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/GraphCommand.java Fri Jan 29 15:17:44 2016
@@ -0,0 +1,96 @@
+/*
+ * 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.run;
+
+import static org.apache.jackrabbit.oak.plugins.segment.FileStoreHelper.openReadOnlyFileStore;
+import static org.apache.jackrabbit.oak.plugins.segment.SegmentGraph.writeGCGraph;
+import static org.apache.jackrabbit.oak.plugins.segment.SegmentGraph.writeSegmentGraph;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.Calendar;
+import java.util.Date;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
+import org.apache.jackrabbit.oak.plugins.segment.file.FileStore;
+
+class GraphCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        OptionParser parser = new OptionParser();
+        OptionSpec<File> directoryArg = parser.nonOptions(
+                "Path to segment store (required)").ofType(File.class);
+        OptionSpec<File> outFileArg = parser.accepts(
+                "output", "Output file").withRequiredArg().ofType(File.class)
+                .defaultsTo(new File("segments.gdf"));
+        OptionSpec<Long> epochArg = parser.accepts(
+                "epoch", "Epoch of the segment time stamps (derived from journal.log if not given)")
+                .withRequiredArg().ofType(Long.class);
+        OptionSpec<Void> gcGraphArg = parser.accepts(
+                "gc", "Write the gc generation graph instead of the full graph");
+        OptionSpec<String> regExpArg = parser.accepts(
+                "pattern", "Regular exception specifying which nodes to include (optional). " +
+                        "Ignore when --gc is specified.")
+                .withRequiredArg().ofType(String.class);
+
+        OptionSet options = parser.parse(args);
+
+        File directory = directoryArg.value(options);
+        if (directory == null) {
+            System.err.println("Dump the segment graph to a file. Usage: graph [File] <options>");
+            parser.printHelpOn(System.err);
+            System.exit(-1);
+        }
+        System.out.println("Opening file store at " + directory);
+        FileStore.ReadOnlyStore fileStore = openReadOnlyFileStore(directory);
+
+        String regExp = regExpArg.value(options);
+
+        File outFile = outFileArg.value(options);
+        Date epoch;
+        if (options.has(epochArg)) {
+            epoch = new Date(epochArg.value(options));
+        } else {
+            Calendar c = Calendar.getInstance();
+            c.setTimeInMillis(new File(directory, "journal.log").lastModified());
+            c.set(Calendar.HOUR_OF_DAY, 0);
+            c.set(Calendar.MINUTE, 0);
+            c.set(Calendar.SECOND, 0);
+            c.set(Calendar.MILLISECOND, 0);
+            epoch = c.getTime();
+        }
+
+        if (outFile.exists()) {
+            outFile.delete();
+        }
+
+        System.out.println("Setting epoch to " + epoch);
+        System.out.println("Writing graph to " + outFile.getAbsolutePath());
+
+        FileOutputStream out = new FileOutputStream(outFile);
+        if (options.has(gcGraphArg)) {
+            writeGCGraph(fileStore, out);
+        } else {
+            writeSegmentGraph(fileStore, out, epoch, regExp);
+        }
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/GraphCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HelpCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HelpCommand.java?rev=1727599&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HelpCommand.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HelpCommand.java Fri Jan 29 15:17:44 2016
@@ -0,0 +1,31 @@
+/*
+ * 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.run;
+
+import com.google.common.base.Joiner;
+
+class HelpCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        System.err.print("Available run modes: ");
+        System.err.println(Joiner.on(", ").join(Mode.values()));
+        System.exit(1);
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HelpCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HistoryCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HistoryCommand.java?rev=1727599&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HistoryCommand.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HistoryCommand.java Fri Jan 29 15:17:44 2016
@@ -0,0 +1,65 @@
+/*
+ * 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.run;
+
+import static org.apache.jackrabbit.oak.plugins.segment.FileStoreHelper.isValidFileStoreOrFail;
+
+import java.io.File;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
+import org.apache.jackrabbit.oak.plugins.segment.file.tooling.RevisionHistory;
+
+class HistoryCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        OptionParser parser = new OptionParser();
+        OptionSpec<File> directoryArg = parser.nonOptions(
+                "Path to segment store (required)").ofType(File.class);
+        OptionSpec<String> journalArg = parser.accepts(
+                "journal", "journal file").withRequiredArg().ofType(String.class)
+                .defaultsTo("journal.log");
+        OptionSpec<String> pathArg = parser.accepts(
+                "path", "Path for which to trace the history").withRequiredArg().ofType(String.class)
+                .defaultsTo("/");
+        OptionSpec<Integer> depthArg = parser.accepts(
+                "depth", "Depth up to which to dump node states").withRequiredArg().ofType(Integer.class)
+                .defaultsTo(0);
+        OptionSet options = parser.parse(args);
+
+        File directory = directoryArg.value(options);
+        if (directory == null) {
+            System.err.println("Trace the history of a path. Usage: history [File] <options>");
+            parser.printHelpOn(System.err);
+            System.exit(-1);
+        }
+
+        String path = pathArg.value(options);
+        int depth = depthArg.value(options);
+        String journalName = journalArg.value(options);
+        File journal = new File(isValidFileStoreOrFail(directory), journalName);
+
+        Iterable<RevisionHistory.HistoryElement> history = new RevisionHistory(directory).getHistory(journal, path);
+        for (RevisionHistory.HistoryElement historyElement : history) {
+            System.out.println(historyElement.toString(depth));
+        }
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HistoryCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HttpServer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HttpServer.java?rev=1727599&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HttpServer.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HttpServer.java Fri Jan 29 15:17:44 2016
@@ -0,0 +1,107 @@
+/*
+ * 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.run;
+
+import java.util.Collections;
+import java.util.Map;
+
+import javax.jcr.Repository;
+
+import org.apache.jackrabbit.oak.Oak;
+import org.apache.jackrabbit.oak.api.ContentRepository;
+import org.apache.jackrabbit.oak.http.OakServlet;
+import org.apache.jackrabbit.oak.jcr.Jcr;
+import org.apache.jackrabbit.oak.remote.content.ContentRemoteRepository;
+import org.apache.jackrabbit.oak.remote.http.RemoteServlet;
+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;
+import org.eclipse.jetty.servlet.ServletHolder;
+
+class HttpServer {
+
+    private final ServletContextHandler context;
+
+    private final Server server;
+
+    public HttpServer(int port) throws Exception {
+        this(port, Collections.singletonMap(new Oak(), ""));
+    }
+
+    public HttpServer(int port, Map<Oak, String> oakMap) throws Exception {
+        context = new ServletContextHandler();
+        context.setContextPath("/");
+
+        for (Map.Entry<Oak, String> entry : oakMap.entrySet()) {
+            addServlets(entry.getKey(), entry.getValue());
+        }
+
+        server = new Server(port);
+        server.setHandler(context);
+        server.start();
+    }
+
+    public void join() throws Exception {
+        server.join();
+    }
+
+    public void stop() throws Exception {
+        server.stop();
+    }
+
+    private void addServlets(Oak oak, String path) {
+        Jcr jcr = new Jcr(oak);
+
+        // 1 - OakServer
+        ContentRepository repository = jcr.createContentRepository();
+        ServletHolder holder = new ServletHolder(new OakServlet(repository));
+        context.addServlet(holder, path + "/*");
+
+        ServletHolder remoteServlet = new ServletHolder(new RemoteServlet(new ContentRemoteRepository(repository)));
+        context.addServlet(remoteServlet, path + "/api/*");
+
+        // 2 - Webdav Server on JCR repository
+        final Repository jcrRepository = jcr.createRepository();
+        @SuppressWarnings("serial")
+        ServletHolder webdav = new ServletHolder(new SimpleWebdavServlet() {
+            @Override
+            public Repository getRepository() {
+                return jcrRepository;
+            }
+        });
+        webdav.setInitParameter(SimpleWebdavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path + "/webdav");
+        webdav.setInitParameter(AbstractWebdavServlet.INIT_PARAM_AUTHENTICATE_HEADER, "Basic realm=\"Oak\"");
+        context.addServlet(webdav, path + "/webdav/*");
+
+        // 3 - JCR Remoting Server
+        @SuppressWarnings("serial")
+        ServletHolder jcrremote = new ServletHolder(new JcrRemotingServlet() {
+            @Override
+            protected Repository getRepository() {
+                return jcrRepository;
+            }
+        });
+        jcrremote.setInitParameter(JCRWebdavServerServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path + "/jcrremote");
+        jcrremote.setInitParameter(AbstractWebdavServlet.INIT_PARAM_AUTHENTICATE_HEADER, "Basic realm=\"Oak\"");
+        context.addServlet(jcrremote, path + "/jcrremote/*");
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HttpServer.java
------------------------------------------------------------------------------
    svn:eol-style = native



Re: svn commit: r1727599 [1/3] - in /jackrabbit/oak/trunk/oak-run/src: main/java/org/apache/jackrabbit/oak/run/ test/java/org/apache/jackrabbit/oak/run/

Posted by Julian Reschke <ju...@gmx.de>.
On 2016-01-29 16:52, Michael Dürig wrote:
>
>
> On 29.1.16 4:17 , frm@apache.org wrote:
>> Author: frm
>> Date: Fri Jan 29 15:17:44 2016
>> New Revision: 1727599
>>
>> URL:http://svn.apache.org/viewvc?rev=1727599&view=rev
>> Log:
>> OAK-3957 - Move the commands of oak-run in independent units
>
> Wow cool! This was overdue...

Now please backport :-)

Re: svn commit: r1727599 [1/3] - in /jackrabbit/oak/trunk/oak-run/src: main/java/org/apache/jackrabbit/oak/run/ test/java/org/apache/jackrabbit/oak/run/

Posted by Michael Dürig <md...@apache.org>.

On 29.1.16 4:17 , frm@apache.org wrote:
> Author: frm
> Date: Fri Jan 29 15:17:44 2016
> New Revision: 1727599
>
> URL:http://svn.apache.org/viewvc?rev=1727599&view=rev
> Log:
> OAK-3957 - Move the commands of oak-run in independent units

Wow cool! This was overdue...

Michael