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 al...@apache.org on 2014/06/09 16:57:42 UTC

svn commit: r1601403 - in /jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer: Explorer.java NodeStoreTree.java

Author: alexparvulescu
Date: Mon Jun  9 14:57:41 2014
New Revision: 1601403

URL: http://svn.apache.org/r1601403
Log:
OAK-1858 Segment Explorer
 - properly close the store on exit
 - added option to run compaction, run the diff between 2 node states, and to trace the node store references to a specific file (wip)

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

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=1601403&r1=1601402&r2=1601403&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 Mon Jun  9 14:57:41 2014
@@ -21,12 +21,21 @@ package org.apache.jackrabbit.oak.explor
 import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
 import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.swing.JFrame;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
+import javax.swing.JSeparator;
 import javax.swing.JSplitPane;
 import javax.swing.JTextArea;
 import javax.swing.UIManager;
@@ -77,9 +86,15 @@ public class Explorer {
         }
     }
 
-    private void createAndShowGUI(String path, FileStore store) {
-        JFrame frame = new JFrame("Explore " + path);
-        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+    private void createAndShowGUI(final String path, final FileStore store) {
+        final JFrame frame = new JFrame("Explore " + path);
+        frame.addWindowListener(new java.awt.event.WindowAdapter() {
+            @Override
+            public void windowClosing(java.awt.event.WindowEvent windowEvent) {
+                store.close();
+                System.exit(0);
+            }
+        });
 
         JPanel content = new JPanel(new GridBagLayout());
 
@@ -88,7 +103,7 @@ public class Explorer {
         log.setLineWrap(true);
         log.setEditable(false);
 
-        NodeStoreTree treePanel = new NodeStoreTree(store, log);
+        final NodeStoreTree treePanel = new NodeStoreTree(store, log);
 
         GridBagConstraints c = new GridBagConstraints();
         c.fill = GridBagConstraints.BOTH;
@@ -99,9 +114,71 @@ public class Explorer {
                 new JScrollPane(treePanel), new JScrollPane(log));
         splitPane.setDividerLocation(0.3);
         content.add(new JScrollPane(splitPane), c);
-
         frame.getContentPane().add(content);
 
+        JMenuBar menuBar = new JMenuBar();
+        menuBar.setMargin(new Insets(2, 2, 2, 2));
+
+        JMenuItem menuCompaction = new JMenuItem("Tar Compaction");
+        menuCompaction.setMnemonic(KeyEvent.VK_C);
+        menuCompaction.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent ev) {
+                int run = JOptionPane.showConfirmDialog(frame,
+                        "Run compaction on the tar files", "Tar Compaction",
+                        JOptionPane.WARNING_MESSAGE, JOptionPane.YES_NO_OPTION);
+                if (run == JOptionPane.YES_OPTION) {
+                    treePanel.compact();
+                }
+            }
+        });
+
+        JMenuItem menuRefs = new JMenuItem("Tar File Refs");
+        menuRefs.setMnemonic(KeyEvent.VK_R);
+        menuRefs.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent ev) {
+                List<String> tarFiles = new ArrayList<String>();
+                for (File f : new File(path).listFiles()) {
+                    if (f.getName().endsWith(".tar")) {
+                        tarFiles.add(f.getName());
+                    }
+                }
+
+                String s = (String) JOptionPane.showInputDialog(frame,
+                        "Choose a tar file", "Tar File References",
+                        JOptionPane.PLAIN_MESSAGE, null, tarFiles.toArray(),
+                        tarFiles.get(0));
+                if (s != null) {
+                    treePanel.printDependenciesToFile(s);
+                    return;
+                }
+            }
+        });
+
+        JMenuItem menuDiff = new JMenuItem("SegmentNodeState diff");
+        menuDiff.setMnemonic(KeyEvent.VK_D);
+        menuDiff.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent ev) {
+                String s = (String) JOptionPane.showInputDialog(frame,
+                        "SegmentNodeState diff\nUsage: <recordId> <recordId> [<path>]",
+                        "SegmentNodeState diff", JOptionPane.PLAIN_MESSAGE);
+                if (s != null) {
+                    treePanel.printDiff(s);
+                    return;
+                }
+            }
+        });
+
+        menuBar.add(menuCompaction);
+        menuBar.add(new JSeparator(JSeparator.VERTICAL));
+        menuBar.add(menuRefs);
+        menuBar.add(new JSeparator(JSeparator.VERTICAL));
+        menuBar.add(menuDiff);
+        menuBar.add(new JSeparator(JSeparator.VERTICAL));
+
+        frame.setJMenuBar(menuBar);
         frame.pack();
         frame.setSize(960, 720);
         frame.setLocationRelativeTo(null);

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=1601403&r1=1601402&r2=1601403&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 Mon Jun  9 14:57:41 2014
@@ -20,9 +20,11 @@ package org.apache.jackrabbit.oak.explor
 
 import java.awt.GridLayout;
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -45,6 +47,8 @@ import org.apache.commons.io.FileUtils;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.commons.json.JsopBuilder;
+import org.apache.jackrabbit.oak.kernel.JsopDiff;
 import org.apache.jackrabbit.oak.plugins.segment.RecordId;
 import org.apache.jackrabbit.oak.plugins.segment.SegmentId;
 import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState;
@@ -58,6 +62,8 @@ import com.google.common.escape.Escapers
 
 class NodeStoreTree extends JPanel implements TreeSelectionListener {
 
+    private final FileStore store;
+
     private final DefaultTreeModel treeModel;
     private final JTree tree;
     private final JTextArea log;
@@ -67,6 +73,7 @@ class NodeStoreTree extends JPanel imple
 
     public NodeStoreTree(FileStore store, JTextArea log) {
         super(new GridLayout(1, 0));
+        this.store = store;
         this.log = log;
 
         index = store.getTarReaderIndex();
@@ -209,11 +216,14 @@ class NodeStoreTree extends JPanel imple
         if ("/".equals(model.getPath())) {
             sb.append("File Index");
             sb.append(newline);
-            for (Entry<String, Set<UUID>> path2Uuid : index.entrySet()) {
-                sb.append(path2Uuid.getKey());
+
+            List<String> files = new ArrayList<String>(store
+                    .getTarReaderIndex().keySet());
+            Collections.sort(files);
+
+            for (String path : files) {
+                sb.append(path);
                 sb.append(newline);
-                // sb.append(path2Uuid.getValue());
-                // sb.append(newline);
             }
             sb.append("----------");
         }
@@ -256,6 +266,152 @@ class NodeStoreTree extends JPanel imple
         return "";
     }
 
+    public void printDependenciesToFile(String file) {
+        if (file == null || file.length() == 0) {
+            return;
+        }
+        StringBuilder sb = new StringBuilder();
+
+        Set<UUID> uuids = new HashSet<UUID>();
+        for (Entry<String, Set<UUID>> e : store.getTarReaderIndex().entrySet()) {
+            if (e.getKey().endsWith(file)) {
+                sb.append("SegmentNodeState references to " + e.getKey());
+                sb.append(newline);
+                uuids = e.getValue();
+            }
+        }
+        List<String> paths = new ArrayList<String>();
+        filterNodeStates(uuids, paths, store.getHead(), "/");
+        for (String p : paths) {
+            sb.append("    ");
+            sb.append(p);
+            sb.append(newline);
+        }
+
+        log.setText(sb.toString());
+    }
+
+    private static void filterNodeStates(Set<UUID> uuids, List<String> paths,
+            SegmentNodeState state, String path) {
+        for (PropertyState ps : state.getProperties()) {
+            if (ps instanceof SegmentPropertyState) {
+                SegmentPropertyState sps = (SegmentPropertyState) ps;
+                SegmentId id = sps.getRecordId().getSegmentId();
+                if (contains(id, uuids)) {
+                    paths.add(path + "@" + ps);
+                }
+            }
+        }
+        for (ChildNodeEntry ce : state.getChildNodeEntries()) {
+            NodeState c = ce.getNodeState();
+            if (c instanceof SegmentNodeState) {
+                filterNodeStates(uuids, paths, (SegmentNodeState) c,
+                        path + ce.getName() + "/");
+            }
+        }
+    }
+
+    private static boolean contains(SegmentId id, Set<UUID> uuids) {
+        for (UUID u : uuids) {
+            if (id.getMostSignificantBits() == u.getMostSignificantBits()
+                    && id.getLeastSignificantBits() == u
+                            .getLeastSignificantBits()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void printDiff(String input) {
+        StringBuilder sb = new StringBuilder();
+        if (input == null || input.trim().length() == 0) {
+            sb.append("Unknown argument: ");
+            sb.append(input);
+            sb.append(newline);
+            log.setText("Usage <recordId> <recordId> [<path>]");
+            return;
+        }
+
+        String[] tokens = input.trim().split(" ");
+        if (tokens.length != 2 && tokens.length != 3) {
+            sb.append("Unknown argument: ");
+            sb.append(input);
+            sb.append(newline);
+            log.setText("Usage <recordId> <recordId> [<path>]");
+            return;
+        }
+        RecordId id1 = null;
+        RecordId id2 = null;
+        try {
+            id1 = RecordId.fromString(store.getTracker(), tokens[0]);
+            id2 = RecordId.fromString(store.getTracker(), tokens[1]);
+        } catch (IllegalArgumentException ex) {
+            sb.append("Unknown argument: ");
+            sb.append(input);
+            sb.append(newline);
+            sb.append("Error: ");
+            sb.append(ex.getMessage());
+            sb.append(newline);
+            log.setText(sb.toString());
+            return;
+        }
+        String path = "/";
+        if (tokens.length == 3) {
+            path = tokens[2];
+        }
+
+        NodeState node1 = new SegmentNodeState(id1);
+        NodeState node2 = new SegmentNodeState(id2);
+        for (String name : PathUtils.elements(path)) {
+            node1 = node1.getChildNode(name);
+            node2 = node2.getChildNode(name);
+        }
+
+        sb.append("SegmentNodeState diff ");
+        sb.append(id1);
+        sb.append(" vs ");
+        sb.append(id2);
+        sb.append(" at ");
+        sb.append(path);
+        sb.append(newline);
+        sb.append("--------");
+        sb.append(newline);
+        sb.append(JsopBuilder.prettyPrint(JsopDiff.diffToJsop(node1, node2)));
+        log.setText(sb.toString());
+    }
+
+    public void compact() {
+        StringBuilder sb = new StringBuilder();
+
+        long s = System.currentTimeMillis();
+        store.gc();
+        store.compact();
+        try {
+            store.flush();
+        } catch (IOException e) {
+            sb.append("IOException " + e.getMessage());
+            e.printStackTrace();
+        }
+        s = System.currentTimeMillis() - s;
+
+        sb.append("Compacted tar segments in " + s + " ms.");
+        sb.append(newline);
+
+        sb.append("File Index");
+        sb.append(newline);
+
+        List<String> files = new ArrayList<String>(store.getTarReaderIndex()
+                .keySet());
+        Collections.sort(files);
+
+        for (String path : files) {
+            sb.append(path);
+            sb.append(newline);
+        }
+        sb.append("----------");
+        log.setText(sb.toString());
+    }
+
     private static class NamePathModel implements Comparable<NamePathModel> {
 
         private final String name;