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 2018/04/19 16:56:05 UTC
[50/50] tinkerpop git commit: TINKERPOP-1656 WIP - basic proof of
concept for bulk mutations
TINKERPOP-1656 WIP - basic proof of concept for bulk mutations
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/bb583e3a
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/bb583e3a
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/bb583e3a
Branch: refs/heads/TINKERPOP-1656
Commit: bb583e3a47aa4ab94ecfe04190073feed4e13a20
Parents: 2591302
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Mar 22 07:01:57 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Thu Apr 19 12:51:43 2018 -0400
----------------------------------------------------------------------
gremlin-benchmark/pom.xml | 2 +-
.../gremlin/process/GraphMutateBenchmark.java | 18 ++-
.../traversal/dsl/graph/GraphTraversal.java | 64 ++++++++--
.../traversal/step/MutatingContainerHolder.java | 53 +++++++++
.../traversal/step/map/MutatingStep.java | 102 ++++++++++++++++
.../traversal/step/util/MutatingContainer.java | 109 +++++++++++++++++
.../strategy/optimization/MutatingStrategy.java | 66 ++++++++++
.../process/traversal/util/TraversalHelper.java | 37 +++++-
.../tinkergraph/structure/TinkerGraph.java | 119 ++++++++++++++++++-
9 files changed, 554 insertions(+), 16 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bb583e3a/gremlin-benchmark/pom.xml
----------------------------------------------------------------------
diff --git a/gremlin-benchmark/pom.xml b/gremlin-benchmark/pom.xml
index 571bc0d..3b8b995 100644
--- a/gremlin-benchmark/pom.xml
+++ b/gremlin-benchmark/pom.xml
@@ -86,7 +86,7 @@ limitations under the License.
<testSourceDirectory>${project.build.sourceDirectory}</testSourceDirectory>
<testClassesDirectory>${project.build.outputDirectory}</testClassesDirectory>
<includes>
- <include>**/*Benchmark*.java</include>
+ <include>**/*MutateBenchmark*.java</include>
</includes>
<excludes>
<exclude>**/*$*.class</exclude>
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bb583e3a/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/process/GraphMutateBenchmark.java
----------------------------------------------------------------------
diff --git a/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/process/GraphMutateBenchmark.java b/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/process/GraphMutateBenchmark.java
index 733e32b..27a9315 100644
--- a/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/process/GraphMutateBenchmark.java
+++ b/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/process/GraphMutateBenchmark.java
@@ -51,6 +51,20 @@ public class GraphMutateBenchmark extends AbstractGraphMutateBenchmark {
@Override
public void prepare() {
super.prepare();
+//
+// withoutStrategies(ConnectiveStrategy.class,
+// InlineFilterStrategy.class,
+// IncidentToAdjacentStrategy.class,
+// AdjacentToIncidentStrategy.class,
+// FilterRankingStrategy.class,
+// MatchPredicateStrategy.class,
+// RepeatUnrollStrategy.class,
+// RangeByIsCountStrategy.class,
+// PathRetractionStrategy.class,
+// LazyBarrierStrategy.class,
+// ProfileStrategy.class,
+// StandardVerificationStrategy.class)
+
a = g.addV().next();
b = g.addV().next();
c = g.addV().next();
@@ -173,8 +187,8 @@ public class GraphMutateBenchmark extends AbstractGraphMutateBenchmark {
}
}
- final Edge e = (Edge) t.next();
- return e;
+ final Edge x = (Edge) t.next();
+ return x;
}
@Benchmark
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bb583e3a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index 222fdab..4ebe1ba 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -37,7 +37,9 @@ import org.apache.tinkerpop.gremlin.process.traversal.lambda.PredicateTraverser;
import org.apache.tinkerpop.gremlin.process.traversal.lambda.TrueTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
import org.apache.tinkerpop.gremlin.process.traversal.step.FromToModulating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.FromToModulating;
import org.apache.tinkerpop.gremlin.process.traversal.step.Mutating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.MutatingContainerHolder;
import org.apache.tinkerpop.gremlin.process.traversal.step.TimesModulating;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
import org.apache.tinkerpop.gremlin.process.traversal.step.branch.BranchStep;
@@ -91,6 +93,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.MeanGlobalStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.MeanLocalStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.MinGlobalStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.MinLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MutatingStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.NoOpBarrierStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderGlobalStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderLocalStep;
@@ -130,6 +133,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SubgraphSt
import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TraversalSideEffectStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TreeSideEffectStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.MutatingContainer;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
@@ -985,7 +989,14 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
*/
public default GraphTraversal<S, Vertex> addV(final String vertexLabel) {
this.asAdmin().getBytecode().addStep(Symbols.addV, vertexLabel);
- return this.asAdmin().addStep(new AddVertexStep<>(this.asAdmin(), vertexLabel));
+
+ final Step endStep = this.asAdmin().getEndStep();
+ final MutatingContainerHolder holder = (endStep instanceof MutatingContainerHolder) ?
+ (MutatingContainerHolder) endStep : new MutatingStep<>(this.asAdmin());
+
+ final MutatingContainer container = new MutatingContainer(MutatingContainer.Operation.ADD_V, holder, T.label, vertexLabel);
+ holder.addMutatingContainer(container);
+ return endStep == holder ? (GraphTraversal) this : this.asAdmin().addStep((Step) holder);
}
/**
@@ -997,7 +1008,14 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
*/
public default GraphTraversal<S, Vertex> addV() {
this.asAdmin().getBytecode().addStep(Symbols.addV);
- return this.asAdmin().addStep(new AddVertexStep<>(this.asAdmin(), null));
+
+ final Step endStep = this.asAdmin().getEndStep();
+ final MutatingContainerHolder holder = (endStep instanceof MutatingContainerHolder) ?
+ (MutatingContainerHolder) endStep : new MutatingStep<>(this.asAdmin());
+
+ final MutatingContainer container = new MutatingContainer(MutatingContainer.Operation.ADD_V, holder);
+ holder.addMutatingContainer(container);
+ return endStep == holder ? (GraphTraversal) this : this.asAdmin().addStep((Step) holder);
}
/**
@@ -1023,7 +1041,17 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
*/
public default GraphTraversal<S, Edge> addE(final String edgeLabel) {
this.asAdmin().getBytecode().addStep(Symbols.addE, edgeLabel);
- return this.asAdmin().addStep(new AddEdgeStep<>(this.asAdmin(), edgeLabel));
+
+ final Step endStep = this.asAdmin().getEndStep();
+ final MutatingContainerHolder holder = (endStep instanceof MutatingContainerHolder) ?
+ (MutatingContainerHolder) endStep : new MutatingStep<>(this.asAdmin());
+
+ final MutatingContainer container = new MutatingContainer(MutatingContainer.Operation.ADD_E, holder);
+ container.setEdgeLabel(edgeLabel);
+ holder.addMutatingContainer(container);
+ return endStep == holder ? (GraphTraversal) this : this.asAdmin().addStep((Step) holder);
+
+ //return this.asAdmin().addStep(new AddEdgeStep<>(this.asAdmin(), edgeLabel));
}
/**
@@ -1036,7 +1064,13 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
*/
public default GraphTraversal<S, E> to(final String toStepLabel) {
this.asAdmin().getBytecode().addStep(Symbols.to, toStepLabel);
- ((FromToModulating) this.asAdmin().getEndStep()).addTo(toStepLabel);
+
+ final Step endStep = this.asAdmin().getEndStep();
+ if (endStep instanceof MutatingContainerHolder) {
+ ((MutatingContainerHolder) endStep).getLastMutatingContainer().setInVLabel(toStepLabel);
+ } else {
+ ((FromToModulating) this.asAdmin().getEndStep()).addTo(toStepLabel);
+ }
return this;
}
@@ -1050,7 +1084,13 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
*/
public default GraphTraversal<S, E> from(final String fromStepLabel) {
this.asAdmin().getBytecode().addStep(Symbols.from, fromStepLabel);
- ((FromToModulating) this.asAdmin().getEndStep()).addFrom(fromStepLabel);
+
+ final Step endStep = this.asAdmin().getEndStep();
+ if (endStep instanceof MutatingContainerHolder) {
+ ((MutatingContainerHolder) endStep).getLastMutatingContainer().setOutVLabel(fromStepLabel);
+ } else {
+ ((FromToModulating) this.asAdmin().getEndStep()).addFrom(fromStepLabel);
+ }
return this;
}
@@ -1065,6 +1105,11 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
*/
public default GraphTraversal<S, E> to(final Traversal<E, Vertex> toVertex) {
this.asAdmin().getBytecode().addStep(Symbols.to, toVertex);
+
+
+ // TODO: trigger explode here if this happens?
+
+
((FromToModulating) this.asAdmin().getEndStep()).addTo(toVertex.asAdmin());
return this;
}
@@ -1080,6 +1125,11 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
*/
public default GraphTraversal<S, E> from(final Traversal<E, Vertex> fromVertex) {
this.asAdmin().getBytecode().addStep(Symbols.from, fromVertex);
+
+
+ // TODO: trigger explode here if this happens?
+
+
((FromToModulating) this.asAdmin().getEndStep()).addFrom(fromVertex.asAdmin());
return this;
}
@@ -2058,7 +2108,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
// if it can be detected that this call to property() is related to an addV/E() then we can attempt to fold
// the properties into that step to gain an optimization for those graphs that support such capabilities.
final Step endStep = this.asAdmin().getEndStep();
- if ((endStep instanceof AddVertexStep || endStep instanceof AddEdgeStep || endStep instanceof AddVertexStartStep) &&
+ if ((endStep instanceof MutatingStep || endStep instanceof AddVertexStep || endStep instanceof AddEdgeStep || endStep instanceof AddVertexStartStep) &&
keyValues.length == 0 && null == cardinality) {
((Mutating) endStep).addPropertyMutations(key, value);
} else {
@@ -2419,7 +2469,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
///////////////////// UTILITY STEPS /////////////////////
/**
- * A step modulator that provides a lable to the step that can be accessed later in the traversal by other steps.
+ * A step modulator that provides a label to the step that can be accessed later in the traversal by other steps.
*
* @param stepLabel the name of the step
* @param stepLabels additional names for the label
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bb583e3a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/MutatingContainerHolder.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/MutatingContainerHolder.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/MutatingContainerHolder.java
new file mode 100644
index 0000000..5f69e58
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/MutatingContainerHolder.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step;
+
+
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.MutatingContainer;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.CallbackRegistry;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.Event;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+import java.util.List;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public interface MutatingContainerHolder {
+
+ public List<MutatingContainer> getMutatingContainers();
+
+ public default MutatingContainer getLastMutatingContainer() {
+ final List<MutatingContainer> containers = getMutatingContainers();
+ return containers.get(containers.size() - 1);
+ }
+
+ public void addMutatingContainer(final MutatingContainer mutatingContainer);
+
+ public default void removeMutatingContainer(final MutatingContainer mutatingContainer) {
+ throw new UnsupportedOperationException("The holder does not support container removal: " + this.getClass().getCanonicalName());
+ }
+
+ public CallbackRegistry<Event> getMutatingCallbackRegistry();
+
+ public Vertex getLabelledVertex(final String label);
+
+ public Graph getGraph();
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bb583e3a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MutatingStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MutatingStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MutatingStep.java
new file mode 100644
index 0000000..d130b7a
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MutatingStep.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Mutating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.MutatingContainerHolder;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.MutatingContainer;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.CallbackRegistry;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.Event;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.ListCallbackRegistry;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public final class MutatingStep<S> extends MapStep<S, Element> implements MutatingContainerHolder, Mutating {
+
+ private Map<String,Vertex> labelledVertices = new HashMap<>();
+ private List<MutatingContainer> mutatingContainers = new ArrayList<>();
+ private CallbackRegistry<Event> callbackRegistry;
+
+ public MutatingStep(final Traversal.Admin traversal, final MutatingContainer... mutatingContainers) {
+ super(traversal);
+ Collections.addAll(this.mutatingContainers, mutatingContainers);
+ }
+
+ @Override
+ protected Element map(final Traverser.Admin<S> traverser) {
+ Element e = null;
+ for (final MutatingContainer container : mutatingContainers) {
+ final Element element = container.get();
+ if (element instanceof Vertex) {
+ // TODO: how to handle multiple labelled stuffs g.addV().as('a').addV().as('a')
+ for (String label : container.getStepLabels()) {
+ labelledVertices.put(label, (Vertex) element);
+ }
+ }
+
+ e = element;
+ }
+
+ return e;
+ }
+
+ @Override
+ public void addPropertyMutations(final Object... keyValues) {
+ final MutatingContainer container = mutatingContainers.get(mutatingContainers.size() - 1);
+ container.addPropertyMutations(keyValues);
+ }
+
+ @Override
+ public Graph getGraph() {
+ return (Graph) this.traversal.getGraph().get();
+ }
+
+ @Override
+ public List<MutatingContainer> getMutatingContainers() {
+ return this.mutatingContainers;
+ }
+
+ @Override
+ public void addMutatingContainer(final MutatingContainer mutatingContainer) {
+ this.mutatingContainers.add(mutatingContainer);
+ }
+
+ @Override
+ public CallbackRegistry<Event> getMutatingCallbackRegistry() {
+ if (null == callbackRegistry) callbackRegistry = new ListCallbackRegistry<>();
+ return callbackRegistry;
+ }
+
+ @Override
+ public Vertex getLabelledVertex(final String label) {
+ return labelledVertices.get(label);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bb583e3a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/MutatingContainer.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/MutatingContainer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/MutatingContainer.java
new file mode 100644
index 0000000..c7c6821
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/MutatingContainer.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.util;
+
+import org.apache.tinkerpop.gremlin.process.traversal.step.Mutating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.MutatingContainerHolder;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.CallbackRegistry;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.Event;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class MutatingContainer implements Supplier<Element>, Mutating, Serializable, Cloneable {
+ public enum Operation implements Function<MutatingContainer, Element> {
+ ADD_V {
+ @Override
+ public Element apply(final MutatingContainer container) {
+ return (container.holder.getGraph()).addVertex(container.keyValues.toArray());
+ }
+ },
+ ADD_E {
+ @Override
+ public Element apply(final MutatingContainer container) {
+ final Vertex outV = container.holder.getLabelledVertex(container.outVLabel);
+ final Vertex inV = container.holder.getLabelledVertex(container.inVLabel);
+ return outV.addEdge(container.edgeLabel, inV, container.keyValues.toArray());
+ }
+ }
+ }
+
+ private final Operation op;
+ private final MutatingContainerHolder holder;
+ private String outVLabel;
+ private String inVLabel;
+ private String edgeLabel;
+ private List<Object> keyValues;
+ private Set<String> labels = Collections.emptySet();
+
+ public MutatingContainer(final Operation op, final MutatingContainerHolder holder, final Object... keyValues) {
+ this.op = op;
+ this.holder = holder;
+ if (keyValues != null && keyValues.length > 0) this.keyValues = new ArrayList<>();
+ Collections.addAll(this.keyValues, keyValues);
+ }
+
+ @Override
+ public void addPropertyMutations(final Object... keyValues) {
+ if (null == this.keyValues) this.keyValues = new ArrayList<>();
+ Collections.addAll(this.keyValues, keyValues);
+ }
+
+ public void setOutVLabel(final String label) {
+ this.outVLabel = label;
+ }
+
+ public void setInVLabel(final String label) {
+ this.inVLabel = label;
+ }
+
+ public void addStepLabels(final Set<String> labels) {
+ this.labels = labels;
+ }
+
+ public void setEdgeLabel(final String label) {
+ this.edgeLabel = label;
+ }
+
+ public Set<String> getStepLabels() {
+ return Collections.unmodifiableSet(labels);
+ }
+
+ @Override
+ public CallbackRegistry<Event> getMutatingCallbackRegistry() {
+ // hmmmmmmmmmmmmm
+ return null;
+ }
+
+ @Override
+ public Element get() {
+ return op.apply(this);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bb583e3a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MutatingStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MutatingStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MutatingStrategy.java
new file mode 100644
index 0000000..552b8be
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/MutatingStrategy.java
@@ -0,0 +1,66 @@
+/*
+ * 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.strategy.optimization;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStartStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MutatingStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+
+import java.util.List;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public final class MutatingStrategy extends AbstractTraversalStrategy<TraversalStrategy.OptimizationStrategy> implements TraversalStrategy.OptimizationStrategy {
+
+ private static final MutatingStrategy INSTANCE = new MutatingStrategy();
+
+ private MutatingStrategy() {}
+
+ @Override
+ public void apply(final Traversal.Admin<?, ?> traversal) {
+ final MutatingStep mutatingStep = new MutatingStep(traversal);
+
+ Step start = null;
+ Step end = null;
+ final List<Step> steps = traversal.getSteps();
+ for (int ix = 0; ix < steps.size(); ix++) {
+ final Step currentStep = steps.get(ix);
+ if (currentStep instanceof AddVertexStep) {
+ //mutatingStep.addMutatingStep(null, (MapStep) currentStep);
+ if (null == start) start = currentStep;
+ }
+
+ end = currentStep;
+ }
+
+ TraversalHelper.removeBetween(start, end);
+ traversal.addStep(mutatingStep);
+ }
+
+ public static MutatingStrategy instance() {
+ return INSTANCE;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bb583e3a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
index eda836a..608e4e9 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
@@ -27,6 +27,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.lambda.ElementValueTravers
import org.apache.tinkerpop.gremlin.process.traversal.lambda.TokenTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
import org.apache.tinkerpop.gremlin.process.traversal.step.HasContainerHolder;
+import org.apache.tinkerpop.gremlin.process.traversal.step.MutatingContainerHolder;
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.RepeatStep;
@@ -38,6 +39,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTraversal
import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeVertexStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.LabelStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MutatingStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertiesStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyMapStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
@@ -46,6 +48,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.MutatingContainer;
+import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
@@ -200,13 +204,25 @@ public final class TraversalHelper {
}
}
+ /**
+ * Removes steps in a traversal starting at the {@code startStep} and ending inclusively with the {@code endStep}.
+ */
+ public static <S, E> void removeBetween(final Step<S, ?> startStep, final Step<?, E> endStep) {
+ removeToTraversal(startStep, endStep, null);
+ }
+
+ /**
+ * Removes steps in a traversal starting at the {@code startStep} and ending inclusively with the {@code endStep},
+ * storing them in the provided {@code newTraversal}. If the {@code newTraversal} is {@code null} then the steps
+ * are simply discarded.
+ */
public static <S, E> void removeToTraversal(final Step<S, ?> startStep, final Step<?, E> endStep, final Traversal.Admin<S, E> newTraversal) {
final Traversal.Admin<?, ?> originalTraversal = startStep.getTraversal();
Step<?, ?> currentStep = startStep;
while (currentStep != endStep && !(currentStep instanceof EmptyStep)) {
final Step<?, ?> temp = currentStep.getNextStep();
originalTraversal.removeStep(currentStep);
- newTraversal.addStep(currentStep);
+ if (newTraversal != null) newTraversal.addStep(currentStep);
currentStep = temp;
}
}
@@ -700,7 +716,8 @@ public final class TraversalHelper {
}
/**
- * Used to left-fold a {@link HasContainer} to a {@link HasContainerHolder} if it exists. Else, append a {@link HasStep}.
+ * Used to left-fold a {@link HasContainer} to a {@link HasContainerHolder} if it exists. Else, append a
+ * {@link HasStep}.
*
* @param traversal the traversal to fold or append.
* @param hasContainer the container to add left or append.
@@ -714,4 +731,20 @@ public final class TraversalHelper {
} else
return (T) traversal.addStep(new HasStep<>(traversal, hasContainer));
}
+
+ /**
+ * Used to left-fold a {@link MutatingContainer} to a {@link MutatingContainerHolder} if it exists. Else, append
+ * a {@link MutatingStep}.
+ *
+ * @param traversal the traversal to fold or append.
+ * @param mutatingContainer the container to add left or append.
+ * @return the has container folded or appended traversal
+ */
+ public static Traversal.Admin addMutatingContainer(final Traversal.Admin traversal, final MutatingContainer mutatingContainer) {
+ if (traversal.getEndStep() instanceof MutatingContainerHolder) {
+ ((MutatingContainerHolder) traversal.getEndStep()).addMutatingContainer(mutatingContainer);
+ return traversal;
+ } else
+ return traversal.addStep(new MutatingStep<>(traversal, mutatingContainer));
+ }
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bb583e3a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
index 5563665..5e722f3 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
@@ -22,6 +22,8 @@ import org.apache.commons.configuration.BaseConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
+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.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.Graph;
@@ -50,7 +52,6 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
-import java.util.stream.Stream;
/**
* An in-memory (with optional persistence on calls to {@link #close()}), reference implementation of the property
@@ -601,7 +602,11 @@ public final class TinkerGraph implements Graph {
LONG {
@Override
public Long getNextId(final TinkerGraph graph) {
- return Stream.generate(() -> (graph.currentId.incrementAndGet())).filter(id -> !graph.vertices.containsKey(id) && !graph.edges.containsKey(id)).findAny().get();
+ long id;
+ do {
+ id = graph.currentId.getAndIncrement();
+ } while (graph.vertices.containsKey(id) || graph.edges.containsKey(id));
+ return id;
}
@Override
@@ -631,7 +636,11 @@ public final class TinkerGraph implements Graph {
INTEGER {
@Override
public Integer getNextId(final TinkerGraph graph) {
- return Stream.generate(() -> (graph.currentId.incrementAndGet())).map(Long::intValue).filter(id -> !graph.vertices.containsKey(id) && !graph.edges.containsKey(id)).findAny().get();
+ long id;
+ do {
+ id = graph.currentId.getAndIncrement();
+ } while (graph.vertices.containsKey(id) || graph.edges.containsKey(id));
+ return (int) id;
}
@Override
@@ -691,7 +700,11 @@ public final class TinkerGraph implements Graph {
ANY {
@Override
public Long getNextId(final TinkerGraph graph) {
- return Stream.generate(() -> (graph.currentId.incrementAndGet())).filter(id -> !graph.vertices.containsKey(id) && !graph.edges.containsKey(id)).findAny().get();
+ long id;
+ do {
+ id = graph.currentId.getAndIncrement();
+ } while (graph.vertices.containsKey(id) || graph.edges.containsKey(id));
+ return id;
}
@Override
@@ -705,4 +718,102 @@ public final class TinkerGraph implements Graph {
}
}
}
+
+ public static void main(String[] args) {
+ GraphTraversalSource g = TinkerGraph.open().traversal();
+ for (int iz = 0; iz < 5000; iz++) {
+ GraphTraversal<Vertex, ?> t = g.addV("person");
+ for (int iy = 0; iy < 32; iy++) {
+ if (iy % 2 == 0)
+ t = t.property("x" + String.valueOf(iy), iy * iz);
+ else
+ t = t.property("x" + String.valueOf(iy), String.valueOf(iy + iz));
+ }
+
+ for (int ix = 0; ix < 100; ix++) {
+ t = t.addV("person");
+ for (int iy = 0; iy < 32; iy++) {
+ if (iy % 2 == 0)
+ t = t.property("x" + String.valueOf(iy), iy * iz);
+ else
+ t = t.property("x" + String.valueOf(iy), String.valueOf(iy + iz));
+ }
+ }
+
+ t.iterate();
+
+ }
+ }
+
+// public static void main(String[] args) {
+// GraphTraversalSource g = TinkerGraph.open().traversal().
+// withoutStrategies(
+// org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ConnectiveStrategy.class,
+// org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.InlineFilterStrategy.class,
+// org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IncidentToAdjacentStrategy.class,
+// org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy.class,
+// org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy.class,
+// org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.MatchPredicateStrategy.class,
+// org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy.class,
+// org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy.class,
+// org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy.class,
+// org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.LazyBarrierStrategy.class,
+// org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ProfileStrategy.class,
+// org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.StandardVerificationStrategy.class).
+// withStrategies(org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.MutatingStrategy.instance());
+// for (int iz = 0; iz < 1000000; iz++) {
+// GraphTraversal<Vertex, ?> t = g.addV("person");
+// for (int iy = 0; iy < 32; iy++) {
+// if (iy % 2 == 0)
+// t = t.property("x" + String.valueOf(iy), iy * iz);
+// else
+// t = t.property("x" + String.valueOf(iy), String.valueOf(iy + iz));
+// }
+//
+// t.iterate();
+//
+// }
+// }
+
+
+// public static void main(String[] args) {
+// final java.util.Random rand = new java.util.Random(584545454L);
+//
+// for (int iz = 0; iz < 10; iz++) {
+// GraphTraversalSource g = TinkerGraph.open().traversal();
+// GraphTraversal<Vertex, ?> t = null;
+// for (int ix = 0; ix < 100; ix++) {
+// if (null == t)
+// t = g.addV("person");
+// else
+// t = t.addV("person");
+//
+// for (int iy = 0; iy < 32; iy++) {
+// if (iy % 2 == 0)
+// t = t.property("x" + String.valueOf(iy), iy * ix);
+// else
+// t = t.property("x" + String.valueOf(iy), String.valueOf(iy + ix));
+// }
+//
+// t = t.as("person" + ix);
+//
+// if (ix > 0) {
+// int edgeCount = ix == 99 ? 6 : 3;
+// for (int ie = 0; ie < edgeCount; ie++) {
+// t = t.addE("knows").from("person" + ix).to("person" + rand.nextInt(ix));
+//
+// for (int iy = 0; iy < 8; iy++) {
+// if (iy % 2 == 0)
+// t = t.property("x" + String.valueOf(iy), iy * ie);
+// else
+// t = t.property("x" + String.valueOf(iy), String.valueOf(iy + ie));
+// }
+// }
+// }
+// }
+//
+// t.iterate();
+//
+// }
+// }
}