You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by al...@apache.org on 2018/10/27 01:45:20 UTC
svn commit: r1844932 - in /jackrabbit/oak/trunk:
oak-run/src/main/groovy/org/apache/jackrabbit/oak/console/commands/
oak-run/src/main/java/org/apache/jackrabbit/oak/exporter/
oak-run/src/main/java/org/apache/jackrabbit/oak/nodestate/
oak-store-spi/src/...
Author: alexkli
Date: Sat Oct 27 01:45:20 2018
New Revision: 1844932
URL: http://svn.apache.org/viewvc?rev=1844932&view=rev
Log:
OAK-7832 - oak-run console export should handle exceptions such as missing segments
Added:
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/nodestate/
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/nodestate/NodeStateHelper.java (with props)
Modified:
jackrabbit/oak/trunk/oak-run/src/main/groovy/org/apache/jackrabbit/oak/console/commands/PnCommand.groovy
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/exporter/NodeStateSerializer.java
jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/json/JsonSerializer.java
Modified: jackrabbit/oak/trunk/oak-run/src/main/groovy/org/apache/jackrabbit/oak/console/commands/PnCommand.groovy
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/groovy/org/apache/jackrabbit/oak/console/commands/PnCommand.groovy?rev=1844932&r1=1844931&r2=1844932&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/groovy/org/apache/jackrabbit/oak/console/commands/PnCommand.groovy (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/groovy/org/apache/jackrabbit/oak/console/commands/PnCommand.groovy Sat Oct 27 01:45:20 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/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/exporter/NodeStateSerializer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/exporter/NodeStateSerializer.java?rev=1844932&r1=1844931&r2=1844932&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/exporter/NodeStateSerializer.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/exporter/NodeStateSerializer.java Sat Oct 27 01:45:20 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) {
Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/nodestate/NodeStateHelper.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/nodestate/NodeStateHelper.java?rev=1844932&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/nodestate/NodeStateHelper.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/nodestate/NodeStateHelper.java Sat Oct 27 01:45:20 2018
@@ -0,0 +1,79 @@
+/**************************************************************************
+ * 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.nodestate;
+
+import static java.lang.Integer.getInteger;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+public abstract class NodeStateHelper {
+
+ private static final int CHILDREN_CAP = getInteger("oak.children.cap", 100);
+
+ public static String nodeStateToString(NodeState state) {
+ if (!state.exists()) {
+ return "{N/A}";
+ }
+ StringBuilder builder = new StringBuilder("{");
+ String separator = " ";
+ for (PropertyState property : state.getProperties()) {
+ builder.append(separator);
+ separator = ", ";
+ try {
+ builder.append(property);
+ } catch (Throwable t) {
+ builder.append(property.getName());
+ builder.append(" = { ERROR on property: ");
+ builder.append(t.getMessage());
+ builder.append(" }");
+ }
+ }
+ int count = CHILDREN_CAP;
+ for (ChildNodeEntry entry : state.getChildNodeEntries()) {
+ if (count-- == 0) {
+ builder.append("...");
+ break;
+ }
+ builder.append(separator);
+ separator = ", ";
+ try {
+ builder.append(childNodeEntryToString(entry));
+ } catch (Throwable t) {
+ builder.append(entry.getName());
+ builder.append(" = { ERROR on node: ");
+ builder.append(t.getMessage());
+ builder.append(" }");
+ }
+ }
+ builder.append(" }");
+ return builder.toString();
+ }
+
+ public static String childNodeEntryToString(ChildNodeEntry entry) {
+ String name = entry.getName();
+ NodeState state = entry.getNodeState();
+ if (state.getChildNodeCount(1) == 0) {
+ return name + " : " + nodeStateToString(state);
+ } else {
+ return name + " = { ... }";
+ }
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/nodestate/NodeStateHelper.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/nodestate/NodeStateHelper.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Modified: jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/json/JsonSerializer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/json/JsonSerializer.java?rev=1844932&r1=1844931&r2=1844932&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/json/JsonSerializer.java (original)
+++ jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/json/JsonSerializer.java Sat Oct 27 01:45:20 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;
}