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/05/24 08:45:07 UTC

svn commit: r1745330 - in /jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak: explorer/ run/

Author: frm
Date: Tue May 24 08:45:07 2016
New Revision: 1745330

URL: http://svn.apache.org/viewvc?rev=1745330&view=rev
Log:
OAK-4337 - Add a flag to choose between segment store implementations in the "explore" command

Added:
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/ExplorerBackend.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/SegmentExplorerBackend.java
      - copied, changed from r1745315, jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/FileStoreWrapper.java
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/SegmentTarExplorerBackend.java   (with props)
Removed:
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/FileStoreWrapper.java
Modified:
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/Explorer.java
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/NodeStoreTree.java
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/SegmentUtils.java

Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/Explorer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/Explorer.java?rev=1745330&r1=1745329&r2=1745330&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/Explorer.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/Explorer.java Tue May 24 08:45:07 2016
@@ -30,6 +30,9 @@ import java.util.List;
 import javax.swing.*;
 import javax.swing.UIManager.LookAndFeelInfo;
 
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
 import org.apache.commons.io.IOUtils;
 
 /**
@@ -40,10 +43,6 @@ import org.apache.commons.io.IOUtils;
  */
 public class Explorer {
 
-    private static boolean getSkipSizeChecks(String... args) {
-        return args.length >= 2 && args[1].equalsIgnoreCase("skip-size-check");
-    }
-
     private static void initLF() {
         try {
             for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
@@ -59,21 +58,34 @@ public class Explorer {
     }
 
     public static void main(String[] args) throws IOException {
-        new Explorer(args);
-    }
+        OptionParser parser = new OptionParser();
+        OptionSpec segmentTar = parser.accepts("segment-tar", "Use oak-segment-tar instead of oak-segment");
+        OptionSpec skipSizeCheck = parser.accepts("skip-size-check", "Don't compute the size of the records");
+        OptionSpec<File> nonOptions = parser.nonOptions().ofType(File.class);
+        OptionSet options = parser.parse(args);
 
-    private final FileStoreWrapper store;
-
-    private Explorer(String[] args) throws IOException {
-        if (args.length == 0) {
-            System.err.println("usage: explore <path> [skip-size-check]");
+        if (options.valuesOf(nonOptions).isEmpty()) {
+            parser.printHelpOn(System.err);
             System.exit(1);
         }
 
-        final File path = new File(args[0]);
-        final boolean skipSizeCheck = getSkipSizeChecks(args);
+        File path = options.valuesOf(nonOptions).get(0);
+
+        ExplorerBackend backend;
+
+        if (options.has(segmentTar)) {
+            backend = new SegmentTarExplorerBackend(path);
+        } else {
+            backend = new SegmentExplorerBackend(path);
+        }
+
+        new Explorer(path, backend, options.has(skipSizeCheck));
+    }
+
+    private final ExplorerBackend backend;
 
-        this.store = new FileStoreWrapper(path);
+    private Explorer(final File path, ExplorerBackend backend, final boolean skipSizeCheck) throws IOException {
+        this.backend = backend;
 
         javax.swing.SwingUtilities.invokeLater(new Runnable() {
             public void run() {
@@ -93,7 +105,7 @@ public class Explorer {
         log.setLineWrap(true);
         log.setEditable(false);
 
-        final NodeStoreTree treePanel = new NodeStoreTree(store, log, skipSizeCheck);
+        final NodeStoreTree treePanel = new NodeStoreTree(backend, log, skipSizeCheck);
 
         final JFrame frame = new JFrame("Explore " + path + " @head");
         frame.addWindowListener(new java.awt.event.WindowAdapter() {
@@ -138,7 +150,7 @@ public class Explorer {
         menuCompaction.addActionListener(new ActionListener() {
             @Override
             public void actionPerformed(ActionEvent ev) {
-                List<String> revs = store.readRevisions();
+                List<String> revs = backend.readRevisions();
                 String s = (String) JOptionPane.showInputDialog(frame,
                         "Revert to a specified revision", "Time Machine",
                         JOptionPane.PLAIN_MESSAGE, null, revs.toArray(),

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/ExplorerBackend.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/ExplorerBackend.java?rev=1745330&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/ExplorerBackend.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/ExplorerBackend.java Tue May 24 08:45:07 2016
@@ -0,0 +1,82 @@
+/*
+ * 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.explorer;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.jackrabbit.oak.api.Blob;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+interface ExplorerBackend {
+
+    void open() throws IOException;
+
+    void close();
+
+    List<String> readRevisions();
+
+    Map<String, Set<UUID>> getTarReaderIndex();
+
+    Map<UUID, List<UUID>> getTarGraph(String file) throws IOException;
+
+    List<String> getTarFiles();
+
+    void getGcRoots(UUID uuidIn, Map<UUID, Set<Entry<UUID, String>>> links) throws IOException;
+
+    Set<UUID> getReferencedSegmentIds();
+
+    NodeState getHead();
+
+    NodeState readNodeState(String recordId);
+
+    void setRevision(String revision);
+
+    boolean isPersisted(NodeState state);
+
+    boolean isPersisted(PropertyState state);
+
+    String getRecordId(NodeState state);
+
+    UUID getSegmentId(NodeState state);
+
+    String getRecordId(PropertyState state);
+
+    UUID getSegmentId(PropertyState state);
+
+    String getTemplateRecordId(NodeState state);
+
+    UUID getTemplateSegmentId(NodeState state);
+
+    String getFile(NodeState state);
+
+    String getFile(PropertyState state);
+
+    String getTemplateFile(NodeState state);
+
+    Map<UUID, String> getBulkSegmentIds(Blob blob);
+
+    String getPersistedCompactionMapStats();
+
+    boolean isExternal(Blob blob);
+}

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

Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/NodeStoreTree.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/NodeStoreTree.java?rev=1745330&r1=1745329&r2=1745330&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/NodeStoreTree.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/NodeStoreTree.java Tue May 24 08:45:07 2016
@@ -57,7 +57,7 @@ import org.apache.jackrabbit.oak.api.Typ
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
-public class NodeStoreTree extends JPanel implements TreeSelectionListener, Closeable {
+class NodeStoreTree extends JPanel implements TreeSelectionListener, Closeable {
 
     private static final long serialVersionUID = 1L;
 
@@ -91,7 +91,7 @@ public class NodeStoreTree extends JPane
         }
     }
 
-    private static void printPropertyState(FileStoreWrapper store, PropertyState state, String parentFile, StringBuilder b) {
+    private static void printPropertyState(ExplorerBackend store, PropertyState state, String parentFile, StringBuilder b) {
         if (store.isPersisted(state)) {
             printRecordId(store.getRecordId(state), store.getFile(state), parentFile, b);
         } else {
@@ -99,7 +99,7 @@ public class NodeStoreTree extends JPane
         }
     }
 
-    private static void printNodeState(FileStoreWrapper store, NodeState state, String parentTarFile, StringBuilder b) {
+    private static void printNodeState(ExplorerBackend store, NodeState state, String parentTarFile, StringBuilder b) {
         if (store.isPersisted(state)) {
             printRecordId(store.getRecordId(state), store.getFile(state), parentTarFile, b);
         } else {
@@ -121,7 +121,7 @@ public class NodeStoreTree extends JPane
         l.append(" (").append(o.getClass().getSimpleName()).append(")");
     }
 
-    private final FileStoreWrapper store;
+    private final ExplorerBackend backend;
 
     private Map<String, Set<UUID>> index;
 
@@ -135,10 +135,10 @@ public class NodeStoreTree extends JPane
 
     private final boolean skipSizeCheck;
 
-    NodeStoreTree(FileStoreWrapper store, JTextArea log, boolean skipSizeCheck)
+    NodeStoreTree(ExplorerBackend backend, JTextArea log, boolean skipSizeCheck)
             throws IOException {
         super(new GridLayout(1, 0));
-        this.store = store;
+        this.backend = backend;
         this.log = log;
         this.skipSizeCheck = skipSizeCheck;
 
@@ -156,15 +156,15 @@ public class NodeStoreTree extends JPane
     }
 
     private void refreshStore() throws IOException {
-        store.open();
+        backend.open();
     }
 
     private void refreshModel() {
-        index = store.getTarReaderIndex();
+        index = backend.getTarReaderIndex();
         sizeCache = newHashMap();
         DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(
-                new NamePathModel("/", "/", store.getHead(), sizeCache,
-                        skipSizeCheck, store), true);
+                new NamePathModel("/", "/", backend.getHead(), sizeCache,
+                        skipSizeCheck, backend), true);
         treeModel = new DefaultTreeModel(rootNode);
         addChildren(rootNode);
         tree.setModel(treeModel);
@@ -196,7 +196,7 @@ public class NodeStoreTree extends JPane
 
             NamePathModel model = (NamePathModel) node.getUserObject();
             NodeState state = model.getState();
-            String recordId = store.getRecordId(state);
+            String recordId = backend.getRecordId(state);
             if (recordId != null) {
                 sb.append("Record ");
                 sb.append(recordId);
@@ -221,7 +221,7 @@ public class NodeStoreTree extends JPane
         for (ChildNodeEntry ce : model.getState().getChildNodeEntries()) {
             NamePathModel c = new NamePathModel(ce.getName(), concat(
                     model.getPath(), ce.getName()), ce.getNodeState(),
-                    sizeCache, skipSizeCheck, store);
+                    sizeCache, skipSizeCheck, backend);
             kids.add(c);
         }
         sort(kids);
@@ -243,17 +243,17 @@ public class NodeStoreTree extends JPane
         NodeState state = model.getState();
         String tarFile = "";
 
-        if (store.isPersisted(state)) {
-            String recordId = store.getRecordId(state);
+        if (backend.isPersisted(state)) {
+            String recordId = backend.getRecordId(state);
             sb.append("Record ").append(recordId);
-            tarFile = store.getFile(state);
+            tarFile = backend.getFile(state);
             if (tarFile != null) {
                 sb.append(" in ").append(tarFile);
             }
             sb.append(newline);
 
-            String templateId = store.getTemplateRecordId(state);
-            String f = store.getTemplateFile(state);
+            String templateId = backend.getTemplateRecordId(state);
+            String f = backend.getTemplateFile(state);
             sb.append("TemplateId ");
             sb.append(templateId);
             if (f != null && !f.equals(tarFile)) {
@@ -303,7 +303,7 @@ public class NodeStoreTree extends JPane
             } else {
                 l.append(toString(ps, 0, tarFile));
             }
-            printPropertyState(store, ps, tarFile, l);
+            printPropertyState(backend, ps, tarFile, l);
             propLines.put(ps.getName(), l.toString());
         }
 
@@ -319,7 +319,7 @@ public class NodeStoreTree extends JPane
             StringBuilder l = new StringBuilder();
             l.append("  + ").append(ce.getName());
             NodeState c = ce.getNodeState();
-            printNodeState(store, c, tarFile, l);
+            printNodeState(backend, c, tarFile, l);
             childLines.put(ce.getName(), l.toString());
         }
         for (String l : childLines.values()) {
@@ -331,7 +331,7 @@ public class NodeStoreTree extends JPane
             sb.append("File Reader Index");
             sb.append(newline);
 
-            for (String path : store.getTarFiles()) {
+            for (String path : backend.getTarFiles()) {
                 sb.append(path);
                 sb.append(newline);
             }
@@ -350,7 +350,7 @@ public class NodeStoreTree extends JPane
             info += "id:" + b.getContentIdentity() + ";";
             info += safeGetLength(b) + ">";
 
-            for (Entry<UUID, String> e : store.getBulkSegmentIds(b).entrySet()) {
+            for (Entry<UUID, String> e : backend.getBulkSegmentIds(b).entrySet()) {
                 info += newline + "        Bulk Segment Id " + e.getKey();
                 if (e.getValue() != null && !e.getValue().equals(tarFile)) {
                     info += " in " + e.getValue();
@@ -410,7 +410,7 @@ public class NodeStoreTree extends JPane
             }
         }
 
-        Set<UUID> inMem = intersection(store.getReferencedSegmentIds(), uuids);
+        Set<UUID> inMem = intersection(backend.getReferencedSegmentIds(), uuids);
         if (!inMem.isEmpty()) {
             sb.append("In Memory segment references: ");
             sb.append(newline);
@@ -419,12 +419,12 @@ public class NodeStoreTree extends JPane
         }
 
         List<String> paths = newArrayList();
-        filterNodeStates(uuids, paths, store.getHead(), "/", store);
+        filterNodeStates(uuids, paths, backend.getHead(), "/", backend);
         printPaths(paths, sb);
 
         sb.append(newline);
         try {
-            Map<UUID, List<UUID>> graph = store.getTarGraph(file);
+            Map<UUID, List<UUID>> graph = backend.getTarGraph(file);
             sb.append("Tar graph:").append(newline);
             for (Entry<UUID, List<UUID>> entry : graph.entrySet()) {
                 sb.append(entry.getKey()).append('=').append(entry.getValue())
@@ -461,12 +461,12 @@ public class NodeStoreTree extends JPane
         }
 
         List<String> paths = newArrayList();
-        filterNodeStates(newHashSet(id), paths, store.getHead(), "/", store);
+        filterNodeStates(newHashSet(id), paths, backend.getHead(), "/", backend);
         printPaths(paths, sb);
 
         Map<UUID, Set<Entry<UUID, String>>> links = newHashMap();
         try {
-            store.getGcRoots(id, links);
+            backend.getGcRoots(id, links);
         } catch (IOException e) {
             sb.append(newline);
             sb.append(e.getMessage());
@@ -480,7 +480,7 @@ public class NodeStoreTree extends JPane
         setText(sb.toString());
     }
 
-    private static void filterNodeStates(Set<UUID> uuids, List<String> paths, NodeState state, String path, FileStoreWrapper store) {
+    private static void filterNodeStates(Set<UUID> uuids, List<String> paths, NodeState state, String path, ExplorerBackend store) {
         Set<String> localPaths = newTreeSet();
         for (PropertyState ps : state.getProperties()) {
             if (store.isPersisted(ps)) {
@@ -548,8 +548,8 @@ public class NodeStoreTree extends JPane
         NodeState node1;
         NodeState node2;
         try {
-            node1 = store.readNodeState(tokens[0]);
-            node2 = store.readNodeState(tokens[1]);
+            node1 = backend.readNodeState(tokens[0]);
+            node2 = backend.readNodeState(tokens[1]);
         } catch (IllegalArgumentException ex) {
             sb.append("Unknown argument: ");
             sb.append(input);
@@ -588,8 +588,8 @@ public class NodeStoreTree extends JPane
     }
 
     private boolean safeRevert(String revision, boolean rollback) {
-        String head = store.getRecordId(store.getHead());
-        store.setRevision(revision);
+        String head = backend.getRecordId(backend.getHead());
+        backend.setRevision(revision);
         try {
             refreshModel();
             if (!rollback) {
@@ -612,12 +612,12 @@ public class NodeStoreTree extends JPane
     }
 
     void printPCMInfo() {
-        setText(store.getPersistedCompactionMapStats());
+        setText(backend.getPersistedCompactionMapStats());
     }
 
     private static class NamePathModel implements Comparable<NamePathModel> {
 
-        private final FileStoreWrapper store;
+        private final ExplorerBackend backend;
         private final String name;
         private final String path;
         private final boolean skipSizeCheck;
@@ -626,13 +626,13 @@ public class NodeStoreTree extends JPane
 
         private Long[] size = {-1L, -1L};
 
-        NamePathModel(String name, String path, NodeState state, Map<String, Long[]> sizeCache, boolean skipSizeCheck, FileStoreWrapper store) {
-            this.store = store;
+        NamePathModel(String name, String path, NodeState state, Map<String, Long[]> sizeCache, boolean skipSizeCheck, ExplorerBackend backend) {
+            this.backend = backend;
             this.name = name;
             this.path = path;
             this.skipSizeCheck = skipSizeCheck;
-            if (!skipSizeCheck && store.isPersisted(state)) {
-                this.size = exploreSize(state, sizeCache, store);
+            if (!skipSizeCheck && backend.isPersisted(state)) {
+                this.size = exploreSize(state, sizeCache, backend);
             }
         }
 
@@ -668,7 +668,7 @@ public class NodeStoreTree extends JPane
         }
 
         private NodeState loadState() {
-            NodeState n = store.getHead();
+            NodeState n = backend.getHead();
             for (String p : elements(path)) {
                 n = n.getChildNode(p);
             }
@@ -698,7 +698,7 @@ public class NodeStoreTree extends JPane
         }
     }
 
-    private static Long[] exploreSize(NodeState ns, Map<String, Long[]> sizeCache, FileStoreWrapper store) {
+    private static Long[] exploreSize(NodeState ns, Map<String, Long[]> sizeCache, ExplorerBackend store) {
         String key = store.getRecordId(ns);
         if (sizeCache.containsKey(key)) {
             return sizeCache.get(key);
@@ -754,7 +754,7 @@ public class NodeStoreTree extends JPane
 
     @Override
     public void close() throws IOException {
-        store.close();
+        backend.close();
     }
 
 }

Copied: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/SegmentExplorerBackend.java (from r1745315, jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/FileStoreWrapper.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/SegmentExplorerBackend.java?p2=jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/SegmentExplorerBackend.java&p1=jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/FileStoreWrapper.java&r1=1745315&r2=1745330&rev=1745330&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/FileStoreWrapper.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/SegmentExplorerBackend.java Tue May 24 08:45:07 2016
@@ -41,7 +41,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.segment.file.FileStore;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
-class FileStoreWrapper {
+class SegmentExplorerBackend implements ExplorerBackend {
 
     private final File path;
 
@@ -49,42 +49,50 @@ class FileStoreWrapper {
 
     private Map<String, Set<UUID>> index;
 
-    FileStoreWrapper(File path) throws IOException {
+    SegmentExplorerBackend(File path) throws IOException {
         this.path = path;
     }
 
-    void open() throws IOException {
+    @Override
+    public void open() throws IOException {
         store = FileStore.builder(path).buildReadOnly();
         index = store.getTarReaderIndex();
     }
 
-    void close() {
+    @Override
+    public void close() {
         store.close();
         store = null;
         index = null;
     }
 
-    List<String> readRevisions() {
+    @Override
+    public List<String> readRevisions() {
         return FileStoreHelper.readRevisions(path);
     }
 
-    Map<String, Set<UUID>> getTarReaderIndex() {
+    @Override
+    public Map<String, Set<UUID>> getTarReaderIndex() {
         return store.getTarReaderIndex();
     }
 
-    Map<UUID, List<UUID>> getTarGraph(String file) throws IOException {
+    @Override
+    public Map<UUID, List<UUID>> getTarGraph(String file) throws IOException {
         return store.getTarGraph(file);
     }
 
-    List<String> getTarFiles() {
+    @Override
+    public List<String> getTarFiles() {
         return FileStoreHelper.getTarFiles(store);
     }
 
-    void getGcRoots(UUID uuidIn, Map<UUID, Set<Entry<UUID, String>>> links) throws IOException {
+    @Override
+    public void getGcRoots(UUID uuidIn, Map<UUID, Set<Entry<UUID, String>>> links) throws IOException {
         FileStoreHelper.getGcRoots(store, uuidIn, links);
     }
 
-    Set<UUID> getReferencedSegmentIds() {
+    @Override
+    public Set<UUID> getReferencedSegmentIds() {
         Set<UUID> ids = newHashSet();
 
         for (SegmentId id : store.getTracker().getReferencedSegmentIds()) {
@@ -94,27 +102,33 @@ class FileStoreWrapper {
         return ids;
     }
 
-    NodeState getHead() {
+    @Override
+    public NodeState getHead() {
         return store.getHead();
     }
 
-    NodeState readNodeState(String recordId) {
+    @Override
+    public NodeState readNodeState(String recordId) {
         return new SegmentNodeState(RecordId.fromString(store.getTracker(), recordId));
     }
 
-    void setRevision(String revision) {
+    @Override
+    public void setRevision(String revision) {
         store.setRevision(revision);
     }
 
-    boolean isPersisted(NodeState state) {
+    @Override
+    public boolean isPersisted(NodeState state) {
         return state instanceof SegmentNodeState;
     }
 
-    boolean isPersisted(PropertyState state) {
+    @Override
+    public boolean isPersisted(PropertyState state) {
         return state instanceof SegmentPropertyState;
     }
 
-    String getRecordId(NodeState state) {
+    @Override
+    public String getRecordId(NodeState state) {
         if (state instanceof SegmentNodeState) {
             return getRecordId((SegmentNodeState) state);
         }
@@ -122,7 +136,8 @@ class FileStoreWrapper {
         return null;
     }
 
-    UUID getSegmentId(NodeState state) {
+    @Override
+    public UUID getSegmentId(NodeState state) {
         if (state instanceof SegmentNodeState) {
             return getSegmentId((SegmentNodeState) state);
         }
@@ -130,7 +145,8 @@ class FileStoreWrapper {
         return null;
     }
 
-    String getRecordId(PropertyState state) {
+    @Override
+    public String getRecordId(PropertyState state) {
         if (state instanceof SegmentPropertyState) {
             return getRecordId((SegmentPropertyState) state);
         }
@@ -138,7 +154,8 @@ class FileStoreWrapper {
         return null;
     }
 
-    UUID getSegmentId(PropertyState state) {
+    @Override
+    public UUID getSegmentId(PropertyState state) {
         if (state instanceof SegmentPropertyState) {
             return getSegmentId((SegmentPropertyState) state);
         }
@@ -146,7 +163,8 @@ class FileStoreWrapper {
         return null;
     }
 
-    String getTemplateRecordId(NodeState state) {
+    @Override
+    public String getTemplateRecordId(NodeState state) {
         if (state instanceof SegmentNodeState) {
             return getTemplateRecordId((SegmentNodeState) state);
         }
@@ -154,7 +172,8 @@ class FileStoreWrapper {
         return null;
     }
 
-    UUID getTemplateSegmentId(NodeState state) {
+    @Override
+    public UUID getTemplateSegmentId(NodeState state) {
         if (state instanceof SegmentNodeState) {
             return getTemplateSegmentId((SegmentNodeState) state);
         }
@@ -162,7 +181,8 @@ class FileStoreWrapper {
         return null;
     }
 
-    String getFile(NodeState state) {
+    @Override
+    public String getFile(NodeState state) {
         if (state instanceof SegmentNodeState) {
             return getFile((SegmentNodeState) state);
         }
@@ -170,7 +190,8 @@ class FileStoreWrapper {
         return null;
     }
 
-    String getFile(PropertyState state) {
+    @Override
+    public String getFile(PropertyState state) {
         if (state instanceof SegmentPropertyState) {
             return getFile((SegmentPropertyState) state);
         }
@@ -178,7 +199,8 @@ class FileStoreWrapper {
         return null;
     }
 
-    String getTemplateFile(NodeState state) {
+    @Override
+    public String getTemplateFile(NodeState state) {
         if (state instanceof SegmentNodeState) {
             return getTemplateFile((SegmentNodeState) state);
         }
@@ -186,7 +208,8 @@ class FileStoreWrapper {
         return null;
     }
 
-    Map<UUID, String> getBulkSegmentIds(Blob blob) {
+    @Override
+    public Map<UUID, String> getBulkSegmentIds(Blob blob) {
         Map<UUID, String> result = Maps.newHashMap();
 
         for (SegmentId segmentId : SegmentBlob.getBulkSegmentIds(blob)) {
@@ -196,11 +219,13 @@ class FileStoreWrapper {
         return result;
     }
 
-    String getPersistedCompactionMapStats() {
+    @Override
+    public String getPersistedCompactionMapStats() {
         return new PCMAnalyser(store).toString();
     }
 
-    boolean isExternal(Blob blob) {
+    @Override
+    public boolean isExternal(Blob blob) {
         if (blob instanceof SegmentBlob) {
             return isExternal((SegmentBlob) blob);
         }

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/SegmentTarExplorerBackend.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/SegmentTarExplorerBackend.java?rev=1745330&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/SegmentTarExplorerBackend.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/SegmentTarExplorerBackend.java Tue May 24 08:45:07 2016
@@ -0,0 +1,370 @@
+/*
+ * 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.explorer;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Sets.newHashSet;
+import static java.util.Collections.reverseOrder;
+import static java.util.Collections.sort;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.AbstractMap.SimpleImmutableEntry;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.UUID;
+
+import com.google.common.collect.Maps;
+import org.apache.jackrabbit.oak.api.Blob;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.segment.RecordId;
+import org.apache.jackrabbit.oak.segment.SegmentBlob;
+import org.apache.jackrabbit.oak.segment.SegmentId;
+import org.apache.jackrabbit.oak.segment.SegmentNodeState;
+import org.apache.jackrabbit.oak.segment.SegmentNodeStateHelper;
+import org.apache.jackrabbit.oak.segment.SegmentPropertyState;
+import org.apache.jackrabbit.oak.segment.file.FileStore;
+import org.apache.jackrabbit.oak.segment.file.JournalReader;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+class SegmentTarExplorerBackend implements ExplorerBackend {
+
+    private final File path;
+
+    private FileStore.ReadOnlyStore store;
+
+    private Map<String, Set<UUID>> index;
+
+    SegmentTarExplorerBackend(File path) throws IOException {
+        this.path = path;
+    }
+
+    @Override
+    public void open() throws IOException {
+        store = FileStore.builder(path).buildReadOnly();
+        index = store.getTarReaderIndex();
+    }
+
+    @Override
+    public void close() {
+        store.close();
+        store = null;
+        index = null;
+    }
+
+    @Override
+    public List<String> readRevisions() {
+        File journal = new File(path, "journal.log");
+
+        if (!journal.exists()) {
+            return newArrayList();
+        }
+
+        List<String> revs = newArrayList();
+        JournalReader journalReader = null;
+
+        try {
+            journalReader = new JournalReader(journal);
+
+            try {
+                revs = newArrayList(journalReader.iterator());
+            } finally {
+                journalReader.close();
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                if (journalReader != null) {
+                    journalReader.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        return revs;
+    }
+
+    @Override
+    public Map<String, Set<UUID>> getTarReaderIndex() {
+        return store.getTarReaderIndex();
+    }
+
+    @Override
+    public Map<UUID, List<UUID>> getTarGraph(String file) throws IOException {
+        return store.getTarGraph(file);
+    }
+
+    @Override
+    public List<String> getTarFiles() {
+        List<String> files = newArrayList();
+        for (String p : store.getTarReaderIndex().keySet()) {
+            files.add(new File(p).getName());
+        }
+        sort(files, reverseOrder());
+        return files;
+    }
+
+    @Override
+    public void getGcRoots(UUID uuidIn, Map<UUID, Set<Entry<UUID, String>>> links) throws IOException {
+        Deque<UUID> todos = new ArrayDeque<UUID>();
+        todos.add(uuidIn);
+        Set<UUID> visited = newHashSet();
+        while (!todos.isEmpty()) {
+            UUID uuid = todos.remove();
+            if (!visited.add(uuid)) {
+                continue;
+            }
+            for (String f : getTarFiles()) {
+                Map<UUID, List<UUID>> graph = store.getTarGraph(f);
+                for (Entry<UUID, List<UUID>> g : graph.entrySet()) {
+                    if (g.getValue() != null && g.getValue().contains(uuid)) {
+                        UUID uuidP = g.getKey();
+                        if (!todos.contains(uuidP)) {
+                            todos.add(uuidP);
+                            Set<Entry<UUID, String>> deps = links.get(uuid);
+                            if (deps == null) {
+                                deps = newHashSet();
+                                links.put(uuid, deps);
+                            }
+                            deps.add(new SimpleImmutableEntry<UUID, String>(
+                                    uuidP, f));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public Set<UUID> getReferencedSegmentIds() {
+        Set<UUID> ids = newHashSet();
+
+        for (SegmentId id : store.getTracker().getReferencedSegmentIds()) {
+            ids.add(id.asUUID());
+        }
+
+        return ids;
+    }
+
+    @Override
+    public NodeState getHead() {
+        return store.getHead();
+    }
+
+    @Override
+    public NodeState readNodeState(String recordId) {
+        return new SegmentNodeState(store, RecordId.fromString(store.getTracker(), recordId));
+    }
+
+    @Override
+    public void setRevision(String revision) {
+        store.setRevision(revision);
+    }
+
+    @Override
+    public boolean isPersisted(NodeState state) {
+        return state instanceof SegmentNodeState;
+    }
+
+    @Override
+    public boolean isPersisted(PropertyState state) {
+        return state instanceof SegmentPropertyState;
+    }
+
+    @Override
+    public String getRecordId(NodeState state) {
+        if (state instanceof SegmentNodeState) {
+            return getRecordId((SegmentNodeState) state);
+        }
+
+        return null;
+    }
+
+    @Override
+    public UUID getSegmentId(NodeState state) {
+        if (state instanceof SegmentNodeState) {
+            return getSegmentId((SegmentNodeState) state);
+        }
+
+        return null;
+    }
+
+    @Override
+    public String getRecordId(PropertyState state) {
+        if (state instanceof SegmentPropertyState) {
+            return getRecordId((SegmentPropertyState) state);
+        }
+
+        return null;
+    }
+
+    @Override
+    public UUID getSegmentId(PropertyState state) {
+        if (state instanceof SegmentPropertyState) {
+            return getSegmentId((SegmentPropertyState) state);
+        }
+
+        return null;
+    }
+
+    @Override
+    public String getTemplateRecordId(NodeState state) {
+        if (state instanceof SegmentNodeState) {
+            return getTemplateRecordId((SegmentNodeState) state);
+        }
+
+        return null;
+    }
+
+    @Override
+    public UUID getTemplateSegmentId(NodeState state) {
+        if (state instanceof SegmentNodeState) {
+            return getTemplateSegmentId((SegmentNodeState) state);
+        }
+
+        return null;
+    }
+
+    @Override
+    public String getFile(NodeState state) {
+        if (state instanceof SegmentNodeState) {
+            return getFile((SegmentNodeState) state);
+        }
+
+        return null;
+    }
+
+    @Override
+    public String getFile(PropertyState state) {
+        if (state instanceof SegmentPropertyState) {
+            return getFile((SegmentPropertyState) state);
+        }
+
+        return null;
+    }
+
+    @Override
+    public String getTemplateFile(NodeState state) {
+        if (state instanceof SegmentNodeState) {
+            return getTemplateFile((SegmentNodeState) state);
+        }
+
+        return null;
+    }
+
+    @Override
+    public Map<UUID, String> getBulkSegmentIds(Blob blob) {
+        Map<UUID, String> result = Maps.newHashMap();
+
+        for (SegmentId segmentId : SegmentBlob.getBulkSegmentIds(blob)) {
+            result.put(segmentId.asUUID(), getFile(segmentId));
+        }
+
+        return result;
+    }
+
+    @Override
+    public String getPersistedCompactionMapStats() {
+        return "";
+    }
+
+    @Override
+    public boolean isExternal(Blob blob) {
+        if (blob instanceof SegmentBlob) {
+            return isExternal((SegmentBlob) blob);
+        }
+
+        return false;
+    }
+
+    private boolean isExternal(SegmentBlob blob) {
+        return blob.isExternal();
+    }
+
+    private String getRecordId(SegmentNodeState state) {
+        return state.getRecordId().toString();
+    }
+
+    private UUID getSegmentId(SegmentNodeState state) {
+        return state.getRecordId().getSegmentId().asUUID();
+    }
+
+    private String getRecordId(SegmentPropertyState state) {
+        return state.getRecordId().toString();
+    }
+
+    private UUID getSegmentId(SegmentPropertyState state) {
+        return state.getRecordId().getSegmentId().asUUID();
+    }
+
+    private String getTemplateRecordId(SegmentNodeState state) {
+        RecordId recordId = SegmentNodeStateHelper.getTemplateId(state);
+
+        if (recordId == null) {
+            return null;
+        }
+
+        return recordId.toString();
+    }
+
+    private UUID getTemplateSegmentId(SegmentNodeState state) {
+        RecordId recordId = SegmentNodeStateHelper.getTemplateId(state);
+
+        if (recordId == null) {
+            return null;
+        }
+
+        return recordId.getSegmentId().asUUID();
+    }
+
+    private String getFile(SegmentNodeState state) {
+        return getFile(state.getRecordId().getSegmentId());
+    }
+
+    private String getFile(SegmentPropertyState state) {
+        return getFile(state.getRecordId().getSegmentId());
+    }
+
+    private String getTemplateFile(SegmentNodeState state) {
+        RecordId recordId = SegmentNodeStateHelper.getTemplateId(state);
+
+        if (recordId == null) {
+            return null;
+        }
+
+        return getFile(recordId.getSegmentId());
+    }
+
+    private String getFile(SegmentId segmentId) {
+        for (Entry<String, Set<UUID>> path2Uuid : index.entrySet()) {
+            for (UUID uuid : path2Uuid.getValue()) {
+                if (uuid.equals(segmentId.asUUID())) {
+                    return new File(path2Uuid.getKey()).getName();
+                }
+            }
+        }
+        return null;
+    }
+
+}

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

Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/SegmentUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/SegmentUtils.java?rev=1745330&r1=1745329&r2=1745330&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/SegmentUtils.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/SegmentUtils.java Tue May 24 08:45:07 2016
@@ -64,7 +64,6 @@ import org.apache.jackrabbit.oak.api.Typ
 import org.apache.jackrabbit.oak.commons.IOUtils;
 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.backup.FileStoreBackup;
 import org.apache.jackrabbit.oak.plugins.backup.FileStoreRestore;