You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2016/02/25 22:46:33 UTC

incubator-tinkerpop git commit: Gremlin OLAP can now do all the same traversals as Gremlin OLTP. In fact, a Gremlin OLAP job is a undulation between distributed traversers and localized traversers. Its really neat -- it like 'breathes'. Fan out, reduce,

Repository: incubator-tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1166 c4b9e7414 -> 6950b198a


Gremlin OLAP can now do all the same traversals as Gremlin OLTP. In fact, a Gremlin OLAP job is a undulation between distributed traversers and localized traversers. Its really neat -- it like 'breathes'. Fan out, reduce, fan out, reduce.... I still have to convert over OrderGlobalStep so its not done done, but yea. Saving work.


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

Branch: refs/heads/TINKERPOP-1166
Commit: 6950b198aff0d1fb4842d972bc145a6eeae539b2
Parents: c4b9e74
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Thu Feb 25 14:46:23 2016 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Thu Feb 25 14:46:23 2016 -0700

----------------------------------------------------------------------
 .../process/computer/MemoryComputeKey.java      |  21 ++++
 .../traversal/TraversalVertexProgram.java       |  93 +++++++++++++---
 .../computer/traversal/TraverserExecutor.java   |  19 +++-
 .../traversal/step/map/ComputerResultStep.java  |   4 +-
 .../mapreduce/ComputerToStandardMapReduce.java  | 110 -------------------
 .../mapreduce/TraverserMapReduce.java           |  15 +--
 .../ComputerVerificationStrategy.java           |  11 +-
 .../gremlin/structure/io/gryo/GryoMapper.java   |   4 +-
 .../step/sideEffect/GroovyGroupTest.groovy      |   5 +
 .../process/computer/GraphComputerTest.java     |  12 +-
 .../traversal/step/sideEffect/GroupTest.java    |  22 ++++
 .../structure/TinkerGraphPlayTest.java          |  11 +-
 12 files changed, 172 insertions(+), 155 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/6950b198/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/MemoryComputeKey.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/MemoryComputeKey.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/MemoryComputeKey.java
index d31164c..7ed12ea 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/MemoryComputeKey.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/MemoryComputeKey.java
@@ -22,6 +22,7 @@ package org.apache.tinkerpop.gremlin.process.computer;
 import org.apache.tinkerpop.gremlin.process.computer.util.MemoryHelper;
 
 import java.io.Serializable;
+import java.util.Collection;
 import java.util.function.BinaryOperator;
 
 /**
@@ -72,6 +73,10 @@ public final class MemoryComputeKey<A> implements Serializable {
         return new MemoryComputeKey<>(key, reducer, isBroadcast, isTransient);
     }
 
+    public static AddOperator addOperator() {
+        return AddOperator.INSTANCE;
+    }
+
     public static SetOperator setOperator() {
         return SetOperator.INSTANCE;
     }
@@ -94,6 +99,22 @@ public final class MemoryComputeKey<A> implements Serializable {
 
     ///////////
 
+    public static class AddOperator implements BinaryOperator<Collection>, Serializable {
+
+        private static final AddOperator INSTANCE = new AddOperator();
+
+        private AddOperator() {
+
+        }
+
+        @Override
+        public Collection apply(final Collection first, final Collection second) {
+            first.addAll(second);
+            return first;
+        }
+    }
+
+
     public static class SetOperator implements BinaryOperator<Object>, Serializable {
 
         private static final SetOperator INSTANCE = new SetOperator();

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/6950b198/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java
index b21df22..8c44ae7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java
@@ -28,8 +28,10 @@ import org.apache.tinkerpop.gremlin.process.computer.MessageScope;
 import org.apache.tinkerpop.gremlin.process.computer.Messenger;
 import org.apache.tinkerpop.gremlin.process.computer.VertexComputeKey;
 import org.apache.tinkerpop.gremlin.process.computer.VertexProgram;
+import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.ComputerResultStep;
 import org.apache.tinkerpop.gremlin.process.computer.traversal.step.sideEffect.mapreduce.TraverserMapReduce;
 import org.apache.tinkerpop.gremlin.process.computer.util.AbstractVertexProgramBuilder;
+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;
@@ -37,10 +39,11 @@ import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.GraphComputing;
 import org.apache.tinkerpop.gremlin.process.traversal.step.MapReducer;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TailGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectCapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.CollectingBarrierStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
 import org.apache.tinkerpop.gremlin.process.traversal.util.PureTraversal;
@@ -52,8 +55,10 @@ import org.apache.tinkerpop.gremlin.structure.Element;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.util.Attachable;
 import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceFactory;
 import org.apache.tinkerpop.gremlin.util.iterator.EmptyIterator;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 
@@ -83,6 +88,9 @@ public final class TraversalVertexProgram implements VertexProgram<TraverserSet<
     private static final String VOTE_TO_HALT = "gremlin.traversalVertexProgram.voteToHalt";
     public static final String TRAVERSAL = "gremlin.traversalVertexProgram.traversal";
 
+    public static final String ALIVE_TRAVERSERS = Graph.Hidden.hide("aliveTraversers");
+    public static final String MUTATED_MEMORY_KEYS = Graph.Hidden.hide("mutatedMemoryKeys");
+
     // TODO: if not an adjacent traversal, use Local message scope -- a dual messaging system.
     private static final Set<MessageScope> MESSAGE_SCOPES = new HashSet<>(Collections.singletonList(MessageScope.Global.instance()));
     private Set<MemoryComputeKey> memoryComputeKeys = new HashSet<>();
@@ -94,6 +102,7 @@ public final class TraversalVertexProgram implements VertexProgram<TraverserSet<
     private PureTraversal<?, ?> traversal;
     private TraversalMatrix<?, ?> traversalMatrix;
     private final Set<MapReduce> mapReducers = new HashSet<>();
+    private boolean keepHaltedTraversersDistributed = true;
 
     private TraversalVertexProgram() {
     }
@@ -122,11 +131,12 @@ public final class TraversalVertexProgram implements VertexProgram<TraverserSet<
             this.mapReducers.add(mapReducer.getMapReduce());
             this.memoryComputeKeys.add(MemoryComputeKey.of(mapReducer.getMapReduce().getMemoryKey(), MemoryComputeKey.setOperator(), false, false));
         }
-        if (!(this.traversal.get().getEndStep() instanceof SideEffectCapStep) &&
-                !(this.traversal.get().getEndStep() instanceof ReducingBarrierStep) &&
-                !(this.traversal.get().getEndStep() instanceof RangeGlobalStep) &&
-                !(this.traversal.get().getEndStep() instanceof TailGlobalStep)) {
+
+        if (this.traversal.get().getParent().asStep().getNextStep() instanceof ComputerResultStep)
+            this.keepHaltedTraversersDistributed = false;
+        if (this.traversal.get().getEndStep() instanceof CollectingBarrierStep || this.traversal.get().getEndStep() instanceof DedupGlobalStep) {
             this.mapReducers.add(new TraverserMapReduce(this.traversal.get()));
+            this.keepHaltedTraversersDistributed = true;
         }
 
         for (final GraphComputing<?> graphComputing : TraversalHelper.getStepsOfAssignableClassRecursively(GraphComputing.class, this.traversal.get())) {
@@ -134,7 +144,10 @@ public final class TraversalVertexProgram implements VertexProgram<TraverserSet<
             graphComputing.getMemoryComputeKey().ifPresent(x -> this.sideEffectKeys.add(x.getKey())); // TODO: when no more MapReducers, you can remove thisi
         }
 
-        this.memoryComputeKeys.add(MemoryComputeKey.of(TraverserMapReduce.TRAVERSERS, MemoryComputeKey.setOperator(), false, false));
+        this.memoryComputeKeys.add(MemoryComputeKey.of(HALTED_TRAVERSERS, MemoryComputeKey.addOperator(), false, false));
+        this.memoryComputeKeys.add(MemoryComputeKey.of(ALIVE_TRAVERSERS, MemoryComputeKey.addOperator(), true, true));
+        this.memoryComputeKeys.add(MemoryComputeKey.of(MUTATED_MEMORY_KEYS, MemoryComputeKey.addOperator(), false, true));
+
     }
 
     @Override
@@ -149,6 +162,9 @@ public final class TraversalVertexProgram implements VertexProgram<TraverserSet<
         for (final ReducingBarrierStep<?, ?> reducingBarrierStep : TraversalHelper.getStepsOfAssignableClassRecursively(ReducingBarrierStep.class, this.traversal.get())) {
             memory.set(reducingBarrierStep.getId(), reducingBarrierStep.getSeedSupplier().get());
         }
+        memory.set(HALTED_TRAVERSERS, new TraverserSet<>());
+        memory.set(ALIVE_TRAVERSERS, new TraverserSet<>());
+        memory.set(MUTATED_MEMORY_KEYS, new HashSet<>());
     }
 
     @Override
@@ -181,6 +197,7 @@ public final class TraversalVertexProgram implements VertexProgram<TraverserSet<
                     if (traverser.asAdmin().isHalted()) {
                         traverser.asAdmin().detach();
                         haltedTraversers.add((Traverser.Admin) traverser);
+                        memory.add(HALTED_TRAVERSERS, new TraverserSet<>(traverser.asAdmin().split()));
                     } else
                         aliveTraverses.add((Traverser.Admin) traverser);
                 });
@@ -195,36 +212,84 @@ public final class TraversalVertexProgram implements VertexProgram<TraverserSet<
                 vertex.<Map<String, Object>>property(VertexTraversalSideEffects.SIDE_EFFECTS).value().remove(key);
             }
         });
-
+        if (!this.keepHaltedTraversersDistributed)
+            vertex.<TraverserSet>property(HALTED_TRAVERSERS).value().clear();
     }
 
     @Override
     public boolean terminate(final Memory memory) {
+        final Set<String> mutatedMemoryKeys = memory.get(MUTATED_MEMORY_KEYS);  // TODO: if not touched we still have to initialize the seeds
         final boolean voteToHalt = memory.<Boolean>get(VOTE_TO_HALT);
+        memory.set(VOTE_TO_HALT, true);
+        memory.set(MUTATED_MEMORY_KEYS, new HashSet<>());
+        memory.set(ALIVE_TRAVERSERS, new TraverserSet<>());
+        ///
         if (voteToHalt) {
-            final TraverserSet<?> localTraversers = new TraverserSet<>();
+            final TraverserSet<Object> toProcessTraversers = new TraverserSet<>();
             for (final GraphComputing<Object> graphComputing : TraversalHelper.getStepsOfAssignableClassRecursively(GraphComputing.class, this.traversal.get())) {
                 graphComputing.getMemoryComputeKey().ifPresent(memoryKey -> {
                     final String key = memoryKey.getKey();
                     if (memory.exists(key)) {
                         if (graphComputing instanceof RangeGlobalStep || graphComputing instanceof TailGlobalStep) {
-                            localTraversers.addAll(((TraverserSet) graphComputing.generateFinalResult(memory.get(key))));
+                            toProcessTraversers.addAll(((TraverserSet) graphComputing.generateFinalResult(memory.get(key))));
                         } else if (graphComputing instanceof ReducingBarrierStep) {
-                            localTraversers.add(this.traversal.get().getTraverserGenerator().generate(graphComputing.generateFinalResult(memory.get(key)), (Step) graphComputing, 1l));
+                            final Traverser.Admin traverser = this.traversal.get().getTraverserGenerator().generate(graphComputing.generateFinalResult(memory.get(key)), ((Step) graphComputing), 1l);
+                            if (((ReducingBarrierStep) graphComputing).hasNext())
+                                ((ReducingBarrierStep) graphComputing).next(); // or else you will get a seed
+                            traverser.setStepId(((Step) graphComputing).getNextStep().getId()); // should really for ReducingBarrierStep seed.
+                            toProcessTraversers.add(traverser);
                         } else {
-                            memory.set(key, graphComputing.generateFinalResult(memory.get(key)));
+                            memory.set(key, graphComputing.generateFinalResult(memory.get(key))); // XXXSideEffectSteps (may need to relocate this to post HALT)
                         }
                     }
                 });
             }
-            memory.set(TraverserMapReduce.TRAVERSERS, localTraversers.iterator());
-            return true;
+            final TraverserSet<?> localAliveTraversers = new TraverserSet<>();
+            final TraverserSet<?> remoteAliveTraversers = new TraverserSet<>();
+            final TraverserSet<?> haltedTraversers = memory.get(HALTED_TRAVERSERS);
+            while (!toProcessTraversers.isEmpty()) {
+                this.processTraversers(toProcessTraversers, localAliveTraversers, remoteAliveTraversers, haltedTraversers);
+                toProcessTraversers.clear();
+                toProcessTraversers.addAll((TraverserSet) localAliveTraversers);
+                localAliveTraversers.clear();
+            }
+            if (!remoteAliveTraversers.isEmpty()) {
+                memory.set(ALIVE_TRAVERSERS, remoteAliveTraversers);
+                return false;
+            } else {
+                memory.set(HALTED_TRAVERSERS, haltedTraversers.iterator());
+                return true;
+            }
         } else {
-            memory.set(VOTE_TO_HALT, true);
             return false;
         }
     }
 
+    private void processTraversers(final TraverserSet<Object> toProcessTraversers, final TraverserSet<?> localAliveTraversers, final TraverserSet<?> remoteAliveTraversers, final TraverserSet<?> haltedTraversers) {
+        toProcessTraversers.forEach(traverser -> {
+                    traverser.set(ReferenceFactory.detach(traverser.get()));
+                    if (traverser.isHalted())
+                        haltedTraversers.add((Traverser.Admin) traverser);
+                    else if (traverser.get() instanceof Attachable && !(traverser.get() instanceof Path)) {
+                        remoteAliveTraversers.add((Traverser.Admin) traverser);
+                    } else {
+                        final Step<?, ?> step = this.traversalMatrix.getStepById(traverser.getStepId());
+                        step.addStart((Traverser.Admin) traverser);
+                        step.forEachRemaining(result -> {
+                            if (result.asAdmin().isHalted())
+                                haltedTraversers.add((Traverser.Admin) result);
+                            else {
+                                if (result.get() instanceof Attachable)
+                                    remoteAliveTraversers.add((Traverser.Admin) result);
+                                else
+                                    localAliveTraversers.add((Traverser.Admin) result);
+                            }
+                        });
+                    }
+                }
+        );
+    }
+
     @Override
     public Set<VertexComputeKey> getVertexComputeKeys() {
         return VERTEX_COMPUTE_KEYS;

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/6950b198/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraverserExecutor.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraverserExecutor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraverserExecutor.java
index ccbbc20..88f9d8d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraverserExecutor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraverserExecutor.java
@@ -37,6 +37,8 @@ import org.apache.tinkerpop.gremlin.structure.Property;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.util.Attachable;
 
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -47,13 +49,25 @@ public final class TraverserExecutor {
 
     public static boolean execute(final Vertex vertex, final Messenger<TraverserSet<?>> messenger, final TraversalMatrix<?, ?> traversalMatrix, final Memory memory) {
 
+        final TraversalSideEffects traversalSideEffects = traversalMatrix.getTraversal().getSideEffects();
         final TraverserSet<Object> haltedTraversers = vertex.value(TraversalVertexProgram.HALTED_TRAVERSERS);
         final AtomicBoolean voteToHalt = new AtomicBoolean(true);
         final TraverserSet<Object> aliveTraversers = new TraverserSet<>();
         final TraverserSet<Object> toProcessTraversers = new TraverserSet<>();
 
+        final TraverserSet<Object> maybeAliveTraversers = memory.get(TraversalVertexProgram.ALIVE_TRAVERSERS);
+        final Iterator<Traverser.Admin<Object>> iterator = maybeAliveTraversers.iterator();
+        while (iterator.hasNext()) {
+            final Traverser.Admin<Object> traverser = iterator.next();
+            if (vertex.equals(TraverserExecutor.getHostingVertex(traverser.get()))) {
+                // iterator.remove(); ConcurrentModificationException
+                traverser.setSideEffects(traversalSideEffects);
+                traverser.attach(Attachable.Method.get(vertex));
+                toProcessTraversers.add(traverser);
+            }
+        }
+
         final Iterator<TraverserSet<?>> messages = messenger.receiveMessages();
-        final TraversalSideEffects traversalSideEffects = traversalMatrix.getTraversal().getSideEffects();
         while (messages.hasNext()) {
             final Iterator<Traverser.Admin<Object>> traversers = (Iterator) messages.next().iterator();
             while (traversers.hasNext()) {
@@ -110,6 +124,7 @@ public final class TraverserExecutor {
     private static void drainStep(final Step<?, ?> step, final TraverserSet<?> aliveTraversers, final TraverserSet<?> haltedTraversers, final Memory memory) {
         if (step instanceof ReducingBarrierStep) {
             memory.add(step.getId(), step.next().get());
+            memory.add(TraversalVertexProgram.MUTATED_MEMORY_KEYS, new HashSet<>(Collections.singleton(step.getId())));
         } else if (step instanceof RangeGlobalStep || step instanceof TailGlobalStep) {
             ((Bypassing) step).setBypass(true);
             final TraverserSet<?> traverserSet = new TraverserSet<>();
@@ -118,11 +133,13 @@ public final class TraverserExecutor {
                 traverserSet.add((Traverser.Admin) traverser);
             });
             memory.add(step.getId(), traverserSet);
+            memory.add(TraversalVertexProgram.MUTATED_MEMORY_KEYS, new HashSet<>(Collections.singleton(step.getId())));
         } else {
             step.forEachRemaining(traverser -> {
                 if (traverser.asAdmin().isHalted()) {
                     traverser.asAdmin().detach();
                     haltedTraversers.add((Traverser.Admin) traverser);
+                    memory.add(TraversalVertexProgram.HALTED_TRAVERSERS, new TraverserSet<>(traverser.asAdmin().split()));
                 } else
                     aliveTraversers.add((Traverser.Admin) traverser);
             });

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/6950b198/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ComputerResultStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ComputerResultStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ComputerResultStep.java
index 52d7a78..c9cee4f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ComputerResultStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ComputerResultStep.java
@@ -19,7 +19,7 @@
 package org.apache.tinkerpop.gremlin.process.computer.traversal.step.map;
 
 import org.apache.tinkerpop.gremlin.process.computer.ComputerResult;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.step.sideEffect.mapreduce.TraverserMapReduce;
+import org.apache.tinkerpop.gremlin.process.computer.traversal.TraversalVertexProgram;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
@@ -89,7 +89,7 @@ public final class ComputerResultStep<S> extends AbstractStep<ComputerResult, S>
                         this.currentIterator = this.getTraversal().getTraverserGenerator().generateIterator(IteratorUtils.of((S) sideEffects), (Step) this, 1l);
                     }
                 } else {
-                    this.currentIterator = result.memory().get(TraverserMapReduce.TRAVERSERS);
+                    this.currentIterator = result.memory().get(TraversalVertexProgram.HALTED_TRAVERSERS);
                 }
                 this.currentIterator = attach(this.currentIterator, result.graph());
             }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/6950b198/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/sideEffect/mapreduce/ComputerToStandardMapReduce.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/sideEffect/mapreduce/ComputerToStandardMapReduce.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/sideEffect/mapreduce/ComputerToStandardMapReduce.java
deleted file mode 100644
index 84f939e..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/sideEffect/mapreduce/ComputerToStandardMapReduce.java
+++ /dev/null
@@ -1,110 +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.computer.traversal.step.sideEffect.mapreduce;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.tinkerpop.gremlin.process.computer.KeyValue;
-import org.apache.tinkerpop.gremlin.process.computer.MapReduce;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.TraversalVertexProgram;
-import org.apache.tinkerpop.gremlin.process.computer.util.VertexProgramHelper;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
-
-import java.util.Iterator;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class ComputerToStandardMapReduce implements MapReduce<MapReduce.NullObject, Traverser<?>, MapReduce.NullObject, Traverser<?>, Iterator<Traverser<?>>> {
-
-    private static final String VERTEX_TRAVERSAL = "gremlin.computerToStandardMapReduce.vertexTraversal";
-
-    private Traversal.Admin<Vertex, ?> traversal;
-
-    private ComputerToStandardMapReduce() {
-    }
-
-    public ComputerToStandardMapReduce(final Traversal.Admin<Vertex, ?> traversal) {
-        this.traversal = traversal;
-    }
-
-    @Override
-    public void loadState(final Graph graph, final Configuration configuration) {
-        this.traversal = VertexProgramHelper.deserialize(configuration, VERTEX_TRAVERSAL);
-    }
-
-    @Override
-    public void storeState(final Configuration configuration) {
-        MapReduce.super.storeState(configuration);
-        VertexProgramHelper.serialize(this.traversal, configuration, VERTEX_TRAVERSAL);
-    }
-
-
-    @Override
-    public boolean doStage(final Stage stage) {
-        return stage.equals(Stage.MAP); // || this.access.equals(Access.HALTED);
-    }
-
-    @Override
-    public void map(final Vertex vertex, final MapEmitter<NullObject, Traverser<?>> emitter) {
-        this.traversal.addStart(this.traversal.getTraverserGenerator().generate(vertex, this.traversal.getStartStep(), 1l));
-        this.traversal.getEndStep().forEachRemaining(emitter::emit);
-    }
-
-    @Override
-    public void combine(final NullObject key, final Iterator<Traverser<?>> values, final ReduceEmitter<NullObject, Traverser<?>> emitter) {
-        this.reduce(key, values, emitter);
-    }
-
-    @Override
-    public void reduce(final NullObject key, final Iterator<Traverser<?>> values, final ReduceEmitter<NullObject, Traverser<?>> emitter) {
-        final TraverserSet<?> traverserSet = new TraverserSet<>();
-        while (values.hasNext()) {
-            traverserSet.add((Traverser.Admin) values.next().asAdmin());
-        }
-        IteratorUtils.removeOnNext(traverserSet.iterator()).forEachRemaining(emitter::emit);
-    }
-
-    @Override
-    public Iterator<Traverser<?>> generateFinalResult(final Iterator<KeyValue<NullObject, Traverser<?>>> keyValues) {
-        return IteratorUtils.map(keyValues, KeyValue::getValue);
-    }
-
-    @Override
-    public String getMemoryKey() {
-        return TraverserMapReduce.TRAVERSERS;
-    }
-
-    @Override
-    public ComputerToStandardMapReduce clone() {
-       try {
-            final ComputerToStandardMapReduce clone = (ComputerToStandardMapReduce) super.clone();
-            clone.traversal = this.traversal.clone();
-            return clone;
-        } catch (final CloneNotSupportedException e) {
-            throw new IllegalStateException(e.getMessage(), e);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/6950b198/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/sideEffect/mapreduce/TraverserMapReduce.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/sideEffect/mapreduce/TraverserMapReduce.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/sideEffect/mapreduce/TraverserMapReduce.java
index 77eb344..1bd0844 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/sideEffect/mapreduce/TraverserMapReduce.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/sideEffect/mapreduce/TraverserMapReduce.java
@@ -27,7 +27,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TailGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.CollectingBarrierStep;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
@@ -49,13 +48,10 @@ import java.util.Optional;
  */
 public final class TraverserMapReduce implements MapReduce<Comparable, Traverser<?>, Comparable, Traverser<?>, Iterator<Traverser<?>>> {
 
-    public static final String TRAVERSERS = Graph.Hidden.hide("traversers");
-
     private Traversal.Admin<?, ?> traversal;
     private Comparator<Comparable> comparator = null;
     private CollectingBarrierStep<?> collectingBarrierStep = null;
     private boolean attachHaltedTraverser = false;
-    private TailGlobalStep<?> tailGlobalStep = null;
     private boolean dedupGlobal = false;
 
     private TraverserMapReduce() {
@@ -93,8 +89,6 @@ public final class TraverserMapReduce implements MapReduce<Comparable, Traverser
                 this.attachHaltedTraverser = ((TraversalParent) this.collectingBarrierStep).getLocalChildren().stream().filter(TraversalHelper::isBeyondElementId).findAny().isPresent();
             }
         }
-        if (traversalEndStep instanceof TailGlobalStep)
-            this.tailGlobalStep = ((TailGlobalStep) traversalEndStep).clone();
         if (traversalEndStep instanceof DedupGlobalStep)
             this.dedupGlobal = true;
 
@@ -102,7 +96,7 @@ public final class TraverserMapReduce implements MapReduce<Comparable, Traverser
 
     @Override
     public boolean doStage(final Stage stage) {
-        return stage.equals(Stage.MAP) || null != this.collectingBarrierStep || null != this.tailGlobalStep || this.dedupGlobal;
+        return stage.equals(Stage.MAP) || null != this.collectingBarrierStep || this.dedupGlobal;
     }
 
     @Override
@@ -156,11 +150,6 @@ public final class TraverserMapReduce implements MapReduce<Comparable, Traverser
             }
             this.collectingBarrierStep.barrierConsumer((TraverserSet) traverserSet);
             return (Iterator) traverserSet.iterator();
-        } else if (null != this.tailGlobalStep) {
-            final TailGlobalStep<?> tailGlobalStep = this.tailGlobalStep;
-            tailGlobalStep.setBypass(false);
-            tailGlobalStep.addStarts(IteratorUtils.map(keyValues, keyValue -> (Traverser) keyValue.getValue()));
-            return (Iterator) tailGlobalStep;
         } else if (this.dedupGlobal) {
             return IteratorUtils.map(keyValues, keyValue -> {
                 keyValue.getValue().asAdmin().setBulk(1l);
@@ -173,7 +162,7 @@ public final class TraverserMapReduce implements MapReduce<Comparable, Traverser
 
     @Override
     public String getMemoryKey() {
-        return TRAVERSERS;
+        return TraversalVertexProgram.HALTED_TRAVERSERS;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/6950b198/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 271e3d3..1eea4c5 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,12 +28,12 @@ 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.Scoping;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TailGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WherePredicateStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTraversalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaCollectingBarrierStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SubgraphStep;
@@ -62,7 +62,6 @@ public final class ComputerVerificationStrategy extends AbstractTraversalStrateg
     ));
 
     public static final Set<Class<? extends Step>> END_STEPS = new HashSet<>(Arrays.asList(
-            ReducingBarrierStep.class,
             SupplyingBarrierStep.class,
             OrderGlobalStep.class,
             DedupGlobalStep.class));
@@ -121,8 +120,10 @@ public final class ComputerVerificationStrategy extends AbstractTraversalStrateg
         }
 
         for (final Step<?, ?> step : traversal.getSteps()) {
-            if ((step instanceof ReducingBarrierStep || step instanceof SupplyingBarrierStep || step instanceof OrderGlobalStep
-                    || step instanceof RangeGlobalStep || step instanceof TailGlobalStep || step instanceof DedupGlobalStep)
+            if (step instanceof ReducingBarrierStep && step.getTraversal().getParent() instanceof UnionStep)
+                throw new VerificationException("Reducing barriers within union()-step are not allowed: " + step, traversal);
+
+            if ((step instanceof SupplyingBarrierStep || step instanceof OrderGlobalStep || step instanceof DedupGlobalStep || step instanceof LambdaCollectingBarrierStep)
                     && (step != endStep || !(traversal.getParent() instanceof TraversalVertexProgramStep)))
                 throw new VerificationException("Global traversals on GraphComputer may not contain mid-traversal barriers: " + step, traversal);
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/6950b198/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java
index d60142b..b0fc923 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java
@@ -325,12 +325,14 @@ public final class GryoMapper implements Mapper<Kryo> {
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(ZonedDateTime.class, kryo -> new JavaTimeSerializers.ZonedDateTimeSerializer(), 104));
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(ZoneOffset.class, kryo -> new JavaTimeSerializers.ZoneOffsetSerializer(), 105));
 
+            add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(MemoryComputeKey.AddOperator.class, null, 126));  // ***LAST ID**
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(MemoryComputeKey.AndOperator.class, null, 107));
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(MemoryComputeKey.OrOperator.class, null, 108));
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(MemoryComputeKey.SetOperator.class, null, 109));
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(MemoryComputeKey.SumLongOperator.class, null, 110));
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(MemoryComputeKey.SumIntegerOperator.class, null, 111));
 
+
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(CountGlobalStep.CountBiOperator.class, null, 112));
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(FoldStep.ListBiOperator.class, null, 113));
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(FoldStep.FoldBiOperator.class, null, 114));
@@ -344,7 +346,7 @@ public final class GryoMapper implements Mapper<Kryo> {
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(TreeStep.TreeBiOperator.class, null, 122));
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(GroupStepV3d0.GroupBiOperatorV3d0.class, null, 123));
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(StoreStep.StoreBiOperator.class, null, 124));
-            add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Operator.class, null, 125)); // ***LAST ID**
+            add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Operator.class, null, 125));
         }};
 
         private final List<IoRegistry> registries = new ArrayList<>();

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/6950b198/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 f21627e..9786986 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
@@ -88,5 +88,10 @@ public abstract class GroovyGroupTest {
         public Traversal<Vertex, Map<String, Long>> get_g_V_groupXaX_byXname_substring_1X_byXconstantX1XX_capXaX() {
             new ScriptTraversal<>(g, "gremlin-groovy", "g.V.group('a').by{it.name[0]}.by(constant(1l)).cap('a')")
         }
+
+        @Override
+        public Traversal<Vertex, String> get_g_V_out_group_byXlabelX_selectXpersonX_unfold_outXcreatedX_name_limitX2X() {
+            new ScriptTraversal<>(g, "gremlin-groovy", "g.V.out.group.by(label).select('person').unfold.out('created').name.limit(2)")
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/6950b198/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
index 6e746f1..2513701 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
@@ -392,7 +392,7 @@ public class GraphComputerTest extends AbstractGremlinProcessTest {
             }
             try {
                 memory.set("a", true);
-               // fail("Setting a memory key that wasn't declared should fail");
+                // fail("Setting a memory key that wasn't declared should fail");
             } catch (Exception e) {
                 validateException(GraphComputer.Exceptions.providedKeyIsNotAMemoryComputeKey("a"), e);
             }
@@ -1912,13 +1912,13 @@ public class GraphComputerTest extends AbstractGremlinProcessTest {
         final Graph graph3 = result3.graph();
         final Memory memory3 = result3.memory();
         assertTrue(memory3.keys().contains("m"));
-        assertTrue(memory3.keys().contains(TraverserMapReduce.TRAVERSERS));
+        assertTrue(memory3.keys().contains(TraversalVertexProgram.HALTED_TRAVERSERS));
         assertEquals(1, memory3.<Map<Long, Long>>get("m").size());
         assertEquals(6, memory3.<Map<Long, Long>>get("m").get(1l).intValue());
-        List<Traverser<String>> traversers = IteratorUtils.list(memory3.<Iterator<Traverser<String>>>get(TraverserMapReduce.TRAVERSERS));
-        assertEquals(6, traversers.size());
-        assertEquals(4l, traversers.stream().map(Traverser::get).filter(s -> s.equals("person")).count());
-        assertEquals(2l, traversers.stream().map(Traverser::get).filter(s -> s.equals("software")).count());
+        List<Traverser<String>> traversers = IteratorUtils.list(memory3.<Iterator<Traverser<String>>>get(TraversalVertexProgram.HALTED_TRAVERSERS));
+        assertEquals(6l, traversers.stream().map(Traverser::bulk).reduce((a, b) -> a + b).get().longValue());
+        assertEquals(4l, traversers.stream().filter(s -> s.get().equals("person")).map(Traverser::bulk).reduce((a, b) -> a + b).get().longValue());
+        assertEquals(2l, traversers.stream().filter(s -> s.get().equals("software")).map(Traverser::bulk).reduce((a, b) -> a + b).get().longValue());
         assertEquals(6, graph3.traversal().V().count().next().intValue());
         assertEquals(6, graph3.traversal().E().count().next().intValue());
         assertEquals(6, graph3.traversal().V().values(TraversalVertexProgram.HALTED_TRAVERSERS).count().next().intValue());

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/6950b198/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 b2298be..ba38c93 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
@@ -24,9 +24,11 @@ import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
@@ -73,6 +75,8 @@ public abstract class GroupTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, Map<String, Long>> get_g_V_groupXaX_byXname_substring_1X_byXconstantX1XX_capXaX();
 
+    public abstract Traversal<Vertex, String> get_g_V_out_group_byXlabelX_selectXpersonX_unfold_outXcreatedX_name_limitX2X();
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_group_byXnameX() {
@@ -194,6 +198,7 @@ public abstract class GroupTest extends AbstractGremlinProcessTest {
     @LoadGraphWith(GRATEFUL)
     public void g_V_repeatXbothXfollowedByXX_timesX2X_group_byXsongTypeX_byXcountX() {
         final Traversal<Vertex, Map<String, Long>> traversal = get_g_V_repeatXbothXfollowedByXX_timesX2X_group_byXsongTypeX_byXcountX();
+        printTraversalForm(traversal);
         checkMap(new HashMap<String, Long>() {{
             put("original", 771317l);
             put("", 160968l);
@@ -206,6 +211,7 @@ public abstract class GroupTest extends AbstractGremlinProcessTest {
     @LoadGraphWith(GRATEFUL)
     public void g_V_repeatXbothXfollowedByXX_timesX2X_groupXaX_byXsongTypeX_byXcountX_capXaX() {
         final Traversal<Vertex, Map<String, Long>> traversal = get_g_V_repeatXbothXfollowedByXX_timesX2X_groupXaX_byXsongTypeX_byXcountX_capXaX();
+        printTraversalForm(traversal);
         checkMap(new HashMap<String, Long>() {{
             put("original", 771317l);
             put("", 160968l);
@@ -218,6 +224,7 @@ public abstract class GroupTest extends AbstractGremlinProcessTest {
     @LoadGraphWith(MODERN)
     public void g_V_group_byXname_substring_1X_byXconstantX1XX() {
         final Traversal<Vertex, Map<String, Long>> traversal = get_g_V_group_byXname_substring_1X_byXconstantX1XX();
+        printTraversalForm(traversal);
         checkMap(new HashMap<String, Long>() {{
             put("m", 1l);
             put("v", 1l);
@@ -233,6 +240,7 @@ public abstract class GroupTest extends AbstractGremlinProcessTest {
     @LoadGraphWith(MODERN)
     public void g_V_groupXaX_byXname_substring_1X_byXconstantX1XX_capXaX() {
         final Traversal<Vertex, Map<String, Long>> traversal = get_g_V_groupXaX_byXname_substring_1X_byXconstantX1XX_capXaX();
+        printTraversalForm(traversal);
         checkMap(new HashMap<String, Long>() {{
             put("m", 1l);
             put("v", 1l);
@@ -244,6 +252,15 @@ public abstract class GroupTest extends AbstractGremlinProcessTest {
         assertFalse(traversal.hasNext());
     }
 
+    @Test
+    @Ignore
+    @LoadGraphWith(MODERN)
+    public void g_V_out_group_byXlabelX_selectXpersonX_unfold_outXcreatedX_name_limitX2X() {
+        final Traversal<Vertex, String> traversal = get_g_V_out_group_byXlabelX_selectXpersonX_unfold_outXcreatedX_name_limitX2X();
+        printTraversalForm(traversal);
+        checkResults(Arrays.asList("ripple", "lop"), traversal);
+    }
+
 
     public static class Traversals extends GroupTest {
 
@@ -306,5 +323,10 @@ public abstract class GroupTest extends AbstractGremlinProcessTest {
         public Traversal<Vertex, Map<String, Long>> get_g_V_groupXaX_byXname_substring_1X_byXconstantX1XX_capXaX() {
             return g.V().<String, Long>group("a").<Vertex>by(v -> v.<String>value("name").substring(0, 1)).by(constant(1l)).cap("a");
         }
+
+        @Override
+        public Traversal<Vertex, String> get_g_V_out_group_byXlabelX_selectXpersonX_unfold_outXcreatedX_name_limitX2X() {
+            return g.V().out().<String, Vertex>group().by(T.label).select("person").unfold().out("created").<String>values("name").limit(2);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/6950b198/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
index 94c7ecc..8b005a8 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
@@ -26,6 +26,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.structure.Column;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
@@ -69,9 +70,13 @@ public class TinkerGraphPlayTest {
         GraphTraversalSource g = graph.traversal().withComputer(); //GraphTraversalSource.computer());
         //System.out.println(g.V().outE("knows").identity().inV().count().is(P.eq(5)).explain());
         //System.out.println(g.V().hasLabel("person").fold().order(Scope.local).by("age").toList());
-        System.out.println(g.V().pageRank().by("pageRank").as("a").out("knows").values("pageRank").as("b").select("a", "b").toString());
-        System.out.println(g.V().pageRank().by("pageRank").as("a").out("knows").values("pageRank").as("b").select("a", "b").iterate().toString());
-        System.out.println(g.V().pageRank().by("pageRank").as("a").out("knows").values("pageRank").as("b").select("a", "b").toList());
+        final Traversal<?,?> traversal = g.V().outE().values("weight").groupCount().unfold(); // unfold.select(values)
+
+        System.out.println(traversal.asAdmin().clone().toString());
+        final Traversal<?,?> clone = traversal.asAdmin().clone();
+        clone.asAdmin().applyStrategies();
+        System.out.println(clone);
+        System.out.println(traversal.asAdmin().clone().toList());
         //System.out.println(g.V().pageRank().order().by(PageRankVertexProgram.PAGE_RANK).valueMap().toList());
     }