You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2015/05/04 17:48:22 UTC

[1/8] incubator-tinkerpop git commit: Add an example for how to register a strategy in Gremlin Server.

Repository: incubator-tinkerpop
Updated Branches:
  refs/heads/gs-protocol 622821bca -> 5f4f162b8


Add an example for how to register a strategy in Gremlin Server.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/1f2a6ad1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/1f2a6ad1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/1f2a6ad1

Branch: refs/heads/gs-protocol
Commit: 1f2a6ad10ae7c924aaf068e82a84856b98d814ca
Parents: 6b93fab
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Mon May 4 09:46:14 2015 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Mon May 4 09:46:14 2015 -0400

----------------------------------------------------------------------
 .../conf/gremlin-server-modern-readonly.yaml    | 44 ++++++++++++++++++++
 .../scripts/generate-modern-readonly.groovy     | 24 +++++++++++
 .../server/op/AbstractEvalOpProcessor.java      |  1 +
 3 files changed, 69 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/1f2a6ad1/gremlin-server/conf/gremlin-server-modern-readonly.yaml
----------------------------------------------------------------------
diff --git a/gremlin-server/conf/gremlin-server-modern-readonly.yaml b/gremlin-server/conf/gremlin-server-modern-readonly.yaml
new file mode 100644
index 0000000..0797799
--- /dev/null
+++ b/gremlin-server/conf/gremlin-server-modern-readonly.yaml
@@ -0,0 +1,44 @@
+# 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.
+
+host: localhost
+port: 8182
+threadPoolWorker: 1
+gremlinPool: 8
+scriptEvaluationTimeout: 30000
+serializedResponseTimeout: 30000
+graphs: {
+  graph: conf/tinkergraph-empty.properties}
+plugins:
+  - tinkerpop.tinkergraph
+scriptEngines: {
+  gremlin-groovy: {
+    imports: [java.lang.Math],
+    staticImports: [java.lang.Math.PI],
+    scripts: [scripts/generate-modern-readonly.groovy]}}
+serializers:
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0 }
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { serializeResultToString: true }}
+metrics: {
+  slf4jReporter: {enabled: true, interval: 180000}}
+threadPoolBoss: 1
+maxInitialLineLength: 4096
+maxHeaderSize: 8192
+maxChunkSize: 8192
+maxContentLength: 65536
+maxAccumulationBufferComponents: 1024
+resultIterationBatchSize: 64

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/1f2a6ad1/gremlin-server/scripts/generate-modern-readonly.groovy
----------------------------------------------------------------------
diff --git a/gremlin-server/scripts/generate-modern-readonly.groovy b/gremlin-server/scripts/generate-modern-readonly.groovy
new file mode 100644
index 0000000..3028217
--- /dev/null
+++ b/gremlin-server/scripts/generate-modern-readonly.groovy
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// Generates the modern graph into an "empty" TinkerGraph
+TinkerFactory.generateModern(graph)
+
+// define the default TraversalSource to bind queries to.
+g = graph.traversal(GraphTraversalSource.build().with(ReadOnlyStrategy.instance()))
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/1f2a6ad1/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
index e9c5039..1a826bf 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
@@ -159,6 +159,7 @@ public abstract class AbstractEvalOpProcessor implements OpProcessor {
             try {
                 handleIterator(context, itty);
             } catch (Exception te) {
+                // todo: throwing here dumps to handeAsync below but no message is returned to the client!!
                 throw new RuntimeException(te);
             }
         }, executor);


[5/8] incubator-tinkerpop git commit: GraphSONReaderReader and GryoRecordReader now directly use the StarGraph.StarVertex as it is simply fed into a VertexWritable. This makes it so we don't create a StarGraph at the XXXReader and then again at the XXXRe

Posted by sp...@apache.org.
GraphSONReaderReader and GryoRecordReader now directly use the StarGraph.StarVertex as it is simply fed into a VertexWritable. This makes it so we don't create a StarGraph at the XXXReader and then again at the XXXRecordReader. 1/2 the amount of objects, memory, and strain on the GC.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/ad3570f8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/ad3570f8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/ad3570f8

Branch: refs/heads/gs-protocol
Commit: ad3570f8f95f60d3e8677ef35d1b8d89ca092239
Parents: 4070af8
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Mon May 4 09:04:57 2015 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon May 4 09:04:57 2015 -0600

----------------------------------------------------------------------
 .../structure/io/graphson/GraphSONRecordReader.java  | 13 ++-----------
 .../hadoop/structure/io/gryo/GryoRecordReader.java   | 15 +--------------
 .../gremlin/hadoop/HadoopGraphProvider.java          | 10 ++++++++--
 3 files changed, 11 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ad3570f8/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/graphson/GraphSONRecordReader.java
----------------------------------------------------------------------
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/graphson/GraphSONRecordReader.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/graphson/GraphSONRecordReader.java
index 497b42f..d0460f3 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/graphson/GraphSONRecordReader.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/graphson/GraphSONRecordReader.java
@@ -26,18 +26,12 @@ import org.apache.hadoop.mapreduce.lib.input.LineRecordReader;
 import org.apache.tinkerpop.gremlin.hadoop.Constants;
 import org.apache.tinkerpop.gremlin.hadoop.structure.io.VertexWritable;
 import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONReader;
 import org.apache.tinkerpop.gremlin.structure.util.Attachable;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
-import org.apache.tinkerpop.gremlin.structure.util.star.StarGraph;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.function.Function;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -64,13 +58,10 @@ public class GraphSONRecordReader extends RecordReader<NullWritable, VertexWrita
         if (!this.lineRecordReader.nextKeyValue())
             return false;
 
-        final StarGraph starGraph = StarGraph.open();
-        final Function<Attachable<Vertex>, Vertex> vertexMaker = attachableVertex -> attachableVertex.attach(Attachable.Method.create(starGraph));
-        final Function<Attachable<Edge>, Edge> edgeMaker = attachableEdge -> attachableEdge.attach(Attachable.Method.create(starGraph));
         try (InputStream in = new ByteArrayInputStream(this.lineRecordReader.getCurrentValue().getBytes())) {
             this.vertexWritable.set(this.hasEdges ?
-                    this.graphsonReader.readVertex(in, vertexMaker, edgeMaker, Direction.BOTH) :
-                    this.graphsonReader.readVertex(in, vertexMaker));
+                    this.graphsonReader.readVertex(in, Attachable::get, Attachable::get, Direction.BOTH) :
+                    this.graphsonReader.readVertex(in, Attachable::get));
             return true;
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ad3570f8/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/gryo/GryoRecordReader.java
----------------------------------------------------------------------
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/gryo/GryoRecordReader.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/gryo/GryoRecordReader.java
index 53b4162..3a12087 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/gryo/GryoRecordReader.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/gryo/GryoRecordReader.java
@@ -27,22 +27,16 @@ import org.apache.hadoop.mapreduce.InputSplit;
 import org.apache.hadoop.mapreduce.RecordReader;
 import org.apache.hadoop.mapreduce.TaskAttemptContext;
 import org.apache.hadoop.mapreduce.lib.input.FileSplit;
-import org.apache.tinkerpop.gremlin.hadoop.Constants;
 import org.apache.tinkerpop.gremlin.hadoop.structure.io.VertexWritable;
-import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoMapper;
 import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoReader;
 import org.apache.tinkerpop.gremlin.structure.io.gryo.VertexTerminator;
 import org.apache.tinkerpop.gremlin.structure.util.Attachable;
-import org.apache.tinkerpop.gremlin.structure.util.star.StarGraph;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.function.Function;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -56,7 +50,6 @@ public class GryoRecordReader extends RecordReader<NullWritable, VertexWritable>
 
     private final GryoReader gryoReader = GryoReader.build().create();
     private final VertexWritable vertexWritable = new VertexWritable();
-    private boolean hasEdges;
 
     private long currentLength = 0;
     private long splitLength;
@@ -76,7 +69,6 @@ public class GryoRecordReader extends RecordReader<NullWritable, VertexWritable>
         // open the file and seek to the start of the split
         this.inputStream = file.getFileSystem(job).open(split.getPath());
         this.splitLength = split.getLength() - (seekToHeader(this.inputStream, start) - start);
-        this.hasEdges = context.getConfiguration().getBoolean(Constants.GREMLIN_HADOOP_GRAPH_INPUT_FORMAT_HAS_EDGES, true);
     }
 
     private static long seekToHeader(final FSDataInputStream inputStream, final long start) throws IOException {
@@ -127,13 +119,8 @@ public class GryoRecordReader extends RecordReader<NullWritable, VertexWritable>
 
             terminatorLocation = ((byte) currentByte) == TERMINATOR[terminatorLocation] ? terminatorLocation + 1 : 0;
             if (terminatorLocation >= TERMINATOR.length) {
-                final StarGraph starGraph = StarGraph.open();
-                final Function<Attachable<Vertex>, Vertex> vertexMaker = attachableVertex -> attachableVertex.attach(Attachable.Method.create(starGraph));
-                final Function<Attachable<Edge>, Edge> edgeMaker = attachableEdge -> attachableEdge.attach(Attachable.Method.create(starGraph));
                 try (InputStream in = new ByteArrayInputStream(output.toByteArray())) {
-                    this.vertexWritable.set(this.hasEdges ?
-                            this.gryoReader.readVertex(in, vertexMaker, edgeMaker, Direction.BOTH) :
-                            this.gryoReader.readVertex(in, vertexMaker));
+                    this.vertexWritable.set(this.gryoReader.readVertex(in, Attachable::get)); // I know how GryoReader works, so I'm cheating here
                     return true;
                 }
             }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ad3570f8/hadoop-gremlin/src/test/java/org/apache/tinkerpop/gremlin/hadoop/HadoopGraphProvider.java
----------------------------------------------------------------------
diff --git a/hadoop-gremlin/src/test/java/org/apache/tinkerpop/gremlin/hadoop/HadoopGraphProvider.java b/hadoop-gremlin/src/test/java/org/apache/tinkerpop/gremlin/hadoop/HadoopGraphProvider.java
index dcca647..f447753 100644
--- a/hadoop-gremlin/src/test/java/org/apache/tinkerpop/gremlin/hadoop/HadoopGraphProvider.java
+++ b/hadoop-gremlin/src/test/java/org/apache/tinkerpop/gremlin/hadoop/HadoopGraphProvider.java
@@ -32,6 +32,7 @@ import org.apache.tinkerpop.gremlin.hadoop.structure.HadoopProperty;
 import org.apache.tinkerpop.gremlin.hadoop.structure.HadoopVertex;
 import org.apache.tinkerpop.gremlin.hadoop.structure.HadoopVertexProperty;
 import org.apache.tinkerpop.gremlin.hadoop.structure.io.graphson.GraphSONInputFormat;
+import org.apache.tinkerpop.gremlin.hadoop.structure.io.gryo.GryoInputFormat;
 import org.apache.tinkerpop.gremlin.hadoop.structure.io.gryo.GryoOutputFormat;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONResourceAccess;
@@ -43,6 +44,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Random;
 import java.util.Set;
 
 /**
@@ -52,6 +54,9 @@ import java.util.Set;
  */
 public class HadoopGraphProvider extends AbstractGraphProvider {
 
+    private static final Random RANDOM = new Random();
+    private boolean graphSONInput = false;
+
     public static Map<String, String> PATHS = new HashMap<>();
     private static final Set<Class> IMPLEMENTATION = new HashSet<Class>() {{
         add(HadoopEdge.class);
@@ -97,9 +102,10 @@ public class HadoopGraphProvider extends AbstractGraphProvider {
 
     @Override
     public Map<String, Object> getBaseConfiguration(final String graphName, final Class<?> test, final String testMethodName, final LoadGraphWith.GraphData loadGraphWith) {
+        this.graphSONInput = RANDOM.nextBoolean();
         return new HashMap<String, Object>() {{
             put(Graph.GRAPH, HadoopGraph.class.getName());
-            put(Constants.GREMLIN_HADOOP_GRAPH_INPUT_FORMAT, GraphSONInputFormat.class.getCanonicalName());
+            put(Constants.GREMLIN_HADOOP_GRAPH_INPUT_FORMAT, graphSONInput ? GraphSONInputFormat.class.getCanonicalName() : GryoInputFormat.class.getCanonicalName());
             put(Constants.GREMLIN_HADOOP_GRAPH_OUTPUT_FORMAT, GryoOutputFormat.class.getCanonicalName());
             put(Constants.GREMLIN_HADOOP_MEMORY_OUTPUT_FORMAT, SequenceFileOutputFormat.class.getCanonicalName());
             put(Constants.GREMLIN_HADOOP_OUTPUT_LOCATION, "hadoop-gremlin/target/test-output");
@@ -141,7 +147,7 @@ public class HadoopGraphProvider extends AbstractGraphProvider {
     }
 
     public void loadGraphDataViaHadoopConfig(final Graph g, final LoadGraphWith.GraphData graphData) {
-        final String type = "json";
+        final String type = this.graphSONInput ? "json" : "kryo";
 
         if (graphData.equals(LoadGraphWith.GraphData.GRATEFUL)) {
             ((HadoopGraph) g).configuration().setInputLocation(PATHS.get("grateful-dead." + type));


[6/8] incubator-tinkerpop git commit: Merge remote-tracking branch 'origin/master'

Posted by sp...@apache.org.
Merge remote-tracking branch 'origin/master'


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/4686df7c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/4686df7c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/4686df7c

Branch: refs/heads/gs-protocol
Commit: 4686df7c158fdc443d8ae76795ae0f96732e2fde
Parents: 408cbee ad3570f
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Mon May 4 11:16:21 2015 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Mon May 4 11:16:21 2015 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   1 +
 .../process/traversal/step/Profileable.java     |  31 ++++++
 .../traversal/step/sideEffect/ProfileStep.java  |   8 +-
 .../traversal/util/ImmutableMetrics.java        |   9 +-
 .../gremlin/process/traversal/util/Metrics.java |   4 +-
 .../util/StandardTraversalMetrics.java          |  37 +++++--
 .../gremlin/structure/util/star/StarGraph.java  |   2 +
 .../traversal/step/sideEffect/ProfileTest.java  | 101 ++++++++++++++-----
 .../hadoop/structure/io/VertexWritable.java     |  10 +-
 .../io/graphson/GraphSONRecordReader.java       |  13 +--
 .../structure/io/gryo/GryoRecordReader.java     |  15 +--
 .../gremlin/hadoop/HadoopGraphProvider.java     |  10 +-
 12 files changed, 167 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4686df7c/CHANGELOG.asciidoc
----------------------------------------------------------------------


[3/8] incubator-tinkerpop git commit: fixed a bug in ProfileStep.MapReduce that occur when there are numerous KeyValues to the same key -- e.g. Hadoop with numerous reducers.

Posted by sp...@apache.org.
fixed a bug in ProfileStep.MapReduce that occur when there are numerous KeyValues to the same key -- e.g. Hadoop with numerous reducers.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/3a3f4d3a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/3a3f4d3a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/3a3f4d3a

Branch: refs/heads/gs-protocol
Commit: 3a3f4d3af963f046902e15dc57617a3b95355414
Parents: 1f2a6ad
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Mon May 4 07:58:33 2015 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon May 4 07:58:33 2015 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   1 +
 .../process/traversal/step/Profileable.java     |  31 ++++++
 .../traversal/step/sideEffect/ProfileStep.java  |   8 +-
 .../traversal/util/ImmutableMetrics.java        |   9 +-
 .../gremlin/process/traversal/util/Metrics.java |   4 +-
 .../util/StandardTraversalMetrics.java          |  37 +++++--
 .../traversal/step/sideEffect/ProfileTest.java  | 101 ++++++++++++++-----
 7 files changed, 148 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/3a3f4d3a/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 7af5087..80ccb74 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -69,6 +69,7 @@ TinkerPop 3.0.0.M9 (NOT OFFICIALLY RELEASED YET)
 * `Attachable` now has a set of static exception messages in an `Exceptions` inner class.
 * Added `StarGraph` which is a heap efficient representation of a vertex and its incident edges (useful for `GraphComputer` implementations).
 * `TraverserSet` uses a `FastNoSuchElementException` on `remove()` for increased performance.
+* Add `Profileable` interface to enable vendors to receive a `Step's MutableMetrics`.
 
 TinkerPop 3.0.0.M8 (Release Date: April 6, 2015)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/3a3f4d3a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Profileable.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Profileable.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Profileable.java
new file mode 100644
index 0000000..eb7a2f1
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Profileable.java
@@ -0,0 +1,31 @@
+/*
+ * 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.tinkerpop.gremlin.process.traversal.step;
+
+import org.apache.tinkerpop.gremlin.process.traversal.util.MutableMetrics;
+
+/**
+ * A Step can implement this interface in order to receive a reference to the MutableMetrics object for the Step. The
+ * MutableMetrics is initialized when the ProfileStrategy executes.
+ *
+ * @author Bob Briody (http://bobbriody.com)
+ */
+public interface Profileable {
+    public void setMetrics(final MutableMetrics metrics);
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/3a3f4d3a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ProfileStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ProfileStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ProfileStep.java
index 29cbfdf..3b94bbf 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ProfileStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ProfileStep.java
@@ -26,6 +26,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.MapReducer;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Profileable;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
@@ -34,6 +35,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.util.MutableMetrics;
 import org.apache.tinkerpop.gremlin.process.traversal.util.StandardTraversalMetrics;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 
 import java.util.Iterator;
 import java.util.List;
@@ -145,6 +147,10 @@ public final class ProfileStep<S> extends AbstractStep<S, S> implements MapReduc
                 prevMetrics = (DependantMutableMetrics) metrics;
             }
 
+            if (step instanceof Profileable) {
+                ((Profileable) step).setMetrics(metrics);
+            }
+
             // Initialize counters (necessary because some steps might end up being 0)
             metrics.incrementCount(TraversalMetrics.ELEMENT_COUNT_ID, 0);
             metrics.incrementCount(TraversalMetrics.TRAVERSER_COUNT_ID, 0);
@@ -209,7 +215,7 @@ public final class ProfileStep<S> extends AbstractStep<S, S> implements MapReduc
 
         @Override
         public StandardTraversalMetrics generateFinalResult(final Iterator<KeyValue<NullObject, StandardTraversalMetrics>> keyValues) {
-            return keyValues.next().getValue();
+            return StandardTraversalMetrics.merge(IteratorUtils.map(keyValues, KeyValue::getValue));
         }
 
         public static ProfileMapReduce instance() {

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/3a3f4d3a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ImmutableMetrics.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ImmutableMetrics.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ImmutableMetrics.java
index 471fc5f..8fae2b0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ImmutableMetrics.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ImmutableMetrics.java
@@ -44,12 +44,15 @@ public class ImmutableMetrics implements Metrics, Serializable {
     }
 
     @Override
-    public long getDuration(TimeUnit unit) {
+    public long getDuration(final TimeUnit unit) {
         return unit.convert(this.durationNs, SOURCE_UNIT);
     }
 
     @Override
-    public long getCount(String key) {
+    public Long getCount(final String key) {
+        if (!counts.containsKey(key)) {
+            return null;
+        }
         return counts.get(key).get();
     }
 
@@ -77,7 +80,7 @@ public class ImmutableMetrics implements Metrics, Serializable {
     }
 
     @Override
-    public ImmutableMetrics getNested(String metricsId) {
+    public ImmutableMetrics getNested(final String metricsId) {
         return nested.get(metricsId);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/3a3f4d3a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/Metrics.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/Metrics.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/Metrics.java
index 4492ee7..7492005 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/Metrics.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/Metrics.java
@@ -37,11 +37,11 @@ public interface Metrics {
     public long getDuration(TimeUnit units);
 
     /**
-     * Get the count for the corresponding countKey.
+     * Get the count for the corresponding countKey. Returns null if countKey does not exist.
      *
      * @param countKey key for counter to get.
      */
-    public long getCount(String countKey);
+    public Long getCount(String countKey);
 
     /**
      * Get the map of all counters. This method copies the internal map.

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/3a3f4d3a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/StandardTraversalMetrics.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/StandardTraversalMetrics.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/StandardTraversalMetrics.java
index 8ea8d6d..6aabea4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/StandardTraversalMetrics.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/StandardTraversalMetrics.java
@@ -47,9 +47,6 @@ public final class StandardTraversalMetrics implements TraversalMetrics, Seriali
 
     public void start(final String metricsId) {
         dirty = true;
-        if (allMetrics.get(metricsId) == null) {
-            System.out.println();
-        }
         allMetrics.get(metricsId).start();
     }
 
@@ -116,21 +113,41 @@ public final class StandardTraversalMetrics implements TraversalMetrics, Seriali
         // Append each StepMetric's row. indexToLabelMap values are ordered by index.
         for (Metrics m : metrics) {
             String rowName = m.getName();
+
+            // Handle indentation
             for (int ii = 0; ii < indent; ii++) {
                 rowName = "  " + rowName;
             }
+            // Abbreviate if necessary
             rowName = StringUtils.abbreviate(rowName, 50);
-            final long itemCount = m.getCount(ELEMENT_COUNT_ID);
-            final long traverserCount = m.getCount(TRAVERSER_COUNT_ID);
 
+            // Grab the values
+            final Long itemCount = m.getCount(ELEMENT_COUNT_ID);
+            final Long traverserCount = m.getCount(TRAVERSER_COUNT_ID);
             Double percentDur = (Double) m.getAnnotation(PERCENT_DURATION_KEY);
-            if (percentDur != null) {
-                sb.append(String.format("%n%-50s %21d %11d %15.3f %8.2f",
-                        rowName, itemCount, traverserCount, m.getDuration(TimeUnit.MICROSECONDS) / 1000.0, percentDur));
+
+            // Build the row string
+
+            sb.append(String.format("%n%-50s", rowName));
+
+            if (itemCount != null) {
+                sb.append(String.format(" %21d", itemCount));
+            } else {
+                sb.append(String.format(" %21s", ""));
+            }
+
+            if (traverserCount != null) {
+                sb.append(String.format(" %11d", traverserCount));
             } else {
-                sb.append(String.format("%n%-50s %21d %11d %15.3f",
-                        rowName, itemCount, traverserCount, m.getDuration(TimeUnit.MICROSECONDS) / 1000.0));
+                sb.append(String.format(" %11s", ""));
+            }
+
+            sb.append(String.format(" %15.3f", m.getDuration(TimeUnit.MICROSECONDS) / 1000.0));
+
+            if (percentDur!=null){
+                sb.append(String.format(" %8.2f", percentDur ));
             }
+
             appendMetrics(m.getNested(), sb, indent + 1);
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/3a3f4d3a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ProfileTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ProfileTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ProfileTest.java
index 01abfd5..fc85b0c 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ProfileTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ProfileTest.java
@@ -24,12 +24,18 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Profileable;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.FlatMapStep;
 import org.apache.tinkerpop.gremlin.process.traversal.util.Metrics;
+import org.apache.tinkerpop.gremlin.process.traversal.util.MutableMetrics;
 import org.apache.tinkerpop.gremlin.process.traversal.util.StandardTraversalMetrics;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.junit.Test;
 
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 
@@ -63,20 +69,20 @@ public abstract class ProfileTest extends AbstractGremlinProcessTest {
         traversalMetrics.toString(); // ensure no exceptions are thrown
 
         Metrics metrics = traversalMetrics.getMetrics(0);
-        assertEquals(6, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID));
-        assertEquals(6, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID));
+        assertEquals(6, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
+        assertEquals(6, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
         assertTrue("Percent duration should be positive.", (Double) metrics.getAnnotation(TraversalMetrics.PERCENT_DURATION_KEY) > 0);
         assertTrue("Times should be positive.", metrics.getDuration(TimeUnit.MICROSECONDS) > 0);
 
         metrics = traversalMetrics.getMetrics(1);
-        assertEquals(6, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID));
-        assertNotEquals(0, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID));
+        assertEquals(6, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
+        assertNotEquals(0, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
         assertTrue("Percent duration should be positive.", (Double) metrics.getAnnotation(TraversalMetrics.PERCENT_DURATION_KEY) > 0);
         assertTrue("Times should be positive.", metrics.getDuration(TimeUnit.MICROSECONDS) > 0);
 
         metrics = traversalMetrics.getMetrics(2);
-        assertEquals(2, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID));
-        assertNotEquals(0, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID));
+        assertEquals(2, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
+        assertNotEquals(0, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
         assertTrue("Percent duration should be positive.", (Double) metrics.getAnnotation(TraversalMetrics.PERCENT_DURATION_KEY) > 0);
         assertTrue("Times should be positive.", metrics.getDuration(TimeUnit.MICROSECONDS) > 0);
 
@@ -99,20 +105,20 @@ public abstract class ProfileTest extends AbstractGremlinProcessTest {
         traversalMetrics.toString(); // ensure no exceptions are thrown
 
         Metrics metrics = traversalMetrics.getMetrics(0);
-        assertEquals(808, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID));
-        assertEquals(808, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID));
+        assertEquals(808, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
+        assertEquals(808, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
         assertTrue("Percent duration should be positive.", (Double) metrics.getAnnotation(TraversalMetrics.PERCENT_DURATION_KEY) > 0);
         assertTrue("Times should be positive.", metrics.getDuration(TimeUnit.MICROSECONDS) > 0);
 
         metrics = traversalMetrics.getMetrics(1);
-        assertEquals(8049, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID));
-        assertNotEquals(0, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID));
+        assertEquals(8049, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
+        assertNotEquals(0, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
         assertTrue("Percent duration should be positive.", (Double) metrics.getAnnotation(TraversalMetrics.PERCENT_DURATION_KEY) > 0);
         assertTrue("Times should be positive.", metrics.getDuration(TimeUnit.MICROSECONDS) > 0);
 
         metrics = traversalMetrics.getMetrics(2);
-        assertEquals(327370, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID));
-        assertNotEquals(0, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID));
+        assertEquals(327370, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
+        assertNotEquals(0, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
         assertTrue("Percent duration should be positive.", (Double) metrics.getAnnotation(TraversalMetrics.PERCENT_DURATION_KEY) > 0);
         assertTrue("Times should be positive.", metrics.getDuration(TimeUnit.MICROSECONDS) > 0);
 
@@ -172,29 +178,29 @@ public abstract class ProfileTest extends AbstractGremlinProcessTest {
         traversalMetrics.toString(); // ensure no exceptions are thrown
 
         Metrics metrics = traversalMetrics.getMetrics(0);
-        assertEquals(6, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID));
-        assertEquals(6, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID));
+        assertEquals(6, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
+        assertEquals(6, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
         assertTrue("Percent duration should be positive.", (Double) metrics.getAnnotation(TraversalMetrics.PERCENT_DURATION_KEY) > 0);
         assertTrue("Times should be positive.", metrics.getDuration(TimeUnit.MICROSECONDS) > 0);
 
         metrics = traversalMetrics.getMetrics(1);
-        assertEquals(72, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID));
-        assertNotEquals(0, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID));
-        assertTrue("Count should be greater than traversers.", metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID) > metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID));
+        assertEquals(72, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
+        assertNotEquals(0, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
+        assertTrue("Count should be greater than traversers.", metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID) > metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
         assertTrue("Percent duration should be positive.", (Double) metrics.getAnnotation(TraversalMetrics.PERCENT_DURATION_KEY) > 0);
         assertTrue("Times should be positive.", metrics.getDuration(TimeUnit.MICROSECONDS) > 0);
 
         // Test the nested global metrics of the repeat step
         final Metrics vertexStepNestedInRepeat = (Metrics) metrics.getNested().toArray()[0];
-        assertEquals(114, vertexStepNestedInRepeat.getCount(TraversalMetrics.ELEMENT_COUNT_ID));
-        assertNotEquals(0, vertexStepNestedInRepeat.getCount(TraversalMetrics.TRAVERSER_COUNT_ID));
-        assertTrue("Count should be greater than traversers.", vertexStepNestedInRepeat.getCount(TraversalMetrics.ELEMENT_COUNT_ID) > vertexStepNestedInRepeat.getCount(TraversalMetrics.TRAVERSER_COUNT_ID));
+        assertEquals(114, vertexStepNestedInRepeat.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
+        assertNotEquals(0, vertexStepNestedInRepeat.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
+        assertTrue("Count should be greater than traversers.", vertexStepNestedInRepeat.getCount(TraversalMetrics.ELEMENT_COUNT_ID) > vertexStepNestedInRepeat.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
         assertTrue("Times should be positive.", vertexStepNestedInRepeat.getDuration(TimeUnit.MICROSECONDS) > 0);
 
         final Metrics repeatEndStepNestedInRepeat = (Metrics) metrics.getNested().toArray()[1];
-        assertEquals(72, repeatEndStepNestedInRepeat.getCount(TraversalMetrics.ELEMENT_COUNT_ID));
-        assertNotEquals(0, repeatEndStepNestedInRepeat.getCount(TraversalMetrics.TRAVERSER_COUNT_ID));
-        assertTrue("Count should be greater than traversers.", repeatEndStepNestedInRepeat.getCount(TraversalMetrics.ELEMENT_COUNT_ID) > repeatEndStepNestedInRepeat.getCount(TraversalMetrics.TRAVERSER_COUNT_ID));
+        assertEquals(72, repeatEndStepNestedInRepeat.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
+        assertNotEquals(0, repeatEndStepNestedInRepeat.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
+        assertTrue("Count should be greater than traversers.", repeatEndStepNestedInRepeat.getCount(TraversalMetrics.ELEMENT_COUNT_ID) > repeatEndStepNestedInRepeat.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
         assertTrue("Times should be positive.", repeatEndStepNestedInRepeat.getDuration(TimeUnit.MICROSECONDS) > 0);
 
 
@@ -219,16 +225,57 @@ public abstract class ProfileTest extends AbstractGremlinProcessTest {
         assertEquals("There should be 3 top-level metrics.", 3, traversalMetrics.getMetrics().size());
 
         Metrics metrics = traversalMetrics.getMetrics(0);
-        assertEquals(6, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID));
-        assertEquals(6, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID));
+        assertEquals(6, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
+        assertEquals(6, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
 
         metrics = traversalMetrics.getMetrics(1);
-        assertEquals(1, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID));
-        assertEquals(1, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID));
+        assertEquals(1, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
+        assertEquals(1, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
 
         assertEquals("Metrics 1 should have 3 nested metrics.", 3, metrics.getNested().size());
     }
 
+    /**
+     * ProfileStrategy callback test. Goal: ensure that a step that implements Profileable gets a callback to setMetrics
+     */
+
+    // Setup a "mock" step to test the strategy
+    static public class MockStep extends FlatMapStep<Vertex, Vertex> implements Profileable {
+        public static boolean callbackCalled = false;
+
+        public MockStep(final Traversal.Admin traversal) {
+            super(traversal);
+        }
+
+        @Override
+        protected Iterator<Vertex> flatMap(final Traverser.Admin<Vertex> traverser) {
+            List<Vertex> l = new ArrayList<>();
+            l.add(traverser.get());
+            return l.iterator();
+        }
+
+        @Override
+        public void setMetrics(final MutableMetrics parentMetrics) {
+            if (parentMetrics != null) {
+                callbackCalled = true;
+            }
+        }
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    @IgnoreEngine(TraversalEngine.Type.COMPUTER)
+    public void testProfileStrategyCallback() {
+        final Traversal<Vertex, StandardTraversalMetrics> t = get_g_V_out_out_profile();
+        MockStep mockStep = new MockStep(t.asAdmin());
+        t.asAdmin().addStep(3, mockStep);
+        t.iterate();
+        assertTrue(mockStep.callbackCalled);
+    }
+
+    /**
+     * Traversals
+     */
     @UseEngine(TraversalEngine.Type.STANDARD)
     @UseEngine(TraversalEngine.Type.COMPUTER)
     public static class Traversals extends ProfileTest {


[8/8] incubator-tinkerpop git commit: Merge remote-tracking branch 'origin/master' into gs-protocol

Posted by sp...@apache.org.
Merge remote-tracking branch 'origin/master' into gs-protocol


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/5f4f162b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/5f4f162b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/5f4f162b

Branch: refs/heads/gs-protocol
Commit: 5f4f162b899ea69b35234d48cda79629b969360b
Parents: 622821b f0cddfa
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Mon May 4 11:43:58 2015 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Mon May 4 11:43:58 2015 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   2 +
 .../process/traversal/step/Profileable.java     |  31 ++++++
 .../traversal/step/sideEffect/ProfileStep.java  |   8 +-
 .../strategy/decoration/ElementIdStrategy.java  |  18 ++++
 .../traversal/util/ImmutableMetrics.java        |   9 +-
 .../gremlin/process/traversal/util/Metrics.java |   4 +-
 .../util/StandardTraversalMetrics.java          |  37 +++++--
 .../gremlin/structure/util/star/StarGraph.java  |   2 +
 .../conf/gremlin-server-modern-readonly.yaml    |  44 ++++++++
 .../scripts/generate-modern-readonly.groovy     |  24 +++++
 .../server/op/AbstractEvalOpProcessor.java      |   1 +
 .../traversal/step/sideEffect/ProfileTest.java  | 101 ++++++++++++++-----
 .../hadoop/structure/io/VertexWritable.java     |  10 +-
 .../io/graphson/GraphSONRecordReader.java       |  13 +--
 .../structure/io/gryo/GryoRecordReader.java     |  15 +--
 .../gremlin/hadoop/HadoopGraphProvider.java     |  10 +-
 16 files changed, 255 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/5f4f162b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
----------------------------------------------------------------------


[2/8] incubator-tinkerpop git commit: Update changelog.

Posted by sp...@apache.org.
Update changelog.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/408cbee8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/408cbee8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/408cbee8

Branch: refs/heads/gs-protocol
Commit: 408cbee890e845325acc7c3b51ff9dc0ec855390
Parents: 1f2a6ad
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Mon May 4 09:54:20 2015 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Mon May 4 09:54:20 2015 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/408cbee8/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 7af5087..b1b554f 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -27,6 +27,7 @@ TinkerPop 3.0.0.M9 (NOT OFFICIALLY RELEASED YET)
 
 * Added `PersistResultGraphAware` interface which is used by `OutputFormats` to specify persistence possibilities for a Hadoop `GraphComputer`.
 * `ElementIdStrategy` now allows the identifier property to be set directly (and not only by specifying `T.id`).
+* Added sample configuration files for registring a `TraversalStrategy` in Gremlin Server.
 * `Path` and `Step` labels are ordered by the order in which the respective `addLabel()` calls were made.
 * A `Step` now has a `Set<String>` of labels. Updated `as()` to take a var args of labels.
 * Dropped `BatchGraph` from the code base - it will be replaced by bulk loader functionality over OLAP.


[7/8] incubator-tinkerpop git commit: Update javadoc on ElementIdStrategy.

Posted by sp...@apache.org.
Update javadoc on ElementIdStrategy.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/f0cddfa7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/f0cddfa7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/f0cddfa7

Branch: refs/heads/gs-protocol
Commit: f0cddfa7b0606fff9de47b6ce0dfa5e15072327c
Parents: 4686df7
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Mon May 4 11:31:57 2015 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Mon May 4 11:31:57 2015 -0400

----------------------------------------------------------------------
 .../strategy/decoration/ElementIdStrategy.java    | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/f0cddfa7/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java
index 9128b46..f7b0d5e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java
@@ -43,7 +43,18 @@ import java.util.UUID;
 import java.util.function.Supplier;
 
 /**
+ * Provides a degree of control over element identifier assignment as some graphs don't provide that feature. This
+ * strategy provides for identifier assignment by enabling users to utilize vertex and edge indices under the hood,
+ * thus simulating that capability.
+ * <p/>
+ * By default, when an identifier is not supplied by the user, newly generated identifiers are {@link UUID} objects.
+ * This behavior can be overriden by setting the {@link Builder#idMaker(Supplier)}.
+ * <p/>
+ * Unless otherwise specified the identifier is stored in the {@code __id} property.  This can be changed by setting
+ * the {@link Builder#idPropertyKey(String}
+ *
  * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public final class ElementIdStrategy extends AbstractTraversalStrategy {
 
@@ -147,11 +158,18 @@ public final class ElementIdStrategy extends AbstractTraversalStrategy {
 
         private Builder() {}
 
+        /**
+         * Creates a new unique identifier for the next created {@link Element}.
+         */
         public Builder idMaker(final Supplier<Object> idMaker) {
             this.idMaker = idMaker;
             return this;
         }
 
+        /**
+         * This key within which to hold the user-specified identifier.  This field should be indexed by the
+         * underlying graph.
+         */
         public Builder idPropertyKey(final String idPropertyKey) {
             this.idPropertyKey = idPropertyKey;
             return this;


[4/8] incubator-tinkerpop git commit: if the vertex is already a StarVertex, then StarGraph.of(vertex) simply returns vertex.graph(). This halfs the object creation and memory footprint of VertexWritable heading to a GraphWriter. Also, VertexWritable aut

Posted by sp...@apache.org.
if the vertex is already a StarVertex, then StarGraph.of(vertex) simply returns vertex.graph(). This halfs the object creation and memory footprint of VertexWritable heading to a GraphWriter. Also, VertexWritable automatically converts to StarVertex on construction and set() so that its always a StarVertex being dealt with (no confusions).


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/4070af81
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/4070af81
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/4070af81

Branch: refs/heads/gs-protocol
Commit: 4070af81829069d78a4476db4ec0d23f96056d02
Parents: 3a3f4d3
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Mon May 4 08:37:36 2015 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon May 4 08:37:36 2015 -0600

----------------------------------------------------------------------
 .../tinkerpop/gremlin/structure/util/star/StarGraph.java  |  2 ++
 .../gremlin/hadoop/structure/io/VertexWritable.java       | 10 ++++++----
 2 files changed, 8 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4070af81/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraph.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraph.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraph.java
index 04e432d..6a98db1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraph.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraph.java
@@ -172,6 +172,8 @@ public final class StarGraph implements Graph, Serializable {
     }
 
     public static StarGraph of(final Vertex vertex) {
+        if (vertex instanceof StarVertex) return (StarGraph) vertex.graph();
+        // else convert to a star graph
         final StarGraph starGraph = new StarGraph();
         final StarVertex starVertex = (StarVertex) starGraph.addVertex(T.id, vertex.id(), T.label, vertex.label());
         vertex.properties().forEachRemaining(vp -> {

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4070af81/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/VertexWritable.java
----------------------------------------------------------------------
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/VertexWritable.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/VertexWritable.java
index f13f9e8..9cd0019 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/VertexWritable.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/VertexWritable.java
@@ -38,21 +38,23 @@ import java.io.Serializable;
  */
 public final class VertexWritable implements Writable, Serializable {
 
-    private Vertex vertex;
+    private StarGraph.StarVertex vertex;
 
     public VertexWritable() {
 
     }
 
     public VertexWritable(final Vertex vertex) {
-        this.vertex = vertex;
+        this.set(vertex);
     }
 
     public void set(final Vertex vertex) {
-        this.vertex = vertex;
+        this.vertex = vertex instanceof StarGraph.StarVertex ?
+                (StarGraph.StarVertex) vertex :
+                StarGraph.of(vertex).getStarVertex();
     }
 
-    public Vertex get() {
+    public StarGraph.StarVertex get() {
         return this.vertex;
     }