Author: alexkli
Date: Sat Oct 27 02:43:08 2018
New Revision: 1844933
URL: http://svn.apache.org/viewvc?rev=1844933&view=rev
Log:
OAK-7832 - oak-run console export should handle exceptions such as missing
segments
Added:
jackrabbit/oak/branches/1.8/oak-run/src/main/java/org/apache/jackrabbit/oak/nodestate/
- copied from r1844932,
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/nodestate/
Modified:
jackrabbit/oak/branches/1.8/oak-run/src/main/groovy/org/apache/jackrabbit/oak/console/commands/PnCommand.groovy
jackrabbit/oak/branches/1.8/oak-run/src/main/java/org/apache/jackrabbit/oak/exporter/NodeStateSerializer.java
jackrabbit/oak/branches/1.8/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/json/JsonSerializer.java
Modified:
jackrabbit/oak/branches/1.8/oak-run/src/main/groovy/org/apache/jackrabbit/oak/console/commands/PnCommand.groovy
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.8/oak-run/src/main/groovy/org/apache/jackrabbit/oak/console/commands/PnCommand.groovy?rev=1844933&r1=1844932&r2=1844933&view=diff
==============================================================================
---
jackrabbit/oak/branches/1.8/oak-run/src/main/groovy/org/apache/jackrabbit/oak/console/commands/PnCommand.groovy
(original)
+++
jackrabbit/oak/branches/1.8/oak-run/src/main/groovy/org/apache/jackrabbit/oak/console/commands/PnCommand.groovy
Sat Oct 27 02:43:08 2018
@@ -20,7 +20,7 @@ package org.apache.jackrabbit.oak.consol
import groovy.transform.CompileStatic
import org.apache.jackrabbit.oak.console.ConsoleSession
-import org.apache.jackrabbit.oak.spi.state.AbstractNodeState
+import org.apache.jackrabbit.oak.nodestate.NodeStateHelper
import org.codehaus.groovy.tools.shell.CommandSupport
import org.codehaus.groovy.tools.shell.Groovysh
@@ -28,18 +28,19 @@ import org.codehaus.groovy.tools.shell.G
class PnCommand extends CommandSupport{
public static final String COMMAND_NAME = 'print-node'
- public PnCommand(Groovysh shell) {
+ PnCommand(Groovysh shell) {
super(shell, COMMAND_NAME, 'pn')
}
@Override
Object execute(List<String> args) {
assertNoArguments(args)
-
io.out.println(AbstractNodeState.toString(getSession().getWorkingNode()))
+
io.out.println(NodeStateHelper.nodeStateToString(getSession().getWorkingNode()))
return null
}
ConsoleSession getSession(){
return (ConsoleSession)variables.session
}
+
}
Modified:
jackrabbit/oak/branches/1.8/oak-run/src/main/java/org/apache/jackrabbit/oak/exporter/NodeStateSerializer.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.8/oak-run/src/main/java/org/apache/jackrabbit/oak/exporter/NodeStateSerializer.java?rev=1844933&r1=1844932&r2=1844933&view=diff
==============================================================================
---
jackrabbit/oak/branches/1.8/oak-run/src/main/java/org/apache/jackrabbit/oak/exporter/NodeStateSerializer.java
(original)
+++
jackrabbit/oak/branches/1.8/oak-run/src/main/java/org/apache/jackrabbit/oak/exporter/NodeStateSerializer.java
Sat Oct 27 02:43:08 2018
@@ -101,9 +101,9 @@ public class NodeStateSerializer {
}
private void serialize(JsopWriter writer, BlobSerializer blobSerializer)
throws IOException {
- JsonSerializer serializer = new JsonSerializer(writer, depth, 0,
maxChildNodes, getFilter(), blobSerializer);
+ JsonSerializer serializer = new JsonSerializer(writer, depth, 0,
maxChildNodes, getFilter(), blobSerializer, true);
NodeState state = NodeStateUtils.getNode(nodeState, path);
- serializer.serialize(state);
+ serializer.serialize(state, path);
}
private BlobSerializer createBlobSerializer(File dir) {
Modified:
jackrabbit/oak/branches/1.8/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/json/JsonSerializer.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.8/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/json/JsonSerializer.java?rev=1844933&r1=1844932&r2=1844933&view=diff
==============================================================================
---
jackrabbit/oak/branches/1.8/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/json/JsonSerializer.java
(original)
+++
jackrabbit/oak/branches/1.8/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/json/JsonSerializer.java
Sat Oct 27 02:43:08 2018
@@ -25,9 +25,12 @@ import static org.apache.jackrabbit.oak.
import static org.apache.jackrabbit.oak.api.Type.NAMES;
import static org.apache.jackrabbit.oak.api.Type.STRING;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
+import org.jetbrains.annotations.NotNull;
import javax.jcr.PropertyType;
import com.google.common.collect.ImmutableList;
@@ -38,19 +41,31 @@ import org.apache.jackrabbit.oak.api.Pro
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.json.JsopTokenizer;
import org.apache.jackrabbit.oak.commons.json.JsopWriter;
+import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
import org.apache.jackrabbit.oak.plugins.memory.MemoryChildNodeEntry;
+import org.apache.jackrabbit.oak.plugins.memory.StringPropertyState;
+import org.apache.jackrabbit.oak.spi.state.AbstractNodeState;
import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.ReadOnlyBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Utility class for serializing node and property states to JSON.
*/
public class JsonSerializer {
+ private static final Logger log =
LoggerFactory.getLogger(JsonSerializer.class);
+
public static final String DEFAULT_FILTER_EXPRESSION =
"{\"properties\":[\"*\", \"-:childNodeCount\"]}";
private static final JsonFilter DEFAULT_FILTER = new
JsonFilter(DEFAULT_FILTER_EXPRESSION);
+ private static final String ERROR_JSON_KEY = "_error";
+ private static final String ERROR_JSON_VALUE_PREFIX = "ERROR: ";
+
private final JsopWriter json;
private final int depth;
@@ -63,86 +78,167 @@ public class JsonSerializer {
private final BlobSerializer blobs;
+ private final boolean catchExceptions;
+
private JsonSerializer(
JsopWriter json, int depth, long offset, int maxChildNodes,
- JsonFilter filter, BlobSerializer blobs) {
+ JsonFilter filter, BlobSerializer blobs, boolean catchExceptions) {
this.json = checkNotNull(json);
this.depth = depth;
this.offset = offset;
this.maxChildNodes = maxChildNodes;
this.filter = checkNotNull(filter);
this.blobs = checkNotNull(blobs);
+ this.catchExceptions = catchExceptions;
}
public JsonSerializer(
int depth, long offset, int maxChildNodes,
String filter, BlobSerializer blobs) {
this(new JsopBuilder(), depth, offset, maxChildNodes,
- new JsonFilter(filter), blobs);
+ new JsonFilter(filter), blobs, false);
}
public JsonSerializer(JsopWriter json,
int depth, long offset, int maxChildNodes,
String filter, BlobSerializer blobs) {
this(json, depth, offset, maxChildNodes,
- new JsonFilter(filter), blobs);
+ new JsonFilter(filter), blobs, false);
+ }
+
+ public JsonSerializer(JsopWriter json,
+ int depth, long offset, int maxChildNodes,
+ String filter, BlobSerializer blobs, boolean
catchExceptions) {
+ this(json, depth, offset, maxChildNodes,
+ new JsonFilter(filter), blobs, catchExceptions);
}
public JsonSerializer(JsopWriter json, BlobSerializer blobs) {
this(json, Integer.MAX_VALUE, 0, Integer.MAX_VALUE,
- DEFAULT_FILTER, blobs);
+ DEFAULT_FILTER, blobs, false);
}
public JsonSerializer(JsopWriter json, String filter, BlobSerializer
blobs) {
this(json, Integer.MAX_VALUE, 0, Integer.MAX_VALUE,
- new JsonFilter(filter), blobs);
+ new JsonFilter(filter), blobs, false);
}
protected JsonSerializer getChildSerializer() {
return new JsonSerializer(
- json, depth - 1, 0, maxChildNodes, filter, blobs);
+ json, depth - 1, 0, maxChildNodes, filter, blobs,
catchExceptions);
}
public void serialize(NodeState node) {
- json.object();
+ serialize(node, "");
+ }
- for (PropertyState property : node.getProperties()) {
- String name = property.getName();
- if (filter.includeProperty(name)) {
- json.key(name);
- serialize(property);
- }
- }
+ public void serialize(NodeState node, String basePath) {
+ json.object();
- int index = 0;
- int count = 0;
- for (ChildNodeEntry child : getChildNodeEntries(node)) {
- String name = child.getName();
- if (filter.includeNode(name) && index++ >= offset) {
- if (count++ >= maxChildNodes) {
- break;
+ try {
+ for (PropertyState property : node.getProperties()) {
+ String name = property.getName();
+ if (filter.includeProperty(name)) {
+ json.key(name);
+ try {
+ serialize(property);
+ } catch (Throwable t) {
+ if (catchExceptions) {
+ String message = "Cannot read property value " +
basePath + "/" + name + " : " + t.getMessage();
+ log.error(message);
+ json.value(ERROR_JSON_VALUE_PREFIX + message);
+ } else {
+ throw t;
+ }
+ }
}
+ }
- json.key(name);
- if (depth > 0) {
- getChildSerializer().serialize(child.getNodeState());
- } else {
- json.object();
- json.endObject();
+ int index = 0;
+ int count = 0;
+ for (ChildNodeEntry child : getChildNodeEntries(node, basePath)) {
+ String name = child.getName();
+ if (filter.includeNode(name) && index++ >= offset) {
+ if (count++ >= maxChildNodes) {
+ break;
+ }
+
+ json.key(name);
+ if (depth > 0) {
+ getChildSerializer().serialize(child.getNodeState(),
basePath + "/" + name);
+ } else {
+ json.object();
+ json.endObject();
+ }
}
}
+ } catch (Throwable t) {
+ if (catchExceptions) {
+ String message = "Cannot read node " + basePath + " : " +
t.getMessage();
+ log.error(message);
+ json.key(ERROR_JSON_KEY);
+ json.value(ERROR_JSON_VALUE_PREFIX + message);
+ } else {
+ throw t;
+ }
}
json.endObject();
}
- private Iterable<? extends ChildNodeEntry> getChildNodeEntries(NodeState
node) {
+ private Iterable<? extends ChildNodeEntry> getChildNodeEntries(NodeState
node, String basePath) {
PropertyState order = node.getProperty(":childOrder");
if (order != null) {
List<String> names = ImmutableList.copyOf(order.getValue(NAMES));
List<ChildNodeEntry> entries =
Lists.newArrayListWithCapacity(names.size());
for (String name : names) {
- entries.add(new MemoryChildNodeEntry(name,
node.getChildNode(name)));
+ try {
+ entries.add(new MemoryChildNodeEntry(name,
node.getChildNode(name)));
+ } catch (Throwable t) {
+ if (catchExceptions) {
+ String message = "Cannot read node " + basePath + "/"
+ name + " : " + t.getMessage();
+ log.error(message);
+
+ // return a placeholder child node entry for tracking
the error into the JSON
+ entries.add(new MemoryChildNodeEntry(name, new
AbstractNodeState() {
+ @Override
+ public boolean exists() {
+ return true;
+ }
+
+ @NotNull
+ @Override
+ public Iterable<? extends PropertyState>
getProperties() {
+ return Collections.singleton(new
StringPropertyState(ERROR_JSON_KEY, ERROR_JSON_VALUE_PREFIX + message));
+ }
+
+ @Override
+ public boolean hasChildNode(@NotNull String name) {
+ return false;
+ }
+
+ @NotNull
+ @Override
+ public NodeState getChildNode(@NotNull String
name) throws IllegalArgumentException {
+ return EmptyNodeState.MISSING_NODE;
+ }
+
+ @NotNull
+ @Override
+ public Iterable<? extends ChildNodeEntry>
getChildNodeEntries() {
+ return Collections.EMPTY_LIST;
+ }
+
+ @NotNull
+ @Override
+ public NodeBuilder builder() {
+ return new ReadOnlyBuilder(this);
+ }
+ }));
+ } else {
+ throw t;
+ }
+ }
}
return entries;
}