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 2017/06/28 12:32:12 UTC

[01/24] tinkerpop git commit: TINKERPOP-1445 Add ellipses for long property values [Forced Update!]

Repository: tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1686 23360e007 -> df914d02f (forced update)


TINKERPOP-1445 Add ellipses for long property values


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

Branch: refs/heads/TINKERPOP-1686
Commit: 47afd7a664ecb7c737341cac7c005e403c0b569e
Parents: b026ca3
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Sun Jun 18 14:25:15 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Sun Jun 18 14:25:15 2017 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 .../gremlin/structure/util/StringFactory.java   |  9 +++----
 .../gremlin/structure/PropertyTest.java         | 28 +++++++++++++++++++-
 3 files changed, 31 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/47afd7a6/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index ff6ff24..eb8ad8a 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.3.0 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* Included an ellipse on long property names that are truncated.
 * Renamed `RangeByIsCountStrategy` to `CountStrategy`.
 * Added more specific typing to various `__` traversal steps. E.g. `<A,Vertex>out()` is `<Vertex,Vertex>out()`.
 * Updated Docker build scripts to include Python dependencies (NOTE: users should remove any previously generated TinkerPop Docker images).

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/47afd7a6/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/StringFactory.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/StringFactory.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/StringFactory.java
index bcead2d..0a1cdb6 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/StringFactory.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/StringFactory.java
@@ -18,6 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.structure.util;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.tinkerpop.gremlin.process.computer.Computer;
 import org.apache.tinkerpop.gremlin.process.computer.ComputerResult;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
@@ -68,12 +69,8 @@ public final class StringFactory {
     private static final String L_BRACKET = "[";
     private static final String R_BRACKET = "]";
     private static final String COMMA_SPACE = ", ";
-    private static final String COLON = ":";
-    private static final String EMPTY_MAP = "{}";
-    private static final String DOTS = "...";
     private static final String DASH = "-";
     private static final String ARROW = "->";
-    private static final String STAR = "*";
     private static final String EMPTY_PROPERTY = "p[empty]";
     private static final String EMPTY_VERTEX_PROPERTY = "vp[empty]";
     private static final String LINE_SEPARATOR = System.getProperty("line.separator");
@@ -106,11 +103,11 @@ public final class StringFactory {
         if (property instanceof VertexProperty) {
             if (!property.isPresent()) return EMPTY_VERTEX_PROPERTY;
             final String valueString = String.valueOf(property.value());
-            return VP + L_BRACKET + property.key() + ARROW + valueString.substring(0, Math.min(valueString.length(), 20)) + R_BRACKET;
+            return VP + L_BRACKET + property.key() + ARROW + StringUtils.abbreviate(valueString, 20) + R_BRACKET;
         } else {
             if (!property.isPresent()) return EMPTY_PROPERTY;
             final String valueString = String.valueOf(property.value());
-            return P + L_BRACKET + property.key() + ARROW + valueString.substring(0, Math.min(valueString.length(), 20)) + R_BRACKET;
+            return P + L_BRACKET + property.key() + ARROW + StringUtils.abbreviate(valueString, 20) + R_BRACKET;
         }
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/47afd7a6/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/PropertyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/PropertyTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/PropertyTest.java
index 43439c8..cb47043 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/PropertyTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/PropertyTest.java
@@ -59,7 +59,7 @@ public class PropertyTest {
     public static class BasicPropertyTest extends AbstractGremlinTest {
         @Test
         @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
-        public void shouldHaveStandardStringRepresentation() {
+        public void shouldHaveStandardStringRepresentationForVertexProperty() {
             final Vertex v = graph.addVertex("name", "marko");
             final Property p = v.property("name");
             assertEquals(StringFactory.propertyString(p), p.toString());
@@ -67,6 +67,32 @@ public class PropertyTest {
 
         @Test
         @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
+        public void shouldHaveTruncatedStringRepresentationForVertexProperty() {
+            final Vertex v = graph.addVertex("name", "maria de la santa cruz rosalina agnelia rodriguez cuellar rene");
+            final Property p = v.property("name");
+            assertEquals(StringFactory.propertyString(p), p.toString());
+        }
+
+        @Test
+        @FeatureRequirementSet(FeatureRequirementSet.Package.SIMPLE)
+        public void shouldHaveStandardStringRepresentationForEdgeProperty() {
+            final Vertex v = graph.addVertex();
+            final Edge e = v.addEdge("self", v, "short", "s");
+            final Property p = e.property("short");
+            assertEquals(StringFactory.propertyString(p), p.toString());
+        }
+
+        @Test
+        @FeatureRequirementSet(FeatureRequirementSet.Package.SIMPLE)
+        public void shouldHaveTruncatedStringRepresentationForEdgeProperty() {
+            final Vertex v = graph.addVertex();
+            final Edge e = v.addEdge("self", v, "long", "s");
+            final Property p = e.property("long", "this is a really long property to truncate");
+            assertEquals(StringFactory.propertyString(p), p.toString());
+        }
+
+        @Test
+        @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
         public void shouldReturnEmptyPropertyIfKeyNonExistent() {
             final Vertex v = graph.addVertex("name", "marko");
             tryCommit(graph, (graph) -> {


[08/24] tinkerpop git commit: Merge branch 'tp32'

Posted by sp...@apache.org.
Merge branch 'tp32'


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

Branch: refs/heads/TINKERPOP-1686
Commit: 1ba875bd7e71617fde993d08db02649575ed020a
Parents: 7d2b46b 1518cc4
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Mon Jun 26 14:31:02 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Mon Jun 26 14:31:02 2017 -0400

----------------------------------------------------------------------
 docs/src/dev/provider/index.asciidoc | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/1ba875bd/docs/src/dev/provider/index.asciidoc
----------------------------------------------------------------------


[20/24] tinkerpop git commit: TINKERPOP-1686 Minor tweaks to finalize MutableMetrics

Posted by sp...@apache.org.
TINKERPOP-1686 Minor tweaks to finalize MutableMetrics

MutableMetrics attached to DefaultTraversalMetrics should not keep getting stuff written to them after the DefaultTraversalMetrics have been finalized.


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

Branch: refs/heads/TINKERPOP-1686
Commit: 4088440507fa4f3682b0058f76419a7bb03e7cc8
Parents: 909c1f6
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Jun 7 13:42:56 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Jun 28 08:31:46 2017 -0400

----------------------------------------------------------------------
 .../traversal/util/DefaultTraversalMetrics.java |  7 +++-
 .../process/traversal/util/MutableMetrics.java  | 41 ++++++++++++++++----
 2 files changed, 38 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/40884405/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java
index 0f19ecc..ed2aa2d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java
@@ -98,6 +98,9 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
         return this.computedMetrics.values();
     }
 
+    /**
+     * The metrics have been computed and can no longer be modified.
+     */
     public boolean isFinalized() {
         return finalized;
     }
@@ -126,7 +129,7 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
      * metrics such that their values can no longer be modified.
      */
     public synchronized void setMetrics(final Traversal.Admin traversal, final boolean onGraphComputer) {
-        if (finalized) throw new IllegalStateException("Metrics have been finalized");
+        if (finalized) throw new IllegalStateException("Metrics have been finalized and cannot be modified");
         finalized = true;
         addTopLevelMetrics(traversal, onGraphComputer);
         handleNestedTraversals(traversal, null, onGraphComputer);
@@ -275,7 +278,7 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
             if (null != metrics) { // this happens when a particular branch never received a .next() call (the metrics were never initialized)
                 if (!onGraphComputer) {
                     // subtract upstream duration.
-                    long durBeforeAdjustment = metrics.getDuration(TimeUnit.NANOSECONDS);
+                    final long durBeforeAdjustment = metrics.getDuration(TimeUnit.NANOSECONDS);
                     // adjust duration
                     metrics.setDuration(metrics.getDuration(TimeUnit.NANOSECONDS) - prevDur, TimeUnit.NANOSECONDS);
                     prevDur = durBeforeAdjustment;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/40884405/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/MutableMetrics.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/MutableMetrics.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/MutableMetrics.java
index 47decf1..34fa370 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/MutableMetrics.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/MutableMetrics.java
@@ -18,6 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.util;
 
+import org.apache.tinkerpop.gremlin.process.traversal.step.Profiling;
+
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
@@ -33,6 +35,11 @@ public class MutableMetrics extends ImmutableMetrics implements Cloneable {
 
     private long tempTime = -1L;
 
+    /**
+     * Determines if metrics have been finalized, meaning that no more may be collected.
+     */
+    private volatile boolean finalized = false;
+
     protected MutableMetrics() {
         // necessary for gryo serialization
     }
@@ -55,10 +62,12 @@ public class MutableMetrics extends ImmutableMetrics implements Cloneable {
     }
 
     public void addNested(final MutableMetrics metrics) {
+        if (finalized) throw new IllegalStateException("Metrics have been finalized and cannot be modified");
         this.nested.put(metrics.getId(), metrics);
     }
 
     public void start() {
+        if (finalized) throw new IllegalStateException("Metrics have been finalized and cannot be modified");
         if (-1 != this.tempTime) {
             throw new IllegalStateException("Internal Error: Concurrent Metrics start. Stop timer before starting timer.");
         }
@@ -66,6 +75,7 @@ public class MutableMetrics extends ImmutableMetrics implements Cloneable {
     }
 
     public void stop() {
+        if (finalized) throw new IllegalStateException("Metrics have been finalized and cannot be modified");
         if (-1 == this.tempTime)
             throw new IllegalStateException("Internal Error: Metrics has not been started. Start timer before stopping timer");
         this.durationNs = this.durationNs + (System.nanoTime() - this.tempTime);
@@ -73,6 +83,7 @@ public class MutableMetrics extends ImmutableMetrics implements Cloneable {
     }
 
     public void incrementCount(final String key, final long incr) {
+        if (finalized) throw new IllegalStateException("Metrics have been finalized and cannot be modified");
         AtomicLong count = this.counts.get(key);
         if (count == null) {
             count = new AtomicLong();
@@ -82,14 +93,17 @@ public class MutableMetrics extends ImmutableMetrics implements Cloneable {
     }
 
     public void setDuration(final long dur, final TimeUnit unit) {
+        if (finalized) throw new IllegalStateException("Metrics have been finalized and cannot be modified");
         this.durationNs = TimeUnit.NANOSECONDS.convert(dur, unit);
     }
 
     public void setCount(final String key, final long val) {
+        if (finalized) throw new IllegalStateException("Metrics have been finalized and cannot be modified");
         this.counts.put(key, new AtomicLong(val));
     }
 
     public void aggregate(final MutableMetrics other) {
+        if (finalized) throw new IllegalStateException("Metrics have been finalized and cannot be modified");
         this.durationNs += other.durationNs;
         for (Map.Entry<String, AtomicLong> otherCount : other.counts.entrySet()) {
             AtomicLong thisCount = this.counts.get(otherCount.getKey());
@@ -114,12 +128,11 @@ public class MutableMetrics extends ImmutableMetrics implements Cloneable {
                     }
                 } else {
                     // Numbers are summed
-                    Number existingNum = (Number) existingVal;
-                    Number otherNum = (Number) p.getValue();
+                    final Number existingNum = (Number) existingVal;
+                    final Number otherNum = (Number) p.getValue();
                     Number newVal;
                     if (existingNum instanceof Double || existingNum instanceof Float) {
-                        newVal =
-                                existingNum.doubleValue() + otherNum.doubleValue();
+                        newVal = existingNum.doubleValue() + otherNum.doubleValue();
                     } else {
                         newVal = existingNum.longValue() + otherNum.longValue();
                     }
@@ -145,11 +158,9 @@ public class MutableMetrics extends ImmutableMetrics implements Cloneable {
     /**
      * Set an annotation value. Support exists for Strings and Numbers only. During a merge, Strings are concatenated
      * into a "," (comma) separated list of distinct values (duplicates are ignored), and Numbers are summed.
-     *
-     * @param key
-     * @param value
      */
     public void setAnnotation(final String key, final Object value) {
+        if (finalized) throw new IllegalStateException("Metrics have been finalized and cannot be modified");
         if (!(value instanceof String) && !(value instanceof Number)) {
             throw new IllegalArgumentException("Metrics annotations only support String and Number values.");
         }
@@ -161,7 +172,21 @@ public class MutableMetrics extends ImmutableMetrics implements Cloneable {
         return (MutableMetrics) nested.get(metricsId);
     }
 
-    public ImmutableMetrics getImmutableClone() {
+    /**
+     * Once these metrics are used in computing the final metrics to report through {@link TraversalMetrics} they
+     * should no longer be modified and are thus finalized.
+     */
+    public boolean isFinalized() {
+        return finalized;
+    }
+
+    /**
+     * Gets a copy of the metrics that is immutable. Once this clone is made, the {@link MutableMetrics} can no
+     * longer be modified themselves. This prevents custom steps that implement {@link Profiling} from adding to
+     * the metrics after the traversal is complete.
+     */
+    public synchronized ImmutableMetrics getImmutableClone() {
+        finalized = true;
         final ImmutableMetrics clone = new ImmutableMetrics();
         copyMembers(clone);
         this.nested.values().forEach(nested -> clone.nested.put(nested.id, ((MutableMetrics) nested).getImmutableClone()));


[14/24] tinkerpop git commit: fixed up the MultiScope test to use MODERN so that it works with Giraph and Spark. Will back tweak to tp31/.

Posted by sp...@apache.org.
fixed up the MultiScope test to use MODERN so that it works with Giraph and Spark. Will back tweak to tp31/.


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

Branch: refs/heads/TINKERPOP-1686
Commit: f1aed80b056c2244ce8b23ab077e8b10ee6939d9
Parents: 5ac61b7 3b8c628
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Jun 27 09:50:15 2017 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Jun 27 09:50:15 2017 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  2 +
 .../process/computer/GraphComputerTest.java     | 75 ++++++++++++++++++--
 .../process/computer/TinkerMessageBoard.java    |  4 +-
 .../process/computer/TinkerMessenger.java       | 22 +++---
 4 files changed, 88 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


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

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f1aed80b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
----------------------------------------------------------------------
diff --cc gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
index 5c66673,02ac5d4..e4b40e8
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
@@@ -24,35 -22,18 +24,32 @@@ import org.apache.commons.configuration
  import org.apache.tinkerpop.gremlin.ExceptionCoverage;
  import org.apache.tinkerpop.gremlin.LoadGraphWith;
  import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
 +import org.apache.tinkerpop.gremlin.process.computer.clustering.peerpressure.PeerPressureVertexProgram;
 +import org.apache.tinkerpop.gremlin.process.computer.ranking.pagerank.PageRankVertexProgram;
 +import org.apache.tinkerpop.gremlin.process.computer.traversal.TraversalVertexProgram;
 +import org.apache.tinkerpop.gremlin.process.computer.util.AbstractVertexProgramBuilder;
  import org.apache.tinkerpop.gremlin.process.computer.util.StaticMapReduce;
  import org.apache.tinkerpop.gremlin.process.computer.util.StaticVertexProgram;
 +import org.apache.tinkerpop.gremlin.process.traversal.Operator;
 +import org.apache.tinkerpop.gremlin.process.traversal.P;
- import org.apache.tinkerpop.gremlin.process.traversal.Path;
 +import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 +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.util.EmptyPath;
 +import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.VerificationException;
 +import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 +import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
  import org.apache.tinkerpop.gremlin.structure.Direction;
 -import org.apache.tinkerpop.gremlin.structure.Element;
 +import org.apache.tinkerpop.gremlin.structure.Edge;
  import org.apache.tinkerpop.gremlin.structure.Graph;
 +import org.apache.tinkerpop.gremlin.structure.Property;
  import org.apache.tinkerpop.gremlin.structure.Vertex;
  import org.apache.tinkerpop.gremlin.structure.VertexProperty;
  import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
  import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 +import org.javatuples.Pair;
- import org.junit.Ignore;
  import org.junit.Test;
  
- import java.util.AbstractMap;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collections;
@@@ -70,15 -50,11 +68,14 @@@ import java.util.concurrent.Future
  
  import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.GRATEFUL;
  import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
 +import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.outE;
- import static org.apache.tinkerpop.gremlin.structure.T.id;
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.assertFalse;
  import static org.junit.Assert.assertTrue;
  import static org.junit.Assert.fail;
 +import static org.junit.Assume.assumeNoException;
 +
+ 
  /**
   * @author Marko A. Rodriguez (http://markorodriguez.com)
   */
@@@ -1588,567 -1468,92 +1585,635 @@@ public class GraphComputerTest extends 
          public void storeState(final Configuration configuration) {
              VertexProgram.super.storeState(configuration);
          }
+     }
+ 
+     /////////////////////////////////////////////
+     @Test
++    @LoadGraphWith(MODERN)
+     public void shouldSupportMultipleScopes() throws ExecutionException, InterruptedException {
 -        Vertex a = graph.addVertex("a");
 -        Vertex b = graph.addVertex("b");
 -        Vertex c = graph.addVertex("c");
 -        a.addEdge("edge", b);
 -        b.addEdge("edge", c);
 -
 -        // Simple graph:
 -        // a -> b -> c
 -
 -        // Execute a traversal program that sends an incoming message of "2" and an outgoing message of "1" from "b"
 -        // then each vertex sums any received messages
 -        ComputerResult result = graph.compute().program(new MultiScopeVertexProgram()).submit().get();
 -
 -        // We expect the results to be {a=2, b=0, c=1}. Instead it is {a=3, b=0, c=3}
 -        assertEquals((Long) result.graph().traversal().V().hasLabel("a").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(),Long.valueOf(2L));
 -        assertEquals((Long) result.graph().traversal().V().hasLabel("b").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(),Long.valueOf(0L));
 -        assertEquals((Long) result.graph().traversal().V().hasLabel("c").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(),Long.valueOf(1L));
++        final ComputerResult result = graph.compute().program(new MultiScopeVertexProgram()).submit().get();
++        assertEquals(result.graph().traversal().V().has("name", "josh").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(), 0L);
++        assertEquals(result.graph().traversal().V().has("name", "lop").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(), 1L);
++        assertEquals(result.graph().traversal().V().has("name", "ripple").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(), 1L);
++        assertEquals(result.graph().traversal().V().has("name", "marko").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(), 2L);
+     }
+ 
 -    public static class MultiScopeVertexProgram implements VertexProgram<Long> {
++    public static class MultiScopeVertexProgram extends StaticVertexProgram<Long> {
+ 
+         private final MessageScope.Local<Long> countMessageScopeIn = MessageScope.Local.of(__::inE);
+         private final MessageScope.Local<Long> countMessageScopeOut = MessageScope.Local.of(__::outE);
+ 
+         private static final String MEMORY_KEY = "count";
+ 
 -        private static final Set<String> COMPUTE_KEYS = Collections.singleton(MEMORY_KEY);
+ 
+         @Override
 -        public void setup(final Memory memory) {}
++        public void setup(final Memory memory) {
++        }
+ 
+         @Override
+         public GraphComputer.Persist getPreferredPersist() {
+             return GraphComputer.Persist.VERTEX_PROPERTIES;
+         }
+ 
+         @Override
 -        public Set<String> getElementComputeKeys() {
 -            return COMPUTE_KEYS;
++        public Set<VertexComputeKey> getVertexComputeKeys() {
++            return Collections.singleton(VertexComputeKey.of(MEMORY_KEY, false));
+         }
+ 
+         @Override
+         public Set<MessageScope> getMessageScopes(final Memory memory) {
+             HashSet<MessageScope> scopes = new HashSet<>();
+             scopes.add(countMessageScopeIn);
+             scopes.add(countMessageScopeOut);
+             return scopes;
+         }
+ 
+         @Override
+         public void execute(Vertex vertex, Messenger<Long> messenger, Memory memory) {
+             switch (memory.getIteration()) {
+                 case 0:
 -                    if (vertex.label().equals("b")) {
++                    if (vertex.value("name").equals("josh")) {
+                         messenger.sendMessage(this.countMessageScopeIn, 2L);
+                         messenger.sendMessage(this.countMessageScopeOut, 1L);
+                     }
+                     break;
+                 case 1:
+                     long edgeCount = IteratorUtils.reduce(messenger.receiveMessages(), 0L, (a, b) -> a + b);
+                     vertex.property(MEMORY_KEY, edgeCount);
+                     break;
+             }
+         }
+ 
+         @Override
+         public boolean terminate(final Memory memory) {
+             return memory.getIteration() == 1;
+         }
+ 
+         @Override
+         public GraphComputer.ResultGraph getPreferredResultGraph() {
+             return GraphComputer.ResultGraph.NEW;
+         }
  
 -        @Override
 -        public MultiScopeVertexProgram clone() {
 +    }
 +
 +    /////////////////////////////////////////////
 +
 +    @Test
 +    @LoadGraphWith(MODERN)
 +    public void shouldSupportGraphFilter() throws Exception {
 +        // if the graph computer does not support graph filter, then make sure its exception handling is correct
 +        if (!graphProvider.getGraphComputer(graph).features().supportsGraphFilter()) {
              try {
 -                return (MultiScopeVertexProgram) super.clone();
 -            } catch (final CloneNotSupportedException e) {
 -                throw new RuntimeException(e);
 +                graphProvider.getGraphComputer(graph).vertices(__.hasLabel("software"));
 +                fail("Should throw an unsupported operation exception");
 +            } catch (final UnsupportedOperationException e) {
 +                assertEquals(GraphComputer.Exceptions.graphFilterNotSupported().getMessage(), e.getMessage());
 +            }
 +            try {
 +                graphProvider.getGraphComputer(graph).edges(__.<Vertex>outE().limit(10));
 +                fail("Should throw an unsupported operation exception");
 +            } catch (final UnsupportedOperationException e) {
 +                assertEquals(GraphComputer.Exceptions.graphFilterNotSupported().getMessage(), e.getMessage());
 +            }
 +            return;
 +        }
 +        /// VERTEX PROGRAM
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("software")).program(new VertexProgramM(VertexProgramM.SOFTWARE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).program(new VertexProgramM(VertexProgramM.PEOPLE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.bothE("knows")).program(new VertexProgramM(VertexProgramM.KNOWS_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).edges(__.bothE("knows")).program(new VertexProgramM(VertexProgramM.PEOPLE_KNOWS_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).edges(__.<Vertex>bothE("knows").has("weight", P.gt(0.5f))).program(new VertexProgramM(VertexProgramM.PEOPLE_KNOWS_WELL_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.<Vertex>bothE().limit(0)).program(new VertexProgramM(VertexProgramM.VERTICES_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.<Vertex>outE().limit(1)).program(new VertexProgramM(VertexProgramM.ONE_OUT_EDGE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(outE()).program(new VertexProgramM(VertexProgramM.OUT_EDGES_ONLY)).submit().get();
 +
 +        /// VERTEX PROGRAM + MAP REDUCE
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("software")).program(new VertexProgramM(VertexProgramM.SOFTWARE_ONLY)).mapReduce(new MapReduceJ(VertexProgramM.SOFTWARE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).program(new VertexProgramM(VertexProgramM.PEOPLE_ONLY)).mapReduce(new MapReduceJ(VertexProgramM.PEOPLE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.bothE("knows")).program(new VertexProgramM(VertexProgramM.KNOWS_ONLY)).mapReduce(new MapReduceJ(VertexProgramM.KNOWS_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).edges(__.bothE("knows")).program(new VertexProgramM(VertexProgramM.PEOPLE_KNOWS_ONLY)).mapReduce(new MapReduceJ(VertexProgramM.PEOPLE_KNOWS_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).edges(__.<Vertex>bothE("knows").has("weight", P.gt(0.5f))).program(new VertexProgramM(VertexProgramM.PEOPLE_KNOWS_WELL_ONLY)).mapReduce(new MapReduceJ(VertexProgramM.PEOPLE_KNOWS_WELL_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.<Vertex>bothE().limit(0)).program(new VertexProgramM(VertexProgramM.VERTICES_ONLY)).mapReduce(new MapReduceJ(VertexProgramM.VERTICES_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.<Vertex>outE().limit(1)).program(new VertexProgramM(VertexProgramM.ONE_OUT_EDGE_ONLY)).mapReduce(new MapReduceJ(VertexProgramM.ONE_OUT_EDGE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(outE()).program(new VertexProgramM(VertexProgramM.OUT_EDGES_ONLY)).mapReduce(new MapReduceJ(VertexProgramM.OUT_EDGES_ONLY)).submit().get();
 +
 +        /// MAP REDUCE ONLY
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("software")).mapReduce(new MapReduceJ(VertexProgramM.SOFTWARE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).mapReduce(new MapReduceJ(VertexProgramM.PEOPLE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.bothE("knows")).mapReduce(new MapReduceJ(VertexProgramM.KNOWS_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).edges(__.bothE("knows")).mapReduce(new MapReduceJ(VertexProgramM.PEOPLE_KNOWS_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).edges(__.<Vertex>bothE("knows").has("weight", P.gt(0.5f))).mapReduce(new MapReduceJ(VertexProgramM.PEOPLE_KNOWS_WELL_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.<Vertex>bothE().limit(0)).mapReduce(new MapReduceJ(VertexProgramM.VERTICES_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.<Vertex>outE().limit(1)).mapReduce(new MapReduceJ(VertexProgramM.ONE_OUT_EDGE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(outE()).mapReduce(new MapReduceJ(VertexProgramM.OUT_EDGES_ONLY)).submit().get();
 +
 +        // EXCEPTION HANDLING
 +        try {
 +            graphProvider.getGraphComputer(graph).vertices(__.out());
 +            fail();
 +        } catch (final IllegalArgumentException e) {
 +            assertEquals(e.getMessage(), GraphComputer.Exceptions.vertexFilterAccessesIncidentEdges(__.out()).getMessage());
 +        }
 +        try {
 +            graphProvider.getGraphComputer(graph).edges(__.<Vertex>out().outE());
 +            fail();
 +        } catch (final IllegalArgumentException e) {
 +            assertEquals(e.getMessage(), GraphComputer.Exceptions.edgeFilterAccessesAdjacentVertices(__.<Vertex>out().outE()).getMessage());
 +        }
 +    }
 +
 +    public static class VertexProgramM implements VertexProgram {
 +
 +        public static final String SOFTWARE_ONLY = "softwareOnly";
 +        public static final String PEOPLE_ONLY = "peopleOnly";
 +        public static final String KNOWS_ONLY = "knowsOnly";
 +        public static final String PEOPLE_KNOWS_ONLY = "peopleKnowsOnly";
 +        public static final String PEOPLE_KNOWS_WELL_ONLY = "peopleKnowsWellOnly";
 +        public static final String VERTICES_ONLY = "verticesOnly";
 +        public static final String ONE_OUT_EDGE_ONLY = "oneOutEdgeOnly";
 +        public static final String OUT_EDGES_ONLY = "outEdgesOnly";
 +
 +        private String state;
 +
 +        public VertexProgramM() {
 +
 +        }
 +
 +        public VertexProgramM(final String state) {
 +            this.state = state;
 +        }
 +
 +        @Override
 +        public void setup(final Memory memory) {
 +
 +        }
 +
 +        @Override
 +        public void execute(final Vertex vertex, final Messenger messenger, final Memory memory) {
 +            switch (this.state) {
 +                case SOFTWARE_ONLY: {
 +                    assertEquals("software", vertex.label());
 +                    assertFalse(vertex.edges(Direction.OUT).hasNext());
 +                    assertTrue(vertex.edges(Direction.IN).hasNext());
 +                    assertTrue(vertex.edges(Direction.IN, "created").hasNext());
 +                    assertFalse(vertex.edges(Direction.IN, "knows").hasNext());
 +                    break;
 +                }
 +                case PEOPLE_ONLY: {
 +                    assertEquals("person", vertex.label());
 +                    assertFalse(vertex.edges(Direction.IN, "created").hasNext());
 +                    assertTrue(IteratorUtils.count(vertex.edges(Direction.BOTH)) > 0);
 +                    break;
 +                }
 +                case KNOWS_ONLY: {
 +                    assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH, "created")));
 +                    if (vertex.value("name").equals("marko"))
 +                        assertEquals(2, IteratorUtils.count(vertex.edges(Direction.BOTH, "knows")));
 +                    else if (vertex.value("name").equals("vadas"))
 +                        assertEquals(1, IteratorUtils.count(vertex.edges(Direction.IN, "knows")));
 +                    else if (vertex.value("name").equals("josh"))
 +                        assertEquals(1, IteratorUtils.count(vertex.edges(Direction.IN, "knows")));
 +                    else {
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH, "knows")));
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH)));
 +                    }
 +                    break;
 +                }
 +                case PEOPLE_KNOWS_ONLY: {
 +                    assertEquals("person", vertex.label());
 +                    assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH, "created")));
 +                    if (vertex.value("name").equals("marko"))
 +                        assertEquals(2, IteratorUtils.count(vertex.edges(Direction.BOTH, "knows")));
 +                    else if (vertex.value("name").equals("vadas"))
 +                        assertEquals(1, IteratorUtils.count(vertex.edges(Direction.IN, "knows")));
 +                    else if (vertex.value("name").equals("josh"))
 +                        assertEquals(1, IteratorUtils.count(vertex.edges(Direction.IN, "knows")));
 +                    else {
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH, "knows")));
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH)));
 +                    }
 +                    break;
 +                }
 +                case PEOPLE_KNOWS_WELL_ONLY: {
 +                    assertEquals("person", vertex.label());
 +                    assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH, "created")));
 +                    if (vertex.value("name").equals("marko")) {
 +                        assertEquals(1, IteratorUtils.count(vertex.edges(Direction.BOTH, "knows")));
 +                        assertEquals(1.0, vertex.edges(Direction.OUT, "knows").next().value("weight"), 0.001);
 +                    } else if (vertex.value("name").equals("vadas"))
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.IN, "knows")));
 +                    else if (vertex.value("name").equals("josh")) {
 +                        assertEquals(1, IteratorUtils.count(vertex.edges(Direction.IN, "knows")));
 +                        assertEquals(1.0, vertex.edges(Direction.IN, "knows").next().value("weight"), 0.001);
 +                    } else {
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH, "knows")));
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH)));
 +                    }
 +                    break;
 +                }
 +                case VERTICES_ONLY: {
 +                    assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH)));
 +                    break;
 +                }
 +                case ONE_OUT_EDGE_ONLY: {
 +                    if (vertex.label().equals("software") || vertex.value("name").equals("vadas"))
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH)));
 +                    else {
 +                        assertEquals(1, IteratorUtils.count(vertex.edges(Direction.OUT)));
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.IN)));
 +                        assertEquals(1, IteratorUtils.count(vertex.edges(Direction.BOTH)));
 +                    }
 +                    break;
 +                }
 +                case OUT_EDGES_ONLY: {
 +                    if (vertex.label().equals("software") || vertex.value("name").equals("vadas"))
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH)));
 +                    else {
 +                        assertTrue(IteratorUtils.count(vertex.edges(Direction.OUT)) > 0);
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.IN)));
 +                        assertEquals(IteratorUtils.count(vertex.edges(Direction.OUT)), IteratorUtils.count(vertex.edges(Direction.BOTH)));
 +                    }
 +                    break;
 +                }
 +                default:
 +                    throw new IllegalStateException("This is an illegal state for this test case: " + this.state);
 +            }
 +        }
 +
 +        @Override
 +        public boolean terminate(final Memory memory) {
 +            return true;
 +        }
 +
 +        @Override
 +        public Set<MessageScope> getMessageScopes(Memory memory) {
 +            return Collections.emptySet();
 +        }
 +
 +        @Override
 +        public GraphComputer.ResultGraph getPreferredResultGraph() {
 +            return GraphComputer.ResultGraph.NEW;
 +        }
 +
 +        @Override
 +        public GraphComputer.Persist getPreferredPersist() {
 +            return GraphComputer.Persist.NOTHING;
 +        }
 +
 +        @Override
 +        @SuppressWarnings("CloneDoesntCallSuperClone,CloneDoesntDeclareCloneNotSupportedException")
 +        public VertexProgramM clone() {
 +            return new VertexProgramM(this.state);
 +        }
 +
 +        @Override
 +        public void loadState(final Graph graph, final Configuration configuration) {
 +            this.state = configuration.getString("state");
 +        }
 +
 +        @Override
 +        public void storeState(final Configuration configuration) {
 +            configuration.setProperty("state", this.state);
 +            VertexProgram.super.storeState(configuration);
 +        }
 +
 +    }
 +
 +    private static class MapReduceJ implements MapReduce<MapReduce.NullObject, Integer, MapReduce.NullObject, Integer, Integer> {
 +
 +        private String state;
 +
 +        public MapReduceJ() {
 +        }
 +
 +        public MapReduceJ(final String state) {
 +            this.state = state;
 +        }
 +
 +        @Override
 +        public void loadState(final Graph graph, final Configuration configuration) {
 +            this.state = configuration.getString("state");
 +        }
 +
 +        @Override
 +        public void storeState(final Configuration configuration) {
 +            configuration.setProperty("state", this.state);
 +            MapReduce.super.storeState(configuration);
 +        }
 +
 +        @Override
 +        @SuppressWarnings("CloneDoesntCallSuperClone,CloneDoesntDeclareCloneNotSupportedException")
 +        public MapReduceJ clone() {
 +            return new MapReduceJ(this.state);
 +        }
 +
 +        @Override
 +        public boolean doStage(final Stage stage) {
 +            return true;
 +        }
 +
 +        @Override
 +        public void map(final Vertex vertex, final MapEmitter<NullObject, Integer> emitter) {
 +            emitter.emit(1);
 +            switch (this.state) {
 +                case VertexProgramM.SOFTWARE_ONLY: {
 +                    assertEquals("software", vertex.label());
 +                    break;
 +                }
 +                case VertexProgramM.PEOPLE_ONLY: {
 +                    assertEquals("person", vertex.label());
 +                    break;
 +                }
 +                case VertexProgramM.KNOWS_ONLY: {
 +                    assertTrue(vertex.label().equals("person") || vertex.label().equals("software"));
 +                    break;
 +                }
 +                case VertexProgramM.PEOPLE_KNOWS_ONLY: {
 +                    assertEquals("person", vertex.label());
 +                    break;
 +                }
 +                case VertexProgramM.PEOPLE_KNOWS_WELL_ONLY: {
 +                    assertEquals("person", vertex.label());
 +                    break;
 +                }
 +                case VertexProgramM.VERTICES_ONLY: {
 +                    assertTrue(vertex.label().equals("person") || vertex.label().equals("software"));
 +                    break;
 +                }
 +                case VertexProgramM.ONE_OUT_EDGE_ONLY: {
 +                    assertTrue(vertex.label().equals("person") || vertex.label().equals("software"));
 +                    break;
 +                }
 +                case VertexProgramM.OUT_EDGES_ONLY: {
 +                    assertTrue(vertex.label().equals("person") || vertex.label().equals("software"));
 +                    break;
 +                }
 +                default:
 +                    throw new IllegalStateException("This is an illegal state for this test case: " + this.state);
 +            }
 +        }
 +
 +        @Override
 +        public void combine(final NullObject key, final Iterator<Integer> values, final ReduceEmitter<NullObject, Integer> emitter) {
 +            this.reduce(key, values, emitter);
 +        }
 +
 +        @Override
 +        public void reduce(final NullObject key, final Iterator<Integer> values, final ReduceEmitter<NullObject, Integer> emitter) {
 +            int count = 0;
 +            while (values.hasNext()) {
 +                count = count + values.next();
 +            }
 +            emitter.emit(count);
 +        }
 +
 +        @Override
 +        public Integer generateFinalResult(final Iterator<KeyValue<NullObject, Integer>> keyValues) {
 +            int counter = keyValues.next().getValue();
 +            assertFalse(keyValues.hasNext());
 +
 +            switch (this.state) {
 +                case VertexProgramM.SOFTWARE_ONLY: {
 +                    assertEquals(2, counter);
 +                    break;
 +                }
 +                case VertexProgramM.PEOPLE_ONLY: {
 +                    assertEquals(4, counter);
 +                    break;
 +                }
 +                case VertexProgramM.KNOWS_ONLY: {
 +                    assertEquals(6, counter);
 +                    break;
 +                }
 +                case VertexProgramM.PEOPLE_KNOWS_ONLY: {
 +                    assertEquals(4, counter);
 +                    break;
 +                }
 +                case VertexProgramM.PEOPLE_KNOWS_WELL_ONLY: {
 +                    assertEquals(4, counter);
 +                    break;
 +                }
 +                case VertexProgramM.VERTICES_ONLY: {
 +                    assertEquals(6, counter);
 +                    break;
 +                }
 +                case VertexProgramM.ONE_OUT_EDGE_ONLY: {
 +                    assertEquals(6, counter);
 +                    break;
 +                }
 +                case VertexProgramM.OUT_EDGES_ONLY: {
 +                    assertEquals(6, counter);
 +                    break;
 +                }
 +                default:
 +                    throw new IllegalStateException("This is an illegal state for this test case: " + this.state);
 +            }
 +            return counter;
 +        }
 +
 +        @Override
 +        public String getMemoryKey() {
 +            return "a";
 +        }
 +    }
 +
 +    @Test
 +    @LoadGraphWith(MODERN)
 +    public void shouldSupportJobChaining() throws Exception {
 +        final ComputerResult result1 = graphProvider.getGraphComputer(graph)
 +                .program(PageRankVertexProgram.build().iterations(5).create(graph)).persist(GraphComputer.Persist.EDGES).result(GraphComputer.ResultGraph.NEW).submit().get();
 +        final Graph graph1 = result1.graph();
 +        final Memory memory1 = result1.memory();
 +        assertEquals(5, memory1.getIteration());
 +        assertEquals(6, graph1.traversal().V().count().next().intValue());
 +        assertEquals(6, graph1.traversal().E().count().next().intValue());
 +        assertEquals(6, graph1.traversal().V().values(PageRankVertexProgram.PAGE_RANK).count().next().intValue());
 +        assertEquals(18, graph1.traversal().V().values().count().next().intValue());
 +        //
 +        final ComputerResult result2 = graph1.compute(graphProvider.getGraphComputer(graph1).getClass())
 +                .program(PeerPressureVertexProgram.build().maxIterations(4).create(graph1)).persist(GraphComputer.Persist.EDGES).result(GraphComputer.ResultGraph.NEW).submit().get();
 +        final Graph graph2 = result2.graph();
 +        final Memory memory2 = result2.memory();
 +        assertTrue(memory2.getIteration() <= 4);
 +        assertEquals(6, graph2.traversal().V().count().next().intValue());
 +        assertEquals(6, graph2.traversal().E().count().next().intValue());
 +        assertEquals(6, graph2.traversal().V().values(PeerPressureVertexProgram.CLUSTER).count().next().intValue());
 +        assertEquals(6, graph2.traversal().V().values(PageRankVertexProgram.PAGE_RANK).count().next().intValue());
 +        assertEquals(24, graph2.traversal().V().values().count().next().intValue());
 +        //
 +        final ComputerResult result3 = graph2.compute(graphProvider.getGraphComputer(graph2).getClass())
 +                .program(TraversalVertexProgram.build().traversal(g.V().groupCount("m").by(__.values(PageRankVertexProgram.PAGE_RANK).count()).label().asAdmin()).create(graph2)).persist(GraphComputer.Persist.EDGES).result(GraphComputer.ResultGraph.NEW).submit().get();
 +        final Graph graph3 = result3.graph();
 +        final Memory memory3 = result3.memory();
 +        assertTrue(memory3.keys().contains("m"));
 +        assertTrue(memory3.keys().contains(TraversalVertexProgram.HALTED_TRAVERSERS));
 +        assertEquals(1, memory3.<Map<Long, Long>>get("m").size());
 +        assertEquals(6, memory3.<Map<Long, Long>>get("m").get(1l).intValue());
 +        List<Traverser<String>> traversers = IteratorUtils.list(memory3.<TraverserSet>get(TraversalVertexProgram.HALTED_TRAVERSERS).iterator());
 +        assertEquals(6l, traversers.stream().map(Traverser::bulk).reduce((a, b) -> a + b).get().longValue());
 +        assertEquals(4l, traversers.stream().filter(s -> s.get().equals("person")).map(Traverser::bulk).reduce((a, b) -> a + b).get().longValue());
 +        assertEquals(2l, traversers.stream().filter(s -> s.get().equals("software")).map(Traverser::bulk).reduce((a, b) -> a + b).get().longValue());
 +        assertEquals(6, graph3.traversal().V().count().next().intValue());
 +        assertEquals(6, graph3.traversal().E().count().next().intValue());
 +        assertEquals(0, graph3.traversal().V().values(TraversalVertexProgram.HALTED_TRAVERSERS).count().next().intValue());
 +        assertEquals(6, graph3.traversal().V().values(PeerPressureVertexProgram.CLUSTER).count().next().intValue());
 +        assertEquals(6, graph3.traversal().V().values(PageRankVertexProgram.PAGE_RANK).count().next().intValue());
 +        assertEquals(24, graph3.traversal().V().values().count().next().intValue()); // no halted traversers
 +
 +        // TODO: add a test the shows DAG behavior -- splitting another TraversalVertexProgram off of the PeerPressureVertexProgram job.
 +    }
 +
 +    ///////////////////////////////////
 +
 +    @Test
 +    @LoadGraphWith(MODERN)
 +    public void shouldSupportPreExistingComputeKeys() throws Exception {
 +        final ComputerResult result = graphProvider.getGraphComputer(graph).program(new VertexProgramN()).submit().get();
 +        result.graph().vertices().forEachRemaining(vertex -> {
 +            if (vertex.label().equals("person")) {
 +                if (vertex.value("name").equals("marko"))
 +                    assertEquals(32, vertex.<Integer>value("age").intValue());
 +                else if (vertex.value("name").equals("peter"))
 +                    assertEquals(38, vertex.<Integer>value("age").intValue());
 +                else if (vertex.value("name").equals("vadas"))
 +                    assertEquals(30, vertex.<Integer>value("age").intValue());
 +                else if (vertex.value("name").equals("josh"))
 +                    assertEquals(35, vertex.<Integer>value("age").intValue());
 +                else
 +                    throw new IllegalStateException("This vertex should not have been accessed: " + vertex);
 +            }
 +        });
 +    }
 +
 +    private static class VertexProgramN extends StaticVertexProgram {
 +
 +        @Override
 +        public void setup(final Memory memory) {
 +
 +        }
 +
 +        @Override
 +        public void execute(final Vertex vertex, final Messenger messenger, final Memory memory) {
 +            if (vertex.label().equals("person"))
 +                vertex.property(VertexProperty.Cardinality.single, "age", vertex.<Integer>value("age") + 1);
 +        }
 +
 +        @Override
 +        public boolean terminate(final Memory memory) {
 +            return memory.getIteration() > 1;
 +        }
 +
 +        @Override
 +        public Set<MessageScope> getMessageScopes(final Memory memory) {
 +            return Collections.emptySet();
 +        }
 +
 +        @Override
 +        public Set<VertexComputeKey> getVertexComputeKeys() {
 +            return Collections.singleton(VertexComputeKey.of("age", false));
 +        }
 +
 +        @Override
 +        public GraphComputer.ResultGraph getPreferredResultGraph() {
 +            return GraphComputer.ResultGraph.NEW;
 +        }
 +
 +        @Override
 +        public GraphComputer.Persist getPreferredPersist() {
 +            return GraphComputer.Persist.VERTEX_PROPERTIES;
 +        }
 +    }
 +
 +    ///////////////////////////////////
 +
 +    @Test
 +    @LoadGraphWith(MODERN)
 +    public void shouldSupportTransientKeys() throws Exception {
 +        final ComputerResult result = graphProvider.getGraphComputer(graph).program(new VertexProgramO()).mapReduce(new MapReduceK()).submit().get();
 +        result.graph().vertices().forEachRemaining(vertex -> {
 +            assertFalse(vertex.property("v1").isPresent());
 +            assertFalse(vertex.property("v2").isPresent());
 +            assertTrue(vertex.property("v3").isPresent());
 +            assertEquals("shouldExist", vertex.value("v3"));
 +            assertTrue(vertex.property("name").isPresent());
 +            if (vertex.label().equals("software"))
 +                assertTrue(vertex.property("lang").isPresent());
 +            else
 +                assertTrue(vertex.property("age").isPresent());
 +            assertEquals(3, IteratorUtils.count(vertex.properties()));
 +            assertEquals(0, IteratorUtils.count(vertex.properties("v1")));
 +            assertEquals(0, IteratorUtils.count(vertex.properties("v2")));
 +            assertEquals(1, IteratorUtils.count(vertex.properties("v3")));
 +            assertEquals(1, IteratorUtils.count(vertex.properties("name")));
 +        });
 +        assertEquals(6l, result.graph().traversal().V().properties("name").count().next().longValue());
 +        assertEquals(0l, result.graph().traversal().V().properties("v1").count().next().longValue());
 +        assertEquals(0l, result.graph().traversal().V().properties("v2").count().next().longValue());
 +        assertEquals(6l, result.graph().traversal().V().properties("v3").count().next().longValue());
 +        assertEquals(6l, result.graph().traversal().V().<String>values("name").dedup().count().next().longValue());
 +        assertEquals(1l, result.graph().traversal().V().<String>values("v3").dedup().count().next().longValue());
 +        assertEquals("shouldExist", result.graph().traversal().V().<String>values("v3").dedup().next());
 +        ///
 +        assertFalse(result.memory().exists("m1"));
 +        assertFalse(result.memory().exists("m2"));
 +        assertTrue(result.memory().exists("m3"));
 +        assertEquals(24l, result.memory().<Long>get("m3").longValue());
 +        assertEquals(2, result.memory().keys().size());  // mapReduceK
 +    }
 +
 +    private static class VertexProgramO extends StaticVertexProgram {
 +
 +        @Override
 +        public void setup(final Memory memory) {
 +            assertFalse(memory.exists("m1"));
 +            assertFalse(memory.exists("m2"));
 +            assertFalse(memory.exists("m3"));
 +        }
 +
 +        @Override
 +        public void execute(final Vertex vertex, final Messenger messenger, final Memory memory) {
 +            if (memory.isInitialIteration()) {
 +                assertFalse(vertex.property("v1").isPresent());
 +                assertFalse(vertex.property("v2").isPresent());
 +                assertFalse(vertex.property("v3").isPresent());
 +                vertex.property("v1", "shouldNotExist");
 +                vertex.property("v2", "shouldNotExist");
 +                vertex.property("v3", "shouldExist");
 +                assertTrue(vertex.property("v1").isPresent());
 +                assertTrue(vertex.property("v2").isPresent());
 +                assertTrue(vertex.property("v3").isPresent());
 +                assertEquals("shouldNotExist", vertex.value("v1"));
 +                assertEquals("shouldNotExist", vertex.value("v2"));
 +                assertEquals("shouldExist", vertex.value("v3"));
 +                //
 +                assertFalse(memory.exists("m1"));
 +                assertFalse(memory.exists("m2"));
 +                assertFalse(memory.exists("m3"));
 +                memory.add("m1", false);
 +                memory.add("m2", true);
 +                memory.add("m3", 2l);
 +                // should still not exist as this pulls from the master memory
 +                assertFalse(memory.exists("m1"));
 +                assertFalse(memory.exists("m2"));
 +                assertFalse(memory.exists("m3"));
 +
 +            } else {
 +                assertTrue(vertex.property("v1").isPresent());
 +                assertTrue(vertex.property("v2").isPresent());
 +                assertTrue(vertex.property("v3").isPresent());
 +                assertEquals("shouldNotExist", vertex.value("v1"));
 +                assertEquals("shouldNotExist", vertex.value("v2"));
 +                assertEquals("shouldExist", vertex.value("v3"));
 +                //
 +                assertTrue(memory.exists("m1"));
 +                assertTrue(memory.exists("m2"));
 +                assertTrue(memory.exists("m3"));
 +                assertFalse(memory.get("m1"));
 +                assertTrue(memory.get("m2"));
 +                assertEquals(12l, memory.<Long>get("m3").longValue());
 +                memory.add("m1", true);
 +                memory.add("m2", true);
 +                memory.add("m3", 2l);
              }
          }
  

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f1aed80b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerMessenger.java
----------------------------------------------------------------------


[23/24] tinkerpop git commit: TINKERPOP-1686 No need for LinkedHashMap

Posted by sp...@apache.org.
TINKERPOP-1686 No need for LinkedHashMap

Order can be determined by the key which is the step number essentially. Had to regenerate the model for IO tests, but this ends up being a breaking change in gryo.


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

Branch: refs/heads/TINKERPOP-1686
Commit: 4e21a26d658b2440a58b89bf28edcba97e4b074a
Parents: e2d474a
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Mon Jun 19 16:33:03 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Jun 28 08:31:46 2017 -0400

----------------------------------------------------------------------
 .../traversal/util/DefaultTraversalMetrics.java    |   7 +++++--
 .../tinkerpop/gremlin/structure/io/Model.java      |   6 +++---
 .../structure/io/gryo/_3_3_0/metrics-v1d0.kryo     | Bin 187 -> 189 bytes
 .../structure/io/gryo/_3_3_0/metrics-v3d0.kryo     | Bin 187 -> 189 bytes
 .../io/gryo/_3_3_0/traversalmetrics-v1d0.kryo      | Bin 294 -> 439 bytes
 .../io/gryo/_3_3_0/traversalmetrics-v3d0.kryo      | Bin 294 -> 439 bytes
 6 files changed, 8 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4e21a26d/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java
index 4047c3b..6053c9c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java
@@ -33,6 +33,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 /**
  * Default implementation for {@link TraversalMetrics} that aggregates {@link ImmutableMetrics} instances from a
@@ -61,7 +62,7 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
     /**
      * {@link ImmutableMetrics} indexed by their step position.
      */
-    private Map<Integer, ImmutableMetrics> positionIndexedMetrics = new LinkedHashMap<>();
+    private Map<Integer, ImmutableMetrics> positionIndexedMetrics = new HashMap<>();
 
     /**
      * Determines if final metrics have been computed
@@ -99,7 +100,9 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
 
     @Override
     public Collection<ImmutableMetrics> getMetrics() {
-        return this.positionIndexedMetrics.values();
+        return positionIndexedMetrics.entrySet().stream().sorted(Map.Entry.comparingByKey()).
+                collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
+                (oldValue, newValue) -> oldValue, LinkedHashMap::new)).values();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4e21a26d/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/Model.java
----------------------------------------------------------------------
diff --git a/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/Model.java b/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/Model.java
index 9b144fe..e10dc11 100644
--- a/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/Model.java
+++ b/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/Model.java
@@ -36,7 +36,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.util.MutableMetrics;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
 import org.apache.tinkerpop.gremlin.structure.Column;
 import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONCompatibility;
@@ -104,6 +103,7 @@ public class Model {
         final GraphTraversalSource g = graph.traversal();
 
         final Compatibility[] noTypeGraphSONPlusGryo3_2_3 = Compatibilities.with(GryoCompatibility.class).beforeRelease("3.2.4").join(Compatibilities.UNTYPED_GRAPHSON).matchToArray();
+        final Compatibility[] noTypeGraphSONPlusGryo3_3_0 = Compatibilities.with(GryoCompatibility.class).beforeRelease("3.3.0").join(Compatibilities.UNTYPED_GRAPHSON).matchToArray();
 
         // IMPORTANT - the "title" or name of the Entry needs to be unique
 
@@ -143,7 +143,7 @@ public class Model {
         final TraversalMetrics tm = createStaticTraversalMetrics();
         final MutableMetrics metrics = new MutableMetrics(tm.getMetrics("7.0.0()"));
         metrics.addNested(new MutableMetrics(tm.getMetrics("3.0.0()")));
-        addGraphProcessEntry(metrics, "Metrics", "", Compatibilities.UNTYPED_GRAPHSON.matchToArray());
+        addGraphProcessEntry(metrics, "Metrics", "", noTypeGraphSONPlusGryo3_3_0);
         addGraphProcessEntry(P.gt(0), "P", "", Compatibilities.UNTYPED_GRAPHSON.matchToArray());
         // A bug in the the Gryo serialization of ConjunctiveP prevented its proper serialization in versions prior to 3.3.0 and 3.2.4.
         addGraphProcessEntry(P.gt(0).and(P.lt(10)), "P and", "", noTypeGraphSONPlusGryo3_2_3);
@@ -151,7 +151,7 @@ public class Model {
         addGraphProcessEntry(P.gt(0).or(P.within(-1, -10, -100)), "P or", "", noTypeGraphSONPlusGryo3_2_3);
         addGraphProcessEntry(Scope.local, "Scope", "", Compatibilities.UNTYPED_GRAPHSON.matchToArray());
         addGraphProcessEntry(T.label, "T", "", Compatibilities.UNTYPED_GRAPHSON.matchToArray());
-        addGraphProcessEntry(createStaticTraversalMetrics(), "TraversalMetrics", "", Compatibilities.UNTYPED_GRAPHSON.matchToArray());
+        addGraphProcessEntry(createStaticTraversalMetrics(), "TraversalMetrics", "", noTypeGraphSONPlusGryo3_3_0);
         addGraphProcessEntry(g.V().hasLabel("person").asAdmin().nextTraverser(), "Traverser", "", Compatibilities.UNTYPED_GRAPHSON.matchToArray());
 
         final Map<String,Object> requestBindings = new HashMap<>();

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4e21a26d/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v1d0.kryo
----------------------------------------------------------------------
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v1d0.kryo
index c098e38..79629c9 100644
Binary files a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v1d0.kryo and b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v1d0.kryo differ

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4e21a26d/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v3d0.kryo
----------------------------------------------------------------------
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v3d0.kryo
index c098e38..79629c9 100644
Binary files a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v3d0.kryo and b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v3d0.kryo differ

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4e21a26d/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v1d0.kryo
----------------------------------------------------------------------
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v1d0.kryo
index 1aee9e9..4065705 100644
Binary files a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v1d0.kryo and b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v1d0.kryo differ

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4e21a26d/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v3d0.kryo
----------------------------------------------------------------------
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v3d0.kryo
index 1aee9e9..4065705 100644
Binary files a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v3d0.kryo and b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v3d0.kryo differ


[24/24] tinkerpop git commit: TINKERPOP-1686 Updated Gryo serialization tests for metrics

Posted by sp...@apache.org.
TINKERPOP-1686 Updated Gryo serialization tests for metrics


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

Branch: refs/heads/TINKERPOP-1686
Commit: df914d02f1c8c22b9972a35ae6c17e83db7269ec
Parents: 7c5294b
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Jun 28 08:27:19 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Jun 28 08:31:47 2017 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                                 |   2 +-
 .../gremlin/structure/io/gryo/GryoVersion.java     |   9 +++++++--
 gremlin-tools/gremlin-io-test/pom.xml              |   2 +-
 .../structure/io/gryo/_3_3_0/metrics-v1d0.kryo     | Bin 189 -> 193 bytes
 .../structure/io/gryo/_3_3_0/metrics-v3d0.kryo     | Bin 189 -> 193 bytes
 .../io/gryo/_3_3_0/traversalmetrics-v1d0.kryo      | Bin 439 -> 455 bytes
 .../io/gryo/_3_3_0/traversalmetrics-v3d0.kryo      | Bin 439 -> 455 bytes
 7 files changed, 9 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/df914d02/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 4edce2c..a00c1ba 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,7 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.3.0 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-* `TraversalMetrics` and `Metrics` Gryo formats changed given internal changes to the implementations.
+* `TraversalMetrics` and `Metrics` Gryo 1.0 formats changed given internal changes to their implementations.
 * Made `TraversalMetrics` safe to write to from multiple threads.
 * Graphite and Ganglia are no longer packaged with the Gremlin Server distribution.
 * `TransactionException` is no longer a class of `AbstractTransaction` and it extends `RuntimeException`.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/df914d02/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
index b524cbc..5ba7a76 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
@@ -146,6 +146,7 @@ import java.util.TimeZone;
 import java.util.TreeMap;
 import java.util.TreeSet;
 import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
 
 /**
@@ -231,6 +232,8 @@ public enum GryoVersion {
             add(GryoTypeReg.of(KryoSerializable.class, 36));
             add(GryoTypeReg.of(LinkedHashMap.class, 47));
             add(GryoTypeReg.of(LinkedHashSet.class, 71));
+            add(GryoTypeReg.of(ConcurrentHashMap.class, 170));
+            add(GryoTypeReg.of(ConcurrentHashMap.Entry.class, 171));               // ***LAST ID***
             add(GryoTypeReg.of(LinkedList.class, 116));
             add(GryoTypeReg.of(Types.LINKED_HASH_MAP_ENTRY_CLASS, 15));
             add(GryoTypeReg.of(Locale.class, 22));
@@ -358,7 +361,7 @@ public enum GryoVersion {
             tryAddDynamicType(this, "org.apache.tinkerpop.gremlin.driver.message.RequestMessage",
                     "org.apache.tinkerpop.gremlin.driver.ser.RequestMessageGryoSerializer", 167);
             tryAddDynamicType(this, "org.apache.tinkerpop.gremlin.driver.message.ResponseMessage",
-                    "org.apache.tinkerpop.gremlin.driver.ser.ResponseMessageGryoSerializer", 169);  // ***LAST ID***
+                    "org.apache.tinkerpop.gremlin.driver.ser.ResponseMessageGryoSerializer", 169);
         }};
     }
 
@@ -405,6 +408,8 @@ public enum GryoVersion {
             add(GryoTypeReg.of(LinkedHashMap.class, 47));
             add(GryoTypeReg.of(LinkedHashSet.class, 71));
             add(GryoTypeReg.of(LinkedList.class, 116));
+            add(GryoTypeReg.of(ConcurrentHashMap.class, 168));
+            add(GryoTypeReg.of(ConcurrentHashMap.Entry.class, 169));           // ***LAST ID***
             add(GryoTypeReg.of(Types.LINKED_HASH_MAP_ENTRY_CLASS, 15));
             add(GryoTypeReg.of(Locale.class, 22));
             add(GryoTypeReg.of(StringBuffer.class, 43));
@@ -523,7 +528,7 @@ public enum GryoVersion {
             add(GryoTypeReg.of(LambdaRestrictionStrategy.class, 158));
             add(GryoTypeReg.of(ReadOnlyStrategy.class, 159));
             add(GryoTypeReg.of(MatchStep.CountMatchAlgorithm.class, 160));
-            add(GryoTypeReg.of(MatchStep.GreedyMatchAlgorithm.class, 167)); // ***LAST ID***
+            add(GryoTypeReg.of(MatchStep.GreedyMatchAlgorithm.class, 167));
         }};
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/df914d02/gremlin-tools/gremlin-io-test/pom.xml
----------------------------------------------------------------------
diff --git a/gremlin-tools/gremlin-io-test/pom.xml b/gremlin-tools/gremlin-io-test/pom.xml
index 60a56dc..afdc79b 100644
--- a/gremlin-tools/gremlin-io-test/pom.xml
+++ b/gremlin-tools/gremlin-io-test/pom.xml
@@ -168,7 +168,7 @@ writeSupportedV1Objects = { writer, mapper ->
 }
 
 mapper = GraphSONMapper.build().
-                        addRegistry(TinkerIoRegistry.instance()).
+                        addRegistry(TinkerIoRegistryV1d0.instance()).
                         addCustomModule(new AbstractGraphSONMessageSerializerV1d0.GremlinServerModule()).
                         version(GraphSONVersion.V1_0).create().createMapper()
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/df914d02/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v1d0.kryo
----------------------------------------------------------------------
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v1d0.kryo
index 79629c9..f660f85 100644
Binary files a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v1d0.kryo and b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v1d0.kryo differ

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/df914d02/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v3d0.kryo
----------------------------------------------------------------------
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v3d0.kryo
index 79629c9..39aa210 100644
Binary files a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v3d0.kryo and b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/metrics-v3d0.kryo differ

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/df914d02/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v1d0.kryo
----------------------------------------------------------------------
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v1d0.kryo
index 4065705..5eeb07d 100644
Binary files a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v1d0.kryo and b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v1d0.kryo differ

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/df914d02/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v3d0.kryo
----------------------------------------------------------------------
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v3d0.kryo
index 4065705..b9d8ae8 100644
Binary files a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v3d0.kryo and b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_3_0/traversalmetrics-v3d0.kryo differ


[02/24] tinkerpop git commit: bugfix

Posted by sp...@apache.org.
bugfix


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

Branch: refs/heads/TINKERPOP-1686
Commit: 28c514da9065683ed90ea6aabc66ffdcbab99c11
Parents: b1c0723
Author: Sheldon <sh...@mindmaps.io>
Authored: Thu Jun 15 18:00:32 2017 +0100
Committer: Sheldon <sh...@mindmaps.io>
Committed: Mon Jun 19 11:20:20 2017 +0100

----------------------------------------------------------------------
 .../process/computer/TinkerMessageBoard.java    |  4 ++--
 .../process/computer/TinkerMessenger.java       | 22 +++++++++++++-------
 2 files changed, 16 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/28c514da/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerMessageBoard.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerMessageBoard.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerMessageBoard.java
index b217801..422ab86 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerMessageBoard.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerMessageBoard.java
@@ -32,8 +32,8 @@ import java.util.concurrent.ConcurrentHashMap;
  */
 final class TinkerMessageBoard<M> {
 
-    public Map<Vertex, Queue<M>> sendMessages = new ConcurrentHashMap<>();
-    public Map<Vertex, Queue<M>> receiveMessages = new ConcurrentHashMap<>();
+    public Map<MessageScope, Map<Vertex,Queue<M>>> sendMessages = new ConcurrentHashMap<>();
+    public Map<MessageScope, Map<Vertex, Queue<M>>> receiveMessages = new ConcurrentHashMap<>();
     public Set<MessageScope> previousMessageScopes = new HashSet<>();
     public Set<MessageScope> currentMessageScopes = new HashSet<>();
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/28c514da/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerMessenger.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerMessenger.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerMessenger.java
index 3298aff..d3f2de5 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerMessenger.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/computer/TinkerMessenger.java
@@ -37,6 +37,7 @@ import java.util.Optional;
 import java.util.Queue;
 import java.util.Spliterator;
 import java.util.Spliterators;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
@@ -59,14 +60,15 @@ public final class TinkerMessenger<M> implements Messenger<M> {
     @Override
     public Iterator<M> receiveMessages() {
         final MultiIterator<M> multiIterator = new MultiIterator<>();
-        for (final MessageScope messageScope : this.messageBoard.previousMessageScopes) {
+        for (final MessageScope messageScope : this.messageBoard.receiveMessages.keySet()) {
+//        for (final MessageScope messageScope : this.messageBoard.previousMessageScopes) {
             if (messageScope instanceof MessageScope.Local) {
                 final MessageScope.Local<M> localMessageScope = (MessageScope.Local<M>) messageScope;
                 final Traversal.Admin<Vertex, Edge> incidentTraversal = TinkerMessenger.setVertexStart(localMessageScope.getIncidentTraversal().get().asAdmin(), this.vertex);
                 final Direction direction = TinkerMessenger.getDirection(incidentTraversal);
                 final Edge[] edge = new Edge[1]; // simulates storage side-effects available in Gremlin, but not Java8 streams
                 multiIterator.addIterator(StreamSupport.stream(Spliterators.spliteratorUnknownSize(VertexProgramHelper.reverse(incidentTraversal.asAdmin()), Spliterator.IMMUTABLE | Spliterator.SIZED), false)
-                        .map(e -> this.messageBoard.receiveMessages.get((edge[0] = e).vertices(direction).next()))
+                        .map(e -> this.messageBoard.receiveMessages.get(messageScope).get((edge[0] = e).vertices(direction).next()))
                         .filter(q -> null != q)
                         .flatMap(Queue::stream)
                         .map(message -> localMessageScope.getEdgeFunction().apply(message, edge[0]))
@@ -74,7 +76,7 @@ public final class TinkerMessenger<M> implements Messenger<M> {
 
             } else {
                 multiIterator.addIterator(Stream.of(this.vertex)
-                        .map(this.messageBoard.receiveMessages::get)
+                        .map(this.messageBoard.receiveMessages.get(messageScope)::get)
                         .filter(q -> null != q)
                         .flatMap(Queue::stream)
                         .iterator());
@@ -85,16 +87,20 @@ public final class TinkerMessenger<M> implements Messenger<M> {
 
     @Override
     public void sendMessage(final MessageScope messageScope, final M message) {
-        this.messageBoard.currentMessageScopes.add(messageScope);
+//        this.messageBoard.currentMessageScopes.add(messageScope);
         if (messageScope instanceof MessageScope.Local) {
-            addMessage(this.vertex, message);
+            addMessage(this.vertex, message, messageScope);
         } else {
-            ((MessageScope.Global) messageScope).vertices().forEach(v -> addMessage(v, message));
+            ((MessageScope.Global) messageScope).vertices().forEach(v -> addMessage(v, message, messageScope));
         }
     }
 
-    private void addMessage(final Vertex vertex, final M message) {
-        this.messageBoard.sendMessages.compute(vertex, (v, queue) -> {
+    private void addMessage(final Vertex vertex, final M message, MessageScope messageScope) {
+        this.messageBoard.sendMessages.compute(messageScope, (ms, messages) -> {
+            if(null==messages) messages = new ConcurrentHashMap<>();
+            return messages;
+        });
+        this.messageBoard.sendMessages.get(messageScope).compute(vertex, (v, queue) -> {
             if (null == queue) queue = new ConcurrentLinkedQueue<>();
             queue.add(null != this.combiner && !queue.isEmpty() ? this.combiner.combine(queue.remove(), message) : message);
             return queue;


[12/24] tinkerpop git commit: Merge branch 'tp31' of https://github.com/sheldonkhall/tinkerpop into tp31

Posted by sp...@apache.org.
Merge branch 'tp31' of https://github.com/sheldonkhall/tinkerpop into tp31


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

Branch: refs/heads/TINKERPOP-1686
Commit: d67b88b2bee75c68d3c5756a8dbf963f9de2df39
Parents: 3d50f5c 99679a0
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Jun 27 07:53:22 2017 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Jun 27 07:53:22 2017 -0600

----------------------------------------------------------------------
 .../process/computer/GraphComputerTest.java     | 93 ++++++++++++++++++++
 .../process/computer/TinkerMessageBoard.java    |  4 +-
 .../process/computer/TinkerMessenger.java       | 22 +++--
 3 files changed, 109 insertions(+), 10 deletions(-)
----------------------------------------------------------------------



[03/24] tinkerpop git commit: add the regression test

Posted by sp...@apache.org.
add the regression test


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

Branch: refs/heads/TINKERPOP-1686
Commit: 99679a037db3e86112471a40cd454114231852b6
Parents: 28c514d
Author: Sheldon <sh...@mindmaps.io>
Authored: Mon Jun 19 10:35:16 2017 +0100
Committer: Sheldon <sh...@mindmaps.io>
Committed: Mon Jun 19 11:20:37 2017 +0100

----------------------------------------------------------------------
 .../process/computer/GraphComputerTest.java     | 93 ++++++++++++++++++++
 1 file changed, 93 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/99679a03/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
index 1af0830..02ac5d4 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
@@ -24,11 +24,14 @@ import org.apache.tinkerpop.gremlin.LoadGraphWith;
 import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
 import org.apache.tinkerpop.gremlin.process.computer.util.StaticMapReduce;
 import org.apache.tinkerpop.gremlin.process.computer.util.StaticVertexProgram;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Element;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -38,9 +41,11 @@ import java.util.Comparator;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
 import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.GRATEFUL;
@@ -1463,6 +1468,94 @@ public class GraphComputerTest extends AbstractGremlinProcessTest {
         public void storeState(final Configuration configuration) {
             VertexProgram.super.storeState(configuration);
         }
+    }
+
+    /////////////////////////////////////////////
+    @Test
+    public void shouldSupportMultipleScopes() throws ExecutionException, InterruptedException {
+        Vertex a = graph.addVertex("a");
+        Vertex b = graph.addVertex("b");
+        Vertex c = graph.addVertex("c");
+        a.addEdge("edge", b);
+        b.addEdge("edge", c);
+
+        // Simple graph:
+        // a -> b -> c
+
+        // Execute a traversal program that sends an incoming message of "2" and an outgoing message of "1" from "b"
+        // then each vertex sums any received messages
+        ComputerResult result = graph.compute().program(new MultiScopeVertexProgram()).submit().get();
+
+        // We expect the results to be {a=2, b=0, c=1}. Instead it is {a=3, b=0, c=3}
+        assertEquals((Long) result.graph().traversal().V().hasLabel("a").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(),Long.valueOf(2L));
+        assertEquals((Long) result.graph().traversal().V().hasLabel("b").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(),Long.valueOf(0L));
+        assertEquals((Long) result.graph().traversal().V().hasLabel("c").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(),Long.valueOf(1L));
+    }
+
+    public static class MultiScopeVertexProgram implements VertexProgram<Long> {
+
+        private final MessageScope.Local<Long> countMessageScopeIn = MessageScope.Local.of(__::inE);
+        private final MessageScope.Local<Long> countMessageScopeOut = MessageScope.Local.of(__::outE);
+
+        private static final String MEMORY_KEY = "count";
+
+        private static final Set<String> COMPUTE_KEYS = Collections.singleton(MEMORY_KEY);
+
+        @Override
+        public void setup(final Memory memory) {}
+
+        @Override
+        public GraphComputer.Persist getPreferredPersist() {
+            return GraphComputer.Persist.VERTEX_PROPERTIES;
+        }
+
+        @Override
+        public Set<String> getElementComputeKeys() {
+            return COMPUTE_KEYS;
+        }
+
+        @Override
+        public Set<MessageScope> getMessageScopes(final Memory memory) {
+            HashSet<MessageScope> scopes = new HashSet<>();
+            scopes.add(countMessageScopeIn);
+            scopes.add(countMessageScopeOut);
+            return scopes;
+        }
+
+        @Override
+        public void execute(Vertex vertex, Messenger<Long> messenger, Memory memory) {
+            switch (memory.getIteration()) {
+                case 0:
+                    if (vertex.label().equals("b")) {
+                        messenger.sendMessage(this.countMessageScopeIn, 2L);
+                        messenger.sendMessage(this.countMessageScopeOut, 1L);
+                    }
+                    break;
+                case 1:
+                    long edgeCount = IteratorUtils.reduce(messenger.receiveMessages(), 0L, (a, b) -> a + b);
+                    vertex.property(MEMORY_KEY, edgeCount);
+                    break;
+            }
+        }
+
+        @Override
+        public boolean terminate(final Memory memory) {
+            return memory.getIteration() == 1;
+        }
+
+        @Override
+        public GraphComputer.ResultGraph getPreferredResultGraph() {
+            return GraphComputer.ResultGraph.NEW;
+        }
+
+        @Override
+        public MultiScopeVertexProgram clone() {
+            try {
+                return (MultiScopeVertexProgram) super.clone();
+            } catch (final CloneNotSupportedException e) {
+                throw new RuntimeException(e);
+            }
+        }
 
     }
 


[13/24] tinkerpop git commit: updated CHANGELOG.

Posted by sp...@apache.org.
updated CHANGELOG.


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

Branch: refs/heads/TINKERPOP-1686
Commit: 3b8c62892b3369a2ada0314f33f0b5122a4d6e82
Parents: d67b88b
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Jun 27 07:54:00 2017 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Jun 27 07:54:00 2017 -0600

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


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3b8c6289/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index d421cb5..5436fd9 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,8 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.1.8 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* Fixed a `MessageScope` bug in `TinkerGraphComputer`.
+
 [[release-3-1-7]]
 TinkerPop 3.1.7 (Release Date: June 12, 2017)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


[11/24] tinkerpop git commit: Merge branch 'tp32'

Posted by sp...@apache.org.
Merge branch 'tp32'


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

Branch: refs/heads/TINKERPOP-1686
Commit: 55af79f78fb8f1c84be8764728695d95ca8bcf18
Parents: 1ba875b 5ac61b7
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Jun 27 07:50:39 2017 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Jun 27 07:50:39 2017 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc                                               | 1 +
 .../gremlin/process/traversal/step/map/EdgeVertexStep.java       | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/55af79f7/CHANGELOG.asciidoc
----------------------------------------------------------------------


[22/24] tinkerpop git commit: TINKERPOP-1686 Refactored DefaultTraversalMetrics

Posted by sp...@apache.org.
TINKERPOP-1686 Refactored DefaultTraversalMetrics

There seems to be some weird problem in gryo serialization for this class that is difficult to reproduce. It seemed to have something to do with nested maps or perhaps TreeMap, but I wasn't able to easily isolate it to create a bug report to Kryo. All I know is that these changes made the serialization failure (a buffer underflow) go away. It also fixed a problem where deserialization with GraphSON did not allow the getMetrics(int) method to work.


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

Branch: refs/heads/TINKERPOP-1686
Commit: e2d474a2d839618c55a60c4b4033bad35402f6e5
Parents: 4088440
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Jun 7 15:06:10 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Jun 28 08:31:46 2017 -0400

----------------------------------------------------------------------
 .../traversal/util/DefaultTraversalMetrics.java | 216 +++++++------------
 1 file changed, 81 insertions(+), 135 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e2d474a2/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java
index ed2aa2d..4047c3b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java
@@ -23,6 +23,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ProfileStep;
+import org.javatuples.Pair;
 
 import java.io.Serializable;
 import java.util.ArrayList;
@@ -31,7 +32,6 @@ import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.TreeMap;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -40,6 +40,7 @@ import java.util.concurrent.TimeUnit;
  *
  * @author Bob Briody (http://bobbriody.com)
  * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public final class DefaultTraversalMetrics implements TraversalMetrics, Serializable {
     /**
@@ -47,8 +48,10 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
      */
     private static final String[] HEADERS = {"Step", "Count", "Traversers", "Time (ms)", "% Dur"};
 
-    private final Map<String, MutableMetrics> metrics = new HashMap<>();
-    private final TreeMap<Integer, String> indexToLabelMap = new TreeMap<>();
+    /**
+     * {@link ImmutableMetrics} indexed by their step identifier.
+     */
+    private final Map<String, ImmutableMetrics> stepIndexedMetrics = new HashMap<>();
 
     /**
      * A computed value representing the total time spent on all steps.
@@ -56,9 +59,9 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
     private long totalStepDuration;
 
     /**
-     * The metrics that are reported to the caller of profile() which are computed once all metrics have been gathered.
+     * {@link ImmutableMetrics} indexed by their step position.
      */
-    private Map<String, ImmutableMetrics> computedMetrics;
+    private Map<Integer, ImmutableMetrics> positionIndexedMetrics = new LinkedHashMap<>();
 
     /**
      * Determines if final metrics have been computed
@@ -71,10 +74,12 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
     /**
      * This is only a convenient constructor needed for GraphSON deserialization.
      */
-    public DefaultTraversalMetrics(final long totalStepDurationNs, final List<MutableMetrics> metricsMap) {
-        this.totalStepDuration = totalStepDurationNs;
-        this.computedMetrics = new LinkedHashMap<>(metricsMap.size());
-        metricsMap.forEach(metric -> this.computedMetrics.put(metric.getId(), metric.getImmutableClone()));
+    public DefaultTraversalMetrics(final long totalStepDurationNs, final List<MutableMetrics> orderedMetrics) {
+        totalStepDuration = totalStepDurationNs;
+        for (int ix = 0; ix < orderedMetrics.size(); ix++) {
+            stepIndexedMetrics.put(orderedMetrics.get(ix).getId(), orderedMetrics.get(ix).getImmutableClone());
+            positionIndexedMetrics.put(ix, orderedMetrics.get(ix).getImmutableClone());
+        }
     }
 
     @Override
@@ -84,18 +89,17 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
 
     @Override
     public Metrics getMetrics(final int index) {
-        // adjust index to account for the injected profile steps
-        return this.computedMetrics.get(this.indexToLabelMap.get(index));
+        return this.positionIndexedMetrics.get(index);
     }
 
     @Override
     public Metrics getMetrics(final String id) {
-        return this.computedMetrics.get(id);
+        return this.stepIndexedMetrics.get(id);
     }
 
     @Override
     public Collection<ImmutableMetrics> getMetrics() {
-        return this.computedMetrics.values();
+        return this.positionIndexedMetrics.values();
     }
 
     /**
@@ -115,7 +119,7 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
 
         sb.append("\n=============================================================================================================");
 
-        appendMetrics(this.computedMetrics.values(), sb, 0);
+        appendMetrics(this.positionIndexedMetrics.values(), sb, 0);
 
         // Append total duration
         sb.append(String.format("%n%50s %21s %11s %15.3f %8s",
@@ -131,137 +135,34 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
     public synchronized void setMetrics(final Traversal.Admin traversal, final boolean onGraphComputer) {
         if (finalized) throw new IllegalStateException("Metrics have been finalized and cannot be modified");
         finalized = true;
-        addTopLevelMetrics(traversal, onGraphComputer);
         handleNestedTraversals(traversal, null, onGraphComputer);
-        computeTotals();
-    }
-
-    private void appendMetrics(final Collection<? extends Metrics> metrics, final StringBuilder sb, final int indent) {
-        // 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);
-
-            // Grab the values
-            final Long itemCount = m.getCount(ELEMENT_COUNT_ID);
-            final Long traverserCount = m.getCount(TRAVERSER_COUNT_ID);
-            final Double percentDur = (Double) m.getAnnotation(PERCENT_DURATION_KEY);
-
-            // 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(" %11s", ""));
-            }
-
-            sb.append(String.format(" %15.3f", m.getDuration(TimeUnit.MICROSECONDS) / 1000.0));
-
-            if (percentDur != null) {
-                sb.append(String.format(" %8.2f", percentDur));
-            }
-
-            // process any annotations
-            final Map<String,Object> annotations = m.getAnnotations();
-            if (!annotations.isEmpty()) {
-                // ignore the PERCENT_DURATION_KEY as that is a TinkerPop annotation that is displayed by default
-                annotations.entrySet().stream().filter(kv -> !kv.getKey().equals(PERCENT_DURATION_KEY)).forEach(kv -> {
-                    final String prefix = "    \\_";
-                    final String separator = "=";
-                    final String k = prefix + StringUtils.abbreviate(kv.getKey(), 30);
-                    final int valueIndentLen = separator.length() + k.length() + indent;
-                    final int leftover = 110 - valueIndentLen;
-
-                    final String[] splitValues = splitOnSize(kv.getValue().toString(), leftover);
-                    for (int ix = 0; ix < splitValues.length; ix++) {
-                        // the first lines gets the annotation prefix. the rest are indented to the separator
-                        if (ix == 0) {
-                            sb.append(String.format("%n%s", k + separator + splitValues[ix]));
-                        } else {
-                            sb.append(String.format("%n%s", padLeft(splitValues[ix], valueIndentLen - 1)));
-                        }
-                    }
-                });
-            }
-
-            appendMetrics(m.getNested(), sb, indent + 1);
-        }
+        addTopLevelMetrics(traversal, onGraphComputer);
     }
 
-    private static String[] splitOnSize(final String text, final int size) {
-        final String[] ret = new String[(text.length() + size - 1) / size];
-
-        int counter = 0;
-        for (int start = 0; start < text.length(); start += size) {
-            ret[counter] = text.substring(start, Math.min(text.length(), start + size));
-            counter++;
-        }
+    private void addTopLevelMetrics(final Traversal.Admin traversal, final boolean onGraphComputer) {
+        this.totalStepDuration = 0;
 
-        return ret;
-    }
+        final List<ProfileStep> profileSteps = TraversalHelper.getStepsOfClass(ProfileStep.class, traversal);
+        final List<Pair<Integer, MutableMetrics>> tempMetrics = new ArrayList<>(profileSteps.size());
 
-    private static String padLeft(final String text, final int amountToPad) {
-        // not sure why this method needed to exist. stupid string format stuff and commons utilities wouldn't
-        // work for some reason in the context this method was used above.
-        String newText = text;
-        for (int ix = 0; ix < amountToPad; ix++) {
-            newText = " " + newText;
-        }
-        return newText;
-    }
+        for (int ii = 0; ii < profileSteps.size(); ii++) {
+            // The index is necessary to ensure that step order is preserved after a merge.
+            final ProfileStep step = profileSteps.get(ii);
+            final MutableMetrics stepMetrics = onGraphComputer ? traversal.getSideEffects().get(step.getId()) : step.getMetrics();
 
-    private void computeTotals() {
-        // Create temp list of ordered metrics
-        final List<MutableMetrics> tempMetrics = new ArrayList<>(this.metrics.size());
-        for (final String label : this.indexToLabelMap.values()) {
-            // The indexToLabelMap is sorted by index (key)
-            tempMetrics.add(this.metrics.get(label).clone());
+            this.totalStepDuration += stepMetrics.getDuration(MutableMetrics.SOURCE_UNIT);
+            tempMetrics.add(Pair.with(ii, stepMetrics.clone()));
         }
 
-        // Calculate total duration
-        this.totalStepDuration = 0;
-        tempMetrics.forEach(metric -> this.totalStepDuration += metric.getDuration(MutableMetrics.SOURCE_UNIT));
-
-        // Assign %'s
         tempMetrics.forEach(m -> {
-            final double dur = m.getDuration(TimeUnit.NANOSECONDS) * 100.d / this.totalStepDuration;
-            m.setAnnotation(PERCENT_DURATION_KEY, dur);
+            final double dur = m.getValue1().getDuration(TimeUnit.NANOSECONDS) * 100.d / this.totalStepDuration;
+            m.getValue1().setAnnotation(PERCENT_DURATION_KEY, dur);
         });
 
-        // Store immutable instances of the calculated metrics
-        this.computedMetrics = new LinkedHashMap<>(this.metrics.size());
-        tempMetrics.forEach(it -> this.computedMetrics.put(it.getId(), it.getImmutableClone()));
-    }
-
-    private void addTopLevelMetrics(final Traversal.Admin traversal, final boolean onGraphComputer) {
-        final List<ProfileStep> profileSteps = TraversalHelper.getStepsOfClass(ProfileStep.class, traversal);
-        for (int ii = 0; ii < profileSteps.size(); ii++) {
-            // The index is necessary to ensure that step order is preserved after a merge.
-            final ProfileStep step = profileSteps.get(ii);
-            if (onGraphComputer) {
-                final MutableMetrics stepMetrics = traversal.getSideEffects().get(step.getId());
-                this.indexToLabelMap.put(ii, stepMetrics.getId());
-                this.metrics.put(stepMetrics.getId(), stepMetrics);
-            } else {
-                final MutableMetrics stepMetrics = step.getMetrics();
-                this.indexToLabelMap.put(ii, stepMetrics.getId());
-                this.metrics.put(stepMetrics.getId(), stepMetrics);
-            }
-        }
+        tempMetrics.forEach(p -> {
+            this.stepIndexedMetrics.put(p.getValue1().getId(), p.getValue1().getImmutableClone());
+            this.positionIndexedMetrics.put(p.getValue0(), p.getValue1().getImmutableClone());
+        });
     }
 
     private void handleNestedTraversals(final Traversal.Admin traversal, final MutableMetrics parentMetrics, final boolean onGraphComputer) {
@@ -315,7 +216,7 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
             // 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);
+            final Double percentDur = (Double) m.getAnnotation(PERCENT_DURATION_KEY);
 
             // Build the row string
 
@@ -339,7 +240,52 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
                 sb.append(String.format(" %8.2f", percentDur));
             }
 
+            // process any annotations
+            final Map<String,Object> annotations = m.getAnnotations();
+            if (!annotations.isEmpty()) {
+                // ignore the PERCENT_DURATION_KEY as that is a TinkerPop annotation that is displayed by default
+                annotations.entrySet().stream().filter(kv -> !kv.getKey().equals(PERCENT_DURATION_KEY)).forEach(kv -> {
+                    final String prefix = "    \\_";
+                    final String separator = "=";
+                    final String k = prefix + StringUtils.abbreviate(kv.getKey(), 30);
+                    final int valueIndentLen = separator.length() + k.length() + indent;
+                    final int leftover = 110 - valueIndentLen;
+
+                    final String[] splitValues = splitOnSize(kv.getValue().toString(), leftover);
+                    for (int ix = 0; ix < splitValues.length; ix++) {
+                        // the first lines gets the annotation prefix. the rest are indented to the separator
+                        if (ix == 0) {
+                            sb.append(String.format("%n%s", k + separator + splitValues[ix]));
+                        } else {
+                            sb.append(String.format("%n%s", padLeft(splitValues[ix], valueIndentLen - 1)));
+                        }
+                    }
+                });
+            }
+
             appendMetrics(m.getNested(), sb, indent + 1);
         }
     }
+
+    private static String[] splitOnSize(final String text, final int size) {
+        final String[] ret = new String[(text.length() + size - 1) / size];
+
+        int counter = 0;
+        for (int start = 0; start < text.length(); start += size) {
+            ret[counter] = text.substring(start, Math.min(text.length(), start + size));
+            counter++;
+        }
+
+        return ret;
+    }
+
+    private static String padLeft(final String text, final int amountToPad) {
+        // not sure why this method needed to exist. stupid string format stuff and commons utilities wouldn't
+        // work for some reason in the context this method was used above.
+        String newText = text;
+        for (int ix = 0; ix < amountToPad; ix++) {
+            newText = " " + newText;
+        }
+        return newText;
+    }
 }


[04/24] tinkerpop git commit: TINKERPOP-1004 Expand usage of TransactionException

Posted by sp...@apache.org.
TINKERPOP-1004 Expand usage of TransactionException

TransactionException is no longer bound to usage by AbstractTransaction. Precribed a more general usage of it with the Transaction interface.


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

Branch: refs/heads/TINKERPOP-1686
Commit: eb0eddca04050cb48d1262c7ff3bc28354f558c6
Parents: 268333b
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue Jun 20 12:57:04 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Tue Jun 20 13:51:45 2017 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 docs/src/upgrade/release-3.3.x.asciidoc         | 66 +++++++++++---------
 .../gremlin/structure/Transaction.java          |  9 ++-
 .../structure/util/AbstractTransaction.java     | 34 ++--------
 .../structure/util/TransactionException.java    | 42 +++++++++++++
 .../gremlin/neo4j/structure/Neo4jGraph.java     |  1 +
 6 files changed, 93 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/eb0eddca/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 58a3a62..610cf7e 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.3.0 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* `TransactionException` is no longer a class of `AbstractTransaction` and it extends `RuntimeException`.
 * Renamed `RangeByIsCountStrategy` to `CountStrategy`.
 * Added more specific typing to various `__` traversal steps. E.g. `<A,Vertex>out()` is `<Vertex,Vertex>out()`.
 * Updated Docker build scripts to include Python dependencies (NOTE: users should remove any previously generated TinkerPop Docker images).

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/eb0eddca/docs/src/upgrade/release-3.3.x.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/upgrade/release-3.3.x.asciidoc b/docs/src/upgrade/release-3.3.x.asciidoc
index dbb40b4..ea8be1b 100644
--- a/docs/src/upgrade/release-3.3.x.asciidoc
+++ b/docs/src/upgrade/release-3.3.x.asciidoc
@@ -255,34 +255,6 @@ link:https://issues.apache.org/jira/browse/TINKERPOP-1420[TINKERPOP-1420], link:
 link:https://issues.apache.org/jira/browse/TINKERPOP-1465[TINKERPOP-1465], link:https://issues.apache.org/jira/browse/TINKERPOP-1526[TINKERPOP-1526],
 link:https://issues.apache.org/jira/browse/TINKERPOP-1612[TINKERPOP-1612], link:https://issues.apache.org/jira/browse/TINKERPOP-1622[TINKERPOP-1622]
 
-Upgrading for Providers
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Graph Database Providers
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-Test Suite Removal
-++++++++++++++++++
-
-A number of test suites that were previously deprecated have been removed which should reduce the burden on graph
-providers who are implementing TinkerPop. Test suites related to perfrmance based on `junit-benchmarks` have been
-removed as have the suites in `gremlin-groovy-test` (in fact, this entire module has been removed). Specifically,
-providers should be concerned with breaking changes related to the removal of:
-
-* `StructurePerformanceSuite`
-* `ProcessPerformanceSuite`
-* `GroovyEnvironmentPerformanceSuite`
-* `GroovyProcessStandardSuite`
-* `GroovyProcessComputerSuite`
-* `GroovyEnvironmentSuite`
-* `GroovyEnvironmentIntegrateSuite`
-
-Those graph providers who relied on these tests should simply remove them from their respective test suites. Beware of
-`OptOut` annotations that reference tests in these suites as test failure will occur if those references are not
-removed.
-
-See: link:https://issues.apache.org/jira/browse/TINKERPOP-1235[TINKERPOP-1235], link:https://issues.apache.org/jira/browse/TINKERPOP-1612[TINKERPOP-1612]
-
 Gremlin-server.sh and Init Scripts
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -322,3 +294,41 @@ spark.serializer=org.apache.tinkerpop.gremlin.spark.structure.io.gryo.GryoSerial
 ```
 
 See: link:https://issues.apache.org/jira/browse/TINKERPOP-1389
+
+Upgrading for Providers
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Graph Database Providers
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Test Suite Removal
+++++++++++++++++++
+
+A number of test suites that were previously deprecated have been removed which should reduce the burden on graph
+providers who are implementing TinkerPop. Test suites related to perfrmance based on `junit-benchmarks` have been
+removed as have the suites in `gremlin-groovy-test` (in fact, this entire module has been removed). Specifically,
+providers should be concerned with breaking changes related to the removal of:
+
+* `StructurePerformanceSuite`
+* `ProcessPerformanceSuite`
+* `GroovyEnvironmentPerformanceSuite`
+* `GroovyProcessStandardSuite`
+* `GroovyProcessComputerSuite`
+* `GroovyEnvironmentSuite`
+* `GroovyEnvironmentIntegrateSuite`
+
+Those graph providers who relied on these tests should simply remove them from their respective test suites. Beware of
+`OptOut` annotations that reference tests in these suites as test failure will occur if those references are not
+removed.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-1235[TINKERPOP-1235], link:https://issues.apache.org/jira/browse/TINKERPOP-1612[TINKERPOP-1612]
+
+TransactionException
+++++++++++++++++++++
+
+The `AbstractTransaction.TransactionException` class is now just `TransactionException` which extends `RuntimeExcetpion`
+rather than `Exception`. Providers should consider using this exception to wrap their own on calls to
+`Transaction.commit()` or `Transaction.rollback()`. By throwing this exception, the TinkerPop stack can better respond
+to transaction problems and it allows for more common, generalized error handling for users.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-1004[TINKERPOP-1004]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/eb0eddca/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Transaction.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Transaction.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Transaction.java
index 82f3820..fdc0295 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Transaction.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Transaction.java
@@ -19,6 +19,7 @@
 package org.apache.tinkerpop.gremlin.structure;
 
 import org.apache.tinkerpop.gremlin.structure.util.AbstractTransaction;
+import org.apache.tinkerpop.gremlin.structure.util.TransactionException;
 
 import java.util.Collections;
 import java.util.Set;
@@ -51,12 +52,16 @@ public interface Transaction extends AutoCloseable {
     public void open();
 
     /**
-     * Commits a transaction.
+     * Commits a transaction. This method may optionally throw {@link TransactionException} on error. Providers should
+     * consider wrapping their transaction exceptions in this TinkerPop exception as it will lead to better error
+     * handling with Gremlin Server and other parts of the stack.
      */
     public void commit();
 
     /**
-     * Rolls back a transaction.
+     * Rolls back a transaction. This method may optionally throw {@link TransactionException} on error. Providers should
+     * consider wrapping their transaction exceptions in this TinkerPop exception as it will lead to better error
+     * handling with Gremlin Server and other parts of the stack.
      */
     public void rollback();
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/eb0eddca/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/AbstractTransaction.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/AbstractTransaction.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/AbstractTransaction.java
index 00d15c5..a0dc48c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/AbstractTransaction.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/AbstractTransaction.java
@@ -101,12 +101,8 @@ public abstract class AbstractTransaction implements Transaction {
     @Override
     public void commit() {
         readWrite();
-        try {
-            doCommit();
-            fireOnCommit();
-        } catch (TransactionException te) {
-            throw new RuntimeException(te);
-        }
+        doCommit();
+        fireOnCommit();
     }
 
     /**
@@ -115,12 +111,8 @@ public abstract class AbstractTransaction implements Transaction {
     @Override
     public void rollback() {
         readWrite();
-        try {
-            doRollback();
-            fireOnRollback();
-        } catch (TransactionException te) {
-            throw new RuntimeException(te);
-        }
+        doRollback();
+        fireOnRollback();
     }
 
     /**
@@ -153,22 +145,4 @@ public abstract class AbstractTransaction implements Transaction {
     public void close() {
         doClose();
     }
-
-    /**
-     * An "internal" exception thrown by providers when calls to {@link AbstractTransaction#doCommit} or
-     * {@link AbstractTransaction#doRollback} fail.
-     */
-    public static class TransactionException extends Exception {
-        public TransactionException(final String message) {
-            super(message);
-        }
-
-        public TransactionException(final Throwable cause) {
-            super(cause);
-        }
-
-        public TransactionException(final String message, final Throwable cause) {
-            super(message, cause);
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/eb0eddca/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/TransactionException.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/TransactionException.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/TransactionException.java
new file mode 100644
index 0000000..b167408
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/TransactionException.java
@@ -0,0 +1,42 @@
+/*
+ * 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.structure.util;
+
+import org.apache.tinkerpop.gremlin.structure.Transaction;
+
+/**
+ * An exception thrown by providers when calls to {@link AbstractTransaction#doCommit} or
+ * {@link AbstractTransaction#doRollback} fail. This exception will be propagated to users on calls to
+ * {@link Transaction#commit()} or {@link Transaction#rollback()}.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class TransactionException extends RuntimeException {
+    public TransactionException(final String message) {
+        super(message);
+    }
+
+    public TransactionException(final Throwable cause) {
+        super(cause);
+    }
+
+    public TransactionException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/eb0eddca/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java
----------------------------------------------------------------------
diff --git a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java
index b92801a..e8e069c 100644
--- a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java
+++ b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/structure/Neo4jGraph.java
@@ -39,6 +39,7 @@ import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 import org.apache.tinkerpop.gremlin.structure.util.AbstractThreadLocalTransaction;
 import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.structure.util.TransactionException;
 import org.apache.tinkerpop.gremlin.structure.util.wrapped.WrappedGraph;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 import org.neo4j.tinkerpop.api.Neo4jFactory;


[16/24] tinkerpop git commit: Merge branch 'tp31' into tp32

Posted by sp...@apache.org.
Merge branch 'tp31' into tp32


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

Branch: refs/heads/TINKERPOP-1686
Commit: 943658531ba8a3bb8050c169ad2180f81cda96db
Parents: f1aed80 e7f5ef7
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Jun 27 10:04:37 2017 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Jun 27 10:04:37 2017 -0600

----------------------------------------------------------------------
 .../tinkerpop/gremlin/process/computer/GraphComputerTest.java  | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/94365853/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
----------------------------------------------------------------------
diff --cc gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
index e4b40e8,e2acd5e..380887b
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
@@@ -73,9 -52,7 +73,8 @@@ import static org.junit.Assert.assertEq
  import static org.junit.Assert.assertFalse;
  import static org.junit.Assert.assertTrue;
  import static org.junit.Assert.fail;
 +import static org.junit.Assume.assumeNoException;
  
- 
  /**
   * @author Marko A. Rodriguez (http://markorodriguez.com)
   */
@@@ -1591,7 -1472,7 +1590,7 @@@ public class GraphComputerTest extends 
      @Test
      @LoadGraphWith(MODERN)
      public void shouldSupportMultipleScopes() throws ExecutionException, InterruptedException {
-         final ComputerResult result = graph.compute().program(new MultiScopeVertexProgram()).submit().get();
 -        final ComputerResult result = graph.compute(graphComputerClass.get()).program(new MultiScopeVertexProgram()).submit().get();
++        final ComputerResult result = graphProvider.getGraphComputer(graph).program(new MultiScopeVertexProgram()).submit().get();
          assertEquals(result.graph().traversal().V().has("name", "josh").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(), 0L);
          assertEquals(result.graph().traversal().V().has("name", "lop").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(), 1L);
          assertEquals(result.graph().traversal().V().has("name", "ripple").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(), 1L);
@@@ -1653,968 -1535,6 +1652,965 @@@
          public GraphComputer.ResultGraph getPreferredResultGraph() {
              return GraphComputer.ResultGraph.NEW;
          }
- 
 +    }
 +
 +    /////////////////////////////////////////////
 +
 +    @Test
 +    @LoadGraphWith(MODERN)
 +    public void shouldSupportGraphFilter() throws Exception {
 +        // if the graph computer does not support graph filter, then make sure its exception handling is correct
 +        if (!graphProvider.getGraphComputer(graph).features().supportsGraphFilter()) {
 +            try {
 +                graphProvider.getGraphComputer(graph).vertices(__.hasLabel("software"));
 +                fail("Should throw an unsupported operation exception");
 +            } catch (final UnsupportedOperationException e) {
 +                assertEquals(GraphComputer.Exceptions.graphFilterNotSupported().getMessage(), e.getMessage());
 +            }
 +            try {
 +                graphProvider.getGraphComputer(graph).edges(__.<Vertex>outE().limit(10));
 +                fail("Should throw an unsupported operation exception");
 +            } catch (final UnsupportedOperationException e) {
 +                assertEquals(GraphComputer.Exceptions.graphFilterNotSupported().getMessage(), e.getMessage());
 +            }
 +            return;
 +        }
 +        /// VERTEX PROGRAM
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("software")).program(new VertexProgramM(VertexProgramM.SOFTWARE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).program(new VertexProgramM(VertexProgramM.PEOPLE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.bothE("knows")).program(new VertexProgramM(VertexProgramM.KNOWS_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).edges(__.bothE("knows")).program(new VertexProgramM(VertexProgramM.PEOPLE_KNOWS_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).edges(__.<Vertex>bothE("knows").has("weight", P.gt(0.5f))).program(new VertexProgramM(VertexProgramM.PEOPLE_KNOWS_WELL_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.<Vertex>bothE().limit(0)).program(new VertexProgramM(VertexProgramM.VERTICES_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.<Vertex>outE().limit(1)).program(new VertexProgramM(VertexProgramM.ONE_OUT_EDGE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(outE()).program(new VertexProgramM(VertexProgramM.OUT_EDGES_ONLY)).submit().get();
 +
 +        /// VERTEX PROGRAM + MAP REDUCE
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("software")).program(new VertexProgramM(VertexProgramM.SOFTWARE_ONLY)).mapReduce(new MapReduceJ(VertexProgramM.SOFTWARE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).program(new VertexProgramM(VertexProgramM.PEOPLE_ONLY)).mapReduce(new MapReduceJ(VertexProgramM.PEOPLE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.bothE("knows")).program(new VertexProgramM(VertexProgramM.KNOWS_ONLY)).mapReduce(new MapReduceJ(VertexProgramM.KNOWS_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).edges(__.bothE("knows")).program(new VertexProgramM(VertexProgramM.PEOPLE_KNOWS_ONLY)).mapReduce(new MapReduceJ(VertexProgramM.PEOPLE_KNOWS_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).edges(__.<Vertex>bothE("knows").has("weight", P.gt(0.5f))).program(new VertexProgramM(VertexProgramM.PEOPLE_KNOWS_WELL_ONLY)).mapReduce(new MapReduceJ(VertexProgramM.PEOPLE_KNOWS_WELL_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.<Vertex>bothE().limit(0)).program(new VertexProgramM(VertexProgramM.VERTICES_ONLY)).mapReduce(new MapReduceJ(VertexProgramM.VERTICES_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.<Vertex>outE().limit(1)).program(new VertexProgramM(VertexProgramM.ONE_OUT_EDGE_ONLY)).mapReduce(new MapReduceJ(VertexProgramM.ONE_OUT_EDGE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(outE()).program(new VertexProgramM(VertexProgramM.OUT_EDGES_ONLY)).mapReduce(new MapReduceJ(VertexProgramM.OUT_EDGES_ONLY)).submit().get();
 +
 +        /// MAP REDUCE ONLY
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("software")).mapReduce(new MapReduceJ(VertexProgramM.SOFTWARE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).mapReduce(new MapReduceJ(VertexProgramM.PEOPLE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.bothE("knows")).mapReduce(new MapReduceJ(VertexProgramM.KNOWS_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).edges(__.bothE("knows")).mapReduce(new MapReduceJ(VertexProgramM.PEOPLE_KNOWS_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).vertices(__.hasLabel("person")).edges(__.<Vertex>bothE("knows").has("weight", P.gt(0.5f))).mapReduce(new MapReduceJ(VertexProgramM.PEOPLE_KNOWS_WELL_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.<Vertex>bothE().limit(0)).mapReduce(new MapReduceJ(VertexProgramM.VERTICES_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(__.<Vertex>outE().limit(1)).mapReduce(new MapReduceJ(VertexProgramM.ONE_OUT_EDGE_ONLY)).submit().get();
 +        graphProvider.getGraphComputer(graph).edges(outE()).mapReduce(new MapReduceJ(VertexProgramM.OUT_EDGES_ONLY)).submit().get();
 +
 +        // EXCEPTION HANDLING
 +        try {
 +            graphProvider.getGraphComputer(graph).vertices(__.out());
 +            fail();
 +        } catch (final IllegalArgumentException e) {
 +            assertEquals(e.getMessage(), GraphComputer.Exceptions.vertexFilterAccessesIncidentEdges(__.out()).getMessage());
 +        }
 +        try {
 +            graphProvider.getGraphComputer(graph).edges(__.<Vertex>out().outE());
 +            fail();
 +        } catch (final IllegalArgumentException e) {
 +            assertEquals(e.getMessage(), GraphComputer.Exceptions.edgeFilterAccessesAdjacentVertices(__.<Vertex>out().outE()).getMessage());
 +        }
 +    }
 +
 +    public static class VertexProgramM implements VertexProgram {
 +
 +        public static final String SOFTWARE_ONLY = "softwareOnly";
 +        public static final String PEOPLE_ONLY = "peopleOnly";
 +        public static final String KNOWS_ONLY = "knowsOnly";
 +        public static final String PEOPLE_KNOWS_ONLY = "peopleKnowsOnly";
 +        public static final String PEOPLE_KNOWS_WELL_ONLY = "peopleKnowsWellOnly";
 +        public static final String VERTICES_ONLY = "verticesOnly";
 +        public static final String ONE_OUT_EDGE_ONLY = "oneOutEdgeOnly";
 +        public static final String OUT_EDGES_ONLY = "outEdgesOnly";
 +
 +        private String state;
 +
 +        public VertexProgramM() {
 +
 +        }
 +
 +        public VertexProgramM(final String state) {
 +            this.state = state;
 +        }
 +
 +        @Override
 +        public void setup(final Memory memory) {
 +
 +        }
 +
 +        @Override
 +        public void execute(final Vertex vertex, final Messenger messenger, final Memory memory) {
 +            switch (this.state) {
 +                case SOFTWARE_ONLY: {
 +                    assertEquals("software", vertex.label());
 +                    assertFalse(vertex.edges(Direction.OUT).hasNext());
 +                    assertTrue(vertex.edges(Direction.IN).hasNext());
 +                    assertTrue(vertex.edges(Direction.IN, "created").hasNext());
 +                    assertFalse(vertex.edges(Direction.IN, "knows").hasNext());
 +                    break;
 +                }
 +                case PEOPLE_ONLY: {
 +                    assertEquals("person", vertex.label());
 +                    assertFalse(vertex.edges(Direction.IN, "created").hasNext());
 +                    assertTrue(IteratorUtils.count(vertex.edges(Direction.BOTH)) > 0);
 +                    break;
 +                }
 +                case KNOWS_ONLY: {
 +                    assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH, "created")));
 +                    if (vertex.value("name").equals("marko"))
 +                        assertEquals(2, IteratorUtils.count(vertex.edges(Direction.BOTH, "knows")));
 +                    else if (vertex.value("name").equals("vadas"))
 +                        assertEquals(1, IteratorUtils.count(vertex.edges(Direction.IN, "knows")));
 +                    else if (vertex.value("name").equals("josh"))
 +                        assertEquals(1, IteratorUtils.count(vertex.edges(Direction.IN, "knows")));
 +                    else {
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH, "knows")));
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH)));
 +                    }
 +                    break;
 +                }
 +                case PEOPLE_KNOWS_ONLY: {
 +                    assertEquals("person", vertex.label());
 +                    assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH, "created")));
 +                    if (vertex.value("name").equals("marko"))
 +                        assertEquals(2, IteratorUtils.count(vertex.edges(Direction.BOTH, "knows")));
 +                    else if (vertex.value("name").equals("vadas"))
 +                        assertEquals(1, IteratorUtils.count(vertex.edges(Direction.IN, "knows")));
 +                    else if (vertex.value("name").equals("josh"))
 +                        assertEquals(1, IteratorUtils.count(vertex.edges(Direction.IN, "knows")));
 +                    else {
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH, "knows")));
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH)));
 +                    }
 +                    break;
 +                }
 +                case PEOPLE_KNOWS_WELL_ONLY: {
 +                    assertEquals("person", vertex.label());
 +                    assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH, "created")));
 +                    if (vertex.value("name").equals("marko")) {
 +                        assertEquals(1, IteratorUtils.count(vertex.edges(Direction.BOTH, "knows")));
 +                        assertEquals(1.0, vertex.edges(Direction.OUT, "knows").next().value("weight"), 0.001);
 +                    } else if (vertex.value("name").equals("vadas"))
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.IN, "knows")));
 +                    else if (vertex.value("name").equals("josh")) {
 +                        assertEquals(1, IteratorUtils.count(vertex.edges(Direction.IN, "knows")));
 +                        assertEquals(1.0, vertex.edges(Direction.IN, "knows").next().value("weight"), 0.001);
 +                    } else {
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH, "knows")));
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH)));
 +                    }
 +                    break;
 +                }
 +                case VERTICES_ONLY: {
 +                    assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH)));
 +                    break;
 +                }
 +                case ONE_OUT_EDGE_ONLY: {
 +                    if (vertex.label().equals("software") || vertex.value("name").equals("vadas"))
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH)));
 +                    else {
 +                        assertEquals(1, IteratorUtils.count(vertex.edges(Direction.OUT)));
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.IN)));
 +                        assertEquals(1, IteratorUtils.count(vertex.edges(Direction.BOTH)));
 +                    }
 +                    break;
 +                }
 +                case OUT_EDGES_ONLY: {
 +                    if (vertex.label().equals("software") || vertex.value("name").equals("vadas"))
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.BOTH)));
 +                    else {
 +                        assertTrue(IteratorUtils.count(vertex.edges(Direction.OUT)) > 0);
 +                        assertEquals(0, IteratorUtils.count(vertex.edges(Direction.IN)));
 +                        assertEquals(IteratorUtils.count(vertex.edges(Direction.OUT)), IteratorUtils.count(vertex.edges(Direction.BOTH)));
 +                    }
 +                    break;
 +                }
 +                default:
 +                    throw new IllegalStateException("This is an illegal state for this test case: " + this.state);
 +            }
 +        }
 +
 +        @Override
 +        public boolean terminate(final Memory memory) {
 +            return true;
 +        }
 +
 +        @Override
 +        public Set<MessageScope> getMessageScopes(Memory memory) {
 +            return Collections.emptySet();
 +        }
 +
 +        @Override
 +        public GraphComputer.ResultGraph getPreferredResultGraph() {
 +            return GraphComputer.ResultGraph.NEW;
 +        }
 +
 +        @Override
 +        public GraphComputer.Persist getPreferredPersist() {
 +            return GraphComputer.Persist.NOTHING;
 +        }
 +
 +        @Override
 +        @SuppressWarnings("CloneDoesntCallSuperClone,CloneDoesntDeclareCloneNotSupportedException")
 +        public VertexProgramM clone() {
 +            return new VertexProgramM(this.state);
 +        }
 +
 +        @Override
 +        public void loadState(final Graph graph, final Configuration configuration) {
 +            this.state = configuration.getString("state");
 +        }
 +
 +        @Override
 +        public void storeState(final Configuration configuration) {
 +            configuration.setProperty("state", this.state);
 +            VertexProgram.super.storeState(configuration);
 +        }
 +
 +    }
 +
 +    private static class MapReduceJ implements MapReduce<MapReduce.NullObject, Integer, MapReduce.NullObject, Integer, Integer> {
 +
 +        private String state;
 +
 +        public MapReduceJ() {
 +        }
 +
 +        public MapReduceJ(final String state) {
 +            this.state = state;
 +        }
 +
 +        @Override
 +        public void loadState(final Graph graph, final Configuration configuration) {
 +            this.state = configuration.getString("state");
 +        }
 +
 +        @Override
 +        public void storeState(final Configuration configuration) {
 +            configuration.setProperty("state", this.state);
 +            MapReduce.super.storeState(configuration);
 +        }
 +
 +        @Override
 +        @SuppressWarnings("CloneDoesntCallSuperClone,CloneDoesntDeclareCloneNotSupportedException")
 +        public MapReduceJ clone() {
 +            return new MapReduceJ(this.state);
 +        }
 +
 +        @Override
 +        public boolean doStage(final Stage stage) {
 +            return true;
 +        }
 +
 +        @Override
 +        public void map(final Vertex vertex, final MapEmitter<NullObject, Integer> emitter) {
 +            emitter.emit(1);
 +            switch (this.state) {
 +                case VertexProgramM.SOFTWARE_ONLY: {
 +                    assertEquals("software", vertex.label());
 +                    break;
 +                }
 +                case VertexProgramM.PEOPLE_ONLY: {
 +                    assertEquals("person", vertex.label());
 +                    break;
 +                }
 +                case VertexProgramM.KNOWS_ONLY: {
 +                    assertTrue(vertex.label().equals("person") || vertex.label().equals("software"));
 +                    break;
 +                }
 +                case VertexProgramM.PEOPLE_KNOWS_ONLY: {
 +                    assertEquals("person", vertex.label());
 +                    break;
 +                }
 +                case VertexProgramM.PEOPLE_KNOWS_WELL_ONLY: {
 +                    assertEquals("person", vertex.label());
 +                    break;
 +                }
 +                case VertexProgramM.VERTICES_ONLY: {
 +                    assertTrue(vertex.label().equals("person") || vertex.label().equals("software"));
 +                    break;
 +                }
 +                case VertexProgramM.ONE_OUT_EDGE_ONLY: {
 +                    assertTrue(vertex.label().equals("person") || vertex.label().equals("software"));
 +                    break;
 +                }
 +                case VertexProgramM.OUT_EDGES_ONLY: {
 +                    assertTrue(vertex.label().equals("person") || vertex.label().equals("software"));
 +                    break;
 +                }
 +                default:
 +                    throw new IllegalStateException("This is an illegal state for this test case: " + this.state);
 +            }
 +        }
 +
 +        @Override
 +        public void combine(final NullObject key, final Iterator<Integer> values, final ReduceEmitter<NullObject, Integer> emitter) {
 +            this.reduce(key, values, emitter);
 +        }
 +
 +        @Override
 +        public void reduce(final NullObject key, final Iterator<Integer> values, final ReduceEmitter<NullObject, Integer> emitter) {
 +            int count = 0;
 +            while (values.hasNext()) {
 +                count = count + values.next();
 +            }
 +            emitter.emit(count);
 +        }
 +
 +        @Override
 +        public Integer generateFinalResult(final Iterator<KeyValue<NullObject, Integer>> keyValues) {
 +            int counter = keyValues.next().getValue();
 +            assertFalse(keyValues.hasNext());
 +
 +            switch (this.state) {
 +                case VertexProgramM.SOFTWARE_ONLY: {
 +                    assertEquals(2, counter);
 +                    break;
 +                }
 +                case VertexProgramM.PEOPLE_ONLY: {
 +                    assertEquals(4, counter);
 +                    break;
 +                }
 +                case VertexProgramM.KNOWS_ONLY: {
 +                    assertEquals(6, counter);
 +                    break;
 +                }
 +                case VertexProgramM.PEOPLE_KNOWS_ONLY: {
 +                    assertEquals(4, counter);
 +                    break;
 +                }
 +                case VertexProgramM.PEOPLE_KNOWS_WELL_ONLY: {
 +                    assertEquals(4, counter);
 +                    break;
 +                }
 +                case VertexProgramM.VERTICES_ONLY: {
 +                    assertEquals(6, counter);
 +                    break;
 +                }
 +                case VertexProgramM.ONE_OUT_EDGE_ONLY: {
 +                    assertEquals(6, counter);
 +                    break;
 +                }
 +                case VertexProgramM.OUT_EDGES_ONLY: {
 +                    assertEquals(6, counter);
 +                    break;
 +                }
 +                default:
 +                    throw new IllegalStateException("This is an illegal state for this test case: " + this.state);
 +            }
 +            return counter;
 +        }
 +
 +        @Override
 +        public String getMemoryKey() {
 +            return "a";
 +        }
 +    }
 +
 +    @Test
 +    @LoadGraphWith(MODERN)
 +    public void shouldSupportJobChaining() throws Exception {
 +        final ComputerResult result1 = graphProvider.getGraphComputer(graph)
 +                .program(PageRankVertexProgram.build().iterations(5).create(graph)).persist(GraphComputer.Persist.EDGES).result(GraphComputer.ResultGraph.NEW).submit().get();
 +        final Graph graph1 = result1.graph();
 +        final Memory memory1 = result1.memory();
 +        assertEquals(5, memory1.getIteration());
 +        assertEquals(6, graph1.traversal().V().count().next().intValue());
 +        assertEquals(6, graph1.traversal().E().count().next().intValue());
 +        assertEquals(6, graph1.traversal().V().values(PageRankVertexProgram.PAGE_RANK).count().next().intValue());
 +        assertEquals(18, graph1.traversal().V().values().count().next().intValue());
 +        //
 +        final ComputerResult result2 = graph1.compute(graphProvider.getGraphComputer(graph1).getClass())
 +                .program(PeerPressureVertexProgram.build().maxIterations(4).create(graph1)).persist(GraphComputer.Persist.EDGES).result(GraphComputer.ResultGraph.NEW).submit().get();
 +        final Graph graph2 = result2.graph();
 +        final Memory memory2 = result2.memory();
 +        assertTrue(memory2.getIteration() <= 4);
 +        assertEquals(6, graph2.traversal().V().count().next().intValue());
 +        assertEquals(6, graph2.traversal().E().count().next().intValue());
 +        assertEquals(6, graph2.traversal().V().values(PeerPressureVertexProgram.CLUSTER).count().next().intValue());
 +        assertEquals(6, graph2.traversal().V().values(PageRankVertexProgram.PAGE_RANK).count().next().intValue());
 +        assertEquals(24, graph2.traversal().V().values().count().next().intValue());
 +        //
 +        final ComputerResult result3 = graph2.compute(graphProvider.getGraphComputer(graph2).getClass())
 +                .program(TraversalVertexProgram.build().traversal(g.V().groupCount("m").by(__.values(PageRankVertexProgram.PAGE_RANK).count()).label().asAdmin()).create(graph2)).persist(GraphComputer.Persist.EDGES).result(GraphComputer.ResultGraph.NEW).submit().get();
 +        final Graph graph3 = result3.graph();
 +        final Memory memory3 = result3.memory();
 +        assertTrue(memory3.keys().contains("m"));
 +        assertTrue(memory3.keys().contains(TraversalVertexProgram.HALTED_TRAVERSERS));
 +        assertEquals(1, memory3.<Map<Long, Long>>get("m").size());
 +        assertEquals(6, memory3.<Map<Long, Long>>get("m").get(1l).intValue());
 +        List<Traverser<String>> traversers = IteratorUtils.list(memory3.<TraverserSet>get(TraversalVertexProgram.HALTED_TRAVERSERS).iterator());
 +        assertEquals(6l, traversers.stream().map(Traverser::bulk).reduce((a, b) -> a + b).get().longValue());
 +        assertEquals(4l, traversers.stream().filter(s -> s.get().equals("person")).map(Traverser::bulk).reduce((a, b) -> a + b).get().longValue());
 +        assertEquals(2l, traversers.stream().filter(s -> s.get().equals("software")).map(Traverser::bulk).reduce((a, b) -> a + b).get().longValue());
 +        assertEquals(6, graph3.traversal().V().count().next().intValue());
 +        assertEquals(6, graph3.traversal().E().count().next().intValue());
 +        assertEquals(0, graph3.traversal().V().values(TraversalVertexProgram.HALTED_TRAVERSERS).count().next().intValue());
 +        assertEquals(6, graph3.traversal().V().values(PeerPressureVertexProgram.CLUSTER).count().next().intValue());
 +        assertEquals(6, graph3.traversal().V().values(PageRankVertexProgram.PAGE_RANK).count().next().intValue());
 +        assertEquals(24, graph3.traversal().V().values().count().next().intValue()); // no halted traversers
 +
 +        // TODO: add a test the shows DAG behavior -- splitting another TraversalVertexProgram off of the PeerPressureVertexProgram job.
 +    }
 +
 +    ///////////////////////////////////
 +
 +    @Test
 +    @LoadGraphWith(MODERN)
 +    public void shouldSupportPreExistingComputeKeys() throws Exception {
 +        final ComputerResult result = graphProvider.getGraphComputer(graph).program(new VertexProgramN()).submit().get();
 +        result.graph().vertices().forEachRemaining(vertex -> {
 +            if (vertex.label().equals("person")) {
 +                if (vertex.value("name").equals("marko"))
 +                    assertEquals(32, vertex.<Integer>value("age").intValue());
 +                else if (vertex.value("name").equals("peter"))
 +                    assertEquals(38, vertex.<Integer>value("age").intValue());
 +                else if (vertex.value("name").equals("vadas"))
 +                    assertEquals(30, vertex.<Integer>value("age").intValue());
 +                else if (vertex.value("name").equals("josh"))
 +                    assertEquals(35, vertex.<Integer>value("age").intValue());
 +                else
 +                    throw new IllegalStateException("This vertex should not have been accessed: " + vertex);
 +            }
 +        });
 +    }
 +
 +    private static class VertexProgramN extends StaticVertexProgram {
  
 +        @Override
 +        public void setup(final Memory memory) {
 +
 +        }
 +
 +        @Override
 +        public void execute(final Vertex vertex, final Messenger messenger, final Memory memory) {
 +            if (vertex.label().equals("person"))
 +                vertex.property(VertexProperty.Cardinality.single, "age", vertex.<Integer>value("age") + 1);
 +        }
 +
 +        @Override
 +        public boolean terminate(final Memory memory) {
 +            return memory.getIteration() > 1;
 +        }
 +
 +        @Override
 +        public Set<MessageScope> getMessageScopes(final Memory memory) {
 +            return Collections.emptySet();
 +        }
 +
 +        @Override
 +        public Set<VertexComputeKey> getVertexComputeKeys() {
 +            return Collections.singleton(VertexComputeKey.of("age", false));
 +        }
 +
 +        @Override
 +        public GraphComputer.ResultGraph getPreferredResultGraph() {
 +            return GraphComputer.ResultGraph.NEW;
 +        }
 +
 +        @Override
 +        public GraphComputer.Persist getPreferredPersist() {
 +            return GraphComputer.Persist.VERTEX_PROPERTIES;
 +        }
 +    }
 +
 +    ///////////////////////////////////
 +
 +    @Test
 +    @LoadGraphWith(MODERN)
 +    public void shouldSupportTransientKeys() throws Exception {
 +        final ComputerResult result = graphProvider.getGraphComputer(graph).program(new VertexProgramO()).mapReduce(new MapReduceK()).submit().get();
 +        result.graph().vertices().forEachRemaining(vertex -> {
 +            assertFalse(vertex.property("v1").isPresent());
 +            assertFalse(vertex.property("v2").isPresent());
 +            assertTrue(vertex.property("v3").isPresent());
 +            assertEquals("shouldExist", vertex.value("v3"));
 +            assertTrue(vertex.property("name").isPresent());
 +            if (vertex.label().equals("software"))
 +                assertTrue(vertex.property("lang").isPresent());
 +            else
 +                assertTrue(vertex.property("age").isPresent());
 +            assertEquals(3, IteratorUtils.count(vertex.properties()));
 +            assertEquals(0, IteratorUtils.count(vertex.properties("v1")));
 +            assertEquals(0, IteratorUtils.count(vertex.properties("v2")));
 +            assertEquals(1, IteratorUtils.count(vertex.properties("v3")));
 +            assertEquals(1, IteratorUtils.count(vertex.properties("name")));
 +        });
 +        assertEquals(6l, result.graph().traversal().V().properties("name").count().next().longValue());
 +        assertEquals(0l, result.graph().traversal().V().properties("v1").count().next().longValue());
 +        assertEquals(0l, result.graph().traversal().V().properties("v2").count().next().longValue());
 +        assertEquals(6l, result.graph().traversal().V().properties("v3").count().next().longValue());
 +        assertEquals(6l, result.graph().traversal().V().<String>values("name").dedup().count().next().longValue());
 +        assertEquals(1l, result.graph().traversal().V().<String>values("v3").dedup().count().next().longValue());
 +        assertEquals("shouldExist", result.graph().traversal().V().<String>values("v3").dedup().next());
 +        ///
 +        assertFalse(result.memory().exists("m1"));
 +        assertFalse(result.memory().exists("m2"));
 +        assertTrue(result.memory().exists("m3"));
 +        assertEquals(24l, result.memory().<Long>get("m3").longValue());
 +        assertEquals(2, result.memory().keys().size());  // mapReduceK
 +    }
 +
 +    private static class VertexProgramO extends StaticVertexProgram {
 +
 +        @Override
 +        public void setup(final Memory memory) {
 +            assertFalse(memory.exists("m1"));
 +            assertFalse(memory.exists("m2"));
 +            assertFalse(memory.exists("m3"));
 +        }
 +
 +        @Override
 +        public void execute(final Vertex vertex, final Messenger messenger, final Memory memory) {
 +            if (memory.isInitialIteration()) {
 +                assertFalse(vertex.property("v1").isPresent());
 +                assertFalse(vertex.property("v2").isPresent());
 +                assertFalse(vertex.property("v3").isPresent());
 +                vertex.property("v1", "shouldNotExist");
 +                vertex.property("v2", "shouldNotExist");
 +                vertex.property("v3", "shouldExist");
 +                assertTrue(vertex.property("v1").isPresent());
 +                assertTrue(vertex.property("v2").isPresent());
 +                assertTrue(vertex.property("v3").isPresent());
 +                assertEquals("shouldNotExist", vertex.value("v1"));
 +                assertEquals("shouldNotExist", vertex.value("v2"));
 +                assertEquals("shouldExist", vertex.value("v3"));
 +                //
 +                assertFalse(memory.exists("m1"));
 +                assertFalse(memory.exists("m2"));
 +                assertFalse(memory.exists("m3"));
 +                memory.add("m1", false);
 +                memory.add("m2", true);
 +                memory.add("m3", 2l);
 +                // should still not exist as this pulls from the master memory
 +                assertFalse(memory.exists("m1"));
 +                assertFalse(memory.exists("m2"));
 +                assertFalse(memory.exists("m3"));
 +
 +            } else {
 +                assertTrue(vertex.property("v1").isPresent());
 +                assertTrue(vertex.property("v2").isPresent());
 +                assertTrue(vertex.property("v3").isPresent());
 +                assertEquals("shouldNotExist", vertex.value("v1"));
 +                assertEquals("shouldNotExist", vertex.value("v2"));
 +                assertEquals("shouldExist", vertex.value("v3"));
 +                //
 +                assertTrue(memory.exists("m1"));
 +                assertTrue(memory.exists("m2"));
 +                assertTrue(memory.exists("m3"));
 +                assertFalse(memory.get("m1"));
 +                assertTrue(memory.get("m2"));
 +                assertEquals(12l, memory.<Long>get("m3").longValue());
 +                memory.add("m1", true);
 +                memory.add("m2", true);
 +                memory.add("m3", 2l);
 +            }
 +        }
 +
 +        @Override
 +        public boolean terminate(final Memory memory) {
 +            assertTrue(memory.exists("m1"));
 +            assertTrue(memory.exists("m2"));
 +            assertTrue(memory.exists("m3"));
 +            if (memory.isInitialIteration()) {
 +                assertFalse(memory.get("m1"));
 +                assertTrue(memory.get("m2"));
 +                assertEquals(12l, memory.<Long>get("m3").longValue());
 +                return false;
 +            } else {
 +                assertTrue(memory.get("m1"));
 +                assertTrue(memory.get("m2"));
 +                assertEquals(24l, memory.<Long>get("m3").longValue());
 +                return true;
 +            }
 +        }
 +
 +        @Override
 +        public Set<MessageScope> getMessageScopes(final Memory memory) {
 +            return Collections.emptySet();
 +        }
 +
 +        @Override
 +        public Set<MemoryComputeKey> getMemoryComputeKeys() {
 +            return new HashSet<>(Arrays.asList(
 +                    MemoryComputeKey.of("m1", Operator.or, true, true),
 +                    MemoryComputeKey.of("m2", Operator.and, true, true),
 +                    MemoryComputeKey.of("m3", Operator.sum, true, false)));
 +        }
 +
 +        @Override
 +        public Set<VertexComputeKey> getVertexComputeKeys() {
 +            return new HashSet<>(Arrays.asList(
 +                    VertexComputeKey.of("v1", true),
 +                    VertexComputeKey.of("v2", true),
 +                    VertexComputeKey.of("v3", false)));
 +        }
 +
 +        @Override
 +        public GraphComputer.ResultGraph getPreferredResultGraph() {
 +            return GraphComputer.ResultGraph.NEW;
 +        }
 +
 +        @Override
 +        public GraphComputer.Persist getPreferredPersist() {
 +            return GraphComputer.Persist.VERTEX_PROPERTIES;
 +        }
 +    }
 +
 +    public static class MapReduceK extends StaticMapReduce {
 +
 +        @Override
 +        public boolean doStage(final Stage stage) {
 +            return stage.equals(Stage.MAP);
 +        }
 +
 +        @Override
 +        public void map(final Vertex vertex, final MapEmitter emitter) {
 +            assertFalse(vertex.property("v1").isPresent());
 +            assertFalse(vertex.property("v2").isPresent());
 +            assertTrue(vertex.property("v3").isPresent());
 +            assertTrue(vertex.property("name").isPresent());
 +            assertEquals(3, IteratorUtils.count(vertex.properties()));
 +            assertEquals(3, IteratorUtils.count(vertex.values()));
 +        }
 +
 +        @Override
 +        public String getMemoryKey() {
 +            return "mapReduceK";
 +        }
 +
 +        @Override
 +        public Object generateFinalResult(final Iterator keyValues) {
 +            return "anObject";
 +        }
 +    }
 +
 +    ///////////////////////////////////
 +
 +    @Test
 +    @LoadGraphWith(MODERN)
 +    public void shouldSupportBroadcastKeys() throws Exception {
 +        final ComputerResult result = graphProvider.getGraphComputer(graph).program(new VertexProgramP()).submit().get();
 +        assertTrue(result.memory().exists("m1"));
 +        assertFalse(result.memory().exists("m2"));
 +        assertFalse(result.memory().exists("m3"));
 +        assertTrue(result.memory().exists("m4"));
 +        assertTrue(result.memory().get("m1"));
 +        assertEquals(-18, result.memory().<Integer>get("m4").intValue());
 +        assertEquals(2, result.memory().keys().size());
 +    }
 +
 +    private static class VertexProgramP extends StaticVertexProgram {
 +
 +        @Override
 +        public void setup(final Memory memory) {
 +            assertFalse(memory.exists("m1"));  // or
 +            assertFalse(memory.exists("m2"));  // and
 +            assertFalse(memory.exists("m3"));  // long
 +            assertFalse(memory.exists("m4"));  // int
 +            memory.set("m1", false);
 +            memory.set("m2", true);
 +            memory.set("m3", 0l);
 +            memory.set("m4", 0);
 +        }
 +
 +        @Override
 +        public void execute(final Vertex vertex, final Messenger messenger, final Memory memory) {
 +            if (memory.isInitialIteration()) {
 +                assertFalse(memory.exists("m1"));
 +                assertTrue(memory.exists("m2"));
 +                assertTrue(memory.get("m2"));
 +                assertFalse(memory.exists("m3"));
 +                assertTrue(memory.exists("m4"));
 +                assertEquals(0, memory.<Integer>get("m4").intValue());
 +                memory.add("m1", false);
 +                memory.add("m2", true);
 +                memory.add("m3", 1l);
 +                memory.add("m4", -1);
 +            } else {
 +                assertFalse(memory.exists("m1")); // no broadcast
 +                assertTrue(memory.exists("m2"));
 +                assertFalse(memory.exists("m3")); // no broadcast
 +                assertTrue(memory.exists("m4"));
 +                try {
 +                    assertFalse(memory.get("m1"));
 +                    fail();
 +                } catch (final Exception e) {
 +                    validateException(Memory.Exceptions.memoryDoesNotExist("m1"), e);
 +                }
 +                assertTrue(memory.get("m2"));
 +                try {
 +                    assertEquals(6l, memory.<Long>get("m3").longValue());
 +                    fail();
 +                } catch (final Exception e) {
 +                    validateException(Memory.Exceptions.memoryDoesNotExist("m3"), e);
 +                }
 +                assertEquals(-6l, memory.<Integer>get("m4").intValue());
 +                ///
 +                memory.add("m1", true);
 +                memory.add("m2", true);
 +                memory.add("m3", 2l);
 +                memory.add("m4", -2);
 +            }
 +        }
 +
 +        @Override
 +        public boolean terminate(final Memory memory) {
 +            assertTrue(memory.exists("m1"));
 +            assertTrue(memory.exists("m2"));
 +            assertTrue(memory.exists("m3"));
 +            assertTrue(memory.exists("m4"));
 +            if (memory.isInitialIteration()) {
 +                assertFalse(memory.get("m1"));
 +                assertTrue(memory.get("m2"));
 +                assertEquals(6l, memory.<Long>get("m3").longValue());
 +                assertEquals(-6, memory.<Integer>get("m4").intValue());
 +                return false;
 +            } else {
 +                assertTrue(memory.get("m1"));
 +                assertTrue(memory.get("m2"));
 +                assertEquals(18l, memory.<Long>get("m3").longValue());
 +                assertEquals(-18, memory.<Integer>get("m4").intValue());
 +                return true;
 +            }
 +        }
 +
 +        @Override
 +        public Set<MessageScope> getMessageScopes(final Memory memory) {
 +            return Collections.emptySet();
 +        }
 +
 +        @Override
 +        public Set<MemoryComputeKey> getMemoryComputeKeys() {
 +            return new HashSet<>(Arrays.asList(
 +                    MemoryComputeKey.of("m1", Operator.or, false, false),
 +                    MemoryComputeKey.of("m2", Operator.and, true, true),
 +                    MemoryComputeKey.of("m3", Operator.sum, false, true),
 +                    MemoryComputeKey.of("m4", Operator.sum, true, false)));
 +        }
 +
 +        @Override
 +        public GraphComputer.ResultGraph getPreferredResultGraph() {
 +            return GraphComputer.ResultGraph.NEW;
 +        }
 +
 +        @Override
 +        public GraphComputer.Persist getPreferredPersist() {
 +            return GraphComputer.Persist.VERTEX_PROPERTIES;
 +        }
 +    }
 +
 +    ///////////////////////////////////
 +
 +    @Test
 +    @LoadGraphWith(MODERN)
 +    public void shouldSucceedWithProperTraverserRequirements() throws Exception {
 +
 +        final VertexProgramQ vp = VertexProgramQ.build().property("pl").create();
 +        final Map<String, List<Integer>> expected = new HashMap<>();
 +        expected.put("vadas", Collections.singletonList(2));
 +        expected.put("lop", Arrays.asList(2, 2, 2, 3));
 +        expected.put("josh", Collections.singletonList(2));
 +        expected.put("ripple", Arrays.asList(2, 3));
 +
 +        try {
 +            g.V().repeat(__.out()).emit().program(vp).dedup()
 +                    .valueMap("name", "pl").forEachRemaining((Map<String, Object> map) -> {
 +
 +                final String name = (String) ((List) map.get("name")).get(0);
 +                final List<Integer> pathLengths = (List<Integer>) map.get("pl");
 +                assertTrue(expected.containsKey(name));
 +                final List<Integer> expectedPathLengths = expected.remove(name);
 +                assertTrue(expectedPathLengths.containsAll(pathLengths));
 +                assertTrue(pathLengths.containsAll(expectedPathLengths));
 +            });
 +
 +            assertTrue(expected.isEmpty());
 +        } catch (VerificationException ex) {
 +            assumeNoException(ex);
 +        }
 +    }
 +
 +    @Test
 +    @LoadGraphWith(MODERN)
 +    public void shouldFailWithImproperTraverserRequirements() throws Exception {
 +        final VertexProgramQ vp = VertexProgramQ.build().property("pl").useTraverserRequirements(false).create();
 +        try {
 +            g.V().repeat(__.out()).emit().program(vp).dedup()
 +                    .forEachRemaining((Vertex v) -> assertFalse(v.property("pl").isPresent()));
 +        } catch (VerificationException ex) {
 +            assumeNoException(ex);
 +        }
 +    }
 +
 +    private static class VertexProgramQ implements VertexProgram<Object> {
 +
 +        private static final String VERTEX_PROGRAM_Q_CFG_PREFIX = "gremlin.vertexProgramQ";
 +        private static final String PROPERTY_CFG_KEY = VERTEX_PROGRAM_Q_CFG_PREFIX + ".property";
 +        private static final String LENGTHS_KEY = VERTEX_PROGRAM_Q_CFG_PREFIX + ".lengths";
 +        private static final String USE_TRAVERSER_REQUIREMENTS_CFG_KEY = VERTEX_PROGRAM_Q_CFG_PREFIX + ".useTraverserRequirements";
 +
 +        private final static Set<MemoryComputeKey> MEMORY_COMPUTE_KEYS = Collections.singleton(
 +                MemoryComputeKey.of(LENGTHS_KEY, Operator.addAll, true, true)
 +        );
 +
 +        private final Set<VertexComputeKey> elementComputeKeys;
 +        private Configuration configuration;
 +        private String propertyKey;
 +        private Set<TraverserRequirement> traverserRequirements;
 +
 +        private VertexProgramQ() {
 +            elementComputeKeys = new HashSet<>();
 +        }
 +
 +        public static Builder build() {
 +            return new Builder();
 +        }
 +
 +        static class Builder extends AbstractVertexProgramBuilder<Builder> {
 +
 +            private Builder() {
 +                super(VertexProgramQ.class);
 +            }
 +
 +            @SuppressWarnings("unchecked")
 +            @Override
 +            public VertexProgramQ create(final Graph graph) {
 +                if (graph != null) {
 +                    ConfigurationUtils.append(graph.configuration().subset(VERTEX_PROGRAM_Q_CFG_PREFIX), configuration);
 +                }
 +                return (VertexProgramQ) VertexProgram.createVertexProgram(graph, configuration);
 +            }
 +
 +            public VertexProgramQ create() {
 +                return create(null);
 +            }
 +
 +            public Builder property(final String name) {
 +                configuration.setProperty(PROPERTY_CFG_KEY, name);
 +                return this;
 +            }
 +
 +            /**
 +             * This is only configurable for the purpose of testing. In a real-world VP this would be a bad pattern.
 +             */
 +            public Builder useTraverserRequirements(final boolean value) {
 +                configuration.setProperty(USE_TRAVERSER_REQUIREMENTS_CFG_KEY, value);
 +                return this;
 +            }
 +        }
 +
 +        @Override
 +        public void storeState(final Configuration config) {
 +            VertexProgram.super.storeState(config);
 +            if (configuration != null) {
 +                ConfigurationUtils.copy(configuration, config);
 +            }
 +        }
 +
 +
 +        @Override
 +        public void loadState(final Graph graph, final Configuration config) {
 +            configuration = new BaseConfiguration();
 +            if (config != null) {
 +                ConfigurationUtils.copy(config, configuration);
 +            }
 +            propertyKey = configuration.getString(PROPERTY_CFG_KEY);
 +            traverserRequirements = configuration.getBoolean(USE_TRAVERSER_REQUIREMENTS_CFG_KEY, true)
 +                    ? Collections.singleton(TraverserRequirement.PATH) : Collections.emptySet();
 +            elementComputeKeys.add(VertexComputeKey.of(propertyKey, false));
 +        }
 +
 +        @Override
 +        public void setup(final Memory memory) {
 +        }
 +
 +        @Override
 +        public void execute(final Vertex vertex, final Messenger messenger, final Memory memory) {
 +            if (memory.isInitialIteration()) {
 +                final Property<TraverserSet> haltedTraversers = vertex.property(TraversalVertexProgram.HALTED_TRAVERSERS);
 +                if (!haltedTraversers.isPresent()) return;
 +                final Iterator iterator = haltedTraversers.value().iterator();
 +                if (iterator.hasNext()) {
 +                    while (iterator.hasNext()) {
 +                        final Traverser t = (Traverser) iterator.next();
 +                        if (!(t.path() instanceof EmptyPath)) {
 +                            final int pathLength = t.path().size();
 +                            final List<Pair<Vertex, Integer>> memoryValue = new LinkedList<>();
 +                            memoryValue.add(Pair.with(vertex, pathLength));
 +                            memory.add(LENGTHS_KEY, memoryValue);
 +                        }
 +                    }
 +                }
 +            } else {
 +                if (memory.exists(LENGTHS_KEY)) {
 +                    final List<Pair<Vertex, Integer>> lengths = memory.get(LENGTHS_KEY);
 +                    for (final Pair<Vertex, Integer> pair : lengths) {
 +                        if (pair.getValue0().equals(vertex)) {
 +                            vertex.property(VertexProperty.Cardinality.list, propertyKey, pair.getValue1());
 +                        }
 +                    }
 +                }
 +            }
 +        }
 +
 +        @Override
 +        public boolean terminate(final Memory memory) {
 +            return !memory.isInitialIteration();
 +        }
 +
 +        @Override
 +        public Set<MessageScope> getMessageScopes(final Memory memory) {
 +            return Collections.emptySet();
 +        }
 +
 +        @Override
 +        public Set<VertexComputeKey> getVertexComputeKeys() {
 +            return elementComputeKeys;
 +        }
 +
 +        @Override
 +        public Set<MemoryComputeKey> getMemoryComputeKeys() {
 +            return MEMORY_COMPUTE_KEYS;
 +        }
 +
 +        @SuppressWarnings({"CloneDoesntDeclareCloneNotSupportedException", "CloneDoesntCallSuperClone"})
 +        @Override
 +        public VertexProgram<Object> clone() {
 +            return this;
 +        }
 +
 +        @Override
 +        public GraphComputer.ResultGraph getPreferredResultGraph() {
 +            return GraphComputer.ResultGraph.NEW;
 +        }
 +
 +        @Override
 +        public GraphComputer.Persist getPreferredPersist() {
 +            return GraphComputer.Persist.VERTEX_PROPERTIES;
 +        }
 +
 +        @Override
 +        public Set<TraverserRequirement> getTraverserRequirements() {
 +            return this.traverserRequirements;
 +        }
 +
 +        @Override
 +        public Features getFeatures() {
 +            return new Features() {
 +                @Override
 +                public boolean requiresVertexPropertyAddition() {
 +                    return true;
 +                }
 +            };
 +        }
- 
- 
      }
  }


[19/24] tinkerpop git commit: TINKERPOP-1686 Update changelog

Posted by sp...@apache.org.
TINKERPOP-1686 Update changelog


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

Branch: refs/heads/TINKERPOP-1686
Commit: 4ebe832710632bf5a623f1534794d7633fe8bf02
Parents: 4e21a26
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Jun 28 07:38:40 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Jun 28 08:31:46 2017 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                      | 2 ++
 docs/src/upgrade/release-3.3.x.asciidoc | 1 +
 2 files changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4ebe8327/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 64f09c6..4edce2c 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,8 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.3.0 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* `TraversalMetrics` and `Metrics` Gryo formats changed given internal changes to the implementations.
+* Made `TraversalMetrics` safe to write to from multiple threads.
 * Graphite and Ganglia are no longer packaged with the Gremlin Server distribution.
 * `TransactionException` is no longer a class of `AbstractTransaction` and it extends `RuntimeException`.
 * Included an ellipse on long property names that are truncated.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4ebe8327/docs/src/upgrade/release-3.3.x.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/upgrade/release-3.3.x.asciidoc b/docs/src/upgrade/release-3.3.x.asciidoc
index 6fefe28..e22cf59 100644
--- a/docs/src/upgrade/release-3.3.x.asciidoc
+++ b/docs/src/upgrade/release-3.3.x.asciidoc
@@ -113,6 +113,7 @@ Changes to IO
 * Gryo incompatibilities with 3.2.x:
 ** `RequestMessage`
 ** `ResponseMessage`
+** `TraversalMetrics`
 
 Graphite and Ganglia
 ^^^^^^^^^^^^^^^^^^^^


[09/24] tinkerpop git commit: made the Direction method protected.

Posted by sp...@apache.org.
made the Direction method protected.


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

Branch: refs/heads/TINKERPOP-1686
Commit: 5ac61b7af2bb19dff84e100965587bd6eae29029
Parents: 2ba8deb
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Fri Jun 23 09:20:02 2017 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Jun 27 07:50:22 2017 -0600

----------------------------------------------------------------------
 .../gremlin/process/traversal/step/map/EdgeVertexStep.java         | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5ac61b7a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeVertexStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeVertexStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeVertexStep.java
index d7ebd32..8bef835 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeVertexStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeVertexStep.java
@@ -35,7 +35,7 @@ import java.util.Set;
  */
 public class EdgeVertexStep extends FlatMapStep<Edge, Vertex> implements AutoCloseable {
 
-    private Direction direction;
+    protected Direction direction;
 
     public EdgeVertexStep(final Traversal.Admin traversal, final Direction direction) {
         super(traversal);


[18/24] tinkerpop git commit: TINKERPOP-1686 WIP toward thread-safety in metrics

Posted by sp...@apache.org.
TINKERPOP-1686 WIP toward thread-safety in metrics

Cleaned up javadocs a bit. Added synchronization around setMetrics().


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

Branch: refs/heads/TINKERPOP-1686
Commit: 909c1f6d6462609d537db89adde92c291d7ff449
Parents: ea20ca1
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Jun 7 09:39:07 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Jun 28 08:31:46 2017 -0400

----------------------------------------------------------------------
 .../process/traversal/step/Profiling.java       |   6 +-
 .../step/sideEffect/ProfileSideEffectStep.java  |  14 ++-
 .../traversal/step/util/ProfileStep.java        |   3 +
 .../traversal/util/DefaultTraversalMetrics.java | 114 ++++++++++++-------
 .../traversal/util/TraversalMetrics.java        |   8 +-
 5 files changed, 96 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/909c1f6d/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Profiling.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Profiling.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Profiling.java
index 3e4ff19..5fa53ee 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Profiling.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Profiling.java
@@ -18,11 +18,13 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.step;
 
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ProfileStrategy;
 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.
+ * A {@link Step} can implement this interface in order to receive a reference to the {@link MutableMetrics} object
+ * for the {@link Step}. The {@link MutableMetrics} is initialized when the {@link ProfileStrategy} executes.
  *
  * @author Bob Briody (http://bobbriody.com)
  */

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/909c1f6d/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ProfileSideEffectStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ProfileSideEffectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ProfileSideEffectStep.java
index be60808..5a60d02 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ProfileSideEffectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ProfileSideEffectStep.java
@@ -45,7 +45,7 @@ public final class ProfileSideEffectStep<S> extends SideEffectStep<S> implements
     }
 
     @Override
-    protected void sideEffect(Traverser.Admin<S> traverser) {
+    protected void sideEffect(final Traverser.Admin<S> traverser) {
     }
 
     @Override
@@ -61,7 +61,8 @@ public final class ProfileSideEffectStep<S> extends SideEffectStep<S> implements
             return start;
         } finally {
             if (!this.onGraphComputer && start == null) {
-                ((DefaultTraversalMetrics) this.getTraversal().getSideEffects().get(this.sideEffectKey)).setMetrics(this.getTraversal(), false);
+                final DefaultTraversalMetrics m = getTraversalMetricsFromSideEffects();
+                if (!m.isFinalized()) m.setMetrics(this.getTraversal(), false);
             }
         }
     }
@@ -70,14 +71,19 @@ public final class ProfileSideEffectStep<S> extends SideEffectStep<S> implements
     public boolean hasNext() {
         boolean start = super.hasNext();
         if (!this.onGraphComputer && !start) {
-            ((DefaultTraversalMetrics) this.getTraversal().getSideEffects().get(this.sideEffectKey)).setMetrics(this.getTraversal(), false);
+            final DefaultTraversalMetrics m = getTraversalMetricsFromSideEffects();
+            if (!m.isFinalized()) m.setMetrics(this.getTraversal(), false);
         }
         return start;
     }
 
+    private DefaultTraversalMetrics getTraversalMetricsFromSideEffects() {
+        return (DefaultTraversalMetrics) this.getTraversal().getSideEffects().get(this.sideEffectKey);
+    }
+
     @Override
     public DefaultTraversalMetrics generateFinalResult(final DefaultTraversalMetrics tm) {
-        if (this.onGraphComputer)
+        if (this.onGraphComputer && !tm.isFinalized())
             tm.setMetrics(this.getTraversal(), true);
         return tm;
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/909c1f6d/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ProfileStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ProfileStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ProfileStep.java
index 9b2276b..0bc5f4f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ProfileStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ProfileStep.java
@@ -90,6 +90,9 @@ public final class ProfileStep<S> extends AbstractStep<S, S> implements MemoryCo
             this.onGraphComputer = TraversalHelper.onGraphComputer(this.getTraversal());
             this.metrics = new MutableMetrics(this.getPreviousStep().getId(), this.getPreviousStep().toString());
             final Step<?, S> previousStep = this.getPreviousStep();
+
+            // give metrics to the step being profiled so that it can add additional data to the metrics like
+            // annotations
             if (previousStep instanceof Profiling)
                 ((Profiling) previousStep).setMetrics(this.metrics);
         }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/909c1f6d/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java
index c5f290a..0f19ecc 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalMetrics.java
@@ -28,7 +28,6 @@ import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -36,6 +35,9 @@ import java.util.TreeMap;
 import java.util.concurrent.TimeUnit;
 
 /**
+ * Default implementation for {@link TraversalMetrics} that aggregates {@link ImmutableMetrics} instances from a
+ * {@link Traversal}.
+ *
  * @author Bob Briody (http://bobbriody.com)
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
@@ -48,12 +50,21 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
     private final Map<String, MutableMetrics> metrics = new HashMap<>();
     private final TreeMap<Integer, String> indexToLabelMap = new TreeMap<>();
 
-    /*
-    The following are computed values upon the completion of profiling in order to report the results back to the user
+    /**
+     * A computed value representing the total time spent on all steps.
      */
     private long totalStepDuration;
+
+    /**
+     * The metrics that are reported to the caller of profile() which are computed once all metrics have been gathered.
+     */
     private Map<String, ImmutableMetrics> computedMetrics;
 
+    /**
+     * Determines if final metrics have been computed
+     */
+    private volatile boolean finalized = false;
+
     public DefaultTraversalMetrics() {
     }
 
@@ -62,7 +73,7 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
      */
     public DefaultTraversalMetrics(final long totalStepDurationNs, final List<MutableMetrics> metricsMap) {
         this.totalStepDuration = totalStepDurationNs;
-        this.computedMetrics = new LinkedHashMap<>(this.metrics.size());
+        this.computedMetrics = new LinkedHashMap<>(metricsMap.size());
         metricsMap.forEach(metric -> this.computedMetrics.put(metric.getId(), metric.getImmutableClone()));
     }
 
@@ -87,6 +98,10 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
         return this.computedMetrics.values();
     }
 
+    public boolean isFinalized() {
+        return finalized;
+    }
+
     @Override
     public String toString() {
         // Build a pretty table of metrics data.
@@ -106,6 +121,18 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
         return sb.toString();
     }
 
+    /**
+     * Extracts metrics from the provided {@code traversal} and computes metrics. Calling this method finalizes the
+     * metrics such that their values can no longer be modified.
+     */
+    public synchronized void setMetrics(final Traversal.Admin traversal, final boolean onGraphComputer) {
+        if (finalized) throw new IllegalStateException("Metrics have been finalized");
+        finalized = true;
+        addTopLevelMetrics(traversal, onGraphComputer);
+        handleNestedTraversals(traversal, null, onGraphComputer);
+        computeTotals();
+    }
+
     private void appendMetrics(final Collection<? extends Metrics> metrics, final StringBuilder sb, final int indent) {
         // Append each StepMetric's row. indexToLabelMap values are ordered by index.
         for (Metrics m : metrics) {
@@ -217,41 +244,7 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
         tempMetrics.forEach(it -> this.computedMetrics.put(it.getId(), it.getImmutableClone()));
     }
 
-    public static DefaultTraversalMetrics merge(final Iterator<DefaultTraversalMetrics> toMerge) {
-        final DefaultTraversalMetrics newTraversalMetrics = new DefaultTraversalMetrics();
-
-        // iterate the incoming TraversalMetrics
-        toMerge.forEachRemaining(inTraversalMetrics -> {
-            // aggregate the internal Metrics
-            inTraversalMetrics.metrics.forEach((metricsId, toAggregate) -> {
-
-                MutableMetrics aggregateMetrics = newTraversalMetrics.metrics.get(metricsId);
-                if (null == aggregateMetrics) {
-                    // need to create a Metrics to aggregate into
-                    aggregateMetrics = new MutableMetrics(toAggregate.getId(), toAggregate.getName());
-
-                    newTraversalMetrics.metrics.put(metricsId, aggregateMetrics);
-                    // Set the index of the Metrics
-                    for (final Map.Entry<Integer, String> entry : inTraversalMetrics.indexToLabelMap.entrySet()) {
-                        if (metricsId.equals(entry.getValue())) {
-                            newTraversalMetrics.indexToLabelMap.put(entry.getKey(), metricsId);
-                            break;
-                        }
-                    }
-                }
-                aggregateMetrics.aggregate(toAggregate);
-            });
-        });
-        return newTraversalMetrics;
-    }
-
-    public void setMetrics(final Traversal.Admin traversal, final boolean onGraphComputer) {
-        addTopLevelMetrics(traversal, onGraphComputer);
-        handleNestedTraversals(traversal, null, onGraphComputer);
-        computeTotals();
-    }
-
-    private void addTopLevelMetrics(Traversal.Admin traversal, final boolean onGraphComputer) {
+    private void addTopLevelMetrics(final Traversal.Admin traversal, final boolean onGraphComputer) {
         final List<ProfileStep> profileSteps = TraversalHelper.getStepsOfClass(ProfileStep.class, traversal);
         for (int ii = 0; ii < profileSteps.size(); ii++) {
             // The index is necessary to ensure that step order is preserved after a merge.
@@ -303,4 +296,47 @@ public final class DefaultTraversalMetrics implements TraversalMetrics, Serializ
             }
         }
     }
+
+    private void appendMetrics(final Collection<? extends Metrics> metrics, final StringBuilder sb, final int indent) {
+        // 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);
+
+            // 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);
+
+            // 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(" %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/tinkerpop/blob/909c1f6d/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalMetrics.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalMetrics.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalMetrics.java
index 6a54680..0dbb2f6 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalMetrics.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalMetrics.java
@@ -46,15 +46,13 @@ public interface TraversalMetrics {
     /**
      * Get the total duration taken by the Traversal.
      *
-     * @param unit
      * @return total duration taken by the Traversal.
      */
-    public long getDuration(TimeUnit unit);
+    public long getDuration(final TimeUnit unit);
 
     /**
      * Get an individual Metrics object by the index of the profiled Step.
      *
-     * @param stepIndex
      * @return an individual Metrics object.
      */
     public Metrics getMetrics(final int stepIndex);
@@ -62,10 +60,12 @@ public interface TraversalMetrics {
     /**
      * Get an individual Metrics object by the id of the profiled Step.
      *
-     * @param id
      * @return an individual Metrics object.
      */
     public Metrics getMetrics(final String id);
 
+    /**
+     * Gets all the metrics.
+     */
     public Collection<? extends Metrics> getMetrics();
 }


[17/24] tinkerpop git commit: Merge branch 'tp32'

Posted by sp...@apache.org.
Merge branch 'tp32'


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

Branch: refs/heads/TINKERPOP-1686
Commit: ea20ca1926b17bca08517ed27793598805341715
Parents: 55af79f 9436585
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Jun 27 10:04:50 2017 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Jun 27 10:04:50 2017 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  2 +
 .../process/computer/GraphComputerTest.java     | 75 ++++++++++++++++++--
 .../process/computer/TinkerMessageBoard.java    |  4 +-
 .../process/computer/TinkerMessenger.java       | 22 +++---
 4 files changed, 86 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


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

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ea20ca19/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
----------------------------------------------------------------------


[07/24] tinkerpop git commit: Fixed dev docs for expected SASL value

Posted by sp...@apache.org.
Fixed dev docs for expected SASL value

This was changed long ago on TINKERPOP-1600 but the docs went stale. Note that the byte array is still supported on 3.2.x. It goes away in 3.3.0.


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

Branch: refs/heads/TINKERPOP-1686
Commit: 1518cc420cc35939aafae790ed79eedfe3751766
Parents: 8bb9908
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Mon Jun 26 14:29:56 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Mon Jun 26 14:29:56 2017 -0400

----------------------------------------------------------------------
 docs/src/dev/provider/index.asciidoc | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/1518cc42/docs/src/dev/provider/index.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/dev/provider/index.asciidoc b/docs/src/dev/provider/index.asciidoc
index 39c235b..de8be1f 100644
--- a/docs/src/dev/provider/index.asciidoc
+++ b/docs/src/dev/provider/index.asciidoc
@@ -827,7 +827,7 @@ evaluated and is committed when the script completes (or rolled back if an error
 [width="100%",cols="2,2,9",options="header"]
 |=========================================================
 |Key |Type |Description
-|sasl |byte[] | *Required* The response to the server authentication challenge.  This value is dependent on the SASL authentication mechanism required by the server.
+|sasl |String | *Required* The response to the server authentication challenge.  This value is dependent on the SASL authentication mechanism required by the server and is Base64 encoded.
 |saslMechanism |String | The SASL mechanism: `PLAIN` or `GSSAPI`. Note that it is up to the server implementation to use or disregard this setting (default implementation in Gremlin Server ignores it).
 |=========================================================
 
@@ -874,7 +874,7 @@ Gremlin Server are deployed, session state is not shared among them.
 |=========================================================
 |Key |Type |Description
 |saslMechanism |String | The SASL mechanism: `PLAIN` or `GSSAPI`. Note that it is up to the server implementation to use or disregard this setting (default implementation in Gremlin Server ignores it).
-|sasl |byte[] | *Required* The response to the server authentication challenge.  This value is dependent on the SASL authentication mechanism required by the server.
+|sasl |String | *Required* The response to the server authentication challenge.  This value is dependent on the SASL authentication mechanism required by the server and is Base64 encoded.
 |=========================================================
 
 '`eval` operation arguments'
@@ -975,7 +975,7 @@ operation is available to clear the cache of a specific side-effect.
 [width="100%",cols="2,2,9",options="header"]
 |=========================================================
 |Key |Type |Description
-|sasl |byte[] | *Required* The response to the server authentication challenge.  This value is dependent on the SASL authentication mechanism required by the server.
+|sasl |String | *Required* The response to the server authentication challenge.  This value is dependent on the SASL authentication mechanism required by the server and is Base64 encoded.
 |=========================================================
 
 '`bytecode` operation arguments'


[10/24] tinkerpop git commit: EdgeVertexStep is no longer final and can be extended by providers.

Posted by sp...@apache.org.
EdgeVertexStep is no longer final and can be extended by providers.


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

Branch: refs/heads/TINKERPOP-1686
Commit: 2ba8debdabfdfdcdce231477b3584299746e9c8c
Parents: 1518cc4
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Thu Jun 22 07:15:15 2017 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Jun 27 07:50:22 2017 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc                                                 | 1 +
 .../gremlin/process/traversal/step/map/EdgeVertexStep.java         | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2ba8debd/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 7a69469..1b46dcf 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -29,6 +29,7 @@ TinkerPop 3.2.6 (Release Date: NOT OFFICIALLY RELEASED YET)
 This release also includes changes from <<release-3-1-8, 3.1.8>>.
 
 * Added annotations to the traversal metrics pretty print.
+* `EdgeVertexStep` is no longer final and can be extended by providers.
 * Fixed `HADOOP_GREMLIN_LIBS` parsing for Windows.
 * Improved GraphSON serialization performance around `VertexProperty`.
 * Changed some tests in `EventStrategyProcessTest` which were enforcing some unintended semantics around transaction state.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2ba8debd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeVertexStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeVertexStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeVertexStep.java
index 87c1561..d7ebd32 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeVertexStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeVertexStep.java
@@ -33,7 +33,7 @@ import java.util.Set;
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class EdgeVertexStep extends FlatMapStep<Edge, Vertex> implements AutoCloseable {
+public class EdgeVertexStep extends FlatMapStep<Edge, Vertex> implements AutoCloseable {
 
     private Direction direction;
 


[15/24] tinkerpop git commit: tweaked the MessageScope bug fix test to use MODERN so it works with Spark and Giraph. Simple tweak to test data, not semantics. CTR.

Posted by sp...@apache.org.
tweaked the MessageScope bug fix test to use MODERN so it works with Spark and Giraph. Simple tweak to test data, not semantics. CTR.


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

Branch: refs/heads/TINKERPOP-1686
Commit: e7f5ef711b1edbd130f23610d993e13d44d5df50
Parents: 3b8c628
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Jun 27 09:55:35 2017 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Jun 27 09:55:35 2017 -0600

----------------------------------------------------------------------
 .../process/computer/GraphComputerTest.java     | 42 +++++---------------
 1 file changed, 10 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e7f5ef71/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
index 02ac5d4..e2acd5e 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
@@ -26,7 +26,6 @@ import org.apache.tinkerpop.gremlin.process.computer.util.StaticMapReduce;
 import org.apache.tinkerpop.gremlin.process.computer.util.StaticVertexProgram;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Element;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
@@ -41,7 +40,6 @@ import java.util.Comparator;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentSkipListSet;
@@ -1472,27 +1470,16 @@ public class GraphComputerTest extends AbstractGremlinProcessTest {
 
     /////////////////////////////////////////////
     @Test
+    @LoadGraphWith(MODERN)
     public void shouldSupportMultipleScopes() throws ExecutionException, InterruptedException {
-        Vertex a = graph.addVertex("a");
-        Vertex b = graph.addVertex("b");
-        Vertex c = graph.addVertex("c");
-        a.addEdge("edge", b);
-        b.addEdge("edge", c);
-
-        // Simple graph:
-        // a -> b -> c
-
-        // Execute a traversal program that sends an incoming message of "2" and an outgoing message of "1" from "b"
-        // then each vertex sums any received messages
-        ComputerResult result = graph.compute().program(new MultiScopeVertexProgram()).submit().get();
-
-        // We expect the results to be {a=2, b=0, c=1}. Instead it is {a=3, b=0, c=3}
-        assertEquals((Long) result.graph().traversal().V().hasLabel("a").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(),Long.valueOf(2L));
-        assertEquals((Long) result.graph().traversal().V().hasLabel("b").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(),Long.valueOf(0L));
-        assertEquals((Long) result.graph().traversal().V().hasLabel("c").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(),Long.valueOf(1L));
+        final ComputerResult result = graph.compute(graphComputerClass.get()).program(new MultiScopeVertexProgram()).submit().get();
+        assertEquals(result.graph().traversal().V().has("name", "josh").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(), 0L);
+        assertEquals(result.graph().traversal().V().has("name", "lop").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(), 1L);
+        assertEquals(result.graph().traversal().V().has("name", "ripple").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(), 1L);
+        assertEquals(result.graph().traversal().V().has("name", "marko").next().property(MultiScopeVertexProgram.MEMORY_KEY).value(), 2L);
     }
 
-    public static class MultiScopeVertexProgram implements VertexProgram<Long> {
+    public static class MultiScopeVertexProgram extends StaticVertexProgram<Long> {
 
         private final MessageScope.Local<Long> countMessageScopeIn = MessageScope.Local.of(__::inE);
         private final MessageScope.Local<Long> countMessageScopeOut = MessageScope.Local.of(__::outE);
@@ -1502,7 +1489,8 @@ public class GraphComputerTest extends AbstractGremlinProcessTest {
         private static final Set<String> COMPUTE_KEYS = Collections.singleton(MEMORY_KEY);
 
         @Override
-        public void setup(final Memory memory) {}
+        public void setup(final Memory memory) {
+        }
 
         @Override
         public GraphComputer.Persist getPreferredPersist() {
@@ -1526,7 +1514,7 @@ public class GraphComputerTest extends AbstractGremlinProcessTest {
         public void execute(Vertex vertex, Messenger<Long> messenger, Memory memory) {
             switch (memory.getIteration()) {
                 case 0:
-                    if (vertex.label().equals("b")) {
+                    if (vertex.value("name").equals("josh")) {
                         messenger.sendMessage(this.countMessageScopeIn, 2L);
                         messenger.sendMessage(this.countMessageScopeOut, 1L);
                     }
@@ -1548,15 +1536,5 @@ public class GraphComputerTest extends AbstractGremlinProcessTest {
             return GraphComputer.ResultGraph.NEW;
         }
 
-        @Override
-        public MultiScopeVertexProgram clone() {
-            try {
-                return (MultiScopeVertexProgram) super.clone();
-            } catch (final CloneNotSupportedException e) {
-                throw new RuntimeException(e);
-            }
-        }
-
     }
-
 }


[06/24] tinkerpop git commit: Merge branch 'TINKERPOP-1445'

Posted by sp...@apache.org.
Merge branch 'TINKERPOP-1445'

Conflicts:
	CHANGELOG.asciidoc


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

Branch: refs/heads/TINKERPOP-1686
Commit: 7d2b46b0f25471d7648e74c15afeb0653d05c084
Parents: 77c0477 47afd7a
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Mon Jun 26 10:18:12 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Mon Jun 26 10:18:12 2017 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 .../gremlin/structure/util/StringFactory.java   |  9 +++----
 .../gremlin/structure/PropertyTest.java         | 28 +++++++++++++++++++-
 3 files changed, 31 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/7d2b46b0/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --cc CHANGELOG.asciidoc
index 4e4844c,eb8ad8a..c34b3ff
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@@ -26,8 -26,7 +26,9 @@@ image::https://raw.githubusercontent.co
  TinkerPop 3.3.0 (Release Date: NOT OFFICIALLY RELEASED YET)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
 +* Graphite and Ganglia are no longer packaged with the Gremlin Server distribution.
 +* `TransactionException` is no longer a class of `AbstractTransaction` and it extends `RuntimeException`.
+ * Included an ellipse on long property names that are truncated.
  * Renamed `RangeByIsCountStrategy` to `CountStrategy`.
  * Added more specific typing to various `__` traversal steps. E.g. `<A,Vertex>out()` is `<Vertex,Vertex>out()`.
  * Updated Docker build scripts to include Python dependencies (NOTE: users should remove any previously generated TinkerPop Docker images).


[21/24] tinkerpop git commit: TINKERPOP-1686 Made MutableMetrics thread-safe for nested results and counts

Posted by sp...@apache.org.
TINKERPOP-1686 Made MutableMetrics thread-safe for nested results and counts


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

Branch: refs/heads/TINKERPOP-1686
Commit: 7c5294badbf37cd45dd375e2dc207be0a0b11243
Parents: 4ebe832
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Jun 28 07:55:51 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Jun 28 08:31:46 2017 -0400

----------------------------------------------------------------------
 .../gremlin/process/traversal/util/ImmutableMetrics.java     | 8 ++++++--
 .../gremlin/process/traversal/util/MutableMetrics.java       | 5 ++++-
 2 files changed, 10 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/7c5294ba/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 a563bbd..d2b1430 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
@@ -23,11 +23,15 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
 
 /**
+ * A {@link Metrics} implementation that cannot be modified.
+ *
  * @author Bob Briody (http://bobbriody.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public class ImmutableMetrics implements Metrics, Serializable {
 
@@ -35,9 +39,9 @@ public class ImmutableMetrics implements Metrics, Serializable {
 
     protected String id;
     protected String name;
-    protected Map<String, AtomicLong> counts = new HashMap<>();
+    protected Map<String, AtomicLong> counts = new ConcurrentHashMap<>();
     protected long durationNs = 0l;
-    protected final Map<String, Object> annotations = new HashMap<>();
+    protected final Map<String, Object> annotations = new ConcurrentHashMap<>();
     protected final Map<String, ImmutableMetrics> nested = new LinkedHashMap<>();
 
     protected ImmutableMetrics() {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/7c5294ba/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/MutableMetrics.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/MutableMetrics.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/MutableMetrics.java
index 34fa370..b3ee5f0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/MutableMetrics.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/MutableMetrics.java
@@ -27,7 +27,10 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
 
 /**
+ * A {@link Metrics} implementation that can be modified.
+ *
  * @author Bob Briody (http://bobbriody.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public class MutableMetrics extends ImmutableMetrics implements Cloneable {
 
@@ -61,7 +64,7 @@ public class MutableMetrics extends ImmutableMetrics implements Cloneable {
         other.getNested().forEach(nested -> this.addNested(new MutableMetrics(nested)));
     }
 
-    public void addNested(final MutableMetrics metrics) {
+    public synchronized void addNested(final MutableMetrics metrics) {
         if (finalized) throw new IllegalStateException("Metrics have been finalized and cannot be modified");
         this.nested.put(metrics.getId(), metrics);
     }


[05/24] tinkerpop git commit: Merge branch 'TINKERPOP-1004'

Posted by sp...@apache.org.
Merge branch 'TINKERPOP-1004'

Conflicts:
	CHANGELOG.asciidoc


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

Branch: refs/heads/TINKERPOP-1686
Commit: 77c0477f539c41cf48da2936fee85f7ab003b517
Parents: 685d1ed eb0eddc
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Mon Jun 26 10:15:57 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Mon Jun 26 10:15:57 2017 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 docs/src/upgrade/release-3.3.x.asciidoc         | 66 +++++++++++---------
 .../gremlin/structure/Transaction.java          |  9 ++-
 .../structure/util/AbstractTransaction.java     | 34 ++--------
 .../structure/util/TransactionException.java    | 42 +++++++++++++
 .../gremlin/neo4j/structure/Neo4jGraph.java     |  1 +
 6 files changed, 93 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/77c0477f/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --cc CHANGELOG.asciidoc
index f6fcfff,610cf7e..4e4844c
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@@ -26,7 -26,7 +26,8 @@@ image::https://raw.githubusercontent.co
  TinkerPop 3.3.0 (Release Date: NOT OFFICIALLY RELEASED YET)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
 +* Graphite and Ganglia are no longer packaged with the Gremlin Server distribution.
+ * `TransactionException` is no longer a class of `AbstractTransaction` and it extends `RuntimeException`.
  * Renamed `RangeByIsCountStrategy` to `CountStrategy`.
  * Added more specific typing to various `__` traversal steps. E.g. `<A,Vertex>out()` is `<Vertex,Vertex>out()`.
  * Updated Docker build scripts to include Python dependencies (NOTE: users should remove any previously generated TinkerPop Docker images).

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/77c0477f/docs/src/upgrade/release-3.3.x.asciidoc
----------------------------------------------------------------------
diff --cc docs/src/upgrade/release-3.3.x.asciidoc
index 20a29de,ea8be1b..6fefe28
--- a/docs/src/upgrade/release-3.3.x.asciidoc
+++ b/docs/src/upgrade/release-3.3.x.asciidoc
@@@ -341,3 -294,41 +313,41 @@@ spark.serializer=org.apache.tinkerpop.g
  ```
  
  See: link:https://issues.apache.org/jira/browse/TINKERPOP-1389
+ 
+ Upgrading for Providers
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ 
+ Graph Database Providers
+ ^^^^^^^^^^^^^^^^^^^^^^^^
+ 
+ Test Suite Removal
+ ++++++++++++++++++
+ 
+ A number of test suites that were previously deprecated have been removed which should reduce the burden on graph
+ providers who are implementing TinkerPop. Test suites related to perfrmance based on `junit-benchmarks` have been
+ removed as have the suites in `gremlin-groovy-test` (in fact, this entire module has been removed). Specifically,
+ providers should be concerned with breaking changes related to the removal of:
+ 
+ * `StructurePerformanceSuite`
+ * `ProcessPerformanceSuite`
+ * `GroovyEnvironmentPerformanceSuite`
+ * `GroovyProcessStandardSuite`
+ * `GroovyProcessComputerSuite`
+ * `GroovyEnvironmentSuite`
+ * `GroovyEnvironmentIntegrateSuite`
+ 
+ Those graph providers who relied on these tests should simply remove them from their respective test suites. Beware of
+ `OptOut` annotations that reference tests in these suites as test failure will occur if those references are not
+ removed.
+ 
+ See: link:https://issues.apache.org/jira/browse/TINKERPOP-1235[TINKERPOP-1235], link:https://issues.apache.org/jira/browse/TINKERPOP-1612[TINKERPOP-1612]
+ 
+ TransactionException
+ ++++++++++++++++++++
+ 
+ The `AbstractTransaction.TransactionException` class is now just `TransactionException` which extends `RuntimeExcetpion`
+ rather than `Exception`. Providers should consider using this exception to wrap their own on calls to
+ `Transaction.commit()` or `Transaction.rollback()`. By throwing this exception, the TinkerPop stack can better respond
+ to transaction problems and it allows for more common, generalized error handling for users.
+ 
 -See: link:https://issues.apache.org/jira/browse/TINKERPOP-1004[TINKERPOP-1004]
++See: link:https://issues.apache.org/jira/browse/TINKERPOP-1004[TINKERPOP-1004]