Author: alexparvulescu Date: Mon Nov 16 15:52:27 2015 New Revision: 1714610
URL: http://svn.apache.org/viewvc?rev=1714610&view=rev Log: OAK-3568 Oak Explorer: add persisted compaction map size Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/plugins/segment/PCMAnalyser.java (with props) 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/Main.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=1714610&r1=1714609&r2=1714610&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 Nov 16 15:52:27 2015 @@ -239,6 +239,15 @@ public class Explorer { } }); + JMenuItem menuPCM = new JMenuItem("Persisted Compaction Maps"); + menuPCM.setMnemonic(KeyEvent.VK_P); + menuPCM.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ev) { + treePanel.printPCMInfo(); + } + }); + menuBar.add(menuReopen); menuBar.add(new JSeparator(JSeparator.VERTICAL)); menuBar.add(menuCompaction); @@ -249,6 +258,8 @@ public class Explorer { menuBar.add(new JSeparator(JSeparator.VERTICAL)); menuBar.add(menuDiff); menuBar.add(new JSeparator(JSeparator.VERTICAL)); + menuBar.add(menuPCM); + menuBar.add(new JSeparator(JSeparator.VERTICAL)); frame.setJMenuBar(menuBar); frame.pack(); 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=1714610&r1=1714609&r2=1714610&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 Nov 16 15:52:27 2015 @@ -63,6 +63,7 @@ import javax.swing.tree.DefaultTreeModel import org.apache.jackrabbit.oak.api.Blob; import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.api.Type; +import org.apache.jackrabbit.oak.plugins.segment.PCMAnalyser; import org.apache.jackrabbit.oak.plugins.segment.RecordId; import org.apache.jackrabbit.oak.plugins.segment.SegmentBlob; import org.apache.jackrabbit.oak.plugins.segment.SegmentId; @@ -647,6 +648,10 @@ public class NodeStoreTree extends JPane return true; } + public void printPCMInfo() { + setText(new PCMAnalyser(store).toString()); + } + private static class NamePathModel implements Comparable<NamePathModel> { private final FileStore store; Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/plugins/segment/PCMAnalyser.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/plugins/segment/PCMAnalyser.java?rev=1714610&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/plugins/segment/PCMAnalyser.java (added) +++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/plugins/segment/PCMAnalyser.java Mon Nov 16 15:52:27 2015 @@ -0,0 +1,206 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.jackrabbit.oak.plugins.segment; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Lists.newArrayList; +import static com.google.common.collect.Queues.newArrayDeque; +import static com.google.common.collect.Sets.newHashSet; +import static org.apache.jackrabbit.oak.plugins.segment.PersistedCompactionMap.PERSISTED_COMPACTION_MAP; +import static org.apache.jackrabbit.oak.plugins.segment.SegmentId.isDataSegmentId; + +import java.io.File; +import java.util.Deque; +import java.util.Formatter; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.jackrabbit.oak.plugins.segment.file.FileStore; + +/** + * RecordUsageAnalyser tailored to extract PersistedCompactionMap history and + * size + */ +public class PCMAnalyser extends RecordUsageAnalyser { + + /** + * Extracts persisted compaction map information. Returns a list of + * compaction map chains + */ + private static List<Deque<PCMInfo>> readPCMHistory(FileStore store) { + List<Deque<PCMInfo>> pcms = newArrayList(); + Deque<PCMInfo> chain = newArrayDeque(); + + Map<String, Set<UUID>> index = store.getTarReaderIndex(); + for (String path : index.keySet()) { + Set<UUID> segments = index.get(path); + String name = new File(path).getName(); + + for (UUID id : segments) { + if (!isDataSegmentId(id.getLeastSignificantBits())) { + continue; + } + Segment s = readSegment(store, id); + for (int r = 0; r < s.getRootCount(); r++) { + if (s.getRootType(r) == RecordType.VALUE) { + RecordId nodeId = new RecordId(s.getSegmentId(), + s.getRootOffset(r)); + String v = Segment.readString(nodeId); + PCMInfo pcm = parsePCMInfo(v, store, name); + if (pcm != null) { + if (!pcm.sameMap(chain.peekLast())) { + pcms.add(chain); + chain = newArrayDeque(); + } + chain.addLast(pcm); + } + } + } + } + } + if (!chain.isEmpty()) { + pcms.add(chain); + } + return pcms; + } + + /** + * Extracts persisted compaction map information, if available, otherwise + * returs null + */ + private static PCMInfo parsePCMInfo(String mapInfo, FileStore store, + String file) { + if (mapInfo == null || !mapInfo.startsWith(PERSISTED_COMPACTION_MAP)) { + return null; + } + SegmentTracker tracker = store.getTracker(); + int idStartIndex = mapInfo.indexOf("id=") + 3; + int idEndIndex = mapInfo.indexOf(",", idStartIndex); + String id = mapInfo.substring(idStartIndex, idEndIndex); + RecordId rid = null; + try { + rid = RecordId.fromString(tracker, id); + } catch (IllegalArgumentException iae) { + // log a warn? + return null; + } + + int baseStartIndex = mapInfo.indexOf("baseId=") + 7; + String base = mapInfo.substring(baseStartIndex, mapInfo.length() - 1); + RecordId bid = null; + if (!"null".equals(base)) { + try { + bid = RecordId.fromString(tracker, base); + } catch (IllegalArgumentException iae) { + // log a warn? + } + } + return new PCMInfo(rid, bid, file); + } + + private static Segment readSegment(FileStore store, UUID id) { + return store.readSegment(new SegmentId(store.getTracker(), id + .getMostSignificantBits(), id.getLeastSignificantBits())); + } + + private final List<Deque<PCMInfo>> pcms; + private final Set<String> errors = newHashSet(); + + public PCMAnalyser(FileStore store) { + pcms = readPCMHistory(store); + for (Deque<PCMInfo> pcm : pcms) { + try { + onPCM(pcm.getFirst().getId()); + } catch (IllegalStateException ex) { + ex.printStackTrace(); + errors.add(ex.getMessage()); + } + } + } + + private void onPCM(RecordId recordId) { + Segment s = recordId.getSegment(); + MapRecord map = s.readMap(recordId); + parseMap(null, recordId, map); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + @SuppressWarnings("resource") + Formatter formatter = new Formatter(sb); + if (pcms.isEmpty()) { + formatter.format("No persisted compaction map found.%n"); + } else { + formatter.format("Persisted compaction map info:%n"); + for (Deque<PCMInfo> pcm : pcms) { + formatter.format("%s%n", pcm); + } + formatter.format("Persisted compaction map size:%n"); + sb.append(super.toString()); + + formatter.format("%n"); + for (String e : errors) { + formatter.format("%s%n", e); + } + } + return sb.toString(); + } + + private static class PCMInfo { + + private final RecordId id; + private final RecordId baseId; + private final String file; + + public PCMInfo(RecordId id, RecordId baseId, String file) { + this.id = checkNotNull(id); + this.baseId = baseId; + this.file = file; + } + + @Override + public String toString() { + return id + "[" + file + "]"; + } + + public RecordId getId() { + return id; + } + + public RecordId getBaseId() { + return baseId; + } + + /** + * Determines if the current PCM can be considered as the next link in + * the current compaction map. If provided 'o' is null, then the current + * PCM is the head + */ + public boolean sameMap(PCMInfo o) { + if (o == null) { + return true; + } + return id.equals(o.getBaseId()); + } + } + +} Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/plugins/segment/PCMAnalyser.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java?rev=1714610&r1=1714609&r2=1714610&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java (original) +++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java Mon Nov 16 15:52:27 2015 @@ -99,6 +99,7 @@ import org.apache.jackrabbit.oak.plugins import org.apache.jackrabbit.oak.plugins.document.util.MapFactory; import org.apache.jackrabbit.oak.plugins.document.util.MongoConnection; import org.apache.jackrabbit.oak.plugins.segment.FileStoreHelper; +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; @@ -1029,13 +1030,12 @@ public final class Main { bulkSize += id.getSegment().size(); } } - System.out.println("\nAvailable for garbage collection:"); - System.out.format( - "%s in %6d data segments%n", + 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", + 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) {
