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 2020/08/30 15:54:45 UTC
[tinkerpop] 01/02: [TINKERPOP-2396] add TraverserSet supplier
option for AbstractStep and ExpandableStepIterator
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch TINKERPOP-2396
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 0ac129373082fd2db316db1691ef9063bbe985a3
Author: Norio Akagi <no...@amazon.com>
AuthorDate: Tue Jul 28 01:53:39 2020 -0700
[TINKERPOP-2396] add TraverserSet supplier option for AbstractStep and ExpandableStepIterator
---
.../traversal/step/filter/RangeGlobalStep.java | 2 +-
.../traversal/step/filter/SampleGlobalStep.java | 2 +-
.../traversal/step/filter/TailGlobalStep.java | 2 +-
.../process/traversal/step/map/MatchStep.java | 7 +--
.../traversal/step/map/NoOpBarrierStep.java | 7 +--
.../traversal/step/sideEffect/AggregateStep.java | 7 +--
.../process/traversal/step/util/AbstractStep.java | 27 ++++++++++-
.../traversal/step/util/CollectingBarrierStep.java | 7 +--
.../step/util/ExpandableStepIterator.java | 18 ++++++-
.../util/function/TraverserSetSupplier.java | 44 +++++++++++++++++
.../util/function/TraverserSetSupplierTest.java | 55 ++++++++++++++++++++++
11 files changed, 161 insertions(+), 17 deletions(-)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeGlobalStep.java
index b99915c..1343aab 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeGlobalStep.java
@@ -167,7 +167,7 @@ public final class RangeGlobalStep<S> extends FilterStep<S> implements Ranging,
public TraverserSet<S> nextBarrier() throws NoSuchElementException {
if(!this.starts.hasNext())
throw FastNoSuchElementException.instance();
- final TraverserSet<S> barrier = new TraverserSet<>();
+ final TraverserSet<S> barrier = this.traverserSetSupplier.get();
while (this.starts.hasNext()) {
barrier.add(this.starts.next());
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
index 5290f97..a4d3458 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
@@ -82,7 +82,7 @@ public final class SampleGlobalStep<S> extends CollectingBarrierStep<S> implemen
totalWeight = totalWeight + (((ProjectedTraverser<S, Number>) s).getProjections().get(0).doubleValue() * s.bulk());
}
///////
- final TraverserSet<S> sampledSet = new TraverserSet<>();
+ final TraverserSet<S> sampledSet = this.traverserSetSupplier.get();
int runningAmountToSample = 0;
while (runningAmountToSample < this.amountToSample) {
boolean reSample = false;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailGlobalStep.java
index 2e31b1f..b8b8037 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailGlobalStep.java
@@ -146,7 +146,7 @@ public final class TailGlobalStep<S> extends AbstractStep<S, S> implements Bypas
public TraverserSet<S> nextBarrier() throws NoSuchElementException {
if (!this.starts.hasNext())
throw FastNoSuchElementException.instance();
- final TraverserSet<S> barrier = new TraverserSet<>();
+ final TraverserSet<S> barrier = this.traverserSetSupplier.get();
while (this.starts.hasNext()) {
barrier.add(this.starts.next());
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
index 9ad7132..f43ae4b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
@@ -70,7 +70,7 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
public enum TraversalType {WHERE_PREDICATE, WHERE_TRAVERSAL, MATCH_TRAVERSAL}
- private List<Traversal.Admin<Object, Object>> matchTraversals = new ArrayList<>();
+ private List<Traversal.Admin<Object, Object>> matchTraversals;
private boolean first = true;
private Set<String> matchStartLabels = new HashSet<>();
private Set<String> matchEndLabels = new HashSet<>();
@@ -91,6 +91,7 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
this.matchTraversals = (List) Stream.of(matchTraversals).map(Traversal::asAdmin).collect(Collectors.toList());
this.matchTraversals.forEach(this::configureStartAndEndSteps); // recursively convert to MatchStep, MatchStartStep, or MatchEndStep
this.matchTraversals.forEach(this::integrateChild);
+ this.standardAlgorithmBarrier = this.traverserSetSupplier.get();
this.computedStartLabel = Helper.computeStartLabel(this.matchTraversals);
}
@@ -246,7 +247,7 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
clone.matchTraversals.add(traversal.clone());
}
if (this.dedups != null) clone.dedups = new HashSet<>();
- clone.standardAlgorithmBarrier = new TraverserSet();
+ clone.standardAlgorithmBarrier = this.traverserSetSupplier.get();
return clone;
}
@@ -353,7 +354,7 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
return this.referencedLabelsMap;
}
- private TraverserSet standardAlgorithmBarrier = new TraverserSet();
+ private TraverserSet standardAlgorithmBarrier;
@Override
protected Iterator<Traverser.Admin<Map<String, E>>> standardAlgorithm() throws NoSuchElementException {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/NoOpBarrierStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/NoOpBarrierStep.java
index bedf078..14421c9 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/NoOpBarrierStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/NoOpBarrierStep.java
@@ -38,7 +38,7 @@ import java.util.Set;
public final class NoOpBarrierStep<S> extends AbstractStep<S, S> implements LocalBarrier<S> {
private int maxBarrierSize;
- private TraverserSet<S> barrier = new TraverserSet<>();
+ private TraverserSet<S> barrier;
public NoOpBarrierStep(final Traversal.Admin traversal) {
this(traversal, Integer.MAX_VALUE);
@@ -47,6 +47,7 @@ public final class NoOpBarrierStep<S> extends AbstractStep<S, S> implements Loca
public NoOpBarrierStep(final Traversal.Admin traversal, final int maxBarrierSize) {
super(traversal);
this.maxBarrierSize = maxBarrierSize;
+ this.barrier = this.traverserSetSupplier.get();
}
@Override
@@ -83,7 +84,7 @@ public final class NoOpBarrierStep<S> extends AbstractStep<S, S> implements Loca
throw FastNoSuchElementException.instance();
else {
final TraverserSet<S> temp = this.barrier;
- this.barrier = new TraverserSet<>();
+ this.barrier = this.traverserSetSupplier.get();
return temp;
}
}
@@ -96,7 +97,7 @@ public final class NoOpBarrierStep<S> extends AbstractStep<S, S> implements Loca
@Override
public NoOpBarrierStep<S> clone() {
final NoOpBarrierStep<S> clone = (NoOpBarrierStep<S>) super.clone();
- clone.barrier = new TraverserSet<>();
+ clone.barrier = this.traverserSetSupplier.get();
return clone;
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateStep.java
index 8d6d960..c7b7a40 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateStep.java
@@ -48,11 +48,12 @@ public final class AggregateStep<S> extends AbstractStep<S, S> implements SideEf
private Traversal.Admin<S, Object> aggregateTraversal = null;
private String sideEffectKey;
- private TraverserSet<S> barrier = new TraverserSet<>();
+ private TraverserSet<S> barrier;
public AggregateStep(final Traversal.Admin traversal, final String sideEffectKey) {
super(traversal);
this.sideEffectKey = sideEffectKey;
+ this.barrier = this.traverserSetSupplier.get();
this.getTraversal().getSideEffects().registerIfAbsent(this.sideEffectKey, (Supplier) BulkSetSupplier.instance(), Operator.addAll);
}
@@ -84,7 +85,7 @@ public final class AggregateStep<S> extends AbstractStep<S, S> implements SideEf
@Override
public AggregateStep<S> clone() {
final AggregateStep<S> clone = (AggregateStep<S>) super.clone();
- clone.barrier = new TraverserSet<>();
+ clone.barrier = this.traverserSetSupplier.get();
if (null != this.aggregateTraversal)
clone.aggregateTraversal = this.aggregateTraversal.clone();
return clone;
@@ -143,7 +144,7 @@ public final class AggregateStep<S> extends AbstractStep<S, S> implements SideEf
throw FastNoSuchElementException.instance();
else {
final TraverserSet<S> temp = this.barrier;
- this.barrier = new TraverserSet<>();
+ this.barrier = this.traverserSetSupplier.get();
return temp;
}
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
index e2757e2..28d0b88 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
@@ -21,9 +21,11 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.util;
import org.apache.tinkerpop.gremlin.process.traversal.Step;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
import org.apache.tinkerpop.gremlin.process.traversal.util.EmptyTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.util.function.TraverserSetSupplier;
import java.util.Collections;
import java.util.Iterator;
@@ -43,13 +45,21 @@ public abstract class AbstractStep<S, E> implements Step<S, E> {
protected ExpandableStepIterator<S> starts;
protected Traverser.Admin<E> nextEnd = null;
protected boolean traverserStepIdAndLabelsSetByChild = false;
+ protected TraverserSetSupplier<S> traverserSetSupplier;
protected Step<?, S> previousStep = EmptyStep.instance();
protected Step<E, ?> nextStep = EmptyStep.instance();
public AbstractStep(final Traversal.Admin traversal) {
this.traversal = traversal;
- this.starts = new ExpandableStepIterator<>(this);
+ this.traverserSetSupplier = TraverserSetSupplier.instance();
+ this.starts = new ExpandableStepIterator<>(this, this.traverserSetSupplier.get());
+ }
+
+ public AbstractStep(final Traversal.Admin traversal, final TraverserSetSupplier<S> traverserSetSupplier) {
+ this.traversal = traversal;
+ this.traverserSetSupplier = traverserSetSupplier;
+ this.starts = new ExpandableStepIterator<>(this, this.traverserSetSupplier.get());
}
@Override
@@ -201,6 +211,21 @@ public abstract class AbstractStep<S, E> implements Step<S, E> {
return result;
}
+ public ExpandableStepIterator<S> getStarts() {
+ return this.starts;
+ }
+
+ /**
+ * Sets a new traverserSupplier so that providers can use their own implementation of TraverserSet instead of the default {@link TraverserSet}.
+ * Note that {@link AbstractStep#starts} also holds TraverserSet but this method doesn't automatically replace the traverserSet for it.
+ * Providers may use {@link ExpandableStepIterator#setTraverserSet(TraverserSet)} independently to replace its TraverserSet.
+ *
+ * @param traverserSetSupplier a new traverserSetSupplier used to spawn a new TraverserSet when necessary in the step.
+ */
+ public void setTraverserSetSupplier(final TraverserSetSupplier<S> traverserSetSupplier) {
+ this.traverserSetSupplier = traverserSetSupplier;
+ }
+
private final Traverser.Admin<E> prepareTraversalForNextStep(final Traverser.Admin<E> traverser) {
if (!this.traverserStepIdAndLabelsSetByChild) {
traverser.setStepId(this.nextStep.getId());
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java
index 8409c9f..ebc3975 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/CollectingBarrierStep.java
@@ -41,7 +41,7 @@ import java.util.function.BinaryOperator;
*/
public abstract class CollectingBarrierStep<S> extends AbstractStep<S, S> implements Barrier<TraverserSet<S>> {
- protected TraverserSet<S> traverserSet = new TraverserSet<>();
+ protected TraverserSet<S> traverserSet;
private int maxBarrierSize;
private boolean barrierConsumed = false;
@@ -51,6 +51,7 @@ public abstract class CollectingBarrierStep<S> extends AbstractStep<S, S> implem
public CollectingBarrierStep(final Traversal.Admin traversal, final int maxBarrierSize) {
super(traversal);
+ this.traverserSet = this.traverserSetSupplier.get();
this.maxBarrierSize = maxBarrierSize;
}
@@ -86,7 +87,7 @@ public abstract class CollectingBarrierStep<S> extends AbstractStep<S, S> implem
if (this.traverserSet.isEmpty())
throw FastNoSuchElementException.instance();
else {
- final TraverserSet<S> temp = new TraverserSet<>();
+ final TraverserSet<S> temp = this.traverserSetSupplier.get();
IteratorUtils.removeOnNext(this.traverserSet.iterator()).forEachRemaining(t -> {
DetachedFactory.detach(t, true); // this should be dynamic
temp.add(t);
@@ -119,7 +120,7 @@ public abstract class CollectingBarrierStep<S> extends AbstractStep<S, S> implem
@Override
public CollectingBarrierStep<S> clone() {
final CollectingBarrierStep<S> clone = (CollectingBarrierStep<S>) super.clone();
- clone.traverserSet = new TraverserSet<>();
+ clone.traverserSet = this.traverserSetSupplier.get();
clone.barrierConsumed = false;
return clone;
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ExpandableStepIterator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ExpandableStepIterator.java
index 30558e8..d84e430 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ExpandableStepIterator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ExpandableStepIterator.java
@@ -30,11 +30,17 @@ import java.util.Iterator;
*/
public final class ExpandableStepIterator<S> implements Iterator<Traverser.Admin<S>>, Serializable {
- private final TraverserSet<S> traverserSet = new TraverserSet<>();
+ private TraverserSet<S> traverserSet;
private final Step<S, ?> hostStep;
public ExpandableStepIterator(final Step<S, ?> hostStep) {
this.hostStep = hostStep;
+ this.traverserSet = new TraverserSet<>();
+ }
+
+ public ExpandableStepIterator(final Step<S, ?> hostStep, final TraverserSet<S> traverserSet) {
+ this.hostStep = hostStep;
+ this.traverserSet = traverserSet;
}
@Override
@@ -53,6 +59,16 @@ public final class ExpandableStepIterator<S> implements Iterator<Traverser.Admin
return this.traverserSet.remove();
}
+ /**
+ * Replaces the traverserSet. Useful when providers want to use their own implementation of TraverserSet instead of default {@link TraverserSet}.
+ * Note that if the existing traverserSet has elements, they are discarded.
+ *
+ * @param traverserSet a new TraverserSet used to manage a set of traversers.
+ */
+ public void setTraverserSet(final TraverserSet<S> traverserSet) {
+ this.traverserSet = traverserSet;
+ }
+
public void add(final Iterator<Traverser.Admin<S>> iterator) {
iterator.forEachRemaining(this.traverserSet::add);
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/TraverserSetSupplier.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/TraverserSetSupplier.java
new file mode 100644
index 0000000..a217d33
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/TraverserSetSupplier.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.util.function;
+
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
+
+import java.io.Serializable;
+import java.util.function.Supplier;
+
+/**
+ * @author Norio Akagi
+ */
+public final class TraverserSetSupplier<S> implements Supplier<TraverserSet<S>>, Serializable {
+
+ private static final TraverserSetSupplier INSTANCE = new TraverserSetSupplier();
+
+ private TraverserSetSupplier() {
+ }
+
+ @Override
+ public TraverserSet<S> get() {
+ return new TraverserSet<>();
+ }
+
+ public static <S> TraverserSetSupplier<S> instance() {
+ return INSTANCE;
+ }
+}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/function/TraverserSetSupplierTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/function/TraverserSetSupplierTest.java
new file mode 100644
index 0000000..d6b057b
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/function/TraverserSetSupplierTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.util.function;
+
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.sameInstance;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+
+/**
+ * @author Norio Akagi
+ */
+public class TraverserSetSupplierTest {
+ @Test
+ public void shouldSupplyTraverserSet() {
+ assertThat(TraverserSetSupplier.instance().get(), hasSize(0));
+ }
+
+ @Test
+ public void shouldSupplyTraverserSetInstance() {
+ assertThat(TraverserSetSupplier.instance().get(), hasSize(0));
+ assertThat(TraverserSetSupplier.instance().get(), instanceOf(TraverserSet.class));
+ }
+
+ @Test
+ public void shouldSupplyNewTraverserSetOnEachInvocation() {
+ final TraverserSet<Object> ts1 = TraverserSetSupplier.instance().get();
+ final TraverserSet<Object> ts2 = TraverserSetSupplier.instance().get();
+ final TraverserSet<Object> ts3 = TraverserSetSupplier.instance().get();
+
+ assertThat(ts1, not(sameInstance(ts2)));
+ assertThat(ts1, not(sameInstance(ts3)));
+ assertThat(ts2, not(sameInstance(ts3)));
+ }
+}