Author: frm
Date: Tue Aug 23 14:33:49 2016
New Revision: 1757382
URL: http://svn.apache.org/viewvc?rev=1757382&view=rev
Log:
OAK-4690 - Create utility backends
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Backup.java
(with props)
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Check.java
(with props)
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Compact.java
(with props)
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugSegments.java
(with props)
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugStore.java
(with props)
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugTars.java
(with props)
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Diff.java
(with props)
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/GenerationGraph.java
(with props)
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/History.java
(with props)
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/PrintingDiff.java
- copied, changed from r1757147,
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/PrintingDiff.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Restore.java
(with props)
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Revisions.java
(with props)
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/SegmentGraph.java
(with props)
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Utils.java
(with props)
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Backup.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Backup.java?rev=1757382&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Backup.java
(added)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Backup.java
Tue Aug 23 14:33:49 2016
@@ -0,0 +1,140 @@
+/*
+ * 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.segment.tool;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static
org.apache.jackrabbit.oak.segment.tool.Utils.newBasicReadOnlyBlobStore;
+import static
org.apache.jackrabbit.oak.segment.tool.Utils.openReadOnlyFileStore;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.jackrabbit.oak.backup.FileStoreBackup;
+import org.apache.jackrabbit.oak.segment.file.FileStore;
+import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException;
+
+/**
+ * Perform a backup of a segment store into a specified folder.
+ */
+public class Backup implements Runnable {
+
+ /**
+ * Create a builder for the {@link Backup} command.
+ *
+ * @return an instance of {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Collect options for the {@link Backup} command.
+ */
+ public static class Builder {
+
+ private File source;
+
+ private File target;
+
+ private boolean fakeBlobStore = FileStoreBackup.USE_FAKE_BLOBSTORE;
+
+ private Builder() {
+ // Prevent external instantiation.
+ }
+
+ /**
+ * The source folder of the backup. This parameter is required. The
path
+ * should point to a valid segment store.
+ *
+ * @param source the path of the source folder of the backup.
+ * @return this builder.
+ */
+ public Builder withSource(File source) {
+ this.source = checkNotNull(source);
+ return this;
+ }
+
+ /**
+ * The target folder of the backup. This parameter is required. The
path
+ * should point to an existing segment store or to an empty folder. If
+ * the folder doesn't exist, it will be created.
+ *
+ * @param target the path of the target folder of the backup.
+ * @return this builder.
+ */
+ public Builder withTarget(File target) {
+ this.target = checkNotNull(target);
+ return this;
+ }
+
+ /**
+ * Simulate the existence of a file-based blob store. This parameter is
+ * not required and defaults to {@code false}.
+ *
+ * @param fakeBlobStore {@code true} if a file-based blob store should
+ * be simulated, {@code false} otherwise.
+ * @return this builder.
+ */
+ public Builder withFakeBlobStore(boolean fakeBlobStore) {
+ this.fakeBlobStore = fakeBlobStore;
+ return this;
+ }
+
+ /**
+ * Create an executable version of the {@link Backup} command.
+ *
+ * @return an instance of {@link Runnable}.
+ */
+ public Runnable build() {
+ checkNotNull(source);
+ checkNotNull(target);
+ return new Backup(this);
+ }
+
+ }
+
+ private final File source;
+
+ private final File target;
+
+ private final boolean fakeBlobStore;
+
+ private Backup(Builder builder) {
+ this.source = builder.source;
+ this.target = builder.target;
+ this.fakeBlobStore = builder.fakeBlobStore;
+ }
+
+ @Override
+ public void run() {
+ try (FileStore fs = newFileStore()) {
+ FileStoreBackup.backup(fs.getReader(), fs.getRevisions(), target);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private FileStore newFileStore() throws IOException,
InvalidFileStoreVersionException {
+ if (fakeBlobStore) {
+ return openReadOnlyFileStore(source, newBasicReadOnlyBlobStore());
+ }
+
+ return openReadOnlyFileStore(source);
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Backup.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Check.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Check.java?rev=1757382&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Check.java
(added)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Check.java
Tue Aug 23 14:33:49 2016
@@ -0,0 +1,165 @@
+/*
+ * 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.segment.tool;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.File;
+
+import org.apache.jackrabbit.oak.segment.file.tooling.ConsistencyChecker;
+
+/**
+ * Perform a consistency check on an existing segment store.
+ */
+public class Check implements Runnable {
+
+ /**
+ * Create a builder for the {@link Check} command.
+ *
+ * @return an instance of {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Collect options for the {@link Check} command.
+ */
+ public static class Builder {
+
+ private File path;
+
+ private String journal;
+
+ private boolean fullTraversal;
+
+ private long debugInterval = Long.MAX_VALUE;
+
+ private long minimumBinaryLength;
+
+ private Builder() {
+ // Prevent external instantiation.
+ }
+
+ /**
+ * The path to an existing segment store. This parameter is required.
+ *
+ * @param path the path to an existing segment store.
+ * @return this builder.
+ */
+ public Builder withPath(File path) {
+ this.path = checkNotNull(path);
+ return this;
+ }
+
+ /**
+ * The path to the journal of the segment store. This parameter is
+ * required.
+ *
+ * @param journal the path to the journal of the segment store.
+ * @return this builder.
+ */
+ public Builder withJournal(String journal) {
+ this.journal = checkNotNull(journal);
+ return this;
+ }
+
+ /**
+ * Should a full traversal of the segment store be performed? This
+ * parameter is not required and defaults to {@code false}.
+ *
+ * @param fullTraversal {@code true} if a full traversal should be
+ * performed, {@code false} otherwise.
+ * @return this builder.
+ */
+ public Builder withFullTraversal(boolean fullTraversal) {
+ this.fullTraversal = fullTraversal;
+ return this;
+ }
+
+ /**
+ * Number of seconds between successive debug print statements. This
+ * parameter is not required and defaults to an arbitrary large number.
+ *
+ * @param debugInterval number of seconds between successive debug
print
+ * statements. It must be strictly positive.
+ * @return this builder.
+ */
+ public Builder withDebugInterval(long debugInterval) {
+ checkArgument(debugInterval > 0);
+ this.debugInterval = debugInterval;
+ return this;
+ }
+
+ /**
+ * Minimum amount of bytes to read from binary properties. This
+ * parameter is not required and defaults to zero.
+ *
+ * @param minimumBinaryLength minimum amount of bytes to read from
+ * binary properties. If this parameter is
+ * set to {@code -1}, every binary property
+ * is read in its entirety.
+ * @return
+ */
+ public Builder withMinimumBinaryLength(long minimumBinaryLength) {
+ this.minimumBinaryLength = minimumBinaryLength;
+ return this;
+ }
+
+ /**
+ * Create an executable version of the {@link Check} command.
+ *
+ * @return an instance of {@link Runnable}.
+ */
+ public Runnable build() {
+ checkNotNull(path);
+ checkNotNull(journal);
+ return new Check(this);
+ }
+
+ }
+
+ private final File path;
+
+ private final String journal;
+
+ private final boolean fullTraversal;
+
+ private final long debugInterval;
+
+ private final long minimumBinaryLength;
+
+ private Check(Builder builder) {
+ this.path = builder.path;
+ this.journal = builder.journal;
+ this.fullTraversal = builder.fullTraversal;
+ this.debugInterval = builder.debugInterval;
+ this.minimumBinaryLength = builder.minimumBinaryLength;
+ }
+
+ @Override
+ public void run() {
+ try {
+ ConsistencyChecker.checkConsistency(path, journal, fullTraversal,
debugInterval, minimumBinaryLength);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Check.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Compact.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Compact.java?rev=1757382&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Compact.java
(added)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Compact.java
Tue Aug 23 14:33:49 2016
@@ -0,0 +1,156 @@
+/*
+ * 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.segment.tool;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static
org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.defaultGCOptions;
+import static
org.apache.jackrabbit.oak.segment.file.FileStoreBuilder.fileStoreBuilder;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions;
+import org.apache.jackrabbit.oak.segment.file.FileStore;
+import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException;
+import org.apache.jackrabbit.oak.segment.file.JournalReader;
+
+/**
+ * Perform an offline compaction of an existing segment store.
+ */
+public class Compact implements Runnable {
+
+ /**
+ * Create a builder for the {@link Compact} command.
+ *
+ * @return an instance of {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Collect options for the {@link Compact} command.
+ */
+ public static class Builder {
+
+ private File path;
+
+ private boolean force;
+
+ private Builder() {
+ // Prevent external instantiation.
+ }
+
+ /**
+ * The path to an existing segment store. This parameter is required.
+ *
+ * @param path the path to an existing segment store.
+ * @return this builder.
+ */
+ public Builder withPath(File path) {
+ this.path = checkNotNull(path);
+ return this;
+ }
+
+ /**
+ * Set whether or not to force compact concurrent commits on top of
+ * already compacted commits after the maximum number of retries has
+ * been reached. Force committing tries to exclusively write lock the
+ * node store.
+ *
+ * @param force {@code true} to force an exclusive commit of the
+ * compacted state, {@code false} otherwise.
+ * @return this builder.
+ */
+ public Builder withForce(boolean force) {
+ this.force = force;
+ return this;
+ }
+
+ /**
+ * Create an executable version of the {@link Compact} command.
+ *
+ * @return an instance of {@link Runnable}.
+ */
+ public Runnable build() {
+ checkNotNull(path);
+ return new Compact(this);
+ }
+
+ }
+
+ private final File path;
+
+ private final boolean force;
+
+ private Compact(Builder builder) {
+ this.path = builder.path;
+ this.force = builder.force;
+ }
+
+ @Override
+ public void run() {
+ try {
+ compact();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void compact() throws IOException,
InvalidFileStoreVersionException {
+ try (FileStore store = newFileStore()) {
+ store.compact();
+ }
+
+ System.out.println(" -> cleaning up");
+ try (FileStore store = newFileStore()) {
+ 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(path, "journal.log");
+
+ try (JournalReader journalReader = new JournalReader(journal)) {
+ head = journalReader.next() + " root " +
System.currentTimeMillis() + "\n";
+ }
+
+ try (RandomAccessFile journalFile = new RandomAccessFile(journal,
"rw")) {
+ System.out.println(" -> writing new " + journal.getName() +
": " + head);
+ journalFile.setLength(0);
+ journalFile.writeBytes(head);
+ journalFile.getChannel().force(false);
+ }
+ }
+ }
+
+ private FileStore newFileStore() throws IOException,
InvalidFileStoreVersionException {
+ return
fileStoreBuilder(path.getAbsoluteFile()).withGCOptions(newGCOptions()).build();
+ }
+
+ private SegmentGCOptions newGCOptions() {
+ return defaultGCOptions().setForceAfterFail(force).setOffline();
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Compact.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugSegments.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugSegments.java?rev=1757382&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugSegments.java
(added)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugSegments.java
Tue Aug 23 14:33:49 2016
@@ -0,0 +1,201 @@
+/*
+ * 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.segment.tool;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.apache.jackrabbit.oak.segment.RecordId.fromString;
+import static
org.apache.jackrabbit.oak.segment.tool.Utils.openReadOnlyFileStore;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.commons.json.JsopBuilder;
+import org.apache.jackrabbit.oak.json.JsopDiff;
+import org.apache.jackrabbit.oak.segment.RecordId;
+import org.apache.jackrabbit.oak.segment.SegmentId;
+import org.apache.jackrabbit.oak.segment.SegmentNodeState;
+import org.apache.jackrabbit.oak.segment.file.FileStore;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+/**
+ * Print debugging information about segments, node records and node record
+ * ranges.
+ */
+public class DebugSegments implements Runnable {
+
+ private static final Pattern SEGMENT_REGEX =
Pattern.compile("([0-9a-f-]+)|(([0-9a-f-]+:[0-9a-f]+)(-([0-9a-f-]+:[0-9a-f]+))?)?(/.*)?");
+
+ /**
+ * Create a builder for the {@link DebugSegments} command.
+ *
+ * @return an instance of {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Collect options for the {@link DebugSegments} command.
+ */
+ public static class Builder {
+
+ private File path;
+
+ private List<String> segments = new ArrayList<>();
+
+ private Builder() {
+ // Prevent external instantiation.
+ }
+
+ /**
+ * The path to an existing segment store. This parameter is required.
+ *
+ * @param path the path to an existing segment store.
+ * @return this builder.
+ */
+ public Builder withPath(File path) {
+ this.path = checkNotNull(path);
+ return this;
+ }
+
+ /**
+ * Add a segment, node record or node record range. It is mandatory to
+ * add at least one of a segment, node record or node record range.
+ * <p>
+ * A segment is specified by its ID, which is specified as a sequence
of
+ * hexadecimal digits and dashes. In example, {@code
+ * 333dc24d-438f-4cca-8b21-3ebf67c05856}.
+ * <p>
+ * A node record is specified by its identifier, with an optional path.
+ * In example, {@code
333dc24d-438f-4cca-8b21-3ebf67c05856:12345/path/to/child}.
+ * If a path is not specified, it is take to be {@code /}. The command
+ * will print information about the node provided by record ID and
about
+ * every child identified by the path.
+ * <p>
+ * A node range record is specified by two node identifiers separated
by
+ * a dash. In example, {@code
333dc24d-438f-4cca-8b21-3ebf67c05856:12345-46116fda-7a72-4dbc-af88-a09322a7753a:67890}.
+ * The command will perform a diff between the two records and print
the
+ * result in the JSOP format.
+ *
+ * @param segment The specification for a segment, a node record or a
+ * node record range.
+ * @return this builder.
+ */
+ public Builder withSegment(String segment) {
+ this.segments.add(checkNotNull(segment));
+ return this;
+ }
+
+ /**
+ * Create an executable version of the {@link DebugSegments} command.
+ *
+ * @return an instance of {@link Runnable}.
+ */
+ public Runnable build() {
+ checkNotNull(path);
+ checkArgument(segments.size() > 0);
+ return new DebugSegments(this);
+ }
+
+ }
+
+ private final File path;
+
+ private final List<String> segments;
+
+ private DebugSegments(Builder builder) {
+ this.path = builder.path;
+ this.segments = new ArrayList<>(builder.segments);
+ }
+
+ @Override
+ public void run() {
+ try (FileStore store = openReadOnlyFileStore(path)) {
+ debugSegments(store);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void debugSegments(FileStore store) {
+ for (String segment : segments) {
+ debugSegment(store, segment);
+ }
+ }
+
+ private void debugSegment(FileStore store, String segment) {
+ Matcher matcher = SEGMENT_REGEX.matcher(segment);
+
+ if (!matcher.matches()) {
+ System.err.println("Unknown argument: " + segment);
+ return;
+ }
+
+ if (matcher.group(1) != null) {
+ UUID uuid = UUID.fromString(matcher.group(1));
+ SegmentId id = store.newSegmentId(uuid.getMostSignificantBits(),
uuid.getLeastSignificantBits());
+ System.out.println(id.getSegment());
+ return;
+ }
+
+ RecordId id1 = store.getRevisions().getHead();
+ RecordId id2 = null;
+
+ if (matcher.group(2) != null) {
+ id1 = fromString(store, matcher.group(3));
+ if (matcher.group(4) != null) {
+ id2 = fromString(store, matcher.group(5));
+ }
+ }
+
+ String path = "/";
+
+ if (matcher.group(6) != null) {
+ path = matcher.group(6);
+ }
+
+ if (id2 == null) {
+ NodeState node = store.getReader().readNode(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);
+ }
+ return;
+ }
+
+ NodeState node1 = store.getReader().readNode(id1);
+ NodeState node2 = store.getReader().readNode(id2);
+ for (String name : PathUtils.elements(path)) {
+ node1 = node1.getChildNode(name);
+ node2 = node2.getChildNode(name);
+ }
+ System.out.println(JsopBuilder.prettyPrint(JsopDiff.diffToJsop(node1,
node2)));
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugSegments.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugStore.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugStore.java?rev=1757382&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugStore.java
(added)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugStore.java
Tue Aug 23 14:33:49 2016
@@ -0,0 +1,172 @@
+/*
+ * 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.segment.tool;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Sets.newHashSet;
+import static org.apache.commons.io.FileUtils.byteCountToDisplaySize;
+import static org.apache.jackrabbit.oak.segment.RecordType.NODE;
+import static
org.apache.jackrabbit.oak.segment.tool.Utils.openReadOnlyFileStore;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Queues;
+import org.apache.jackrabbit.oak.segment.RecordId;
+import org.apache.jackrabbit.oak.segment.RecordUsageAnalyser;
+import org.apache.jackrabbit.oak.segment.Segment;
+import org.apache.jackrabbit.oak.segment.SegmentId;
+import org.apache.jackrabbit.oak.segment.file.FileStore;
+
+/**
+ * Print debugging information about a segment store.
+ */
+public class DebugStore implements Runnable {
+
+ /**
+ * Create a builder for the {@link DebugStore} command.
+ *
+ * @return an instance of {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Collect options for the {@link DebugStore} command.
+ */
+ public static class Builder {
+
+ private File path;
+
+ private Builder() {
+ // Prevent external instantiation
+ }
+
+ /**
+ * The path to an existing segment store. This parameter is required.
+ *
+ * @param path the path to an existing segment store.
+ * @return this builder.
+ */
+ public Builder withPath(File path) {
+ this.path = checkNotNull(path);
+ return this;
+ }
+
+ /**
+ * Create an executable version of the {@link DebugStore} command.
+ *
+ * @return an instance of {@link Runnable}.
+ */
+ public Runnable build() {
+ checkNotNull(path);
+ return new DebugStore(this);
+ }
+
+ }
+
+ private final File path;
+
+ private DebugStore(Builder builder) {
+ this.path = builder.path;
+ }
+
+ @Override
+ public void run() {
+ try (FileStore store = openReadOnlyFileStore(path)) {
+ debugFileStore(store);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ 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;
+
+ RecordUsageAnalyser analyser = new
RecordUsageAnalyser(store.getReader());
+
+ 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.getRevisions().getHead().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);
+ }
+
+ 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();
+ }
+ }
+ }
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugStore.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugTars.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugTars.java?rev=1757382&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugTars.java
(added)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugTars.java
Tue Aug 23 14:33:49 2016
@@ -0,0 +1,264 @@
+/*
+ * 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.segment.tool;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Sets.newTreeSet;
+import static
org.apache.jackrabbit.oak.segment.SegmentNodeStateHelper.getTemplateId;
+import static
org.apache.jackrabbit.oak.segment.tool.Utils.openReadOnlyFileStore;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.jcr.PropertyType;
+
+import com.google.common.escape.Escapers;
+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.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.SegmentPropertyState;
+import org.apache.jackrabbit.oak.segment.file.FileStore;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+/**
+ * Print information about one or more TAR files from an existing segment
store.
+ */
+public class DebugTars implements Runnable {
+
+ /**
+ * Create a builder for the {@link DebugTars} command.
+ *
+ * @return an instance of {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Collect options for the {@link DebugTars} command.
+ */
+ public static class Builder {
+
+ private File path;
+
+ private List<String> tars = new ArrayList<>();
+
+ private int maxCharDisplay = Integer.getInteger("max.char.display",
60);
+
+ private Builder() {
+ // Prevent external instantiation.
+ }
+
+ /**
+ * The path to an existing segment store. This parameter is required.
+ *
+ * @param path the path to an existing segment store.
+ * @return this builder.
+ */
+ public Builder withPath(File path) {
+ this.path = checkNotNull(path);
+ return this;
+ }
+
+ /**
+ * Add a TAR file. The command will print information about every TAR
+ * file added via this method. It is mandatory to add at least one TAR
+ * file.
+ *
+ * @param tar the name of a TAR file.
+ * @return this builder.
+ */
+ public Builder withTar(String tar) {
+ checkArgument(tar.endsWith(".tar"));
+ this.tars.add(tar);
+ return this;
+ }
+
+ /**
+ * Create an executable version of the {@link DebugTars} command.
+ *
+ * @return an instance of {@link Runnable}.
+ */
+ public Runnable build() {
+ checkNotNull(path);
+ checkArgument(tars.size() > 0);
+ return new DebugTars(this);
+ }
+
+ }
+
+ private final File path;
+
+ private final List<String> tars;
+
+ private final int maxCharDisplay;
+
+ private DebugTars(Builder builder) {
+ this.path = builder.path;
+ this.tars = new ArrayList<>(builder.tars);
+ this.maxCharDisplay = builder.maxCharDisplay;
+ }
+
+ @Override
+ public void run() {
+ try (FileStore store = openReadOnlyFileStore(path)) {
+ debugTarFiles(store);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void debugTarFiles(FileStore store) {
+ for (String tar : tars) {
+ debugTarFile(store, tar);
+ }
+ }
+
+ private void debugTarFile(FileStore store, String t) {
+ File tar = new File(path, t);
+
+ if (!tar.exists()) {
+ System.out.println("file doesn't exist, skipping " + t);
+ return;
+ }
+
+ 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(t)) {
+ hasrefs = true;
+ uuids = e.getValue();
+ }
+ }
+
+ if (hasrefs) {
+ System.out.println("SegmentNodeState references to " + t);
+ List<String> paths = new ArrayList<String>();
+ filterNodeStates(uuids, paths, store.getHead(), "/");
+ for (String p : paths) {
+ System.out.println(" " + p);
+ }
+ } else {
+ System.out.println("No references to " + t);
+ }
+
+ try {
+ Map<UUID, List<UUID>> graph = store.getTarGraph(t);
+ 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:");
+ e.printStackTrace();
+ }
+ }
+
+ private void filterNodeStates(Set<UUID> uuids, List<String> paths,
SegmentNodeState state, String path) {
+ Set<String> localPaths = newTreeSet();
+ for (PropertyState ps : state.getProperties()) {
+ if (ps instanceof SegmentPropertyState) {
+ SegmentPropertyState sps = (SegmentPropertyState) ps;
+ RecordId recordId = sps.getRecordId();
+ UUID id = recordId.getSegmentId().asUUID();
+ if (uuids.contains(id)) {
+ if (ps.getType().tag() == PropertyType.STRING) {
+ String val = "";
+ if (ps.count() > 0) {
+ // only shows the first value, do we need more?
+ val = displayString(ps.getValue(Type.STRING, 0));
+ }
+ localPaths.add(getLocalPath(path, ps, val, recordId));
+ } else {
+ localPaths.add(getLocalPath(path, ps, recordId));
+ }
+
+ }
+ if (ps.getType().tag() == PropertyType.BINARY) {
+ // look for extra segment references
+ for (int i = 0; i < ps.count(); i++) {
+ Blob b = ps.getValue(Type.BINARY, i);
+ for (SegmentId sbid :
SegmentBlob.getBulkSegmentIds(b)) {
+ UUID bid = sbid.asUUID();
+ if (!bid.equals(id) && uuids.contains(bid)) {
+ localPaths.add(getLocalPath(path, ps,
recordId));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ RecordId stateId = state.getRecordId();
+ if (uuids.contains(stateId.getSegmentId().asUUID())) {
+ localPaths.add(path + " [SegmentNodeState@" + stateId + "]");
+ }
+
+ RecordId templateId = getTemplateId(state);
+ if (uuids.contains(templateId.getSegmentId().asUUID())) {
+ localPaths.add(path + "[Template@" + templateId + "]");
+ }
+ paths.addAll(localPaths);
+ for (ChildNodeEntry ce : state.getChildNodeEntries()) {
+ NodeState c = ce.getNodeState();
+ if (c instanceof SegmentNodeState) {
+ filterNodeStates(uuids, paths, (SegmentNodeState) c,
+ path + ce.getName() + "/");
+ }
+ }
+ }
+
+ private String getLocalPath(String path, PropertyState ps, String value,
RecordId id) {
+ return path + ps.getName() + " = " + value + " [SegmentPropertyState<"
+ ps.getType() + ">@" + id + "]";
+ }
+
+ private String getLocalPath(String path, PropertyState ps, RecordId id) {
+ return path + ps + " [SegmentPropertyState<" + ps.getType() + ">@" +
id + "]";
+ }
+
+ private String displayString(String value) {
+ if (maxCharDisplay > 0 && value.length() > maxCharDisplay) {
+ value = value.substring(0, maxCharDisplay) + "... (" +
value.length() + " chars)";
+ }
+
+ String escaped = Escapers.builder()
+ .setSafeRange(' ', '~')
+ .addEscape('"', "\\\"")
+ .addEscape('\\', "\\\\")
+ .build()
+ .escape(value);
+
+ return '"' + escaped + '"';
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/DebugTars.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Diff.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Diff.java?rev=1757382&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Diff.java
(added)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Diff.java
Tue Aug 23 14:33:49 2016
@@ -0,0 +1,302 @@
+/*
+ * 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.segment.tool;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Lists.reverse;
+import static org.apache.jackrabbit.oak.commons.PathUtils.elements;
+import static org.apache.jackrabbit.oak.segment.RecordId.fromString;
+import static
org.apache.jackrabbit.oak.segment.file.FileStoreBuilder.fileStoreBuilder;
+import static
org.apache.jackrabbit.oak.segment.tool.Utils.newBasicReadOnlyBlobStore;
+import static org.apache.jackrabbit.oak.segment.tool.Utils.readRevisions;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.jackrabbit.oak.segment.RecordId;
+import org.apache.jackrabbit.oak.segment.SegmentNotFoundException;
+import org.apache.jackrabbit.oak.segment.file.FileStore.ReadOnlyStore;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+/**
+ * Shows the differences between two head states.
+ */
+public class Diff implements Runnable {
+
+ /**
+ * Create a builder for the {@link Diff} command.
+ *
+ * @return an instance of {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Collect options for the {@link Diff} command.
+ */
+ public static class Builder {
+
+ private File path;
+
+ private String interval;
+
+ private boolean incremental;
+
+ private File out;
+
+ private String filter;
+
+ private boolean ignoreMissingSegments;
+
+ private Builder() {
+ // Prevent external instantiation.
+ }
+
+ /**
+ * The path to an existing segment store. This parameter is required.
+ *
+ * @param path the path to an existing segment store.
+ * @return this builder.
+ */
+ public Builder withPath(File path) {
+ this.path = checkNotNull(path);
+ return this;
+ }
+
+ /**
+ * The two node records to diff specified as a record ID interval. This
+ * parameter is required.
+ * <p>
+ * The interval is specified as two record IDs separated by two full
+ * stops ({@code ..}). In example, {@code
333dc24d-438f-4cca-8b21-3ebf67c05856:12345..46116fda-7a72-4dbc-af88-a09322a7753a:67890}.
+ * Instead of using a full record ID, it is possible to use the special
+ * placeholder {@code head}. This placeholder is translated to the
+ * record ID of the most recent head state.
+ *
+ * @param interval an interval between two node record IDs.
+ * @return this builder.
+ */
+ public Builder withInterval(String interval) {
+ this.interval = checkNotNull(interval);
+ return this;
+ }
+
+ /**
+ * Set whether or not to perform an incremental diff of the specified
+ * interval. An incremental diff shows every change between the two
+ * records at every revision available to the segment store. This
+ * parameter is not mandatory and defaults to {@code false}.
+ *
+ * @param incremental {@code true} to perform an incremental diff,
+ * {@code false} otherwise.
+ * @return this builder.
+ */
+ public Builder withIncremental(boolean incremental) {
+ this.incremental = incremental;
+ return this;
+ }
+
+ /**
+ * The file where the output of this command is stored. this parameter
+ * is mandatory.
+ *
+ * @param file the output file.
+ * @return this builder.
+ */
+ public Builder withOutput(File file) {
+ this.out = checkNotNull(file);
+ return this;
+ }
+
+ /**
+ * The path to a subtree. If specified, this parameter allows to
+ * restrict the diff to the specified subtree. This parameter is not
+ * mandatory and defaults to the entire tree.
+ *
+ * @param filter a path used as as filter for the resulting diff.
+ * @return this builder.
+ */
+ public Builder withFilter(String filter) {
+ this.filter = checkNotNull(filter);
+ return this;
+ }
+
+ /**
+ * Whether to ignore exceptions caused by missing segments in the
+ * segment store. This paramter is not mandatory and defaults to {@code
+ * false}.
+ *
+ * @param ignoreMissingSegments {@code true} to ignore exceptions
caused
+ * by missing segments, {@code false}
+ * otherwise.
+ * @return this builder.
+ */
+ public Builder withIgnoreMissingSegments(boolean
ignoreMissingSegments) {
+ this.ignoreMissingSegments = ignoreMissingSegments;
+ return this;
+ }
+
+ /**
+ * Create an executable version of the {@link Diff} command.
+ *
+ * @return an instance of {@link Runnable}.
+ */
+ public Runnable build() {
+ checkNotNull(path);
+ checkNotNull(interval);
+ checkNotNull(out);
+ checkNotNull(filter);
+ return new Diff(this);
+ }
+
+ }
+
+ private final File path;
+
+ private final String interval;
+
+ private final boolean incremental;
+
+ private final File out;
+
+ private final String filter;
+
+ private final boolean ignoreMissingSegments;
+
+ private Diff(Builder builder) {
+ this.path = builder.path;
+ this.interval = builder.interval;
+ this.incremental = builder.incremental;
+ this.out = builder.out;
+ this.filter = builder.filter;
+ this.ignoreMissingSegments = builder.ignoreMissingSegments;
+ }
+
+ @Override
+ public void run() {
+ try {
+ diff();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void diff() throws Exception {
+ System.out.println("Store " + path);
+ System.out.println("Writing diff to " + out);
+
+ String[] tokens = interval.trim().split("\\.\\.");
+
+ if (tokens.length != 2) {
+ System.out.println("Error parsing revision interval '" + interval
+ "'.");
+ return;
+ }
+
+ try (ReadOnlyStore store =
fileStoreBuilder(path).withBlobStore(newBasicReadOnlyBlobStore()).buildReadOnly())
{
+ RecordId idL;
+
+ try {
+ if (tokens[0].equalsIgnoreCase("head")) {
+ idL = store.getRevisions().getHead();
+ } else {
+ idL = fromString(store, tokens[0]);
+ }
+ } catch (IllegalArgumentException e) {
+ System.out.println("Invalid left endpoint for interval " +
interval);
+ return;
+ }
+
+ RecordId idR;
+
+ try {
+ if (tokens[1].equalsIgnoreCase("head")) {
+ idR = store.getRevisions().getHead();
+ } else {
+ idR = fromString(store, tokens[1]);
+ }
+ } catch (IllegalArgumentException e) {
+ System.out.println("Invalid left endpoint for interval " +
interval);
+ return;
+ }
+
+ long start = System.currentTimeMillis();
+
+ try (PrintWriter pw = new PrintWriter(out)) {
+ if (incremental) {
+ List<String> revs = readRevisions(path);
+ System.out.println("Generating diff between " + idL + "
and " + idR + " incrementally. Found " + revs.size() + " revisions.");
+
+ int s = revs.indexOf(idL.toString10());
+ int e = revs.indexOf(idR.toString10());
+ if (s == -1 || e == -1) {
+ System.out.println("Unable to match input revisions
with FileStore.");
+ return;
+ }
+ List<String> revDiffs = revs.subList(Math.min(s, e),
Math.max(s, e) + 1);
+ if (s > e) {
+ // reverse list
+ revDiffs = reverse(revDiffs);
+ }
+ if (revDiffs.size() < 2) {
+ System.out.println("Nothing to diff: " + revDiffs);
+ return;
+ }
+ Iterator<String> revDiffsIt = revDiffs.iterator();
+ RecordId idLt = fromString(store, revDiffsIt.next());
+ while (revDiffsIt.hasNext()) {
+ RecordId idRt = fromString(store, revDiffsIt.next());
+ boolean good = diff(store, idLt, idRt, pw);
+ idLt = idRt;
+ if (!good && !ignoreMissingSegments) {
+ break;
+ }
+ }
+ } else {
+ System.out.println("Generating diff between " + idL + "
and " + idR);
+ diff(store, idL, idR, pw);
+ }
+ }
+
+ long dur = System.currentTimeMillis() - start;
+ System.out.println("Finished in " + dur + " ms.");
+ }
+ }
+
+ private boolean diff(ReadOnlyStore store, RecordId idL, RecordId idR,
PrintWriter pw) throws IOException {
+ pw.println("rev " + idL + ".." + idR);
+ try {
+ NodeState before =
store.getReader().readNode(idL).getChildNode("root");
+ NodeState after =
store.getReader().readNode(idR).getChildNode("root");
+ for (String name : elements(filter)) {
+ before = before.getChildNode(name);
+ after = after.getChildNode(name);
+ }
+ after.compareAgainstBaseState(before, new PrintingDiff(pw,
filter));
+ return true;
+ } catch (SegmentNotFoundException ex) {
+ System.out.println(ex.getMessage());
+ pw.println("#SNFE " + ex.getSegmentId());
+ return false;
+ }
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Diff.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/GenerationGraph.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/GenerationGraph.java?rev=1757382&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/GenerationGraph.java
(added)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/GenerationGraph.java
Tue Aug 23 14:33:49 2016
@@ -0,0 +1,113 @@
+/*
+ * 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.segment.tool;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.apache.jackrabbit.oak.segment.SegmentGraph.writeGCGraph;
+import static
org.apache.jackrabbit.oak.segment.tool.Utils.openReadOnlyFileStore;
+
+import java.io.File;
+import java.io.OutputStream;
+
+import org.apache.jackrabbit.oak.segment.file.FileStore.ReadOnlyStore;
+
+/**
+ * Generates a garbage collection generation graph. The graph is written in <a
+ * href="https://gephi.github.io/users/supported-graph-formats/gdf-format/">the
+ * Guess GDF format</a>, which is easily imported into <a
+ * href="https://gephi.github.io/">Gephi</a>.
+ */
+public class GenerationGraph implements Runnable {
+
+ /**
+ * Create a builder for the {@link GenerationGraph} command.
+ *
+ * @return an instance of {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Collect options for the {@link GenerationGraph} command.
+ */
+ public static class Builder {
+
+ private File path;
+
+ private OutputStream out;
+
+ private Builder() {
+ // Prevent external instantiation.
+ }
+
+ /**
+ * The path to an existing segment store. This parameter is required.
+ *
+ * @param path the path to an existing segment store.
+ * @return this builder.
+ */
+ public Builder withPath(File path) {
+ this.path = checkNotNull(path);
+ return this;
+ }
+
+ /**
+ * The destination of the output of the command. This parameter is
+ * mandatory.
+ *
+ * @param out the destination of the output of the command.
+ * @return this builder.
+ */
+ public Builder withOutput(OutputStream out) {
+ this.out = checkNotNull(out);
+ return this;
+ }
+
+ /**
+ * Create an executable version of the {@link GenerationGraph} command.
+ *
+ * @return an instance of {@link Runnable}.
+ */
+ public Runnable build() {
+ checkNotNull(path);
+ checkNotNull(out);
+ return new GenerationGraph(this);
+ }
+
+ }
+
+ private final File path;
+
+ private final OutputStream out;
+
+ private GenerationGraph(Builder builder) {
+ this.path = builder.path;
+ this.out = builder.out;
+ }
+
+ @Override
+ public void run() {
+ try (ReadOnlyStore store = openReadOnlyFileStore(path)) {
+ writeGCGraph(store, out);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/GenerationGraph.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/History.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/History.java?rev=1757382&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/History.java
(added)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/History.java
Tue Aug 23 14:33:49 2016
@@ -0,0 +1,154 @@
+/*
+ * 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.segment.tool;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.File;
+import java.util.Iterator;
+
+import org.apache.jackrabbit.oak.segment.file.tooling.RevisionHistory;
+import
org.apache.jackrabbit.oak.segment.file.tooling.RevisionHistory.HistoryElement;
+
+/**
+ * Prints the revision history of an existing segment store. Optionally, it can
+ * narrow to the output to the history of a single node.
+ */
+public class History implements Runnable {
+
+ /**
+ * Create a builder for the {@link History} command.
+ *
+ * @return an instance of {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Collect options for the {@link History} command.
+ */
+ public static class Builder {
+
+ private File path;
+
+ private File journal;
+
+ private String node;
+
+ private int depth;
+
+ private Builder() {
+ // Prevent external instantiation.
+ }
+
+ /**
+ * The path to an existing segment store. This parameter is required.
+ *
+ * @param path the path to an existing segment store.
+ * @return this builder.
+ */
+ public Builder withPath(File path) {
+ this.path = checkNotNull(path);
+ return this;
+ }
+
+ /**
+ * The path to the journal. This parameter is required.
+ *
+ * @param journal the path to the journal.
+ * @return this builder.
+ */
+ public Builder withJournal(File journal) {
+ this.journal = checkNotNull(journal);
+ return this;
+ }
+
+ /**
+ * A path to a node. If specified, the history will be restricted to
the
+ * subtree pointed to by this node. This parameter is not mandatory and
+ * defaults to the entire tree.
+ *
+ * @param node a path to a node.
+ * @return this builder.
+ */
+ public Builder withNode(String node) {
+ this.node = checkNotNull(node);
+ return this;
+ }
+
+ /**
+ * Maximum depth of the history. If specified, this command will print
+ * information about the history of every node at or below the provided
+ * depth. This parameter is not mandatory and defaults to zero.
+ *
+ * @param depth the depth of the subtree.
+ * @return this builder.
+ */
+ public Builder withDepth(int depth) {
+ checkArgument(depth >= 0);
+ this.depth = depth;
+ return this;
+ }
+
+ /**
+ * Create an executable version of the {@link History} command.
+ *
+ * @return an instance of {@link Runnable}.
+ */
+ public Runnable build() {
+ checkNotNull(path);
+ checkNotNull(journal);
+ checkNotNull(node);
+ return new History(this);
+ }
+
+ }
+
+ private final File path;
+
+ private final File journal;
+
+ private final String node;
+
+ private final int depth;
+
+ private History(Builder builder) {
+ this.path = builder.path;
+ this.journal = builder.journal;
+ this.node = builder.node;
+ this.depth = builder.depth;
+ }
+
+ @Override
+ public void run() {
+ try {
+ run(new RevisionHistory(path).getHistory(journal, node));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void run(Iterator<HistoryElement> history) {
+ while (history.hasNext()) {
+ System.out.println(history.next().toString(depth));
+ }
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/History.java
------------------------------------------------------------------------------
svn:eol-style = native
Copied:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/PrintingDiff.java
(from r1757147,
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/PrintingDiff.java)
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/PrintingDiff.java?p2=jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/PrintingDiff.java&p1=jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/PrintingDiff.java&r1=1757147&r2=1757382&rev=1757382&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/PrintingDiff.java
(original)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/PrintingDiff.java
Tue Aug 23 14:33:49 2016
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.jackrabbit.oak.run;
+package org.apache.jackrabbit.oak.segment.tool;
import static com.google.common.collect.Iterables.transform;
import static org.apache.commons.io.FileUtils.byteCountToDisplaySize;
@@ -136,4 +136,5 @@ final class PrintingDiff implements Node
}
return ps.getName() + "<" + ps.getType() + ">" + val.toString();
}
+
}
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Restore.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Restore.java?rev=1757382&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Restore.java
(added)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Restore.java
Tue Aug 23 14:33:49 2016
@@ -0,0 +1,106 @@
+/*
+ * 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.segment.tool;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.File;
+
+import org.apache.jackrabbit.oak.backup.FileStoreRestore;
+
+/**
+ * Restore a backup of a segment store into an existing segment store.
+ */
+public class Restore implements Runnable {
+
+ /**
+ * Create a builder for the {@link Restore} command.
+ *
+ * @return an instance of {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Collect options for the {@link Restore} command.
+ */
+ public static class Builder {
+
+ private File source;
+
+ private File target;
+
+ private Builder() {
+ // Prevent external instantiation.
+ }
+
+ /**
+ * The source path of the restore. This parameter is mandatory.
+ *
+ * @param source the source path of the restore.
+ * @return this builder.
+ */
+ public Builder withSource(File source) {
+ this.source = checkNotNull(source);
+ return this;
+ }
+
+ /**
+ * The target of the restore. This parameter is mandatory.
+ *
+ * @param target the target of the restore.
+ * @return this builder.
+ */
+ public Builder withTarget(File target) {
+ this.target = checkNotNull(target);
+ return this;
+ }
+
+ /**
+ * Create an executable version of the {@link Restore} command.
+ *
+ * @return an instance of {@link Runnable}.
+ */
+ public Runnable build() {
+ checkNotNull(source);
+ checkNotNull(target);
+ return new Restore(this);
+ }
+
+ }
+
+ private final File source;
+
+ private final File target;
+
+ private Restore(Builder builder) {
+ this.source = builder.source;
+ this.target = builder.target;
+ }
+
+ @Override
+ public void run() {
+ try {
+ FileStoreRestore.restore(source, target);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Restore.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Revisions.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Revisions.java?rev=1757382&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Revisions.java
(added)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Revisions.java
Tue Aug 23 14:33:49 2016
@@ -0,0 +1,127 @@
+/*
+ * 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.segment.tool;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.apache.jackrabbit.oak.segment.tool.Utils.readRevisions;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * Collect and print the revisions of a segment store.
+ */
+public class Revisions implements Runnable {
+
+ /**
+ * Create a builder for the {@link Revisions} command.
+ *
+ * @return an instance of {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Collect options for the {@link Revisions} command.
+ */
+ public static class Builder {
+
+ private File path;
+
+ private File out;
+
+ private Builder() {
+ // Prevent external instantiation.
+ }
+
+ /**
+ * The path to an existing segment store. This parameter is required.
+ *
+ * @param path the path to an existing segment store.
+ * @return this builder.
+ */
+ public Builder withPath(File path) {
+ this.path = checkNotNull(path);
+ return this;
+ }
+
+ /**
+ * The file where the output of this command is stored. this parameter
+ * is mandatory.
+ *
+ * @param out the output file.
+ * @return this builder.
+ */
+ public Builder withOutput(File out) {
+ this.out = checkNotNull(out);
+ return this;
+ }
+
+ /**
+ * Create an executable version of the {@link Revisions} command.
+ *
+ * @return an instance of {@link Runnable}.
+ */
+ public Runnable build() {
+ checkNotNull(path);
+ checkNotNull(out);
+ return new Revisions(this);
+ }
+
+ }
+
+ private final File path;
+
+ private final File out;
+
+ private Revisions(Builder builder) {
+ this.path = builder.path;
+ this.out = builder.out;
+ }
+
+ @Override
+ public void run() {
+ try {
+ listRevisions();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void listRevisions() throws IOException {
+ System.out.println("Store " + path);
+ System.out.println("Writing revisions to " + out);
+
+ List<String> revs = readRevisions(path);
+
+ if (revs.isEmpty()) {
+ System.out.println("No revisions found.");
+ return;
+ }
+
+ try (PrintWriter pw = new PrintWriter(out)) {
+ for (String r : revs) {
+ pw.println(r);
+ }
+ }
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Revisions.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/SegmentGraph.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/SegmentGraph.java?rev=1757382&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/SegmentGraph.java
(added)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/SegmentGraph.java
Tue Aug 23 14:33:49 2016
@@ -0,0 +1,144 @@
+/*
+ * 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.segment.tool;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.apache.jackrabbit.oak.segment.SegmentGraph.writeSegmentGraph;
+import static
org.apache.jackrabbit.oak.segment.tool.Utils.openReadOnlyFileStore;
+
+import java.io.File;
+import java.io.OutputStream;
+import java.util.Date;
+
+import org.apache.jackrabbit.oak.segment.file.FileStore.ReadOnlyStore;
+
+/**
+ * Generates a segment collection generation graph. The graph is written in <a
+ * href="https://gephi.github.io/users/supported-graph-formats/gdf-format/">the
+ * Guess GDF format</a>, which is easily imported into <a
+ * href="https://gephi.github.io/">Gephi</a>.
+ */
+public class SegmentGraph implements Runnable {
+
+ /**
+ * Create a builder for the {@link SegmentGraph} command.
+ *
+ * @return an instance of {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Collect options for the {@link SegmentGraph} command.
+ */
+ public static class Builder {
+
+ private File path;
+
+ private Date epoch;
+
+ private String filter;
+
+ private OutputStream out;
+
+ private Builder() {
+ // Prevent external instantiation.
+ }
+
+ /**
+ * The path to an existing segment store. This parameter is required.
+ *
+ * @param path the path to an existing segment store.
+ * @return this builder.
+ */
+ public Builder withPath(File path) {
+ this.path = checkNotNull(path);
+ return this;
+ }
+
+ /**
+ * Filter out segments that were created before the specified epoch.
+ * This parameter is not mandatory and by default is not specified,
thus
+ * including every segment in the output.
+ *
+ * @param epoch the minimum creation time of the reported segments.
+ * @return this builder.
+ */
+ public Builder withEpoch(Date epoch) {
+ this.epoch = checkNotNull(epoch);
+ return this;
+ }
+
+ /**
+ * A regular expression that can be used to select a specific subset of
+ * the segments.
+ *
+ * @param filter a regular expression.
+ * @return this builder.
+ */
+ public Builder withFilter(String filter) {
+ this.filter = checkNotNull(filter);
+ return this;
+ }
+
+ /**
+ * The destination of the output of the command. This parameter is
+ * mandatory.
+ *
+ * @param out the destination of the output of the command.
+ * @return this builder.
+ */
+ public Builder withOutput(OutputStream out) {
+ this.out = checkNotNull(out);
+ return this;
+ }
+
+ public Runnable build() {
+ checkNotNull(path);
+ checkNotNull(out);
+ return new SegmentGraph(this);
+ }
+
+ }
+
+ private final File path;
+
+ private final OutputStream out;
+
+ private final Date epoch;
+
+ private final String filter;
+
+ private SegmentGraph(Builder builder) {
+ this.path = builder.path;
+ this.out = builder.out;
+ this.epoch = builder.epoch;
+ this.filter = builder.filter;
+ }
+
+ @Override
+ public void run() {
+ try (ReadOnlyStore store = openReadOnlyFileStore(path)) {
+ writeSegmentGraph(store, out, epoch, filter);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/SegmentGraph.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Utils.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Utils.java?rev=1757382&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Utils.java
(added)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Utils.java
Tue Aug 23 14:33:49 2016
@@ -0,0 +1,97 @@
+/*
+ * 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.segment.tool;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Lists.newArrayList;
+import static
org.apache.jackrabbit.oak.segment.file.FileStoreBuilder.fileStoreBuilder;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.jackrabbit.oak.segment.file.FileStore;
+import org.apache.jackrabbit.oak.segment.file.FileStore.ReadOnlyStore;
+import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException;
+import org.apache.jackrabbit.oak.segment.file.JournalReader;
+import org.apache.jackrabbit.oak.segment.file.tooling.BasicReadOnlyBlobStore;
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+
+class Utils {
+
+ private static final boolean TAR_STORAGE_MEMORY_MAPPED =
Boolean.getBoolean("tar.memoryMapped");
+
+ private static final int TAR_SEGMENT_CACHE_SIZE =
Integer.getInteger("cache", 256);
+
+ static FileStore openReadOnlyFileStore(File path, BlobStore blobStore)
throws IOException, InvalidFileStoreVersionException {
+ return fileStoreBuilder(isValidFileStoreOrFail(path))
+ .withSegmentCacheSize(TAR_SEGMENT_CACHE_SIZE)
+ .withMemoryMapping(TAR_STORAGE_MEMORY_MAPPED)
+ .withBlobStore(blobStore)
+ .buildReadOnly();
+ }
+
+ static ReadOnlyStore openReadOnlyFileStore(File path) throws IOException,
InvalidFileStoreVersionException {
+ return fileStoreBuilder(isValidFileStoreOrFail(path))
+ .withSegmentCacheSize(TAR_SEGMENT_CACHE_SIZE)
+ .withMemoryMapping(TAR_STORAGE_MEMORY_MAPPED)
+ .buildReadOnly();
+ }
+
+ static BlobStore newBasicReadOnlyBlobStore() {
+ return new BasicReadOnlyBlobStore();
+ }
+
+ static List<String> readRevisions(File store) {
+ File journal = new File(store, "journal.log");
+
+ if (journal.exists()) {
+ try (JournalReader journalReader = new JournalReader(journal)) {
+ return newArrayList(journalReader);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ return newArrayList();
+ }
+
+ private static File isValidFileStoreOrFail(File store) {
+ checkArgument(isValidFileStore(store), "Invalid FileStore directory "
+ store);
+ return store;
+ }
+
+ private static boolean isValidFileStore(File store) {
+ if (!store.exists()) {
+ return false;
+ }
+
+ if (!store.isDirectory()) {
+ return false;
+ }
+
+ for (String f : store.list()) {
+ if ("journal.log".equals(f)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/tool/Utils.java
------------------------------------------------------------------------------
svn:eol-style = native