You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2015/03/17 19:42:43 UTC
[6/6] incubator-tinkerpop git commit: Add PartitionStrategy and
related tests as a TraversalStrategy.
Add PartitionStrategy and related tests as a TraversalStrategy.
Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/85dfcc79
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/85dfcc79
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/85dfcc79
Branch: refs/heads/master
Commit: 85dfcc79acf51f00a3fdd4e742c6b6b7d25b58c3
Parents: f896de1
Author: Stephen Mallette <sp...@apache.org>
Authored: Tue Mar 17 14:42:11 2015 -0400
Committer: Stephen Mallette <sp...@apache.org>
Committed: Tue Mar 17 14:42:11 2015 -0400
----------------------------------------------------------------------
.../process/graph/traversal/step/Mutating.java | 9 +
.../graph/traversal/step/map/AddEdgeStep.java | 33 ++-
.../traversal/step/map/AddVertexStartStep.java | 3 +
.../graph/traversal/step/map/AddVertexStep.java | 4 +
.../strategy/decoration/PartitionStrategy.java | 100 +++++++++
.../decoration/PartitionStrategyTest.java | 130 +++++++++++
.../gremlin/process/ProcessComputerSuite.java | 7 +-
.../gremlin/process/ProcessStandardSuite.java | 6 +-
.../PartitionStrategyProcessTest.java | 218 +++++++++++++++++++
.../decoration/ReadOnlyStrategyProcessTest.java | 116 ++++++++++
.../decoration/ReadOnlyStrategyTest.java | 116 ----------
11 files changed, 613 insertions(+), 129 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/85dfcc79/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/Mutating.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/Mutating.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/Mutating.java
new file mode 100644
index 0000000..2a2ac16
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/Mutating.java
@@ -0,0 +1,9 @@
+package org.apache.tinkerpop.gremlin.process.graph.traversal.step;
+
+/**
+ * A marker interface for steps that modify the graph.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public interface Mutating {
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/85dfcc79/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/AddEdgeStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/AddEdgeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/AddEdgeStep.java
index b413c0a..6c5dc6d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/AddEdgeStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/AddEdgeStep.java
@@ -20,6 +20,7 @@ package org.apache.tinkerpop.gremlin.process.graph.traversal.step.map;
import org.apache.tinkerpop.gremlin.process.Traversal;
import org.apache.tinkerpop.gremlin.process.Traverser;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.step.Mutating;
import org.apache.tinkerpop.gremlin.process.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Edge;
@@ -34,32 +35,48 @@ import java.util.Set;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
*/
-public final class AddEdgeStep extends FlatMapStep<Vertex, Edge> {
+public final class AddEdgeStep extends FlatMapStep<Vertex, Edge> implements Mutating {
private static final Set<TraverserRequirement> REQUIREMENTS = EnumSet.of(TraverserRequirement.OBJECT);
- private final String label;
+ private final String edgeLabel;
private final Object[] keyValues;
private final List<Vertex> vertices;
private final Direction direction;
- public AddEdgeStep(final Traversal.Admin traversal, final Direction direction, final String label, final Vertex vertex, final Object... keyValues) {
- this(traversal, direction, label, IteratorUtils.of(vertex), keyValues);
+ public AddEdgeStep(final Traversal.Admin traversal, final Direction direction, final String edgeLabel, final Vertex vertex, final Object... keyValues) {
+ this(traversal, direction, edgeLabel, IteratorUtils.of(vertex), keyValues);
}
- public AddEdgeStep(final Traversal.Admin traversal, final Direction direction, final String label, final Iterator<Vertex> vertices, final Object... keyValues) {
+ public AddEdgeStep(final Traversal.Admin traversal, final Direction direction, final String edgeLabel, final Iterator<Vertex> vertices, final Object... keyValues) {
super(traversal);
this.direction = direction;
- this.label = label;
+ this.edgeLabel = edgeLabel;
this.vertices = IteratorUtils.list(vertices);
this.keyValues = keyValues;
}
+ public Direction getDirection() {
+ return direction;
+ }
+
+ public String getEdgeLabel() {
+ return edgeLabel;
+ }
+
+ public Object[] getKeyValues() {
+ return keyValues;
+ }
+
+ public List<Vertex> getVertices() {
+ return vertices;
+ }
+
@Override
protected Iterator<Edge> flatMap(final Traverser.Admin<Vertex> traverser) {
return IteratorUtils.map(this.vertices.iterator(), this.direction.equals(Direction.OUT) ?
- vertex -> traverser.get().addEdge(this.label, vertex, this.keyValues) :
- vertex -> vertex.addEdge(this.label, traverser.get(), this.keyValues));
+ vertex -> traverser.get().addEdge(this.edgeLabel, vertex, this.keyValues) :
+ vertex -> vertex.addEdge(this.edgeLabel, traverser.get(), this.keyValues));
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/85dfcc79/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/AddVertexStartStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/AddVertexStartStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/AddVertexStartStep.java
index debd910..3b54d3a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/AddVertexStartStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/AddVertexStartStep.java
@@ -37,6 +37,9 @@ public final class AddVertexStartStep extends AbstractStep<Vertex, Vertex> {
this.keyValues = keyValues;
}
+ public Object[] getKeyValues() {
+ return keyValues;
+ }
@Override
protected Traverser<Vertex> processNextStart() {
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/85dfcc79/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/AddVertexStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/AddVertexStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/AddVertexStep.java
index 5b5eadd..ef5cb57 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/AddVertexStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/AddVertexStep.java
@@ -37,6 +37,10 @@ public final class AddVertexStep<S> extends MapStep<S, Vertex> {
this.graph = this.getTraversal().getGraph().get();
}
+ public Object[] getKeyValues() {
+ return keyValues;
+ }
+
@Override
protected Vertex map(final Traverser.Admin<S> traverser) {
return this.graph.addVertex(this.keyValues);
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/85dfcc79/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategy.java
new file mode 100644
index 0000000..00cb44e
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategy.java
@@ -0,0 +1,100 @@
+package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration;
+
+import org.apache.tinkerpop.gremlin.process.Step;
+import org.apache.tinkerpop.gremlin.process.Traversal;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.step.filter.HasStep;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.step.map.AddVertexStartStep;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.step.map.AddVertexStep;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.step.map.EdgeOtherVertexStep;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.step.map.EdgeVertexStep;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.step.map.VertexStep;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.step.map.AddEdgeStep;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.step.sideEffect.GraphStep;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.strategy.AbstractTraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.graph.util.HasContainer;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.structure.Contains;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class PartitionStrategy extends AbstractTraversalStrategy {
+ private String writePartition;
+ private final String partitionKey;
+ private final Set<String> readPartitions = new HashSet<>();
+
+ public PartitionStrategy(final String partitionKey, final String partition) {
+ this.writePartition = partition;
+ this.addReadPartition(partition);
+ this.partitionKey = partitionKey;
+ }
+
+ public String getWritePartition() {
+ return this.writePartition;
+ }
+
+ public void setWritePartition(final String writePartition) {
+ this.writePartition = writePartition;
+ this.readPartitions.add(writePartition);
+ }
+
+ public String getPartitionKey() {
+ return this.partitionKey;
+ }
+
+ public Set<String> getReadPartitions() {
+ return Collections.unmodifiableSet(this.readPartitions);
+ }
+
+ public void removeReadPartition(final String readPartition) {
+ this.readPartitions.remove(readPartition);
+ }
+
+ public void addReadPartition(final String readPartition) {
+ this.readPartitions.add(readPartition);
+ }
+
+ public void clearReadPartitions() {
+ this.readPartitions.clear();
+ }
+
+ @Override
+ public void apply(final Traversal.Admin<?, ?> traversal) {
+ // todo: what about "add vertex"
+ final List<Step> stepsToInsertHasAfter = new ArrayList<>();
+ stepsToInsertHasAfter.addAll(TraversalHelper.getStepsOfAssignableClass(GraphStep.class, traversal));
+ stepsToInsertHasAfter.addAll(TraversalHelper.getStepsOfAssignableClass(VertexStep.class, traversal));
+ stepsToInsertHasAfter.addAll(TraversalHelper.getStepsOfAssignableClass(EdgeOtherVertexStep.class, traversal));
+ stepsToInsertHasAfter.addAll(TraversalHelper.getStepsOfAssignableClass(AddEdgeStep.class, traversal));
+ stepsToInsertHasAfter.addAll(TraversalHelper.getStepsOfAssignableClass(EdgeVertexStep.class, traversal));
+ stepsToInsertHasAfter.addAll(TraversalHelper.getStepsOfAssignableClass(AddVertexStep.class, traversal));
+
+ // all steps that return a vertex need to have has(paritionKey,within,partitionValues) injected after it
+ stepsToInsertHasAfter.forEach(s -> TraversalHelper.insertAfterStep(
+ new HasStep(traversal, new HasContainer(partitionKey, Contains.within, new ArrayList<>(readPartitions))), s, traversal));
+
+ // all write edge steps need to have partition keys tossed into the property key/value list after mutating steps
+ TraversalHelper.getStepsOfAssignableClass(AddEdgeStep.class, traversal).forEach(s -> {
+ final Object[] keyValues = Stream.concat(Stream.of(s.getKeyValues()), Stream.of(partitionKey, writePartition)).toArray();
+ TraversalHelper.replaceStep(s, new AddEdgeStep(traversal, s.getDirection(), s.getEdgeLabel(), s.getVertices().iterator(), keyValues), traversal);
+ });
+
+ // all write vertex steps need to have partition keys tossed into the property key/value list after mutating steps
+ TraversalHelper.getStepsOfAssignableClass(AddVertexStep.class, traversal).forEach(s -> {
+ final Object[] keyValues = Stream.concat(Stream.of(s.getKeyValues()), Stream.of(partitionKey, writePartition)).toArray();
+ TraversalHelper.replaceStep(s, new AddVertexStep(traversal, keyValues), traversal);
+ });
+
+ TraversalHelper.getStepsOfAssignableClass(AddVertexStartStep.class, traversal).forEach(s -> {
+ final Object[] keyValues = Stream.concat(Stream.of(s.getKeyValues()), Stream.of(partitionKey, writePartition)).toArray();
+ TraversalHelper.replaceStep(s, new AddVertexStartStep(traversal, keyValues), traversal);
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/85dfcc79/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyTest.java
new file mode 100644
index 0000000..e06dbdd
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyTest.java
@@ -0,0 +1,130 @@
+package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration;
+
+import org.apache.tinkerpop.gremlin.process.Traversal;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.DefaultGraphTraversal;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.__;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.step.filter.HasStep;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.step.map.AddEdgeStep;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.step.map.AddVertexStep;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.step.sideEffect.GraphStep;
+import org.apache.tinkerpop.gremlin.process.graph.util.HasContainer;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.structure.Contains;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
+import org.javatuples.Pair;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+@RunWith(Parameterized.class)
+public class PartitionStrategyTest {
+ private static Traversal traversalWithAddV;
+ static {
+ final Graph mockedGraph = mock(Graph.class);
+ final DefaultGraphTraversal t = new DefaultGraphTraversal<>(mockedGraph);
+ t.asAdmin().addStep(new GraphStep<>(t.asAdmin(), Vertex.class));
+ traversalWithAddV = t.addV();
+ }
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Iterable<Object[]> data() {
+ return Arrays.asList(new Object[][]{
+ {"bothV()", __.bothV(), 1, false},
+ {"inV()", __.inV(), 1, false},
+ {"outV()", __.outV(), 1, false},
+ {"in()", __.in(), 1, false},
+ {"in(args)", __.in("test"), 1, false},
+ {"both()", __.both(), 1, false},
+ {"both(args)", __.both("test"), 1, false},
+ {"out()", __.out(), 1, false},
+ {"out(args)", __.out("test"), 1, false},
+ {"out().inE().otherV", __.out().inE().otherV(), 3, false},
+ {"addV()", traversalWithAddV, 2, true},
+ {"addInE()", __.addInE("test", "x"), 1, true},
+ {"addOutE()", __.addOutE("test", "x"), 1, true},
+ {"addInE()", __.addInE("test", "x", "other", "args"), 1, true},
+ {"addOutE()", __.addOutE("test", "x", "other", "args"), 1, true},
+ {"addBothE(OUT)", __.addE(Direction.OUT, "test", "x"), 1, true},
+ {"addBothE(IN)", __.addE(Direction.IN, "test", "x"), 1, true},
+ {"in().out()", __.in().out(), 2, false},
+ {"out().out().out()", __.out().out().out(), 3, false},
+ {"in().out().in()", __.in().out().in(), 3, false},
+ {"inE().outV().inE().outV()", __.inE().outV().inE().outV(), 4, false}});
+ }
+
+ @Parameterized.Parameter(value = 0)
+ public String name;
+
+ @Parameterized.Parameter(value = 1)
+ public Traversal traversal;
+
+ @Parameterized.Parameter(value = 2)
+ public int expectedInsertedSteps;
+
+ @Parameterized.Parameter(value = 3)
+ public boolean hasMutatingStep;
+
+ @Test
+ public void shouldIncludeAdditionalHasStepsAndAppendPartitionOnMutatingSteps() {
+ final PartitionStrategy strategy = new PartitionStrategy("p", "a");
+
+ if (hasMutatingStep) {
+ if (TraversalHelper.hasStepOfAssignableClass(AddEdgeStep.class, traversal.asAdmin())) {
+ final Direction d = TraversalHelper.getStepsOfClass(AddEdgeStep.class, traversal.asAdmin()).get(0).getDirection();
+ strategy.apply(traversal.asAdmin());
+
+ final List<AddEdgeStep> addEdgeSteps = TraversalHelper.getStepsOfAssignableClass(AddEdgeStep.class, traversal.asAdmin());
+ assertEquals(1, addEdgeSteps.size());
+
+ addEdgeSteps.forEach(s -> {
+ final Object[] keyValues = s.getKeyValues();
+ final List<Pair<String, Object>> pairs = ElementHelper.asPairs(keyValues);
+ assertEquals("test", s.getEdgeLabel());
+ assertEquals(d, s.getDirection());
+ assertTrue(pairs.stream().anyMatch(p -> p.getValue0().equals("p") && p.getValue1().equals("a")));
+ });
+ } else if (TraversalHelper.hasStepOfAssignableClass(AddVertexStep.class, traversal.asAdmin())) {
+ strategy.apply(traversal.asAdmin());
+
+ final List<AddVertexStep> addVertexSteps = TraversalHelper.getStepsOfAssignableClass(AddVertexStep.class, traversal.asAdmin());
+ assertEquals(1, addVertexSteps.size());
+
+ addVertexSteps.forEach(s -> {
+ final Object[] keyValues = s.getKeyValues();
+ final List<Pair<String, Object>> pairs = ElementHelper.asPairs(keyValues);
+ assertTrue(pairs.stream().anyMatch(p -> p.getValue0().equals("p") && p.getValue1().equals("a")));
+ });
+ } else
+ fail("This test should not be marked as having a mutating step or there is something else amiss.");
+ } else {
+ strategy.apply(traversal.asAdmin());
+ }
+
+ final List<HasStep> steps = TraversalHelper.getStepsOfClass(HasStep.class, traversal.asAdmin());
+ assertEquals(expectedInsertedSteps, steps.size());
+
+ final List<String> keySet = new ArrayList<>(strategy.getReadPartitions());
+ steps.forEach(s -> {
+ assertEquals(1, s.getHasContainers().size());
+ final HasContainer hasContainer = (HasContainer) s.getHasContainers().get(0);
+ assertEquals("p", hasContainer.key);
+ assertEquals(keySet, hasContainer.value);
+ assertEquals(Contains.within, hasContainer.predicate);
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/85dfcc79/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
index 74c4275..4257c7c 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
@@ -67,8 +67,8 @@ import org.apache.tinkerpop.gremlin.process.graph.traversal.step.sideEffect.Side
import org.apache.tinkerpop.gremlin.process.graph.traversal.step.sideEffect.StoreTest;
import org.apache.tinkerpop.gremlin.process.graph.traversal.step.sideEffect.TreeTest;
import org.apache.tinkerpop.gremlin.process.graph.traversal.strategy.TraversalVerificationStrategyTest;
-import org.apache.tinkerpop.gremlin.process.traversal.engine.StandardTraversalEngine;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ReadOnlyStrategyTest;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategyProcessTest;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ReadOnlyStrategyProcessTest;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.RunnerBuilder;
@@ -177,7 +177,8 @@ public class ProcessComputerSuite extends AbstractGremlinSuite {
TraversalVerificationStrategyTest.ComputerTraversals.class,
// decorations
- ReadOnlyStrategyTest.class
+ ReadOnlyStrategyProcessTest.class,
+ PartitionStrategyProcessTest.class
};
/**
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/85dfcc79/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
index 0a10ace..5cd74b1 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
@@ -72,7 +72,8 @@ import org.apache.tinkerpop.gremlin.process.graph.traversal.step.sideEffect.Tree
import org.apache.tinkerpop.gremlin.process.graph.traversal.step.util.TraversalSideEffectsTest;
import org.apache.tinkerpop.gremlin.process.graph.traversal.strategy.TraversalVerificationStrategyTest;
import org.apache.tinkerpop.gremlin.process.traversal.CoreTraversalTest;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ReadOnlyStrategyTest;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategyProcessTest;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ReadOnlyStrategyProcessTest;
import org.apache.tinkerpop.gremlin.process.util.PathTest;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.RunnerBuilder;
@@ -186,7 +187,8 @@ public class ProcessStandardSuite extends AbstractGremlinSuite {
// PageRankVertexProgramTest.class
// decorations
- ReadOnlyStrategyTest.class
+ ReadOnlyStrategyProcessTest.class,
+ PartitionStrategyProcessTest.class
};
/**
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/85dfcc79/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyProcessTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyProcessTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyProcessTest.java
new file mode 100644
index 0000000..c707f30
--- /dev/null
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyProcessTest.java
@@ -0,0 +1,218 @@
+/*
+ * 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.decoration;
+
+import org.apache.tinkerpop.gremlin.FeatureRequirementSet;
+import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
+import org.apache.tinkerpop.gremlin.process.TraversalEngine;
+import org.apache.tinkerpop.gremlin.process.UseEngine;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+@UseEngine(TraversalEngine.Type.STANDARD)
+@UseEngine(TraversalEngine.Type.COMPUTER)
+public class PartitionStrategyProcessTest extends AbstractGremlinProcessTest {
+ private static final String partition = "gremlin.partitionGraphStrategy.partition";
+ private final PartitionStrategy partitionStrategy = new PartitionStrategy(partition, "A");
+
+ @Test
+ @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
+ public void shouldAppendPartitionToVertex() {
+ final Vertex v = create().addV("any", "thing").next();
+
+ assertNotNull(v);
+ assertEquals("thing", v.property("any").value());
+ assertEquals("A", v.property(partition).value());
+ }
+
+ @Test
+ @FeatureRequirementSet(FeatureRequirementSet.Package.SIMPLE)
+ public void shouldAppendPartitionToEdge() {
+ final GraphTraversalSource source = create();
+ final Vertex v1 = source.addV("any", "thing").next();
+ final Vertex v2 = source.addV("some", "thing").next();
+ final Edge e = source.V(v1.id()).addInE("connectsTo", v2, "every", "thing").next();
+
+ assertNotNull(v1);
+ assertEquals("thing", v1.property("any").value());
+ assertEquals("A", v2.property(partition).value());
+
+ assertNotNull(v2);
+ assertEquals("thing", v2.property("some").value());
+ assertEquals("A", v2.property(partition).value());
+
+ assertNotNull(e);
+ assertEquals("thing", e.property("every").value());
+ assertEquals("connectsTo", e.label());
+ assertEquals("A", e.property(partition).value());
+ }
+
+ @Test
+ @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
+ public void shouldWriteVerticesToMultiplePartitions() {
+ final GraphTraversalSource source = create();
+ final Vertex vA = source.addV("any", "a").next();
+ partitionStrategy.setWritePartition("B");
+ final Vertex vB = source.addV("any", "b").next();
+
+ assertNotNull(vA);
+ assertEquals("a", vA.property("any").value());
+ assertEquals("A", vA.property(partition).value());
+
+ assertNotNull(vB);
+ assertEquals("b", vB.property("any").value());
+ assertEquals("B", vB.property(partition).value());
+
+ partitionStrategy.removeReadPartition("B");
+ source.V().forEachRemaining(v -> assertEquals("a", v.property("any").value()));
+
+ partitionStrategy.removeReadPartition("A");
+ partitionStrategy.addReadPartition("B");
+
+ source.V().forEachRemaining(v -> assertEquals("b", v.property("any").value()));
+
+ partitionStrategy.addReadPartition("A");
+ assertEquals(new Long(2), source.V().count().next());
+ }
+
+ @Test
+ @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
+ public void shouldThrowExceptionOnVInDifferentPartition() {
+ final GraphTraversalSource source = create();
+ final Vertex vA = source.addV("any", "a").next();
+ assertEquals(vA.id(), source.V(vA.id()).id().next());
+
+ partitionStrategy.clearReadPartitions();
+
+ try {
+ g.V(vA.id());
+ } catch (Exception ex) {
+ final Exception expected = Graph.Exceptions.elementNotFound(Vertex.class, vA.id());
+ assertEquals(expected.getClass(), ex.getClass());
+ assertEquals(expected.getMessage(), ex.getMessage());
+ }
+ }
+
+ @Test
+ @FeatureRequirementSet(FeatureRequirementSet.Package.SIMPLE)
+ public void shouldThrowExceptionOnEInDifferentPartition() {
+ final GraphTraversalSource source = create();
+ final Vertex vA = source.addV("any", "a").next();
+ final Edge e = source.V(vA.id()).addOutE("knows", vA).next();
+ assertEquals(e.id(), g.E(e.id()).id().next());
+
+ partitionStrategy.clearReadPartitions();
+
+ try {
+ g.E(e.id());
+ } catch (Exception ex) {
+ final Exception expected = Graph.Exceptions.elementNotFound(Edge.class, e.id());
+ assertEquals(expected.getClass(), ex.getClass());
+ assertEquals(expected.getMessage(), ex.getMessage());
+ }
+ }
+
+ @Test
+ @FeatureRequirementSet(FeatureRequirementSet.Package.SIMPLE)
+ public void shouldWriteToMultiplePartitions() {
+ final GraphTraversalSource source = create();
+ final Vertex vA = source.addV("any", "a").next();
+ final Vertex vAA = source.addV("any", "aa").next();
+ final Edge eAtoAA = source.V(vA.id()).addOutE("a->a", vAA).next();
+
+ partitionStrategy.setWritePartition("B");
+ final Vertex vB = source.addV("any", "b").next();
+ boolean x = source.V(vA.id()).hasNext();
+ source.V(vA.id()).addOutE("a->b", vB).next();
+
+ partitionStrategy.setWritePartition("C");
+ final Vertex vC = source.addV("any", "c").next();
+ final Edge eBtovC = source.V(vB.id()).addOutE("b->c", vC).next();
+ final Edge eAtovC = source.V(vA.id()).addOutE("a->c", vC).next();
+
+ partitionStrategy.clearReadPartitions();
+ assertEquals(0, IteratorUtils.count(source.V()));
+ assertEquals(0, IteratorUtils.count(source.E()));
+
+ partitionStrategy.addReadPartition("A");
+ assertEquals(new Long(2), source.V().count().next());
+ assertEquals(new Long(1), source.E().count().next());
+ assertEquals(new Long(1), source.V(vA.id()).outE().count().next());
+ assertEquals(eAtoAA.id(), source.V(vA.id()).outE().next().id());
+ assertEquals(new Long(1), source.V(vA.id()).out().count().next());
+ assertEquals(vAA.id(), source.V(vA.id()).out().next().id());
+
+ final Vertex vA1 = source.V(vA.id()).next();
+ assertEquals(new Long(1), source.V(vA1).outE().count().next());
+ assertEquals(eAtoAA.id(), source.V(vA1).outE().next().id());
+ assertEquals(new Long(1), source.V(vA1).out().count().next());
+ assertEquals(vAA.id(), source.V(vA1).out().next().id());
+
+ partitionStrategy.addReadPartition("B");
+ assertEquals(new Long(3), source.V().count().next());
+ assertEquals(new Long(2), source.E().count().next());
+
+ partitionStrategy.addReadPartition("C");
+ assertEquals(new Long(4), source.V().count().next());
+ assertEquals(new Long(4), source.E().count().next());
+
+ partitionStrategy.removeReadPartition("A");
+ partitionStrategy.removeReadPartition("B");
+
+ assertEquals(1, IteratorUtils.count(source.V()));
+ // two edges are in the "C" partition, but one each of their incident vertices are not
+ assertEquals(2, IteratorUtils.count(source.E()));
+
+ // two edges are in the "C" partition, but one each of their incident vertices are not
+ assertEquals(new Long(2), source.V(vC.id()).inE().count().next());
+ assertEquals(new Long(0), source.V(vC.id()).in().count().next());
+
+ partitionStrategy.addReadPartition("B");
+
+ // excluded vertices; vA is not in {B,C}
+ assertEquals(new Long(2), source.V(vC.id()).inE().count().next());
+ assertEquals(new Long(1), source.V(vC.id()).in().count().next());
+ assertEquals(vC.id(), source.E(eBtovC.id()).inV().id().next());
+ assertEquals(vB.id(), source.E(eBtovC.id()).outV().id().next());
+ assertEquals(vC.id(), source.E(eAtovC.id()).inV().id().next());
+ assertFalse(source.E(eAtovC.id()).outV().hasNext());
+ }
+
+ private GraphTraversalSource create() {
+ resetPartitionStrategy();
+ return graphProvider.traversal(graph, partitionStrategy);
+ }
+
+ private void resetPartitionStrategy() {
+ partitionStrategy.clearReadPartitions();
+ partitionStrategy.setWritePartition("A");
+ partitionStrategy.addReadPartition("A");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/85dfcc79/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ReadOnlyStrategyProcessTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ReadOnlyStrategyProcessTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ReadOnlyStrategyProcessTest.java
new file mode 100644
index 0000000..b031db7
--- /dev/null
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ReadOnlyStrategyProcessTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.decoration;
+
+import org.apache.tinkerpop.gremlin.FeatureRequirement;
+import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
+import org.apache.tinkerpop.gremlin.process.Traversal;
+import org.apache.tinkerpop.gremlin.process.TraversalEngine;
+import org.apache.tinkerpop.gremlin.process.UseEngine;
+import org.apache.tinkerpop.gremlin.process.graph.traversal.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+@UseEngine(TraversalEngine.Type.STANDARD)
+@UseEngine(TraversalEngine.Type.COMPUTER)
+public class ReadOnlyStrategyProcessTest extends AbstractGremlinProcessTest {
+ @Test
+ public void shouldTraverseV() {
+ assertTraversal(create().V(), false);
+ }
+
+ @Test
+ public void shouldTraverseV_out() {
+ assertTraversal(create().V().out(), false);
+ }
+
+ @Test
+ public void shouldTraverseV_in() {
+ assertTraversal(create().V().in(), false);
+ }
+
+ @Test
+ public void shouldTraverseV_in_in() {
+ assertTraversal(create().V().in(), false);
+ }
+
+ @Test
+ public void shouldTraverseE() {
+ assertTraversal(create().E(), false);
+ }
+
+ @Test
+ @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
+ public void shouldNotTraverseV_out_addInE() {
+ assertTraversal(create().V().as("a").out().addInE("test", "a"), true);
+ }
+
+ @Test
+ @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
+ public void shouldNotTraverseV_out_addOutE() {
+ assertTraversal(create().V().as("a").out().addOutE("test", "a"), true);
+ }
+
+ @Test
+ @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
+ public void shouldNotTraverseV_In_addInE() {
+ assertTraversal(create().V().as("a").in().addInE("test", "a"), true);
+ }
+
+ @Test
+ @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
+ public void shouldNotTraverseV_In_addOutE() {
+ assertTraversal(create().V().as("a").in().addOutE("test", "a"), true);
+ }
+
+ @Test
+ @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
+ public void shouldNotTraverseV_In_addEXINX() {
+ assertTraversal(create().V().as("a").in().addE(Direction.IN, "test", "a"), true);
+ }
+
+ @Test
+ @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
+ public void shouldNotTraverseV_In_addEXOUTX() {
+ assertTraversal(create().V().as("a").in().addE(Direction.OUT, "test", "a"), true);
+ }
+
+ private GraphTraversalSource create() {
+ return graphProvider.traversal(graph, ReadOnlyStrategy.instance());
+ }
+
+ private void assertTraversal(final Traversal t, final boolean hasMutatingStep) {
+ try {
+ t.asAdmin().applyStrategies();
+ if (hasMutatingStep) fail("The strategy should have found a mutating step.");
+ } catch (IllegalStateException ise) {
+ if (!hasMutatingStep)
+ fail("The traversal should not have failed as there is no mutating step.");
+ else
+ assertEquals("The provided traversal has a mutating step and thus is not read only", ise.getMessage());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/85dfcc79/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ReadOnlyStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ReadOnlyStrategyTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ReadOnlyStrategyTest.java
deleted file mode 100644
index 43a38d5..0000000
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ReadOnlyStrategyTest.java
+++ /dev/null
@@ -1,116 +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.strategy.decoration;
-
-import org.apache.tinkerpop.gremlin.FeatureRequirement;
-import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
-import org.apache.tinkerpop.gremlin.process.Traversal;
-import org.apache.tinkerpop.gremlin.process.TraversalEngine;
-import org.apache.tinkerpop.gremlin.process.UseEngine;
-import org.apache.tinkerpop.gremlin.process.graph.traversal.GraphTraversalSource;
-import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-@UseEngine(TraversalEngine.Type.STANDARD)
-@UseEngine(TraversalEngine.Type.COMPUTER)
-public class ReadOnlyStrategyTest extends AbstractGremlinProcessTest {
- @Test
- public void shouldTraverseV() {
- assertTraversal(create().V(), false);
- }
-
- @Test
- public void shouldTraverseV_out() {
- assertTraversal(create().V().out(), false);
- }
-
- @Test
- public void shouldTraverseV_in() {
- assertTraversal(create().V().in(), false);
- }
-
- @Test
- public void shouldTraverseV_in_in() {
- assertTraversal(create().V().in(), false);
- }
-
- @Test
- public void shouldTraverseE() {
- assertTraversal(create().E(), false);
- }
-
- @Test
- @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
- public void shouldNotTraverseV_out_addInE() {
- assertTraversal(create().V().as("a").out().addInE("test", "a"), true);
- }
-
- @Test
- @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
- public void shouldNotTraverseV_out_addOutE() {
- assertTraversal(create().V().as("a").out().addOutE("test", "a"), true);
- }
-
- @Test
- @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
- public void shouldNotTraverseV_In_addInE() {
- assertTraversal(create().V().as("a").in().addInE("test", "a"), true);
- }
-
- @Test
- @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
- public void shouldNotTraverseV_In_addOutE() {
- assertTraversal(create().V().as("a").in().addOutE("test", "a"), true);
- }
-
- @Test
- @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
- public void shouldNotTraverseV_In_addEXINX() {
- assertTraversal(create().V().as("a").in().addE(Direction.IN, "test", "a"), true);
- }
-
- @Test
- @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
- public void shouldNotTraverseV_In_addEXOUTX() {
- assertTraversal(create().V().as("a").in().addE(Direction.OUT, "test", "a"), true);
- }
-
- private GraphTraversalSource create() {
- return graphProvider.traversal(graph, ReadOnlyStrategy.instance());
- }
-
- private void assertTraversal(final Traversal t, final boolean hasMutatingStep) {
- try {
- t.asAdmin().applyStrategies();
- if (hasMutatingStep) fail("The strategy should have found a mutating step.");
- } catch (IllegalStateException ise) {
- if (!hasMutatingStep)
- fail("The traversal should not have failed as there is no mutating step.");
- else
- assertEquals("The provided traversal has a mutating step and thus is not read only", ise.getMessage());
- }
- }
-}