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/01/23 12:45:41 UTC

[01/17] tinkerpop git commit: Created OrdertedTraverser which allows us to move beyond the star graph for OrderGlobalStep by()-projections. Moreover, it reduces the complexity of ordering as the objects of comparison are already determined. Going to gene [Forced Update!]

Repository: tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1560 061bbc42c -> 97265772d (forced update)


Created OrdertedTraverser which allows us to move beyond the star graph for OrderGlobalStep by()-projections. Moreover, it reduces the complexity of ordering as the objects of comparison are already determined. Going to generalize fully to a ProjectedTraverser which will allow us to do the same for SampleGlobalStep, DedupGlobalStep, and down the road maintain order even as the computation is re-distributed to workers.


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

Branch: refs/heads/TINKERPOP-1560
Commit: 501e97a1ecb23f76b2fddba8eaed1dba4a5a839e
Parents: e80a4cd
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Wed Jan 18 09:08:24 2017 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Wed Jan 18 09:08:24 2017 -0700

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   1 +
 .../traversal/step/map/OrderGlobalStep.java     |  61 ++---
 .../step/util/CollectingBarrierStep.java        |   4 +-
 .../ComputerVerificationStrategy.java           |   5 +-
 .../traversal/traverser/OrderedTraverser.java   | 235 +++++++++++++++++++
 .../gremlin/structure/io/gryo/GryoVersion.java  |   4 +-
 6 files changed, 277 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/501e97a1/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 4f3f9ce..86c6b4f 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.4 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* `OrderGlobalStep` now emits traversers with their `by()`-projections and thus, can move beyond the local star graph.
 * SASL negotiation supports both a byte array and Base64 encoded bytes as a string for authentication to Gremlin Server.
 * Deprecated `TinkerIoRegistry` replacing it with the more consistently named `TinkerIoRegistryV1d0`.
 * Made error messaging more consistent during result iteration timeouts in Gremlin Server.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/501e97a1/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
index a7d21b2..ac5df90 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
@@ -27,10 +27,10 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.ComparatorHolder;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.CollectingBarrierStep;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.OrderedTraverser;
 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.util.StringFactory;
-import org.apache.tinkerpop.gremlin.util.function.ChainedComparator;
 import org.javatuples.Pair;
 
 import java.io.Serializable;
@@ -49,8 +49,8 @@ import java.util.stream.Collectors;
 public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBarrierStep<S> implements ComparatorHolder<S, C>, TraversalParent, ByModulating {
 
     private List<Pair<Traversal.Admin<S, C>, Comparator<C>>> comparators = new ArrayList<>();
-    private ChainedComparator<S, C> chainedComparator = null;
     private long limit = Long.MAX_VALUE;
+    private boolean isShuffle = false;
 
     public OrderGlobalStep(final Traversal.Admin traversal) {
         super(traversal);
@@ -58,12 +58,30 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
 
     @Override
     public void barrierConsumer(final TraverserSet<S> traverserSet) {
-        if (null == this.chainedComparator)
-            this.chainedComparator = new ChainedComparator<>(true, this.comparators);
-        if (this.chainedComparator.isShuffle())
+        if (this.isShuffle)
             traverserSet.shuffle();
         else
-            traverserSet.sort((Comparator) this.chainedComparator);
+            traverserSet.sort(Comparator.naturalOrder());
+    }
+
+    @Override
+    public void processAllStarts() {
+        if (this.starts.hasNext()) {
+            while (this.starts.hasNext()) {
+                this.traverserSet.add(new OrderedTraverser<S>(this.starts.next(), (List) this.comparators));
+            }
+            this.barrierConsumer(this.traverserSet);
+        }
+    }
+
+    @Override
+    public Traverser.Admin<S> processNextStart() {
+        if (!this.traverserSet.isEmpty()) {
+            return this.traverserSet.remove();
+        } else if (this.starts.hasNext()) {
+            this.processAllStarts();
+        }
+        return ((OrderedTraverser) this.traverserSet.remove()).getInternal();
     }
 
     public void setLimit(final long limit) {
@@ -76,6 +94,7 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
 
     @Override
     public void addComparator(final Traversal.Admin<S, C> traversal, final Comparator<C> comparator) {
+        this.isShuffle = Order.shuffle == (Comparator) comparator;
         this.comparators.add(new Pair<>(this.integrateChild(traversal), comparator));
     }
 
@@ -125,7 +144,6 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
         for (final Pair<Traversal.Admin<S, C>, Comparator<C>> comparator : this.comparators) {
             clone.comparators.add(new Pair<>(comparator.getValue0().clone(), comparator.getValue1()));
         }
-        clone.chainedComparator = null;
         return clone;
     }
 
@@ -137,47 +155,34 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
 
     @Override
     public MemoryComputeKey<TraverserSet<S>> getMemoryComputeKey() {
-        if (null == this.chainedComparator)
-            this.chainedComparator = new ChainedComparator<>(true, this.comparators);
-        return MemoryComputeKey.of(this.getId(), new OrderBiOperator<>(this.chainedComparator, this.limit), false, true);
+        return MemoryComputeKey.of(this.getId(), new OrderBiOperator<>(this.limit, this.isShuffle), false, true);
     }
 
     ////////////////
 
-    public static final class OrderBiOperator<S> implements BinaryOperator<TraverserSet<S>>, Serializable, Cloneable {
+    public static final class OrderBiOperator<S> implements BinaryOperator<TraverserSet<S>>, Serializable {
 
-        private ChainedComparator chainedComparator;
         private long limit;
+        private boolean isShuffle;
 
         private OrderBiOperator() {
             // for serializers that need a no-arg constructor
         }
 
-        public OrderBiOperator(final ChainedComparator<S, ?> chainedComparator, final long limit) {
-            this.chainedComparator = chainedComparator;
+        public OrderBiOperator(final long limit, final boolean isShuffle) {
             this.limit = limit;
-        }
-
-        @Override
-        public OrderBiOperator<S> clone() {
-            try {
-                final OrderBiOperator<S> clone = (OrderBiOperator<S>) super.clone();
-                clone.chainedComparator = this.chainedComparator.clone();
-                return clone;
-            } catch (final CloneNotSupportedException e) {
-                throw new IllegalStateException(e.getMessage(), e);
-            }
+            this.isShuffle = isShuffle;
         }
 
         @Override
         public TraverserSet<S> apply(final TraverserSet<S> setA, final TraverserSet<S> setB) {
             setA.addAll(setB);
             if (Long.MAX_VALUE != this.limit && setA.bulkSize() > this.limit) {
-                if (this.chainedComparator.isShuffle())
+                if (this.isShuffle)
                     setA.shuffle();
                 else
-                    setA.sort(this.chainedComparator);
-                long counter = 0l;
+                    setA.sort(Comparator.naturalOrder());
+                long counter = 0L;
                 final Iterator<Traverser.Admin<S>> traversers = setA.iterator();
                 while (traversers.hasNext()) {
                     final Traverser.Admin<S> traverser = traversers.next();

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/501e97a1/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java
index f9c85a2..b0cce80 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java
@@ -39,8 +39,8 @@ import java.util.function.BinaryOperator;
  */
 public abstract class CollectingBarrierStep<S> extends AbstractStep<S, S> implements Barrier<TraverserSet<S>> {
 
-    private TraverserSet<S> traverserSet = new TraverserSet<>();
-    private int maxBarrierSize;
+    protected TraverserSet<S> traverserSet = new TraverserSet<>();
+    protected int maxBarrierSize;
 
     public CollectingBarrierStep(final Traversal.Admin traversal) {
         this(traversal, Integer.MAX_VALUE);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/501e97a1/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ComputerVerificationStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ComputerVerificationStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ComputerVerificationStrategy.java
index fc73fc3..5777adb 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ComputerVerificationStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ComputerVerificationStrategy.java
@@ -28,6 +28,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.GraphComputing;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Mutating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.SampleGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SubgraphStep;
@@ -86,8 +87,8 @@ public final class ComputerVerificationStrategy extends AbstractTraversalStrateg
                     throw new VerificationException("Local traversals may not traverse past the local star-graph on GraphComputer: " + traversalOptional.get(), traversal);
             }
 
-            // collecting barriers and dedup global use can only operate on the element and its properties (no incidences)
-            if (step instanceof CollectingBarrierStep && step instanceof TraversalParent) {
+            // sample step use can only operate on the element and its properties (no incidences)
+            if (step instanceof SampleGlobalStep) {
                 if (((TraversalParent) step).getLocalChildren().stream().filter(t -> !TraversalHelper.isLocalProperties(t)).findAny().isPresent())
                     throw new VerificationException("The following barrier step can not process the incident edges of a vertex on GraphComputer: " + step, traversal);
             }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/501e97a1/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/OrderedTraverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/OrderedTraverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/OrderedTraverser.java
new file mode 100644
index 0000000..4dddaa3
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/OrderedTraverser.java
@@ -0,0 +1,235 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.tinkerpop.gremlin.process.traversal.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Order;
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
+import org.apache.tinkerpop.gremlin.structure.util.Attachable;
+import org.javatuples.Pair;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Function;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class OrderedTraverser<T> implements Traverser.Admin<T> {
+
+    private Traverser.Admin<T> internal;
+    private int order;
+    private final List<Pair<Object, Comparator<?>>> orderChecks = new ArrayList<>();
+
+    private OrderedTraverser() {
+        // for serialization
+    }
+
+    public OrderedTraverser(final Traverser.Admin<T> internal, final List<Pair<Traversal.Admin<T, ?>, Comparator>> checks) {
+        this(internal, 0);
+        for (final Pair<Traversal.Admin<T, ?>, Comparator> pairs : checks) {
+            this.orderChecks.add(Pair.with(TraversalUtil.apply(this.internal, pairs.getValue0()), pairs.getValue1()));
+        }
+    }
+
+    public OrderedTraverser(final Traverser.Admin<T> internal, final int order) {
+        this.internal = internal instanceof OrderedTraverser ? ((OrderedTraverser) internal).internal : internal;
+        this.order = order;
+    }
+
+    public Traverser.Admin<T> getInternal() {
+        return this.internal;
+    }
+
+    public int order() {
+        return this.order;
+    }
+
+    @Override
+    public void merge(final Admin<?> other) {
+        this.internal.merge(other);
+    }
+
+    @Override
+    public <R> Admin<R> split(R r, Step<T, R> step) {
+        return new OrderedTraverser<>(this.internal.split(r, step), this.order);
+    }
+
+    @Override
+    public Admin<T> split() {
+        return new OrderedTraverser<>(this.internal.split(), this.order);
+    }
+
+    @Override
+    public void addLabels(final Set<String> labels) {
+        this.internal.addLabels(labels);
+    }
+
+    @Override
+    public void keepLabels(final Set<String> labels) {
+        this.internal.keepLabels(labels);
+    }
+
+    @Override
+    public void dropLabels(final Set<String> labels) {
+        this.internal.dropLabels(labels);
+    }
+
+    @Override
+    public void dropPath() {
+        this.internal.dropPath();
+    }
+
+    @Override
+    public void set(final T t) {
+        this.internal.set(t);
+    }
+
+    @Override
+    public void incrLoops(final String stepLabel) {
+        this.internal.incrLoops(stepLabel);
+    }
+
+    @Override
+    public void resetLoops() {
+        this.internal.resetLoops();
+    }
+
+    @Override
+    public String getStepId() {
+        return this.internal.getStepId();
+    }
+
+    @Override
+    public void setStepId(final String stepId) {
+        this.internal.setStepId(stepId);
+    }
+
+    @Override
+    public void setBulk(final long count) {
+        this.internal.setBulk(count);
+    }
+
+    @Override
+    public Admin<T> detach() {
+        this.internal = this.internal.detach();
+        return this;
+    }
+
+    @Override
+    public T attach(final Function<Attachable<T>, T> method) {
+        return this.internal.attach(method);
+    }
+
+    @Override
+    public void setSideEffects(final TraversalSideEffects sideEffects) {
+        this.internal.setSideEffects(sideEffects);
+    }
+
+    @Override
+    public TraversalSideEffects getSideEffects() {
+        return this.internal.getSideEffects();
+    }
+
+    @Override
+    public Set<String> getTags() {
+        return this.internal.getTags();
+    }
+
+    @Override
+    public T get() {
+        return this.internal.get();
+    }
+
+    @Override
+    public <S> S sack() {
+        return this.internal.sack();
+    }
+
+    @Override
+    public <S> void sack(final S object) {
+        this.internal.sack(object);
+    }
+
+    @Override
+    public Path path() {
+        return this.internal.path();
+    }
+
+    @Override
+    public int loops() {
+        return this.internal.loops();
+    }
+
+    @Override
+    public long bulk() {
+        return this.internal.bulk();
+    }
+
+    @Override
+    public int hashCode() {
+        return this.internal.hashCode();
+    }
+
+    @Override
+    public boolean equals(final Object object) {
+        return object instanceof OrderedTraverser && ((OrderedTraverser) object).internal.equals(this.internal);
+    }
+
+    @Override
+    public OrderedTraverser<T> clone() {
+        try {
+            final OrderedTraverser<T> clone = (OrderedTraverser<T>) super.clone();
+            clone.internal = (Traverser.Admin<T>) this.internal.clone();
+            return clone;
+        } catch (final CloneNotSupportedException e) {
+            throw new IllegalStateException(e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public int compareTo(final Traverser<T> o) {
+        if (!(o instanceof OrderedTraverser))
+            return 0;
+        else {
+            if (this.orderChecks.isEmpty()) {
+                return Order.incr.compare(this.get(), o.get());
+            } else {
+                final OrderedTraverser<T> other = (OrderedTraverser<T>) o;
+                for (int i = 0; i < this.orderChecks.size(); i++) {
+                    final Comparator comparator = this.orderChecks.get(i).getValue1();
+                    final Object thisObject = this.orderChecks.get(i).getValue0();
+                    final Object otherObject = other.orderChecks.get(i).getValue0();
+                    final int comparison = comparator.compare(thisObject, otherObject);
+                    if (comparison != 0)
+                        return comparison;
+
+                }
+                return 0;
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/501e97a1/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 0bd9e87..a04f2d9 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
@@ -51,6 +51,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.traverser.LP_O_OB_P_S_SE_S
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.LP_O_OB_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.O_OB_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.O_Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.OrderedTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
 import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
 import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalMetrics;
@@ -221,7 +222,7 @@ public enum GryoVersion {
             add(GryoTypeReg.of(AbstractMap.SimpleImmutableEntry.class, 121));
             add(GryoTypeReg.of(java.sql.Timestamp.class, 161));
             add(GryoTypeReg.of(InetAddress.class, 162, new UtilSerializers.InetAddressSerializer()));
-            add(GryoTypeReg.of(ByteBuffer.class, 163, new UtilSerializers.ByteBufferSerializer()));  // ***LAST ID***
+            add(GryoTypeReg.of(ByteBuffer.class, 163, new UtilSerializers.ByteBufferSerializer()));
 
             add(GryoTypeReg.of(ReferenceEdge.class, 81));
             add(GryoTypeReg.of(ReferenceVertexProperty.class, 82));
@@ -245,6 +246,7 @@ public enum GryoVersion {
             add(GryoTypeReg.of(O_OB_S_SE_SL_Traverser.class, 89));
             add(GryoTypeReg.of(LP_O_OB_S_SE_SL_Traverser.class, 90));
             add(GryoTypeReg.of(LP_O_OB_P_S_SE_SL_Traverser.class, 91));
+            add(GryoTypeReg.of(OrderedTraverser.class, 164));   // ***LAST ID***
             add(GryoTypeReg.of(DefaultRemoteTraverser.class, 123, new GryoSerializers.DefaultRemoteTraverserSerializer()));
 
             add(GryoTypeReg.of(Bytecode.class, 122, new GryoSerializers.BytecodeSerializer()));


[17/17] tinkerpop git commit: TINKERPOP-1560 Used ManagedConcurrentValueMap in GremlinGroovyClassLoader

Posted by sp...@apache.org.
TINKERPOP-1560 Used ManagedConcurrentValueMap in GremlinGroovyClassLoader

By configuring the ManagedConcurrentValueMap to have weak references, the GremlinGroovyClassLoader, and therefore the GremlinGroovyScriptEngine, are now able to "forget" classes that are no longer used. It was determined that the cache of these classes would grow indefinitely for each script passed to the GremlinGroovyScriptEngine, thus allowing the metaspace to continue to grow. It isn't really possible to write tests to verify that this change works, but I did test manually by watching memory usage in a profiler and could see that metaspace memory stayed stable and that classes were unloading from the classloader over time.


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

Branch: refs/heads/TINKERPOP-1560
Commit: 97265772db79618cd5de83bb45d22f3e2bb6be9e
Parents: f84f454
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri Jan 20 11:54:45 2017 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Mon Jan 23 07:45:26 2017 -0500

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 .../groovy/jsr223/GremlinGroovyClassLoader.java | 24 ++++++++-
 .../jsr223/ManagedConcurrentValueMap.java       |  4 ++
 .../GremlinGroovyScriptEngineIntegrateTest.java | 55 ++++++++++++++++++++
 4 files changed, 82 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/97265772/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index fb0f8da..5e06a1c 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -34,6 +34,7 @@ TinkerPop 3.2.4 (Release Date: NOT OFFICIALLY RELEASED YET)
 * SASL negotiation supports both a byte array and Base64 encoded bytes as a string for authentication to Gremlin Server.
 * Deprecated `TinkerIoRegistry` replacing it with the more consistently named `TinkerIoRegistryV1d0`.
 * Made error messaging more consistent during result iteration timeouts in Gremlin Server.
+* Fixed a memory leak in the classloader for the `GremlinGroovyScriptEngine` where classes in the loader were not releasing from memory as a strong reference was always maintained.
 * `PathRetractionStrategy` does not add a `NoOpBarrierStep` to the end of local children as its wasted computation in 99% of traversals.
 * Fixed a bug in `AddVertexStartStep` where if a side-effect was being used in the parametrization, an NPE occurred.
 * Fixed a bug in `LazyBarrierStrategy` where `profile()` was deactivating it accidentally.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/97265772/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyClassLoader.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyClassLoader.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyClassLoader.java
index e987ce0..2bc122c 100644
--- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyClassLoader.java
+++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyClassLoader.java
@@ -20,19 +20,39 @@ package org.apache.tinkerpop.gremlin.groovy.jsr223;
 
 import groovy.lang.GroovyClassLoader;
 import org.codehaus.groovy.control.CompilerConfiguration;
+import org.codehaus.groovy.util.ReferenceBundle;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
 
 /**
- * A {@code GroovyClassLoader} extension that provides access to the {@code removeClassCacheEntry(String)} method.
+ * A {@code GroovyClassLoader} extension that uses a {@link ManagedConcurrentValueMap} configured with soft references.
+ * In this way, the classloader will "forget" scripts allowing them to be garbage collected and thus prevent memory
+ * issues in JVM metaspace.
  *
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 class GremlinGroovyClassLoader extends GroovyClassLoader {
+    private final ManagedConcurrentValueMap<String, Class> classSoftCache;
+
     public GremlinGroovyClassLoader(final ClassLoader parent, final CompilerConfiguration conf) {
         super(parent, conf);
+        classSoftCache = new ManagedConcurrentValueMap<>(ReferenceBundle.getSoftBundle());
     }
 
     @Override
     protected void removeClassCacheEntry(final String name) {
-        super.removeClassCacheEntry(name);
+        this.classSoftCache.remove(name);
+    }
+
+    @Override
+    protected void setClassCacheEntry(final Class cls) {
+        this.classSoftCache.put(cls.getName(), cls);
+    }
+
+    @Override
+    protected Class getClassCacheEntry(final String name) {
+        if(null == name)  return null;
+        return this.classSoftCache.get(name);
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/97265772/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ManagedConcurrentValueMap.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ManagedConcurrentValueMap.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ManagedConcurrentValueMap.java
index dce056b..f1ee00d 100644
--- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ManagedConcurrentValueMap.java
+++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ManagedConcurrentValueMap.java
@@ -76,6 +76,10 @@ class ManagedConcurrentValueMap<K, V> {
         internalMap.put(key, ref);
     }
 
+    public void remove(final K key) {
+        internalMap.remove(key);
+    }
+
     /**
      * Clear the map.
      */

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/97265772/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/jsr223/GremlinGroovyScriptEngineIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/jsr223/GremlinGroovyScriptEngineIntegrateTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/jsr223/GremlinGroovyScriptEngineIntegrateTest.java
new file mode 100644
index 0000000..5242d3b
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/jsr223/GremlinGroovyScriptEngineIntegrateTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.jsr223;
+
+import org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine;
+import org.javatuples.Pair;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class GremlinGroovyScriptEngineIntegrateTest {
+    @Test
+    @Ignore("This is not a test that needs to run on build - it's more for profiling the GremlinGroovyScriptEngine")
+    public void shouldTest() throws Exception {
+        final Random r = new Random();
+        final List<Pair<String, Integer>> scripts = new ArrayList<>();
+        final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine();
+        for (int ix = 0; ix < 1000000; ix++) {
+            final String script = "1 + " + ix;
+            final int output = (int) engine.eval(script);
+            assertEquals(1 + ix, output);
+
+            if (ix % 1000 == 0) scripts.add(Pair.with(script, output));
+
+            if (ix % 25 == 0) {
+                final Pair<String,Integer> p = scripts.get(r.nextInt(scripts.size()));
+                assertEquals(p.getValue1().intValue(), (int) engine.eval(p.getValue0()));
+            }
+        }
+    }
+}


[02/17] tinkerpop git commit: remember user's working directory when script files are being loaded in execution mode

Posted by sp...@apache.org.
remember user's working directory when script files are being loaded in execution mode


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

Branch: refs/heads/TINKERPOP-1560
Commit: 8fd6dbbe9cc0b98d124cd3fdf739377289300ce8
Parents: e80a4cd
Author: Daniel Kuppitz <da...@hotmail.com>
Authored: Wed Jan 18 17:18:46 2017 +0100
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Wed Jan 18 17:18:46 2017 +0100

----------------------------------------------------------------------
 gremlin-console/src/main/bin/gremlin.sh                      | 4 +++-
 .../org/apache/tinkerpop/gremlin/console/Console.groovy      | 8 +++++++-
 2 files changed, 10 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8fd6dbbe/gremlin-console/src/main/bin/gremlin.sh
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/bin/gremlin.sh b/gremlin-console/src/main/bin/gremlin.sh
index 901610b..d8c94db 100755
--- a/gremlin-console/src/main/bin/gremlin.sh
+++ b/gremlin-console/src/main/bin/gremlin.sh
@@ -22,6 +22,8 @@
 set -e
 set -u
 
+USER_DIR=`pwd`
+
 cd $(dirname $0)
 DIR=`pwd`
 
@@ -90,7 +92,7 @@ while getopts ":l" opt; do
     esac
 done
 
-JAVA_OPTIONS="${JAVA_OPTIONS} -Dtinkerpop.ext=${USER_EXT_DIR:-${SYSTEM_EXT_DIR}} -Dlog4j.configuration=conf/log4j-console.properties -Dgremlin.log4j.level=$GREMLIN_LOG_LEVEL"
+JAVA_OPTIONS="${JAVA_OPTIONS} -Duser.working_dir=${USER_DIR} -Dtinkerpop.ext=${USER_EXT_DIR:-${SYSTEM_EXT_DIR}} -Dlog4j.configuration=conf/log4j-console.properties -Dgremlin.log4j.level=$GREMLIN_LOG_LEVEL"
 JAVA_OPTIONS=$(awk -v RS=' ' '!/^$/ {if (!x[$0]++) print}' <<< "${JAVA_OPTIONS}" | grep -v '^$' | paste -sd ' ' -)
 
 if [ -n "$SCRIPT_DEBUG" ]; then

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8fd6dbbe/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Console.groovy
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Console.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Console.groovy
index a2e518c..0788f42 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Console.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Console.groovy
@@ -378,7 +378,13 @@ class Console {
                 groovy.execute("args = []")
             }
 
-            final File file = new File(scriptFile)
+            File file = new File(scriptFile)
+            if (!file.exists() && !file.isAbsolute()) {
+                final String userWorkingDir = System.getProperty("user.working_dir");
+                if (userWorkingDir != null) {
+                    file = new File(userWorkingDir, scriptFile);
+                }
+            }
             int lineNumber = 0
             def lines = file.readLines()
             for (String line : lines) {


[14/17] tinkerpop git commit: Merge branch 'TINKERPOP-1605' into tp32

Posted by sp...@apache.org.
Merge branch 'TINKERPOP-1605' into tp32


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

Branch: refs/heads/TINKERPOP-1560
Commit: 67a10923d77098f403efc187ba43781443d1ed8f
Parents: 8ad2911 8fd6dbb
Author: Daniel Kuppitz <da...@hotmail.com>
Authored: Sat Jan 21 12:04:46 2017 +0100
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Sat Jan 21 12:04:46 2017 +0100

----------------------------------------------------------------------
 gremlin-console/src/main/bin/gremlin.sh                      | 4 +++-
 .../org/apache/tinkerpop/gremlin/console/Console.groovy      | 8 +++++++-
 2 files changed, 10 insertions(+), 2 deletions(-)
----------------------------------------------------------------------



[03/17] tinkerpop git commit: We now have ProjectedTraveser which is a Traverser with List of projections. OrderGlobalStep uses this and thus, can order for everything within the local star graph. Added MultiComparator which is like ChainedCompar Posted by sp...@apache.org.
We now have ProjectedTraveser which is a Traverser with List<Object> of projections. OrderGlobalStep uses this and thus, can order for everything within the local star graph. Added MultiComparator which is like ChainedComparator but doesn't contain traversal projections -- just comparators.


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

Branch: refs/heads/TINKERPOP-1560
Commit: 5045f67f469e163d1363f953672a3f38b4ff2a3f
Parents: 501e97a
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Wed Jan 18 09:38:21 2017 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Wed Jan 18 09:38:21 2017 -0700

----------------------------------------------------------------------
 .../traversal/step/map/OrderGlobalStep.java     |  39 ++-
 .../traversal/traverser/OrderedTraverser.java   | 235 -------------------
 .../traversal/traverser/ProjectedTraverser.java | 199 ++++++++++++++++
 .../gremlin/structure/io/gryo/GryoVersion.java  |   8 +-
 .../gremlin/util/function/MultiComparator.java  |  60 +++++
 5 files changed, 295 insertions(+), 246 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5045f67f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
index ac5df90..9c071f1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
@@ -27,10 +27,12 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.ComparatorHolder;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.CollectingBarrierStep;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.OrderedTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.ProjectedTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.util.function.MultiComparator;
 import org.javatuples.Pair;
 
 import java.io.Serializable;
@@ -49,6 +51,7 @@ import java.util.stream.Collectors;
 public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBarrierStep<S> implements ComparatorHolder<S, C>, TraversalParent, ByModulating {
 
     private List<Pair<Traversal.Admin<S, C>, Comparator<C>>> comparators = new ArrayList<>();
+    private MultiComparator<C> multiComparator = null;
     private long limit = Long.MAX_VALUE;
     private boolean isShuffle = false;
 
@@ -61,14 +64,16 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
         if (this.isShuffle)
             traverserSet.shuffle();
         else
-            traverserSet.sort(Comparator.naturalOrder());
+            traverserSet.sort((Comparator) this.multiComparator);
     }
 
     @Override
     public void processAllStarts() {
+        if (null == this.multiComparator)
+            this.multiComparator = this.createMultiComparator();
         if (this.starts.hasNext()) {
             while (this.starts.hasNext()) {
-                this.traverserSet.add(new OrderedTraverser<S>(this.starts.next(), (List) this.comparators));
+                this.traverserSet.add(this.createOrderedTraverser(this.starts.next()));
             }
             this.barrierConsumer(this.traverserSet);
         }
@@ -81,7 +86,7 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
         } else if (this.starts.hasNext()) {
             this.processAllStarts();
         }
-        return ((OrderedTraverser) this.traverserSet.remove()).getInternal();
+        return ((ProjectedTraverser) this.traverserSet.remove()).getInternal();
     }
 
     public void setLimit(final long limit) {
@@ -155,7 +160,25 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
 
     @Override
     public MemoryComputeKey<TraverserSet<S>> getMemoryComputeKey() {
-        return MemoryComputeKey.of(this.getId(), new OrderBiOperator<>(this.limit, this.isShuffle), false, true);
+        if (null == this.multiComparator)
+            this.multiComparator = this.createMultiComparator();
+        return MemoryComputeKey.of(this.getId(), new OrderBiOperator<>(this.limit, this.isShuffle, this.multiComparator), false, true);
+    }
+
+    private ProjectedTraverser<S> createOrderedTraverser(final Traverser.Admin<S> traverser) {
+        final List<Object> projections = new ArrayList<>(this.comparators.size());
+        for (final Pair<Traversal.Admin<S, C>, Comparator<C>> pair : this.comparators) {
+            projections.add(TraversalUtil.apply(traverser, pair.getValue0()));
+        }
+        return new ProjectedTraverser<S>(traverser, projections);
+    }
+
+    private MultiComparator<C> createMultiComparator() {
+        final List<Comparator<C>> list = new ArrayList<>(this.comparators.size());
+        for (final Pair<Traversal.Admin<S, C>, Comparator<C>> pair : this.comparators) {
+            list.add(pair.getValue1());
+        }
+        return new MultiComparator<>(list);
     }
 
     ////////////////
@@ -164,14 +187,16 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
 
         private long limit;
         private boolean isShuffle;
+        private MultiComparator comparator;
 
         private OrderBiOperator() {
             // for serializers that need a no-arg constructor
         }
 
-        public OrderBiOperator(final long limit, final boolean isShuffle) {
+        public OrderBiOperator(final long limit, final boolean isShuffle, final MultiComparator multiComparator) {
             this.limit = limit;
             this.isShuffle = isShuffle;
+            this.comparator = multiComparator;
         }
 
         @Override
@@ -181,7 +206,7 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
                 if (this.isShuffle)
                     setA.shuffle();
                 else
-                    setA.sort(Comparator.naturalOrder());
+                    setA.sort(this.comparator);
                 long counter = 0L;
                 final Iterator<Traverser.Admin<S>> traversers = setA.iterator();
                 while (traversers.hasNext()) {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5045f67f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/OrderedTraverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/OrderedTraverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/OrderedTraverser.java
deleted file mode 100644
index 4dddaa3..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/OrderedTraverser.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.tinkerpop.gremlin.process.traversal.traverser;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Order;
-import org.apache.tinkerpop.gremlin.process.traversal.Path;
-import org.apache.tinkerpop.gremlin.process.traversal.Step;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
-import org.apache.tinkerpop.gremlin.structure.util.Attachable;
-import org.javatuples.Pair;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Function;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class OrderedTraverser<T> implements Traverser.Admin<T> {
-
-    private Traverser.Admin<T> internal;
-    private int order;
-    private final List<Pair<Object, Comparator<?>>> orderChecks = new ArrayList<>();
-
-    private OrderedTraverser() {
-        // for serialization
-    }
-
-    public OrderedTraverser(final Traverser.Admin<T> internal, final List<Pair<Traversal.Admin<T, ?>, Comparator>> checks) {
-        this(internal, 0);
-        for (final Pair<Traversal.Admin<T, ?>, Comparator> pairs : checks) {
-            this.orderChecks.add(Pair.with(TraversalUtil.apply(this.internal, pairs.getValue0()), pairs.getValue1()));
-        }
-    }
-
-    public OrderedTraverser(final Traverser.Admin<T> internal, final int order) {
-        this.internal = internal instanceof OrderedTraverser ? ((OrderedTraverser) internal).internal : internal;
-        this.order = order;
-    }
-
-    public Traverser.Admin<T> getInternal() {
-        return this.internal;
-    }
-
-    public int order() {
-        return this.order;
-    }
-
-    @Override
-    public void merge(final Admin<?> other) {
-        this.internal.merge(other);
-    }
-
-    @Override
-    public <R> Admin<R> split(R r, Step<T, R> step) {
-        return new OrderedTraverser<>(this.internal.split(r, step), this.order);
-    }
-
-    @Override
-    public Admin<T> split() {
-        return new OrderedTraverser<>(this.internal.split(), this.order);
-    }
-
-    @Override
-    public void addLabels(final Set<String> labels) {
-        this.internal.addLabels(labels);
-    }
-
-    @Override
-    public void keepLabels(final Set<String> labels) {
-        this.internal.keepLabels(labels);
-    }
-
-    @Override
-    public void dropLabels(final Set<String> labels) {
-        this.internal.dropLabels(labels);
-    }
-
-    @Override
-    public void dropPath() {
-        this.internal.dropPath();
-    }
-
-    @Override
-    public void set(final T t) {
-        this.internal.set(t);
-    }
-
-    @Override
-    public void incrLoops(final String stepLabel) {
-        this.internal.incrLoops(stepLabel);
-    }
-
-    @Override
-    public void resetLoops() {
-        this.internal.resetLoops();
-    }
-
-    @Override
-    public String getStepId() {
-        return this.internal.getStepId();
-    }
-
-    @Override
-    public void setStepId(final String stepId) {
-        this.internal.setStepId(stepId);
-    }
-
-    @Override
-    public void setBulk(final long count) {
-        this.internal.setBulk(count);
-    }
-
-    @Override
-    public Admin<T> detach() {
-        this.internal = this.internal.detach();
-        return this;
-    }
-
-    @Override
-    public T attach(final Function<Attachable<T>, T> method) {
-        return this.internal.attach(method);
-    }
-
-    @Override
-    public void setSideEffects(final TraversalSideEffects sideEffects) {
-        this.internal.setSideEffects(sideEffects);
-    }
-
-    @Override
-    public TraversalSideEffects getSideEffects() {
-        return this.internal.getSideEffects();
-    }
-
-    @Override
-    public Set<String> getTags() {
-        return this.internal.getTags();
-    }
-
-    @Override
-    public T get() {
-        return this.internal.get();
-    }
-
-    @Override
-    public <S> S sack() {
-        return this.internal.sack();
-    }
-
-    @Override
-    public <S> void sack(final S object) {
-        this.internal.sack(object);
-    }
-
-    @Override
-    public Path path() {
-        return this.internal.path();
-    }
-
-    @Override
-    public int loops() {
-        return this.internal.loops();
-    }
-
-    @Override
-    public long bulk() {
-        return this.internal.bulk();
-    }
-
-    @Override
-    public int hashCode() {
-        return this.internal.hashCode();
-    }
-
-    @Override
-    public boolean equals(final Object object) {
-        return object instanceof OrderedTraverser && ((OrderedTraverser) object).internal.equals(this.internal);
-    }
-
-    @Override
-    public OrderedTraverser<T> clone() {
-        try {
-            final OrderedTraverser<T> clone = (OrderedTraverser<T>) super.clone();
-            clone.internal = (Traverser.Admin<T>) this.internal.clone();
-            return clone;
-        } catch (final CloneNotSupportedException e) {
-            throw new IllegalStateException(e.getMessage(), e);
-        }
-    }
-
-    @Override
-    public int compareTo(final Traverser<T> o) {
-        if (!(o instanceof OrderedTraverser))
-            return 0;
-        else {
-            if (this.orderChecks.isEmpty()) {
-                return Order.incr.compare(this.get(), o.get());
-            } else {
-                final OrderedTraverser<T> other = (OrderedTraverser<T>) o;
-                for (int i = 0; i < this.orderChecks.size(); i++) {
-                    final Comparator comparator = this.orderChecks.get(i).getValue1();
-                    final Object thisObject = this.orderChecks.get(i).getValue0();
-                    final Object otherObject = other.orderChecks.get(i).getValue0();
-                    final int comparison = comparator.compare(thisObject, otherObject);
-                    if (comparison != 0)
-                        return comparison;
-
-                }
-                return 0;
-            }
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5045f67f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
new file mode 100644
index 0000000..67e723a
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
@@ -0,0 +1,199 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.tinkerpop.gremlin.process.traversal.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.structure.util.Attachable;
+
+import java.util.List;
+import java.util.Set;
+import java.util.function.Function;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class ProjectedTraverser<T> implements Traverser.Admin<T> {
+
+    private Traverser.Admin<T> internal;
+    private List<Object> projections;
+
+    private ProjectedTraverser() {
+        // for serialization
+    }
+
+    public ProjectedTraverser(final Traverser.Admin<T> internal, final List<Object> projections) {
+        this.internal = internal;
+        this.projections = projections;
+    }
+
+
+    public Traverser.Admin<T> getInternal() {
+        return this.internal;
+    }
+
+    public List<Object> getProjections() {
+        return this.projections;
+    }
+
+    @Override
+    public void merge(final Admin<?> other) {
+        this.internal.merge(other);
+    }
+
+    @Override
+    public <R> Admin<R> split(R r, Step<T, R> step) {
+        return new ProjectedTraverser<>(this.internal.split(r, step), this.projections);
+    }
+
+    @Override
+    public Admin<T> split() {
+        return new ProjectedTraverser<>(this.internal.split(), this.projections);
+    }
+
+    @Override
+    public void addLabels(final Set<String> labels) {
+        this.internal.addLabels(labels);
+    }
+
+    @Override
+    public void keepLabels(final Set<String> labels) {
+        this.internal.keepLabels(labels);
+    }
+
+    @Override
+    public void dropLabels(final Set<String> labels) {
+        this.internal.dropLabels(labels);
+    }
+
+    @Override
+    public void dropPath() {
+        this.internal.dropPath();
+    }
+
+    @Override
+    public void set(final T t) {
+        this.internal.set(t);
+    }
+
+    @Override
+    public void incrLoops(final String stepLabel) {
+        this.internal.incrLoops(stepLabel);
+    }
+
+    @Override
+    public void resetLoops() {
+        this.internal.resetLoops();
+    }
+
+    @Override
+    public String getStepId() {
+        return this.internal.getStepId();
+    }
+
+    @Override
+    public void setStepId(final String stepId) {
+        this.internal.setStepId(stepId);
+    }
+
+    @Override
+    public void setBulk(final long count) {
+        this.internal.setBulk(count);
+    }
+
+    @Override
+    public Admin<T> detach() {
+        this.internal = this.internal.detach();
+        return this;
+    }
+
+    @Override
+    public T attach(final Function<Attachable<T>, T> method) {
+        return this.internal.attach(method);
+    }
+
+    @Override
+    public void setSideEffects(final TraversalSideEffects sideEffects) {
+        this.internal.setSideEffects(sideEffects);
+    }
+
+    @Override
+    public TraversalSideEffects getSideEffects() {
+        return this.internal.getSideEffects();
+    }
+
+    @Override
+    public Set<String> getTags() {
+        return this.internal.getTags();
+    }
+
+    @Override
+    public T get() {
+        return this.internal.get();
+    }
+
+    @Override
+    public <S> S sack() {
+        return this.internal.sack();
+    }
+
+    @Override
+    public <S> void sack(final S object) {
+        this.internal.sack(object);
+    }
+
+    @Override
+    public Path path() {
+        return this.internal.path();
+    }
+
+    @Override
+    public int loops() {
+        return this.internal.loops();
+    }
+
+    @Override
+    public long bulk() {
+        return this.internal.bulk();
+    }
+
+    @Override
+    public int hashCode() {
+        return this.internal.hashCode();
+    }
+
+    @Override
+    public boolean equals(final Object object) {
+        return object instanceof ProjectedTraverser && ((ProjectedTraverser) object).internal.equals(this.internal);
+    }
+
+    @Override
+    public ProjectedTraverser<T> clone() {
+        try {
+            final ProjectedTraverser<T> clone = (ProjectedTraverser<T>) super.clone();
+            clone.internal = (Traverser.Admin<T>) this.internal.clone();
+            return clone;
+        } catch (final CloneNotSupportedException e) {
+            throw new IllegalStateException(e.getMessage(), e);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5045f67f/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 a04f2d9..f4e31fd 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
@@ -51,13 +51,11 @@ import org.apache.tinkerpop.gremlin.process.traversal.traverser.LP_O_OB_P_S_SE_S
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.LP_O_OB_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.O_OB_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.O_Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.OrderedTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.ProjectedTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
-import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
 import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalMetrics;
 import org.apache.tinkerpop.gremlin.process.traversal.util.ImmutableMetrics;
 import org.apache.tinkerpop.gremlin.process.traversal.util.MutableMetrics;
-import org.apache.tinkerpop.gremlin.process.traversal.util.OrP;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalExplanation;
 import org.apache.tinkerpop.gremlin.structure.Column;
 import org.apache.tinkerpop.gremlin.structure.Direction;
@@ -81,6 +79,7 @@ import org.apache.tinkerpop.gremlin.structure.util.star.StarGraph;
 import org.apache.tinkerpop.gremlin.structure.util.star.StarGraphSerializer;
 import org.apache.tinkerpop.gremlin.util.function.HashSetSupplier;
 import org.apache.tinkerpop.gremlin.util.function.Lambda;
+import org.apache.tinkerpop.gremlin.util.function.MultiComparator;
 import org.apache.tinkerpop.shaded.kryo.KryoSerializable;
 import org.apache.tinkerpop.shaded.kryo.serializers.JavaSerializer;
 import org.javatuples.Pair;
@@ -246,7 +245,7 @@ public enum GryoVersion {
             add(GryoTypeReg.of(O_OB_S_SE_SL_Traverser.class, 89));
             add(GryoTypeReg.of(LP_O_OB_S_SE_SL_Traverser.class, 90));
             add(GryoTypeReg.of(LP_O_OB_P_S_SE_SL_Traverser.class, 91));
-            add(GryoTypeReg.of(OrderedTraverser.class, 164));   // ***LAST ID***
+            add(GryoTypeReg.of(ProjectedTraverser.class, 164));
             add(GryoTypeReg.of(DefaultRemoteTraverser.class, 123, new GryoSerializers.DefaultRemoteTraverserSerializer()));
 
             add(GryoTypeReg.of(Bytecode.class, 122, new GryoSerializers.BytecodeSerializer()));
@@ -261,6 +260,7 @@ public enum GryoVersion {
             add(GryoTypeReg.of(SackFunctions.Barrier.class, 135));
             add(GryoTypeReg.of(TraversalOptionParent.Pick.class, 137));
             add(GryoTypeReg.of(HashSetSupplier.class, 136, new UtilSerializers.HashSetSupplierSerializer()));
+            add(GryoTypeReg.of(MultiComparator.class, 165));   // ***LAST ID***
 
             add(GryoTypeReg.of(TraverserSet.class, 58));
             add(GryoTypeReg.of(Tree.class, 61));

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5045f67f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java
new file mode 100644
index 0000000..427aa3d
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java
@@ -0,0 +1,60 @@
+/*
+ *  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.util.function;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Order;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.ProjectedTraverser;
+
+import java.io.Serializable;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class MultiComparator<C> implements Comparator<C>, Serializable {
+
+    private final List<Comparator> comparators;
+
+    public MultiComparator(final List<Comparator<C>> comparators) {
+        this.comparators = (List) comparators;
+    }
+
+    @Override
+    public int compare(final C objectA, final C objectB) {
+        if (this.comparators.isEmpty()) {
+            return Order.incr.compare(objectA, objectB);
+        } else {
+            for (int i = 0; i < this.comparators.size(); i++) {
+                final int comparison = this.comparators.get(i).compare(this.getObject(objectA, i), this.getObject(objectB, i));
+                if (comparison != 0)
+                    return comparison;
+            }
+            return 0;
+        }
+    }
+
+    private final Object getObject(final C object, final int index) {
+        if (object instanceof ProjectedTraverser)
+            return ((ProjectedTraverser) object).getProjections().get(index);
+        else
+            return object;
+    }
+}


[10/17] tinkerpop git commit: @dkuppitz found an optimization trick for MultiComparator. The startIndex for comparing should start after the last Order.shuffle.

Posted by sp...@apache.org.
@dkuppitz found an optimization trick for MultiComparator. The startIndex for comparing should start after the last Order.shuffle.


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

Branch: refs/heads/TINKERPOP-1560
Commit: 341ebf9811c15d65231ea31c3617723c2fd0ab09
Parents: 379a6e5
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Thu Jan 19 08:23:42 2017 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Thu Jan 19 08:23:42 2017 -0700

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  2 +-
 .../gremlin/structure/io/gryo/GryoVersion.java  |  4 +-
 .../gremlin/util/function/MultiComparator.java  | 15 +++--
 .../util/function/MultiComparatorTest.java      | 69 ++++++++++++++++++++
 4 files changed, 81 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/341ebf98/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 88cbf32..5f28790 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,7 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.4 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-* `GroupBiOperator` no longer maintains state and thus, no more side-effect related OLAP inconsistencies.
+* `GroupBiOperator` no longer maintains a detached traversal and thus, no more side-effect related OLAP inconsistencies.
 * Added `ProjectedTraverser` which wraps a traverser with a `List<Object>` of projected data.
 * Fixed an optimization bug in `CollectionBarrierSteps` where the barrier was being consumed on each `addBarrier()`.
 * `OrderGlobalStep` and `SampleGlobalStep` use `ProjectedTraverser` and now can work up to the local star graph in OLAP.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/341ebf98/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 f4e31fd..7818f6b 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
@@ -292,13 +292,13 @@ public enum GryoVersion {
             add(GryoTypeReg.of(Operator.class, 107));
             add(GryoTypeReg.of(FoldStep.FoldBiOperator.class, 108));
             add(GryoTypeReg.of(GroupCountStep.GroupCountBiOperator.class, 109));
-            add(GryoTypeReg.of(GroupStep.GroupBiOperator.class, 117, new JavaSerializer())); // because they contain traversals
+            add(GryoTypeReg.of(GroupStep.GroupBiOperator.class, 117, new JavaSerializer()));
             add(GryoTypeReg.of(MeanGlobalStep.MeanGlobalBiOperator.class, 110));
             add(GryoTypeReg.of(MeanGlobalStep.MeanNumber.class, 111));
             add(GryoTypeReg.of(TreeStep.TreeBiOperator.class, 112));
             add(GryoTypeReg.of(GroupStepV3d0.GroupBiOperatorV3d0.class, 113));
             add(GryoTypeReg.of(RangeGlobalStep.RangeBiOperator.class, 114));
-            add(GryoTypeReg.of(OrderGlobalStep.OrderBiOperator.class, 118, new JavaSerializer())); // because they contain traversals
+            add(GryoTypeReg.of(OrderGlobalStep.OrderBiOperator.class, 118, new JavaSerializer()));
             add(GryoTypeReg.of(ProfileStep.ProfileBiOperator.class, 119));
         }};
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/341ebf98/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java
index 5d24ddf..d97d147 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java
@@ -33,6 +33,7 @@ public final class MultiComparator<C> implements Comparator<C>, Serializable {
 
     private List<Comparator> comparators;
     private boolean isShuffle;
+    int startIndex = 0;
 
     private MultiComparator() {
         // for serialization purposes
@@ -41,6 +42,10 @@ public final class MultiComparator<C> implements Comparator<C>, Serializable {
     public MultiComparator(final List<Comparator<C>> comparators) {
         this.comparators = (List) comparators;
         this.isShuffle = !this.comparators.isEmpty() && Order.shuffle == this.comparators.get(this.comparators.size() - 1);
+        for (int i = 0; i < this.comparators.size(); i++) {
+            if (this.comparators.get(i) == Order.shuffle)
+                this.startIndex = i + 1;
+        }
     }
 
     @Override
@@ -48,12 +53,10 @@ public final class MultiComparator<C> implements Comparator<C>, Serializable {
         if (this.comparators.isEmpty()) {
             return Order.incr.compare(objectA, objectB);
         } else {
-            for (int i = 0; i < this.comparators.size(); i++) {
-                if (Order.shuffle != this.comparators.get(i)) {
-                    final int comparison = this.comparators.get(i).compare(this.getObject(objectA, i), this.getObject(objectB, i));
-                    if (comparison != 0)
-                        return comparison;
-                }
+            for (int i = this.startIndex; i < this.comparators.size(); i++) {
+                final int comparison = this.comparators.get(i).compare(this.getObject(objectA, i), this.getObject(objectB, i));
+                if (comparison != 0)
+                    return comparison;
             }
             return 0;
         }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/341ebf98/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/function/MultiComparatorTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/function/MultiComparatorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/function/MultiComparatorTest.java
new file mode 100644
index 0000000..de2a741
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/function/MultiComparatorTest.java
@@ -0,0 +1,69 @@
+/*
+ *  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.util.function;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Order;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Random;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public class MultiComparatorTest {
+
+    private static final Random RANDOM = new Random();
+
+    @Test
+    public void shouldHandleShuffleCorrectly() {
+        MultiComparator<Object> comparator = new MultiComparator<>(Arrays.asList(Order.incr, Order.decr, Order.shuffle));
+        assertTrue(comparator.isShuffle()); // because its a shuffle, the comparator simply returns 0
+        for (int i = 0; i < 100; i++) {
+            assertEquals(0, comparator.compare(RANDOM.nextInt(), RANDOM.nextInt()));
+        }
+        //
+        comparator = new MultiComparator<>(Arrays.asList(Order.incr, Order.shuffle, Order.decr));
+        assertEquals(1, comparator.compare(1, 2));
+        assertEquals(-1, comparator.compare(2, 1));
+        assertEquals(0, comparator.compare(2, 2));
+        assertEquals(2, comparator.startIndex);
+        assertFalse(comparator.isShuffle());
+        //
+        comparator = new MultiComparator<>(Arrays.asList(Order.incr, Order.shuffle, Order.decr, Order.shuffle, Order.incr));
+        assertEquals(-1, comparator.compare(1, 2));
+        assertEquals(1, comparator.compare(2, 1));
+        assertEquals(0, comparator.compare(2, 2));
+        assertEquals(4, comparator.startIndex);
+        assertFalse(comparator.isShuffle());
+        //
+        comparator = new MultiComparator<>(Collections.emptyList());
+        assertEquals(-1, comparator.compare(1, 2));
+        assertEquals(1, comparator.compare(2, 1));
+        assertEquals(0, comparator.compare(2, 2));
+        assertEquals(0, comparator.startIndex);
+        assertFalse(comparator.isShuffle());
+    }
+}


[12/17] 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/60022999
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/60022999
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/60022999

Branch: refs/heads/TINKERPOP-1560
Commit: 6002299925e7ef68275b9576331aac1194642bef
Parents: d54b490
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Thu Jan 19 10:16:43 2017 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Thu Jan 19 10:16:43 2017 -0700

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


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/60022999/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 5f28790..fb0f8da 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.4 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* Fixed a bug associated with user-provided maps and `GroupSideEffectStep`.
 * `GroupBiOperator` no longer maintains a detached traversal and thus, no more side-effect related OLAP inconsistencies.
 * Added `ProjectedTraverser` which wraps a traverser with a `List<Object>` of projected data.
 * Fixed an optimization bug in `CollectionBarrierSteps` where the barrier was being consumed on each `addBarrier()`.


[08/17] tinkerpop git commit: moved all the GroupStep work against tp32/

Posted by sp...@apache.org.
moved all the GroupStep work against tp32/


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

Branch: refs/heads/TINKERPOP-1560
Commit: 3496402a4e0c2803031d3b88086aabd5c6a2cfd8
Parents: 97cc07d
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Thu Jan 19 04:16:56 2017 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Thu Jan 19 04:16:56 2017 -0700

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   1 +
 .../process/traversal/step/map/GroupStep.java   | 263 +++----------------
 .../step/sideEffect/GroupSideEffectStep.java    |  50 ++--
 .../step/sideEffect/GroovyGroupTest.groovy      |   5 +
 .../traversal/step/sideEffect/GroupTest.java    |  30 ++-
 5 files changed, 91 insertions(+), 258 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3496402a/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 4f3f9ce..74751fa 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.4 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* `GroupBiOperator` no longer maintains state and thus, no more side-effect related OLAP inconsistencies.
 * SASL negotiation supports both a byte array and Base64 encoded bytes as a string for authentication to Gremlin Server.
 * Deprecated `TinkerIoRegistry` replacing it with the more consistently named `TinkerIoRegistryV1d0`.
 * Made error messaging more consistent during result iteration timeouts in Gremlin Server.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3496402a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
index d6ce421..07ca4ae 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
@@ -19,7 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 
-import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Operator;
 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.__;
@@ -29,22 +29,14 @@ import org.apache.tinkerpop.gremlin.process.traversal.lambda.IdentityTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.lambda.TokenTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Barrier;
 import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
-import org.apache.tinkerpop.gremlin.process.traversal.step.LambdaHolder;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.util.function.HashMapSupplier;
-import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
-import org.javatuples.Pair;
 
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -60,14 +52,14 @@ public final class GroupStep<S, K, V> extends ReducingBarrierStep<S, Map<K, V>>
 
     private char state = 'k';
     private Traversal.Admin<S, K> keyTraversal;
-    private Traversal.Admin<S, ?> preTraversal;
     private Traversal.Admin<S, V> valueTraversal;
+    private Barrier barrierStep;
 
     public GroupStep(final Traversal.Admin traversal) {
         super(traversal);
         this.valueTraversal = this.integrateChild(__.fold().asAdmin());
-        this.preTraversal = this.integrateChild(generatePreTraversal(this.valueTraversal));
-        this.setReducingBiOperator(new GroupBiOperator<>(this.valueTraversal));
+        this.barrierStep = TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, this.valueTraversal).orElse(null);
+        this.setReducingBiOperator(new GroupBiOperator<>(null == this.barrierStep ? Operator.assign : this.barrierStep.getMemoryComputeKey().getReducer()));
         this.setSeedSupplier(HashMapSupplier.instance());
     }
 
@@ -78,8 +70,8 @@ public final class GroupStep<S, K, V> extends ReducingBarrierStep<S, Map<K, V>>
             this.state = 'v';
         } else if ('v' == this.state) {
             this.valueTraversal = this.integrateChild(convertValueTraversal(kvTraversal));
-            this.preTraversal = this.integrateChild(generatePreTraversal(this.valueTraversal));
-            this.setReducingBiOperator(new GroupBiOperator<>(this.valueTraversal));
+            this.barrierStep = TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, this.valueTraversal).orElse(null);
+            this.setReducingBiOperator(new GroupBiOperator<>(null == this.barrierStep ? Operator.assign : this.barrierStep.getMemoryComputeKey().getReducer()));
             this.state = 'x';
         } else {
             throw new IllegalStateException("The key and value traversals for group()-step have already been set: " + this);
@@ -89,17 +81,13 @@ public final class GroupStep<S, K, V> extends ReducingBarrierStep<S, Map<K, V>>
     @Override
     public Map<K, V> projectTraverser(final Traverser.Admin<S> traverser) {
         final Map<K, V> map = new HashMap<>(1);
-        if (null == this.preTraversal) {
-            map.put(TraversalUtil.applyNullable(traverser, this.keyTraversal), (V) traverser);
-        } else {
-            final TraverserSet traverserSet = new TraverserSet<>();
-            this.preTraversal.reset();
-            this.preTraversal.addStart(traverser);
-            while (this.preTraversal.hasNext()) {
-                traverserSet.add(this.preTraversal.nextTraverser());
-            }
-            map.put(TraversalUtil.applyNullable(traverser, this.keyTraversal), (V) traverserSet);
-        }
+        this.valueTraversal.reset();
+        this.valueTraversal.addStart(traverser);
+        if (null == this.barrierStep) {
+            if (this.valueTraversal.hasNext())
+                map.put(TraversalUtil.applyNullable(traverser, this.keyTraversal), (V) this.valueTraversal.next());
+        } else if (this.barrierStep.hasNextBarrier())
+            map.put(TraversalUtil.applyNullable(traverser, this.keyTraversal), (V) this.barrierStep.nextBarrier());
         return map;
     }
 
@@ -110,12 +98,10 @@ public final class GroupStep<S, K, V> extends ReducingBarrierStep<S, Map<K, V>>
 
     @Override
     public List<Traversal.Admin<?, ?>> getLocalChildren() {
-        final List<Traversal.Admin<?, ?>> children = new ArrayList<>(3);
+        final List<Traversal.Admin<?, ?>> children = new ArrayList<>(2);
         if (null != this.keyTraversal)
             children.add(this.keyTraversal);
         children.add(this.valueTraversal);
-        if (null != this.preTraversal)
-            children.add(this.preTraversal);
         return children;
     }
 
@@ -130,8 +116,7 @@ public final class GroupStep<S, K, V> extends ReducingBarrierStep<S, Map<K, V>>
         if (null != this.keyTraversal)
             clone.keyTraversal = this.keyTraversal.clone();
         clone.valueTraversal = this.valueTraversal.clone();
-        clone.preTraversal = (Traversal.Admin<S, ?>) GroupStep.generatePreTraversal(clone.valueTraversal);
-        clone.setReducingBiOperator(new GroupBiOperator<>(clone.valueTraversal));
+        clone.barrierStep = TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, clone.valueTraversal).orElse(null);
         return clone;
     }
 
@@ -140,7 +125,6 @@ public final class GroupStep<S, K, V> extends ReducingBarrierStep<S, Map<K, V>>
         super.setTraversal(parentTraversal);
         integrateChild(this.keyTraversal);
         integrateChild(this.valueTraversal);
-        integrateChild(this.preTraversal);
     }
 
     @Override
@@ -158,180 +142,31 @@ public final class GroupStep<S, K, V> extends ReducingBarrierStep<S, Map<K, V>>
 
     ///////////////////////
 
-    public static final class GroupBiOperator<K, V> implements BinaryOperator<Map<K, V>>, Serializable, Cloneable {
-
-        // size limit before Barrier.processAllStarts() to lazy reduce
-        private static final int SIZE_LIMIT = 1000;
-
-        private Traversal.Admin<?, V> valueTraversal;
-        private Barrier barrierStep;
+    public static final class GroupBiOperator<K, V> implements BinaryOperator<Map<K, V>>, Serializable {
 
-        public GroupBiOperator(final Traversal.Admin<?, V> valueTraversal) {
-            // if there is a lambda that can not be serialized, then simply use TraverserSets
-            if (TraversalHelper.hasStepOfAssignableClassRecursively(LambdaHolder.class, valueTraversal)) {
-                this.valueTraversal = null;
-                this.barrierStep = null;
-            } else {
-                this.valueTraversal = valueTraversal.clone();
-                this.barrierStep = TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, this.valueTraversal).orElse(null);
-            }
-        }
+        private BinaryOperator<V> barrierAggregator;
 
         public GroupBiOperator() {
             // no-arg constructor for serialization
         }
 
-        @Override
-        public GroupBiOperator<K, V> clone() {
-            try {
-                final GroupBiOperator<K, V> clone = (GroupBiOperator<K, V>) super.clone();
-                if (null != this.valueTraversal) {
-                    clone.valueTraversal = this.valueTraversal.clone();
-                    clone.barrierStep = TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, clone.valueTraversal).orElse(null);
-                }
-                return clone;
-            } catch (final CloneNotSupportedException e) {
-                throw new IllegalStateException(e.getMessage(), e);
-            }
+        public GroupBiOperator(final BinaryOperator<V> barrierAggregator) {
+            this.barrierAggregator = barrierAggregator;
         }
 
         @Override
         public Map<K, V> apply(final Map<K, V> mapA, final Map<K, V> mapB) {
             for (final K key : mapB.keySet()) {
-                Object objectA = mapA.get(key);
-                final Object objectB = mapB.get(key);
-                assert null != objectB;
-                if (null == objectA) {
+                V objectA = mapA.get(key);
+                final V objectB = mapB.get(key);
+                if (null == objectA)
                     objectA = objectB;
-                } else {
-                    // TRAVERSER
-                    if (objectA instanceof Traverser.Admin) {
-                        if (objectB instanceof Traverser.Admin) {
-                            final TraverserSet set = new TraverserSet();
-                            set.add((Traverser.Admin) objectA);
-                            set.add((Traverser.Admin) objectB);
-                            objectA = set;
-                        } else if (objectB instanceof TraverserSet) {
-                            final TraverserSet set = (TraverserSet) objectB;
-                            set.add((Traverser.Admin) objectA);
-                            if (null != this.barrierStep && set.size() > SIZE_LIMIT) {
-                                this.valueTraversal.reset();
-                                ((Step) this.barrierStep).addStarts(set.iterator());
-                                objectA = this.barrierStep.nextBarrier();
-                            } else
-                                objectA = objectB;
-                        } else if (objectB instanceof Pair) {
-                            final TraverserSet set = (TraverserSet) ((Pair) objectB).getValue0();
-                            set.add((Traverser.Admin) objectA);
-                            if (set.size() > SIZE_LIMIT) {    // barrier step can never be null -- no need to check
-                                this.valueTraversal.reset();
-                                ((Step) this.barrierStep).addStarts(set.iterator());
-                                this.barrierStep.addBarrier(((Pair) objectB).getValue1());
-                                objectA = this.barrierStep.nextBarrier();
-                            } else
-                                objectA = Pair.with(set, ((Pair) objectB).getValue1());
-                        } else
-                            objectA = Pair.with(new TraverserSet((Traverser.Admin) objectA), objectB);
-                        // TRAVERSER SET
-                    } else if (objectA instanceof TraverserSet) {
-                        if (objectB instanceof Traverser.Admin) {
-                            final TraverserSet set = (TraverserSet) objectA;
-                            set.add((Traverser.Admin) objectB);
-                            if (null != this.barrierStep && set.size() > SIZE_LIMIT) {
-                                this.valueTraversal.reset();
-                                ((Step) this.barrierStep).addStarts(set.iterator());
-                                objectA = this.barrierStep.nextBarrier();
-                            }
-                        } else if (objectB instanceof TraverserSet) {
-                            final TraverserSet set = (TraverserSet) objectA;
-                            set.addAll((TraverserSet) objectB);
-                            if (null != this.barrierStep && set.size() > SIZE_LIMIT) {
-                                this.valueTraversal.reset();
-                                ((Step) this.barrierStep).addStarts(set.iterator());
-                                objectA = this.barrierStep.nextBarrier();
-                            }
-                        } else if (objectB instanceof Pair) {
-                            final TraverserSet set = (TraverserSet) objectA;
-                            set.addAll((TraverserSet) ((Pair) objectB).getValue0());
-                            if (set.size() > SIZE_LIMIT) {  // barrier step can never be null -- no need to check
-                                this.valueTraversal.reset();
-                                ((Step) this.barrierStep).addStarts(set.iterator());
-                                this.barrierStep.addBarrier(((Pair) objectB).getValue1());
-                                objectA = this.barrierStep.nextBarrier();
-                            } else
-                                objectA = Pair.with(set, ((Pair) objectB).getValue1());
-                        } else
-                            objectA = Pair.with(objectA, objectB);
-                        // TRAVERSER SET + BARRIER
-                    } else if (objectA instanceof Pair) {
-                        if (objectB instanceof Traverser.Admin) {
-                            final TraverserSet set = ((TraverserSet) ((Pair) objectA).getValue0());
-                            set.add((Traverser.Admin) objectB);
-                            if (set.size() > SIZE_LIMIT) { // barrier step can never be null -- no need to check
-                                this.valueTraversal.reset();
-                                ((Step) this.barrierStep).addStarts(set.iterator());
-                                this.barrierStep.addBarrier(((Pair) objectA).getValue1());
-                                objectA = this.barrierStep.nextBarrier();
-                            }
-                        } else if (objectB instanceof TraverserSet) {
-                            final TraverserSet set = (TraverserSet) ((Pair) objectA).getValue0();
-                            set.addAll((TraverserSet) objectB);
-                            if (set.size() > SIZE_LIMIT) {   // barrier step can never be null -- no need to check
-                                this.valueTraversal.reset();
-                                ((Step) this.barrierStep).addStarts(set.iterator());
-                                this.barrierStep.addBarrier(((Pair) objectA).getValue1());
-                                objectA = this.barrierStep.nextBarrier();
-                            }
-                        } else if (objectB instanceof Pair) {
-                            this.valueTraversal.reset();
-                            this.barrierStep.addBarrier(((Pair) objectA).getValue1());
-                            this.barrierStep.addBarrier(((Pair) objectB).getValue1());
-                            ((Step) this.barrierStep).addStarts(((TraverserSet) ((Pair) objectA).getValue0()).iterator());
-                            ((Step) this.barrierStep).addStarts(((TraverserSet) ((Pair) objectB).getValue0()).iterator());
-                            objectA = this.barrierStep.nextBarrier();
-                        } else {
-                            this.valueTraversal.reset();
-                            this.barrierStep.addBarrier(((Pair) objectA).getValue1());
-                            this.barrierStep.addBarrier(objectB);
-                            ((Step) this.barrierStep).addStarts(((TraverserSet) ((Pair) objectA).getValue0()).iterator());
-                            objectA = this.barrierStep.nextBarrier();
-                        }
-                        // BARRIER
-                    } else {
-                        if (objectB instanceof Traverser.Admin) {
-                            objectA = Pair.with(new TraverserSet<>((Traverser.Admin) objectB), objectA);
-                        } else if (objectB instanceof TraverserSet) {
-                            objectA = Pair.with(objectB, objectA);
-                        } else if (objectB instanceof Pair) {
-                            this.valueTraversal.reset();
-                            this.barrierStep.addBarrier(objectA);
-                            this.barrierStep.addBarrier(((Pair) objectB).getValue1());
-                            ((Step) this.barrierStep).addStarts(((TraverserSet) ((Pair) objectB).getValue0()).iterator());
-                            objectA = this.barrierStep.nextBarrier();
-                        } else {
-                            this.valueTraversal.reset();
-                            this.barrierStep.addBarrier(objectA);
-                            this.barrierStep.addBarrier(objectB);
-                            objectA = this.barrierStep.nextBarrier();
-                        }
-                    }
-                }
-                mapA.put(key, (V) objectA);
+                else if (null != objectB)
+                    objectA = this.barrierAggregator.apply(objectA, objectB);
+                mapA.put(key, objectA);
             }
             return mapA;
         }
-
-        // necessary to control Java Serialization to ensure proper clearing of internal traverser data
-        private void writeObject(final ObjectOutputStream outputStream) throws IOException {
-            // necessary as a non-root child is being sent over the wire
-            if (null != this.valueTraversal) this.valueTraversal.setParent(EmptyStep.instance());
-            outputStream.writeObject(null == this.valueTraversal ? null : this.valueTraversal.clone()); // todo: reset() instead?
-        }
-
-        private void readObject(final ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
-            this.valueTraversal = (Traversal.Admin<?, V>) inputStream.readObject();
-            this.barrierStep = null == this.valueTraversal ? null : TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, this.valueTraversal).orElse(null);
-        }
     }
 
 
@@ -343,55 +178,19 @@ public final class GroupStep<S, K, V> extends ReducingBarrierStep<S, Map<K, V>>
                 valueTraversal instanceof IdentityTraversal ||
                 valueTraversal.getStartStep() instanceof LambdaMapStep && ((LambdaMapStep) valueTraversal.getStartStep()).getMapFunction() instanceof FunctionTraverser) {
             return (Traversal.Admin<S, E>) __.map(valueTraversal).fold();
-        } else {
+        } else
             return valueTraversal;
-        }
-    }
-
-    public static Traversal.Admin<?, ?> generatePreTraversal(final Traversal.Admin<?, ?> valueTraversal) {
-        if (!TraversalHelper.hasStepOfAssignableClass(Barrier.class, valueTraversal))
-            return valueTraversal.clone();
-        final Traversal.Admin<?, ?> first = __.identity().asAdmin();
-        boolean updated = false;
-        for (final Step step : valueTraversal.getSteps()) {
-            if (step instanceof Barrier)
-                break;
-            first.addStep(step.clone());
-            updated = true;
-        }
-        return updated ? first : null;
     }
 
     public static <K, V> Map<K, V> doFinalReduction(final Map<K, Object> map, final Traversal.Admin<?, V> valueTraversal) {
-        final Map<K, V> reducedMap = new HashMap<>(map.size());
-        final Barrier reducingBarrierStep = TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, valueTraversal).orElse(null);
-        IteratorUtils.removeOnNext(map.entrySet().iterator()).forEachRemaining(entry -> {
-            if (null == reducingBarrierStep) {
-                if (entry.getValue() instanceof TraverserSet) {
-                    if (!((TraverserSet) entry.getValue()).isEmpty())
-                        reducedMap.put(entry.getKey(), ((TraverserSet<V>) entry.getValue()).peek().get());
-                } else
-                    reducedMap.put(entry.getKey(), (V) entry.getValue());
-            } else {
+        TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, valueTraversal).ifPresent(barrierStep -> {
+            for (final K key : map.keySet()) {
                 valueTraversal.reset();
-                if (entry.getValue() instanceof Traverser.Admin)
-                    ((Step) reducingBarrierStep).addStart((Traverser.Admin) entry.getValue());
-                else if (entry.getValue() instanceof TraverserSet)
-                    ((Step) reducingBarrierStep).addStarts(((TraverserSet) entry.getValue()).iterator());
-                else if (entry.getValue() instanceof Pair) {
-                    ((Step) reducingBarrierStep).addStarts(((TraverserSet) (((Pair) entry.getValue()).getValue0())).iterator());
-                    reducingBarrierStep.addBarrier((((Pair) entry.getValue()).getValue1()));
-                } else
-                    reducingBarrierStep.addBarrier(entry.getValue());
+                barrierStep.addBarrier(map.get(key));
                 if (valueTraversal.hasNext())
-                    reducedMap.put(entry.getKey(), valueTraversal.next());
+                    map.put(key, valueTraversal.next());
             }
         });
-        assert map.isEmpty();
-        map.clear();
-        map.putAll(reducedMap);
         return (Map<K, V>) map;
     }
-}
-
-
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3496402a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java
index 0e8a4f5..9847a53 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java
@@ -18,15 +18,17 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect;
 
+import org.apache.tinkerpop.gremlin.process.traversal.Operator;
 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.Barrier;
 import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.SideEffectCapable;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStep;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.util.function.HashMapSupplier;
@@ -44,8 +46,8 @@ public final class GroupSideEffectStep<S, K, V> extends SideEffectStep<S> implem
 
     private char state = 'k';
     private Traversal.Admin<S, K> keyTraversal;
-    private Traversal.Admin<S, ?> preTraversal;
     private Traversal.Admin<S, V> valueTraversal;
+    private Barrier barrierStep;
     ///
     private String sideEffectKey;
 
@@ -53,8 +55,11 @@ public final class GroupSideEffectStep<S, K, V> extends SideEffectStep<S> implem
         super(traversal);
         this.sideEffectKey = sideEffectKey;
         this.valueTraversal = this.integrateChild(__.fold().asAdmin());
-        this.preTraversal = this.integrateChild(GroupStep.generatePreTraversal(this.valueTraversal));
-        this.getTraversal().getSideEffects().registerIfAbsent(this.sideEffectKey, HashMapSupplier.instance(), new GroupStep.GroupBiOperator<>(this.valueTraversal));
+        this.barrierStep = TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, this.valueTraversal).orElse(null);
+        this.getTraversal().getSideEffects().registerIfAbsent(this.sideEffectKey, HashMapSupplier.instance(),
+                new GroupStep.GroupBiOperator<>(null == this.barrierStep ?
+                        Operator.assign :
+                        this.barrierStep.getMemoryComputeKey().getReducer()));
     }
 
     @Override
@@ -64,8 +69,11 @@ public final class GroupSideEffectStep<S, K, V> extends SideEffectStep<S> implem
             this.state = 'v';
         } else if ('v' == this.state) {
             this.valueTraversal = this.integrateChild(GroupStep.convertValueTraversal(kvTraversal));
-            this.preTraversal = this.integrateChild(GroupStep.generatePreTraversal(this.valueTraversal));
-            this.getTraversal().getSideEffects().register(this.sideEffectKey, null, new GroupStep.GroupBiOperator<>(this.valueTraversal));
+            this.barrierStep = TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, this.valueTraversal).orElse(null);
+            this.getTraversal().getSideEffects().register(this.sideEffectKey, null,
+                    new GroupStep.GroupBiOperator<>(null == this.barrierStep ?
+                            Operator.assign :
+                            this.barrierStep.getMemoryComputeKey().getReducer()));
             this.state = 'x';
         } else {
             throw new IllegalStateException("The key and value traversals for group()-step have already been set: " + this);
@@ -75,18 +83,15 @@ public final class GroupSideEffectStep<S, K, V> extends SideEffectStep<S> implem
     @Override
     protected void sideEffect(final Traverser.Admin<S> traverser) {
         final Map<K, V> map = new HashMap<>(1);
-        if (null == this.preTraversal) {
-            map.put(TraversalUtil.applyNullable(traverser, this.keyTraversal), (V) traverser.split());
-        } else {
-            final TraverserSet traverserSet = new TraverserSet<>();
-            this.preTraversal.reset();
-            this.preTraversal.addStart(traverser.split());
-            while(this.preTraversal.hasNext()) {
-                traverserSet.add(this.preTraversal.nextTraverser());
-            }
-            map.put(TraversalUtil.applyNullable(traverser, this.keyTraversal), (V) traverserSet);
-        }
-        this.getTraversal().getSideEffects().add(this.sideEffectKey, map);
+        this.valueTraversal.reset();
+        this.valueTraversal.addStart(traverser);
+        if (null == this.barrierStep) {
+            if (this.valueTraversal.hasNext())
+                map.put(TraversalUtil.applyNullable(traverser, this.keyTraversal), (V) this.valueTraversal.next());
+        } else if (this.barrierStep.hasNextBarrier())
+            map.put(TraversalUtil.applyNullable(traverser, this.keyTraversal), (V) this.barrierStep.nextBarrier());
+        if (!map.isEmpty())
+            this.getTraversal().getSideEffects().add(this.sideEffectKey, map);
     }
 
     @Override
@@ -101,12 +106,10 @@ public final class GroupSideEffectStep<S, K, V> extends SideEffectStep<S> implem
 
     @Override
     public List<Traversal.Admin<?, ?>> getLocalChildren() {
-        final List<Traversal.Admin<?, ?>> children = new ArrayList<>(3);
+        final List<Traversal.Admin<?, ?>> children = new ArrayList<>(2);
         if (null != this.keyTraversal)
             children.add(this.keyTraversal);
         children.add(this.valueTraversal);
-        if (null != this.preTraversal)
-            children.add(this.preTraversal);
         return children;
     }
 
@@ -121,7 +124,7 @@ public final class GroupSideEffectStep<S, K, V> extends SideEffectStep<S> implem
         if (null != this.keyTraversal)
             clone.keyTraversal = this.keyTraversal.clone();
         clone.valueTraversal = this.valueTraversal.clone();
-        clone.preTraversal = (Traversal.Admin<S, ?>) GroupStep.generatePreTraversal(clone.valueTraversal);
+        clone.barrierStep = TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, clone.valueTraversal).orElse(null);
         return clone;
     }
 
@@ -130,7 +133,6 @@ public final class GroupSideEffectStep<S, K, V> extends SideEffectStep<S> implem
         super.setTraversal(parentTraversal);
         this.integrateChild(this.keyTraversal);
         this.integrateChild(this.valueTraversal);
-        this.integrateChild(this.preTraversal);
     }
 
     @Override
@@ -145,4 +147,4 @@ public final class GroupSideEffectStep<S, K, V> extends SideEffectStep<S> implem
     public Map<K, V> generateFinalResult(final Map<K, ?> object) {
         return GroupStep.doFinalReduction((Map<K, Object>) object, this.valueTraversal);
     }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3496402a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyGroupTest.groovy
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyGroupTest.groovy b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyGroupTest.groovy
index 84da296..3ce9efe 100644
--- a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyGroupTest.groovy
+++ b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyGroupTest.groovy
@@ -123,5 +123,10 @@ public abstract class GroovyGroupTest {
         public Traversal<Vertex, Map<String, String>> get_g_V_groupXmX_byXnameX_byXinXknowsX_nameX_capXmX() {
             new ScriptTraversal<>(g, "gremlin-groovy", "g.V.group('m').by('name').by(__.in('knows').name).cap('m')")
         }
+
+        @Override
+        public Traversal<Vertex, Map<String, Number>> get_g_V_group_byXlabelX_byXbothE_groupXaX_byXlabelX_byXweight_sumX_weight_sumX() {
+            new ScriptTraversal<>(g, "gremlin-groovy", "g.V.group().by(label).by(bothE().group('a').by(label).by(values('weight').sum).weight.sum)")
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3496402a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java
index 036c8c8..71b15a5 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java
@@ -37,10 +37,12 @@ import java.util.Map;
 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.__.both;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.bothE;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.constant;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.count;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.outE;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.values;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -90,6 +92,8 @@ public abstract class GroupTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, Map<String, String>> get_g_V_groupXmX_byXnameX_byXinXknowsX_nameX_capXmX();
 
+    public abstract Traversal<Vertex, Map<String, Number>> get_g_V_group_byXlabelX_byXbothE_groupXaX_byXlabelX_byXweight_sumX_weight_sumX();
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_group_byXnameX() {
@@ -441,6 +445,23 @@ public abstract class GroupTest extends AbstractGremlinProcessTest {
         checkSideEffects(traversal.asAdmin().getSideEffects(), "m", HashMap.class);
     }
 
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_group_byXlabelX_byXbothE_groupXaX_byXlabelX_byXweight_sumX_weight_sumX() {
+        final Traversal<Vertex, Map<String, Number>> traversal = get_g_V_group_byXlabelX_byXbothE_groupXaX_byXlabelX_byXweight_sumX_weight_sumX();
+        printTraversalForm(traversal);
+        final Map<String, Number> map = traversal.next();
+        assertFalse(traversal.hasNext());
+        assertEquals(2, map.size());
+        assertEquals(2.0d, map.get("software").doubleValue(), 0.01d);
+        assertEquals(5.0d, map.get("person").doubleValue(), 0.01d);
+        checkSideEffects(traversal.asAdmin().getSideEffects(), "a", HashMap.class);
+        final Map<String, Number> sideEffect = traversal.asAdmin().getSideEffects().get("a");
+        assertEquals(2, sideEffect.size());
+        assertEquals(4.0d, sideEffect.get("created").doubleValue(), 0.01d);
+        assertEquals(3.0d, sideEffect.get("knows").doubleValue(), 0.01d);
+    }
+
     public static class Traversals extends GroupTest {
 
         @Override
@@ -525,17 +546,22 @@ public abstract class GroupTest extends AbstractGremlinProcessTest {
 
         @Override
         public Traversal<Vertex, Map<Long, Map<String, List<Vertex>>>> get_g_V_group_byXbothE_countX_byXgroup_byXlabelXX() {
-            return g.V().<Long, Map<String, List<Vertex>>>group().by(__.bothE().count()).by(__.group().by(T.label));
+            return g.V().<Long, Map<String, List<Vertex>>>group().by(bothE().count()).by(__.group().by(T.label));
         }
 
         @Override
         public Traversal<Vertex, Map<String, Map<String, Number>>> get_g_V_outXfollowedByX_group_byXsongTypeX_byXbothE_group_byXlabelX_byXweight_sumXX() {
-            return g.V().out("followedBy").<String, Map<String, Number>>group().by("songType").by(__.bothE().group().by(T.label).by(__.values("weight").sum()));
+            return g.V().out("followedBy").<String, Map<String, Number>>group().by("songType").by(bothE().group().by(T.label).by(values("weight").sum()));
         }
 
         @Override
         public Traversal<Vertex, Map<String, String>> get_g_V_groupXmX_byXnameX_byXinXknowsX_nameX_capXmX() {
             return g.V().group("m").by("name").by(__.in("knows").values("name")).cap("m");
         }
+
+        @Override
+        public Traversal<Vertex, Map<String, Number>> get_g_V_group_byXlabelX_byXbothE_groupXaX_byXlabelX_byXweight_sumX_weight_sumX() {
+            return g.V().<String, Number>group().by(T.label).by(bothE().group("a").by(T.label).by(values("weight").sum()).values("weight").sum());
+        }
     }
 }


[11/17] tinkerpop git commit: A proof that TINKERPOP-1261 is fixed given the refactor of GroupBiOperator.

Posted by sp...@apache.org.
A proof that TINKERPOP-1261 is fixed given the refactor of GroupBiOperator.


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

Branch: refs/heads/TINKERPOP-1560
Commit: d54b490a66837e98077fa1e90f45ad20497c1a19
Parents: 341ebf9
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Thu Jan 19 08:57:36 2017 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Thu Jan 19 08:57:36 2017 -0700

----------------------------------------------------------------------
 .../step/sideEffect/GroovyGroupTest.groovy      |  5 ++++
 .../traversal/step/sideEffect/GroupTest.java    | 30 ++++++++++++++++++++
 2 files changed, 35 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d54b490a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyGroupTest.groovy
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyGroupTest.groovy b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyGroupTest.groovy
index 3ce9efe..fc0c55d 100644
--- a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyGroupTest.groovy
+++ b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyGroupTest.groovy
@@ -128,5 +128,10 @@ public abstract class GroovyGroupTest {
         public Traversal<Vertex, Map<String, Number>> get_g_V_group_byXlabelX_byXbothE_groupXaX_byXlabelX_byXweight_sumX_weight_sumX() {
             new ScriptTraversal<>(g, "gremlin-groovy", "g.V.group().by(label).by(bothE().group('a').by(label).by(values('weight').sum).weight.sum)")
         }
+
+        @Override
+        public Traversal<Vertex, Map<String, List<Object>>> get_g_withSideEffectXa__marko_666_noone_blahX_V_groupXaX_byXnameX_byXoutE_label_foldX_capXaX() {
+            new ScriptTraversal<>(g, "gremlin-groovy", "g.withSideEffect('a', map).V().group('a').by('name').by(outE().label.fold).cap('a')", "map", new HashMap<>(["marko": [666], "noone": ["blah"]]));
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d54b490a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java
index 71b15a5..5f2504e 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java
@@ -28,9 +28,12 @@ import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 
@@ -94,6 +97,8 @@ public abstract class GroupTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, Map<String, Number>> get_g_V_group_byXlabelX_byXbothE_groupXaX_byXlabelX_byXweight_sumX_weight_sumX();
 
+    public abstract Traversal<Vertex, Map<String, List<Object>>> get_g_withSideEffectXa__marko_666_noone_blahX_V_groupXaX_byXnameX_byXoutE_label_foldX_capXaX();
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_group_byXnameX() {
@@ -462,6 +467,23 @@ public abstract class GroupTest extends AbstractGremlinProcessTest {
         assertEquals(3.0d, sideEffect.get("knows").doubleValue(), 0.01d);
     }
 
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_withSideEffectXa__marko_666_noone_blahX_V_groupXaX_byXnameX_byXoutE_label_foldX_capXaX() {
+        final Traversal<Vertex, Map<String, List<Object>>> traversal = get_g_withSideEffectXa__marko_666_noone_blahX_V_groupXaX_byXnameX_byXoutE_label_foldX_capXaX();
+        printTraversalForm(traversal);
+        final Map<String, List<Object>> map = traversal.next();
+        assertEquals(7, map.size());
+        assertEquals(Collections.singleton("blah"), new HashSet<>(map.get("noone")));
+        assertEquals(new HashSet<>(Arrays.asList("created", "knows", 666)), new HashSet<>(map.get("marko")));
+        assertEquals(Collections.singleton("created"), new HashSet<>(map.get("josh")));
+        assertEquals(Collections.singleton("created"), new HashSet<>(map.get("peter")));
+        assertEquals(Collections.emptySet(), new HashSet<>(map.get("vadas")));
+        assertEquals(Collections.emptySet(), new HashSet<>(map.get("lop")));
+        assertEquals(Collections.emptySet(), new HashSet<>(map.get("ripple")));
+        checkSideEffects(traversal.asAdmin().getSideEffects(), "a", HashMap.class);
+    }
+
     public static class Traversals extends GroupTest {
 
         @Override
@@ -563,5 +585,13 @@ public abstract class GroupTest extends AbstractGremlinProcessTest {
         public Traversal<Vertex, Map<String, Number>> get_g_V_group_byXlabelX_byXbothE_groupXaX_byXlabelX_byXweight_sumX_weight_sumX() {
             return g.V().<String, Number>group().by(T.label).by(bothE().group("a").by(T.label).by(values("weight").sum()).values("weight").sum());
         }
+
+        @Override
+        public Traversal<Vertex, Map<String, List<Object>>> get_g_withSideEffectXa__marko_666_noone_blahX_V_groupXaX_byXnameX_byXoutE_label_foldX_capXaX() {
+            final Map<String, List<Object>> map = new HashMap<>();
+            map.put("marko", new ArrayList<>(Collections.singleton(666)));
+            map.put("noone", new ArrayList<>(Collections.singleton("blah")));
+            return g.withSideEffect("a", map).V().group("a").by("name").by(outE().label().fold()).cap("a");
+        }
     }
 }


[13/17] tinkerpop git commit: introduced a minor bug into CollectingBarrierStep that would only be noticed by asynchrnous traversal execution engines. I noticed it in the GraphActors branch. Also, added a toString() to ProjectedTraverser. CTR.

Posted by sp...@apache.org.
introduced a minor bug into CollectingBarrierStep that would only be noticed by asynchrnous traversal execution engines. I noticed it in the GraphActors branch. Also, added a toString() to ProjectedTraverser. CTR.


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

Branch: refs/heads/TINKERPOP-1560
Commit: 8ad291134d1b9febdae437e855812185b41c73db
Parents: 6002299
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Thu Jan 19 13:01:07 2017 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Thu Jan 19 13:01:07 2017 -0700

----------------------------------------------------------------------
 .../process/traversal/step/util/CollectingBarrierStep.java      | 4 ++--
 .../gremlin/process/traversal/traverser/ProjectedTraverser.java | 5 +++++
 2 files changed, 7 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8ad29113/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java
index f99201d..8409c9f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java
@@ -97,8 +97,8 @@ public abstract class CollectingBarrierStep<S> extends AbstractStep<S, S> implem
 
     @Override
     public void addBarrier(final TraverserSet<S> barrier) {
-        this.traverserSet = barrier;
-        this.traverserSet.forEach(traverser -> traverser.setSideEffects(this.getTraversal().getSideEffects()));
+        barrier.forEach(traverser -> traverser.setSideEffects(this.getTraversal().getSideEffects()));
+        this.traverserSet.addAll(barrier);
         this.barrierConsumed = false;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8ad29113/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
index 128e377..602f88f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
@@ -182,6 +182,11 @@ public final class ProjectedTraverser<T, P> implements Traverser.Admin<T> {
     }
 
     @Override
+    public String toString() {
+        return this.baseTraverser.toString();
+    }
+
+    @Override
     public ProjectedTraverser<T, P> clone() {
         try {
             final ProjectedTraverser<T, P> clone = (ProjectedTraverser<T, P>) super.clone();


[16/17] tinkerpop git commit: Fixed and simplified 'language not supported' formatting

Posted by sp...@apache.org.
Fixed and simplified 'language not supported' formatting


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

Branch: refs/heads/TINKERPOP-1560
Commit: f84f454ec456ec0d3ad39fc01c0d71b1fa217d4b
Parents: 62785dc
Author: Joshua Shinavier <jo...@fortytwo.net>
Authored: Fri Jan 20 22:24:29 2017 -0800
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Mon Jan 23 07:32:23 2017 -0500

----------------------------------------------------------------------
 .../tinkerpop/gremlin/groovy/engine/ScriptEngines.java  | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f84f454e/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEngines.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEngines.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEngines.java
index 6911419..7dcfc5c 100644
--- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEngines.java
+++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEngines.java
@@ -110,8 +110,7 @@ public class ScriptEngines implements AutoCloseable {
      * Evaluate a script with {@code Bindings} for a particular language.
      */
     public Object eval(final String script, final Bindings bindings, final String language) throws ScriptException {
-        if (!scriptEngines.containsKey(language))
-            throw new IllegalArgumentException(String.format("Language [%s] not supported", language));
+        checkLanguageIsSupported(language);
 
         awaitControlOp();
 
@@ -126,8 +125,7 @@ public class ScriptEngines implements AutoCloseable {
      */
     public Object eval(final Reader reader, final Bindings bindings, final String language)
             throws ScriptException {
-        if (!scriptEngines.containsKey(language))
-            throw new IllegalArgumentException("Language [%s] not supported");
+        checkLanguageIsSupported(language);
 
         awaitControlOp();
 
@@ -454,4 +452,10 @@ public class ScriptEngines implements AutoCloseable {
         all.putAll(bindings);
         return all;
     }
+
+    private void checkLanguageIsSupported(final String language) {
+        if (!scriptEngines.containsKey(language)) {
+            throw new IllegalArgumentException(String.format("Language [%s] not supported", language));
+        }
+    }
 }


[06/17] tinkerpop git commit: added a private no-arg constructor to MultiComparator so it can be serialized.

Posted by sp...@apache.org.
added a private no-arg constructor to MultiComparator so it can be serialized.


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

Branch: refs/heads/TINKERPOP-1560
Commit: ee1ab08b0b8c7c6dca85d9ff046dcff739549387
Parents: 91e1f50
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Wed Jan 18 11:20:07 2017 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Wed Jan 18 11:20:07 2017 -0700

----------------------------------------------------------------------
 .../tinkerpop/gremlin/util/function/MultiComparator.java     | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ee1ab08b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java
index b7176ab..5d24ddf 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java
@@ -31,8 +31,12 @@ import java.util.List;
  */
 public final class MultiComparator<C> implements Comparator<C>, Serializable {
 
-    private final List<Comparator> comparators;
-    private final boolean isShuffle;
+    private List<Comparator> comparators;
+    private boolean isShuffle;
+
+    private MultiComparator() {
+        // for serialization purposes
+    }
 
     public MultiComparator(final List<Comparator<C>> comparators) {
         this.comparators = (List) comparators;


[15/17] tinkerpop git commit: CTR: added another script evaluation test in `validate-distribution.sh`.

Posted by sp...@apache.org.
CTR: added another script evaluation test in `validate-distribution.sh`.


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

Branch: refs/heads/TINKERPOP-1560
Commit: 62785dcb686be7d56bf207a0ef4279f912cbe41e
Parents: 67a1092
Author: Daniel Kuppitz <da...@hotmail.com>
Authored: Sat Jan 21 12:29:28 2017 +0100
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Sat Jan 21 12:29:28 2017 +0100

----------------------------------------------------------------------
 bin/validate-distribution.sh | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/62785dcb/bin/validate-distribution.sh
----------------------------------------------------------------------
diff --git a/bin/validate-distribution.sh b/bin/validate-distribution.sh
index 2148610..3c2cc95 100755
--- a/bin/validate-distribution.sh
+++ b/bin/validate-distribution.sh
@@ -169,9 +169,13 @@ echo "OK"
 if [ "${TYPE}" = "CONSOLE" ]; then
   echo -n "* testing script evaluation ... "
   SCRIPT="x = org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory.createModern().traversal().V().count().next(); println x; x"
-  SCRIPT_FILENAME="${TMP_DIR}/test.groovy"
-  echo ${SCRIPT} > ${SCRIPT_FILENAME}
+  SCRIPT_FILENAME="test.groovy"
+  SCRIPT_PATH="${TMP_DIR}/${SCRIPT_FILENAME}"
+  echo ${SCRIPT} > ${SCRIPT_PATH}
   [[ `bin/gremlin.sh <<< ${SCRIPT} | grep '^==>' | sed -e 's/^==>//'` -eq 6 ]] || { echo "failed to evaluate sample script"; exit 1; }
-  [[ `bin/gremlin.sh -e ${SCRIPT_FILENAME}` -eq 6 ]] || { echo "failed to evaluate sample script using -e option"; exit 1; }
+  [[ `bin/gremlin.sh -e ${SCRIPT_PATH}` -eq 6 ]] || { echo "failed to evaluate sample script using -e option"; exit 1; }
+  CONSOLE_DIR=`pwd`
+  cd ${TMP_DIR}
+  [[ `${CONSOLE_DIR}/bin/gremlin.sh -e ${SCRIPT_FILENAME}` -eq 6 ]] || { echo "failed to evaluate sample script using -e option (using a different working directory and a relative script path)"; exit 1; }
   echo "OK"
 fi


[05/17] tinkerpop git commit: updated CHANGELOG and tweaked ProjectTraverser variable naming.

Posted by sp...@apache.org.
updated CHANGELOG and tweaked ProjectTraverser variable naming.


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

Branch: refs/heads/TINKERPOP-1560
Commit: 91e1f50c8b95d295a86cba6f3c9db7a002664233
Parents: b2f0c57
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Wed Jan 18 11:17:05 2017 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Wed Jan 18 11:17:05 2017 -0700

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  3 +-
 .../traversal/traverser/ProjectedTraverser.java | 69 +++++++++-----------
 2 files changed, 34 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/91e1f50c/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 86c6b4f..052257f 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,7 +26,8 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.4 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-* `OrderGlobalStep` now emits traversers with their `by()`-projections and thus, can move beyond the local star graph.
+* Added `ProjectedTraverser` which wraps a traverser with a `List<Object>` of projected data.
+* `OrderGlobalStep` and `SampleGlobalStep` now emit traversers with their `by()`-projections and thus, can move beyond the local star graph.
 * SASL negotiation supports both a byte array and Base64 encoded bytes as a string for authentication to Gremlin Server.
 * Deprecated `TinkerIoRegistry` replacing it with the more consistently named `TinkerIoRegistryV1d0`.
 * Made error messaging more consistent during result iteration timeouts in Gremlin Server.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/91e1f50c/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
index 5cecdc4..128e377 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
@@ -34,163 +34,158 @@ import java.util.function.Function;
  */
 public final class ProjectedTraverser<T, P> implements Traverser.Admin<T> {
 
-    private Traverser.Admin<T> internal;
+    private Traverser.Admin<T> baseTraverser;
     private List<P> projections;
 
     private ProjectedTraverser() {
         // for serialization
     }
 
-    public ProjectedTraverser(final Traverser.Admin<T> internal, final List<P> projections) {
-        this.internal = internal;
+    public ProjectedTraverser(final Traverser.Admin<T> baseTraverser, final List<P> projections) {
+        this.baseTraverser = baseTraverser;
         this.projections = projections;
     }
 
-
-    public Traverser.Admin<T> getInternal() {
-        return this.internal;
-    }
-
     public List<P> getProjections() {
         return this.projections;
     }
 
     @Override
     public void merge(final Admin<?> other) {
-        this.internal.merge(other);
+        this.baseTraverser.merge(other);
     }
 
     @Override
-    public <R> Admin<R> split(R r, Step<T, R> step) {
-        return new ProjectedTraverser<>(this.internal.split(r, step), this.projections);
+    public <R> Admin<R> split(final R r, final Step<T, R> step) {
+        return new ProjectedTraverser<>(this.baseTraverser.split(r, step), this.projections);
     }
 
     @Override
     public Admin<T> split() {
-        return new ProjectedTraverser<>(this.internal.split(), this.projections);
+        return new ProjectedTraverser<>(this.baseTraverser.split(), this.projections);
     }
 
     @Override
     public void addLabels(final Set<String> labels) {
-        this.internal.addLabels(labels);
+        this.baseTraverser.addLabels(labels);
     }
 
     @Override
     public void keepLabels(final Set<String> labels) {
-        this.internal.keepLabels(labels);
+        this.baseTraverser.keepLabels(labels);
     }
 
     @Override
     public void dropLabels(final Set<String> labels) {
-        this.internal.dropLabels(labels);
+        this.baseTraverser.dropLabels(labels);
     }
 
     @Override
     public void dropPath() {
-        this.internal.dropPath();
+        this.baseTraverser.dropPath();
     }
 
     @Override
     public void set(final T t) {
-        this.internal.set(t);
+        this.baseTraverser.set(t);
     }
 
     @Override
     public void incrLoops(final String stepLabel) {
-        this.internal.incrLoops(stepLabel);
+        this.baseTraverser.incrLoops(stepLabel);
     }
 
     @Override
     public void resetLoops() {
-        this.internal.resetLoops();
+        this.baseTraverser.resetLoops();
     }
 
     @Override
     public String getStepId() {
-        return this.internal.getStepId();
+        return this.baseTraverser.getStepId();
     }
 
     @Override
     public void setStepId(final String stepId) {
-        this.internal.setStepId(stepId);
+        this.baseTraverser.setStepId(stepId);
     }
 
     @Override
     public void setBulk(final long count) {
-        this.internal.setBulk(count);
+        this.baseTraverser.setBulk(count);
     }
 
     @Override
     public Admin<T> detach() {
-        this.internal = this.internal.detach();
+        this.baseTraverser = this.baseTraverser.detach();
         return this;
     }
 
     @Override
     public T attach(final Function<Attachable<T>, T> method) {
-        return this.internal.attach(method);
+        return this.baseTraverser.attach(method);
     }
 
     @Override
     public void setSideEffects(final TraversalSideEffects sideEffects) {
-        this.internal.setSideEffects(sideEffects);
+        this.baseTraverser.setSideEffects(sideEffects);
     }
 
     @Override
     public TraversalSideEffects getSideEffects() {
-        return this.internal.getSideEffects();
+        return this.baseTraverser.getSideEffects();
     }
 
     @Override
     public Set<String> getTags() {
-        return this.internal.getTags();
+        return this.baseTraverser.getTags();
     }
 
     @Override
     public T get() {
-        return this.internal.get();
+        return this.baseTraverser.get();
     }
 
     @Override
     public <S> S sack() {
-        return this.internal.sack();
+        return this.baseTraverser.sack();
     }
 
     @Override
     public <S> void sack(final S object) {
-        this.internal.sack(object);
+        this.baseTraverser.sack(object);
     }
 
     @Override
     public Path path() {
-        return this.internal.path();
+        return this.baseTraverser.path();
     }
 
     @Override
     public int loops() {
-        return this.internal.loops();
+        return this.baseTraverser.loops();
     }
 
     @Override
     public long bulk() {
-        return this.internal.bulk();
+        return this.baseTraverser.bulk();
     }
 
     @Override
     public int hashCode() {
-        return this.internal.hashCode();
+        return this.baseTraverser.hashCode();
     }
 
     @Override
     public boolean equals(final Object object) {
-        return object instanceof ProjectedTraverser && ((ProjectedTraverser) object).internal.equals(this.internal);
+        return object instanceof ProjectedTraverser && ((ProjectedTraverser) object).baseTraverser.equals(this.baseTraverser);
     }
 
     @Override
     public ProjectedTraverser<T, P> clone() {
         try {
             final ProjectedTraverser<T, P> clone = (ProjectedTraverser<T, P>) super.clone();
-            clone.internal = (Traverser.Admin<T>) this.internal.clone();
+            clone.baseTraverser = (Traverser.Admin<T>) this.baseTraverser.clone();
             return clone;
         } catch (final CloneNotSupportedException e) {
             throw new IllegalStateException(e.getMessage(), e);
@@ -198,6 +193,6 @@ public final class ProjectedTraverser<T, P> implements Traverser.Admin<T> {
     }
 
     public static <T> Traverser.Admin<T> tryUnwrap(final Traverser.Admin<T> traverser) {
-        return traverser instanceof ProjectedTraverser ? ((ProjectedTraverser) traverser).getInternal() : traverser;
+        return traverser instanceof ProjectedTraverser ? ((ProjectedTraverser) traverser).baseTraverser : traverser;
     }
 }
\ No newline at end of file


[04/17] tinkerpop git commit: Removed a PathProcessor.ID constraint from ComputerVerificationStrategy. Moreover, sampling and ordering is more efficient as the projected data is co-located with the traverser in the new ProjectedTraverser wrapper. Going t

Posted by sp...@apache.org.
Removed a PathProcessor.ID constraint from ComputerVerificationStrategy. Moreover, sampling and ordering is more efficient as the projected data is co-located with the traverser in the new ProjectedTraverser wrapper. Going to leave it at this for tp32/... Moving forward, we can make it so we don't need to DetachFactory.detach(true) for CollectingBarrierStep by maintaining 'future data.' Its complicated and I don't want to introduce potential bugs.


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

Branch: refs/heads/TINKERPOP-1560
Commit: b2f0c57df6fd9191904213622ae718a0790d7a03
Parents: 5045f67
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Wed Jan 18 11:07:32 2017 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Wed Jan 18 11:07:32 2017 -0700

----------------------------------------------------------------------
 .../traversal/step/filter/SampleGlobalStep.java | 19 ++++++++++++--
 .../traversal/step/map/OrderGlobalStep.java     | 27 +++++---------------
 .../step/util/CollectingBarrierStep.java        | 24 ++++++++++-------
 .../ComputerVerificationStrategy.java           |  8 ------
 .../traversal/traverser/ProjectedTraverser.java | 16 +++++++-----
 .../gremlin/util/function/MultiComparator.java  | 14 +++++++---
 6 files changed, 60 insertions(+), 48 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b2f0c57d/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
index 0a4da58..2b2cf20 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
@@ -24,6 +24,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.CollectingBarrierStep;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.ProjectedTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
@@ -64,6 +65,15 @@ public final class SampleGlobalStep<S> extends CollectingBarrierStep<S> implemen
     }
 
     @Override
+    public void processAllStarts() {
+        if (this.starts.hasNext()) {
+            while (this.starts.hasNext()) {
+                this.traverserSet.add(this.createProjectedTraverser(this.starts.next()));
+            }
+        }
+    }
+
+    @Override
     public void barrierConsumer(final TraverserSet<S> traverserSet) {
         // return the entire traverser set if the set is smaller than the amount to sample
         if (traverserSet.bulkSize() <= this.amountToSample)
@@ -71,7 +81,7 @@ public final class SampleGlobalStep<S> extends CollectingBarrierStep<S> implemen
         //////////////// else sample the set
         double totalWeight = 0.0d;
         for (final Traverser.Admin<S> s : traverserSet) {
-            totalWeight = totalWeight + TraversalUtil.apply(s, this.probabilityTraversal).doubleValue() * s.bulk();
+            totalWeight = totalWeight + (((ProjectedTraverser<S, Number>) s).getProjections().get(0).doubleValue() * s.bulk());
         }
         ///////
         final TraverserSet<S> sampledSet = new TraverserSet<>();
@@ -82,7 +92,7 @@ public final class SampleGlobalStep<S> extends CollectingBarrierStep<S> implemen
             for (final Traverser.Admin<S> s : traverserSet) {
                 long sampleBulk = sampledSet.contains(s) ? sampledSet.get(s).bulk() : 0;
                 if (sampleBulk < s.bulk()) {
-                    final double currentWeight = TraversalUtil.apply(s, this.probabilityTraversal).doubleValue();
+                    final double currentWeight = ((ProjectedTraverser<S, Number>) s).getProjections().get(0).doubleValue();
                     for (int i = 0; i < (s.bulk() - sampleBulk); i++) {
                         runningWeight = runningWeight + currentWeight;
                         if (RANDOM.nextDouble() <= ((runningWeight / totalWeight))) {
@@ -104,6 +114,11 @@ public final class SampleGlobalStep<S> extends CollectingBarrierStep<S> implemen
         traverserSet.addAll(sampledSet);
     }
 
+
+    private final ProjectedTraverser<S, Number> createProjectedTraverser(final Traverser.Admin<S> traverser) {
+        return new ProjectedTraverser<>(traverser, Collections.singletonList(TraversalUtil.apply(traverser, this.probabilityTraversal)));
+    }
+
     @Override
     public Set<TraverserRequirement> getRequirements() {
         return this.getSelfAndChildRequirements(TraverserRequirement.BULK);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b2f0c57d/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
index 9c071f1..55d8650 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
@@ -73,22 +73,11 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
             this.multiComparator = this.createMultiComparator();
         if (this.starts.hasNext()) {
             while (this.starts.hasNext()) {
-                this.traverserSet.add(this.createOrderedTraverser(this.starts.next()));
+                this.traverserSet.add(this.createProjectedTraverser(this.starts.next()));
             }
-            this.barrierConsumer(this.traverserSet);
         }
     }
 
-    @Override
-    public Traverser.Admin<S> processNextStart() {
-        if (!this.traverserSet.isEmpty()) {
-            return this.traverserSet.remove();
-        } else if (this.starts.hasNext()) {
-            this.processAllStarts();
-        }
-        return ((ProjectedTraverser) this.traverserSet.remove()).getInternal();
-    }
-
     public void setLimit(final long limit) {
         this.limit = limit;
     }
@@ -162,18 +151,18 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
     public MemoryComputeKey<TraverserSet<S>> getMemoryComputeKey() {
         if (null == this.multiComparator)
             this.multiComparator = this.createMultiComparator();
-        return MemoryComputeKey.of(this.getId(), new OrderBiOperator<>(this.limit, this.isShuffle, this.multiComparator), false, true);
+        return MemoryComputeKey.of(this.getId(), new OrderBiOperator<>(this.limit, this.multiComparator), false, true);
     }
 
-    private ProjectedTraverser<S> createOrderedTraverser(final Traverser.Admin<S> traverser) {
+    private final ProjectedTraverser<S,Object> createProjectedTraverser(final Traverser.Admin<S> traverser) {
         final List<Object> projections = new ArrayList<>(this.comparators.size());
         for (final Pair<Traversal.Admin<S, C>, Comparator<C>> pair : this.comparators) {
             projections.add(TraversalUtil.apply(traverser, pair.getValue0()));
         }
-        return new ProjectedTraverser<S>(traverser, projections);
+        return new ProjectedTraverser<>(traverser, projections);
     }
 
-    private MultiComparator<C> createMultiComparator() {
+    private final MultiComparator<C> createMultiComparator() {
         final List<Comparator<C>> list = new ArrayList<>(this.comparators.size());
         for (final Pair<Traversal.Admin<S, C>, Comparator<C>> pair : this.comparators) {
             list.add(pair.getValue1());
@@ -186,16 +175,14 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
     public static final class OrderBiOperator<S> implements BinaryOperator<TraverserSet<S>>, Serializable {
 
         private long limit;
-        private boolean isShuffle;
         private MultiComparator comparator;
 
         private OrderBiOperator() {
             // for serializers that need a no-arg constructor
         }
 
-        public OrderBiOperator(final long limit, final boolean isShuffle, final MultiComparator multiComparator) {
+        public OrderBiOperator(final long limit, final MultiComparator multiComparator) {
             this.limit = limit;
-            this.isShuffle = isShuffle;
             this.comparator = multiComparator;
         }
 
@@ -203,7 +190,7 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
         public TraverserSet<S> apply(final TraverserSet<S> setA, final TraverserSet<S> setB) {
             setA.addAll(setB);
             if (Long.MAX_VALUE != this.limit && setA.bulkSize() > this.limit) {
-                if (this.isShuffle)
+                if (this.comparator.isShuffle())
                     setA.shuffle();
                 else
                     setA.sort(this.comparator);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b2f0c57d/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java
index b0cce80..f99201d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java
@@ -23,11 +23,13 @@ import org.apache.tinkerpop.gremlin.process.traversal.Operator;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Barrier;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.ProjectedTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
 import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedFactory;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 
 import java.util.Collections;
 import java.util.NoSuchElementException;
@@ -40,7 +42,8 @@ import java.util.function.BinaryOperator;
 public abstract class CollectingBarrierStep<S> extends AbstractStep<S, S> implements Barrier<TraverserSet<S>> {
 
     protected TraverserSet<S> traverserSet = new TraverserSet<>();
-    protected int maxBarrierSize;
+    private int maxBarrierSize;
+    private boolean barrierConsumed = false;
 
     public CollectingBarrierStep(final Traversal.Admin traversal) {
         this(traversal, Integer.MAX_VALUE);
@@ -68,7 +71,6 @@ public abstract class CollectingBarrierStep<S> extends AbstractStep<S, S> implem
                     this.traverserSet.add(this.starts.next());
                 }
             }
-            this.barrierConsumer(this.traverserSet);
         }
     }
 
@@ -85,11 +87,10 @@ public abstract class CollectingBarrierStep<S> extends AbstractStep<S, S> implem
             throw FastNoSuchElementException.instance();
         else {
             final TraverserSet<S> temp = new TraverserSet<>();
-            this.traverserSet.iterator().forEachRemaining(t -> {
+            IteratorUtils.removeOnNext(this.traverserSet.iterator()).forEachRemaining(t -> {
                 DetachedFactory.detach(t, true); // this should be dynamic
                 temp.add(t);
             });
-            this.traverserSet.clear();
             return temp;
         }
     }
@@ -98,23 +99,28 @@ public abstract class CollectingBarrierStep<S> extends AbstractStep<S, S> implem
     public void addBarrier(final TraverserSet<S> barrier) {
         this.traverserSet = barrier;
         this.traverserSet.forEach(traverser -> traverser.setSideEffects(this.getTraversal().getSideEffects()));
-        this.barrierConsumer(this.traverserSet);
+        this.barrierConsumed = false;
     }
 
     @Override
     public Traverser.Admin<S> processNextStart() {
-        if (!this.traverserSet.isEmpty()) {
-            return this.traverserSet.remove();
-        } else if (this.starts.hasNext()) {
+        if (this.traverserSet.isEmpty() && this.starts.hasNext()) {
             this.processAllStarts();
+            this.barrierConsumed = false;
+        }
+        //
+        if (!this.barrierConsumed) {
+            this.barrierConsumer(this.traverserSet);
+            this.barrierConsumed = true;
         }
-        return this.traverserSet.remove();
+        return ProjectedTraverser.tryUnwrap(this.traverserSet.remove());
     }
 
     @Override
     public CollectingBarrierStep<S> clone() {
         final CollectingBarrierStep<S> clone = (CollectingBarrierStep<S>) super.clone();
         clone.traverserSet = new TraverserSet<>();
+        clone.barrierConsumed = false;
         return clone;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b2f0c57d/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ComputerVerificationStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ComputerVerificationStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ComputerVerificationStrategy.java
index 5777adb..ef9b95c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ComputerVerificationStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ComputerVerificationStrategy.java
@@ -28,11 +28,9 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.GraphComputing;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Mutating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.SampleGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SubgraphStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.CollectingBarrierStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ProfileStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
@@ -87,12 +85,6 @@ public final class ComputerVerificationStrategy extends AbstractTraversalStrateg
                     throw new VerificationException("Local traversals may not traverse past the local star-graph on GraphComputer: " + traversalOptional.get(), traversal);
             }
 
-            // sample step use can only operate on the element and its properties (no incidences)
-            if (step instanceof SampleGlobalStep) {
-                if (((TraversalParent) step).getLocalChildren().stream().filter(t -> !TraversalHelper.isLocalProperties(t)).findAny().isPresent())
-                    throw new VerificationException("The following barrier step can not process the incident edges of a vertex on GraphComputer: " + step, traversal);
-            }
-
             // this is a problem because sideEffect.merge() is transient on the OLAP reduction
             if (TraversalHelper.getRootTraversal(traversal).getTraverserRequirements().contains(TraverserRequirement.ONE_BULK))
                 throw new VerificationException("One bulk is currently not supported on GraphComputer: " + step, traversal);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b2f0c57d/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
index 67e723a..5cecdc4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/ProjectedTraverser.java
@@ -32,16 +32,16 @@ import java.util.function.Function;
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class ProjectedTraverser<T> implements Traverser.Admin<T> {
+public final class ProjectedTraverser<T, P> implements Traverser.Admin<T> {
 
     private Traverser.Admin<T> internal;
-    private List<Object> projections;
+    private List<P> projections;
 
     private ProjectedTraverser() {
         // for serialization
     }
 
-    public ProjectedTraverser(final Traverser.Admin<T> internal, final List<Object> projections) {
+    public ProjectedTraverser(final Traverser.Admin<T> internal, final List<P> projections) {
         this.internal = internal;
         this.projections = projections;
     }
@@ -51,7 +51,7 @@ public final class ProjectedTraverser<T> implements Traverser.Admin<T> {
         return this.internal;
     }
 
-    public List<Object> getProjections() {
+    public List<P> getProjections() {
         return this.projections;
     }
 
@@ -187,13 +187,17 @@ public final class ProjectedTraverser<T> implements Traverser.Admin<T> {
     }
 
     @Override
-    public ProjectedTraverser<T> clone() {
+    public ProjectedTraverser<T, P> clone() {
         try {
-            final ProjectedTraverser<T> clone = (ProjectedTraverser<T>) super.clone();
+            final ProjectedTraverser<T, P> clone = (ProjectedTraverser<T, P>) super.clone();
             clone.internal = (Traverser.Admin<T>) this.internal.clone();
             return clone;
         } catch (final CloneNotSupportedException e) {
             throw new IllegalStateException(e.getMessage(), e);
         }
     }
+
+    public static <T> Traverser.Admin<T> tryUnwrap(final Traverser.Admin<T> traverser) {
+        return traverser instanceof ProjectedTraverser ? ((ProjectedTraverser) traverser).getInternal() : traverser;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b2f0c57d/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java
index 427aa3d..b7176ab 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/MultiComparator.java
@@ -32,9 +32,11 @@ import java.util.List;
 public final class MultiComparator<C> implements Comparator<C>, Serializable {
 
     private final List<Comparator> comparators;
+    private final boolean isShuffle;
 
     public MultiComparator(final List<Comparator<C>> comparators) {
         this.comparators = (List) comparators;
+        this.isShuffle = !this.comparators.isEmpty() && Order.shuffle == this.comparators.get(this.comparators.size() - 1);
     }
 
     @Override
@@ -43,14 +45,20 @@ public final class MultiComparator<C> implements Comparator<C>, Serializable {
             return Order.incr.compare(objectA, objectB);
         } else {
             for (int i = 0; i < this.comparators.size(); i++) {
-                final int comparison = this.comparators.get(i).compare(this.getObject(objectA, i), this.getObject(objectB, i));
-                if (comparison != 0)
-                    return comparison;
+                if (Order.shuffle != this.comparators.get(i)) {
+                    final int comparison = this.comparators.get(i).compare(this.getObject(objectA, i), this.getObject(objectB, i));
+                    if (comparison != 0)
+                        return comparison;
+                }
             }
             return 0;
         }
     }
 
+    public boolean isShuffle() {
+        return this.isShuffle;
+    }
+
     private final Object getObject(final C object, final int index) {
         if (object instanceof ProjectedTraverser)
             return ((ProjectedTraverser) object).getProjections().get(index);


[09/17] tinkerpop git commit: Merge branch 'TINKERPOP-1248' into tp32

Posted by sp...@apache.org.
Merge branch 'TINKERPOP-1248' into tp32


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

Branch: refs/heads/TINKERPOP-1560
Commit: 379a6e5e9e19b1de72fba3c7c401e4424028a88a
Parents: 3496402 973484d
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Thu Jan 19 05:33:22 2017 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Thu Jan 19 05:33:22 2017 -0700

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   3 +
 .../traversal/step/filter/SampleGlobalStep.java |  19 +-
 .../traversal/step/map/OrderGlobalStep.java     |  68 ++++---
 .../step/util/CollectingBarrierStep.java        |  24 ++-
 .../ComputerVerificationStrategy.java           |   7 -
 .../traversal/traverser/ProjectedTraverser.java | 198 +++++++++++++++++++
 .../gremlin/structure/io/gryo/GryoVersion.java  |   8 +-
 .../gremlin/util/function/MultiComparator.java  |  72 +++++++
 8 files changed, 349 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/379a6e5e/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --cc CHANGELOG.asciidoc
index 74751fa,25ff3e9..88cbf32
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@@ -26,7 -26,8 +26,10 @@@ image::https://raw.githubusercontent.co
  TinkerPop 3.2.4 (Release Date: NOT OFFICIALLY RELEASED YET)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
 +* `GroupBiOperator` no longer maintains state and thus, no more side-effect related OLAP inconsistencies.
+ * Added `ProjectedTraverser` which wraps a traverser with a `List<Object>` of projected data.
++* Fixed an optimization bug in `CollectionBarrierSteps` where the barrier was being consumed on each `addBarrier()`.
+ * `OrderGlobalStep` and `SampleGlobalStep` use `ProjectedTraverser` and now can work up to the local star graph in OLAP.
  * SASL negotiation supports both a byte array and Base64 encoded bytes as a string for authentication to Gremlin Server.
  * Deprecated `TinkerIoRegistry` replacing it with the more consistently named `TinkerIoRegistryV1d0`.
  * Made error messaging more consistent during result iteration timeouts in Gremlin Server.


[07/17] tinkerpop git commit: Not going to touch GroupStep in this ticket. Too complicated ... will do for the next release. Minor tweaks and cleanups.

Posted by sp...@apache.org.
Not going to touch GroupStep in this ticket. Too complicated ... will do for the next release. Minor tweaks and cleanups.


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

Branch: refs/heads/TINKERPOP-1560
Commit: 973484d19a81ada87e95f9d3c2b0b66988f362d9
Parents: ee1ab08
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Wed Jan 18 12:25:41 2017 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Wed Jan 18 12:25:41 2017 -0700

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  2 +-
 .../traversal/step/filter/SampleGlobalStep.java |  8 +++-----
 .../traversal/step/map/OrderGlobalStep.java     | 21 ++++++++------------
 3 files changed, 12 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/973484d1/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 052257f..25ff3e9 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -27,7 +27,7 @@ TinkerPop 3.2.4 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 * Added `ProjectedTraverser` which wraps a traverser with a `List<Object>` of projected data.
-* `OrderGlobalStep` and `SampleGlobalStep` now emit traversers with their `by()`-projections and thus, can move beyond the local star graph.
+* `OrderGlobalStep` and `SampleGlobalStep` use `ProjectedTraverser` and now can work up to the local star graph in OLAP.
 * SASL negotiation supports both a byte array and Base64 encoded bytes as a string for authentication to Gremlin Server.
 * Deprecated `TinkerIoRegistry` replacing it with the more consistently named `TinkerIoRegistryV1d0`.
 * Made error messaging more consistent during result iteration timeouts in Gremlin Server.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/973484d1/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
index 2b2cf20..28d2fb4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
@@ -66,10 +66,8 @@ public final class SampleGlobalStep<S> extends CollectingBarrierStep<S> implemen
 
     @Override
     public void processAllStarts() {
-        if (this.starts.hasNext()) {
-            while (this.starts.hasNext()) {
-                this.traverserSet.add(this.createProjectedTraverser(this.starts.next()));
-            }
+        while (this.starts.hasNext()) {
+            this.traverserSet.add(this.createProjectedTraverser(this.starts.next()));
         }
     }
 
@@ -97,7 +95,7 @@ public final class SampleGlobalStep<S> extends CollectingBarrierStep<S> implemen
                         runningWeight = runningWeight + currentWeight;
                         if (RANDOM.nextDouble() <= ((runningWeight / totalWeight))) {
                             final Traverser.Admin<S> split = s.split();
-                            split.setBulk(1l);
+                            split.setBulk(1L);
                             sampledSet.add(split);
                             runningAmountToSample++;
                             totalWeight = totalWeight - currentWeight;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/973484d1/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
index 55d8650..e5c5834 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
@@ -53,7 +53,6 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
     private List<Pair<Traversal.Admin<S, C>, Comparator<C>>> comparators = new ArrayList<>();
     private MultiComparator<C> multiComparator = null;
     private long limit = Long.MAX_VALUE;
-    private boolean isShuffle = false;
 
     public OrderGlobalStep(final Traversal.Admin traversal) {
         super(traversal);
@@ -61,7 +60,9 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
 
     @Override
     public void barrierConsumer(final TraverserSet<S> traverserSet) {
-        if (this.isShuffle)
+        if (null == this.multiComparator) this.multiComparator = this.createMultiComparator();
+        //
+        if (this.multiComparator.isShuffle())
             traverserSet.shuffle();
         else
             traverserSet.sort((Comparator) this.multiComparator);
@@ -69,12 +70,8 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
 
     @Override
     public void processAllStarts() {
-        if (null == this.multiComparator)
-            this.multiComparator = this.createMultiComparator();
-        if (this.starts.hasNext()) {
-            while (this.starts.hasNext()) {
-                this.traverserSet.add(this.createProjectedTraverser(this.starts.next()));
-            }
+        while (this.starts.hasNext()) {
+            this.traverserSet.add(this.createProjectedTraverser(this.starts.next()));
         }
     }
 
@@ -88,7 +85,6 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
 
     @Override
     public void addComparator(final Traversal.Admin<S, C> traversal, final Comparator<C> comparator) {
-        this.isShuffle = Order.shuffle == (Comparator) comparator;
         this.comparators.add(new Pair<>(this.integrateChild(traversal), comparator));
     }
 
@@ -149,13 +145,12 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
 
     @Override
     public MemoryComputeKey<TraverserSet<S>> getMemoryComputeKey() {
-        if (null == this.multiComparator)
-            this.multiComparator = this.createMultiComparator();
+        if (null == this.multiComparator) this.multiComparator = this.createMultiComparator();
         return MemoryComputeKey.of(this.getId(), new OrderBiOperator<>(this.limit, this.multiComparator), false, true);
     }
 
-    private final ProjectedTraverser<S,Object> createProjectedTraverser(final Traverser.Admin<S> traverser) {
-        final List<Object> projections = new ArrayList<>(this.comparators.size());
+    private final ProjectedTraverser<S, C> createProjectedTraverser(final Traverser.Admin<S> traverser) {
+        final List<C> projections = new ArrayList<>(this.comparators.size());
         for (final Pair<Traversal.Admin<S, C>, Comparator<C>> pair : this.comparators) {
             projections.add(TraversalUtil.apply(traverser, pair.getValue0()));
         }