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 <[email protected]> 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))); + } +}
