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 10a8b75a0bd48054d85362e0a0ca99b9264bcf51 Author: Stephen Mallette <[email protected]> AuthorDate: Sun Aug 30 05:28:14 2020 -0400 TINKERPOP-2396 Added Traversal.getTraverserSetSupplier() In this way the steps get their TraverserSetSupplier from the Traversal that spawned it which matches a bit with how Traverser objects get generated. This approach seems better than what I had suggested in JIRA where TraversalStrategy implementations might be used. --- CHANGELOG.asciidoc | 3 ++- docs/src/upgrade/release-3.4.x.asciidoc | 15 ++++++++++++- .../gremlin/process/traversal/Traversal.java | 11 ++++++++++ .../gremlin/process/traversal/TraversalSource.java | 2 +- .../traversal/step/filter/RangeGlobalStep.java | 2 +- .../traversal/step/filter/SampleGlobalStep.java | 2 +- .../traversal/step/filter/TailGlobalStep.java | 2 +- .../process/traversal/step/map/MatchStep.java | 4 ++-- .../traversal/step/map/NoOpBarrierStep.java | 6 +++--- .../traversal/step/sideEffect/AggregateStep.java | 6 +++--- .../process/traversal/step/util/AbstractStep.java | 25 +++------------------- .../traversal/step/util/CollectingBarrierStep.java | 6 +++--- .../step/util/ExpandableStepIterator.java | 13 +---------- .../process/traversal/util/DefaultTraversal.java | 4 +--- 14 files changed, 47 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index fc23846..b4b4eae 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -27,7 +27,8 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima * Removed `Connection` from `Connection Pool` when server closes a connection with no pending requests in Java Driver. * Improved initialization time of Java Driver if the default serializer is replaced. * Fixed bug in Javascript `Translator` that wasn't handling child traversals well. -* Fix an interator leak in HasContainer. +* Fixed an iterator leak in `HasContainer`. +* Added `Traversal.getTraverserSetSupplier()` to allow providers to supply their own `TraverserSet` instances. [[release-3-4-8]] === TinkerPop 3.4.8 (Release Date: August 3, 2020) diff --git a/docs/src/upgrade/release-3.4.x.asciidoc b/docs/src/upgrade/release-3.4.x.asciidoc index 658659c..4e13782 100644 --- a/docs/src/upgrade/release-3.4.x.asciidoc +++ b/docs/src/upgrade/release-3.4.x.asciidoc @@ -21,14 +21,27 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima *Avant-Gremlin Construction #3 for Theremin and Flowers* -== TinkerPop 3.4.8 +== TinkerPop 3.4.9 *Release Date: NOT OFFICIALLY RELEASED YET* Please see the link:https://github.com/apache/tinkerpop/blob/3.4.9/CHANGELOG.asciidoc#release-3-4-9[changelog] for a complete list of all the modifications that are part of this release. +=== Upgrading for Providers + +==== Graph System Providers + +===== Custom TraverserSet + +It is now possible to provide a custom `TraverserSet` to `Step` implementations that make use of those objects to +introduce new logic for how they are populated and managed. Providers can take advantage of this capability by +constructing their own `Traversal` implementation and overriding the `getTraverserSetSupplier()` method. When new +`TraverserSet` instances are needed during traversal execution, steps will consult this method to get those instances. +link:https://issues.apache.org/jira/browse/TINKERPOP-2396[TINKERPOP-2396] + +== TinkerPop 3.4.8 *Release Date: August 3, 2020* diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traversal.java index 3b02254..11c12c3 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traversal.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traversal.java @@ -30,6 +30,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffect 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.traverser.TraverserRequirement; +import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet; import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalExplanation; import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper; import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics; @@ -49,9 +50,11 @@ import java.util.Spliterators; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.Supplier; import java.util.stream.Stream; import java.util.stream.StreamSupport; import org.apache.tinkerpop.gremlin.structure.util.CloseableIterator; +import org.apache.tinkerpop.gremlin.util.function.TraverserSetSupplier; /** * A {@link Traversal} represents a directed walk over a {@link Graph}. @@ -429,6 +432,14 @@ public interface Traversal<S, E> extends Iterator<E>, Serializable, Cloneable, A public TraverserGenerator getTraverserGenerator(); /** + * Gets a generator that creates new {@link TraverserSet} instances for steps in the traversal. Providers may + * override this default implementation to provider their own {@link TraverserSet}. + */ + public default Supplier<TraverserSet<S>> getTraverserSetSupplier() { + return TraverserSetSupplier.instance(); + } + + /** * Get the set of all {@link TraverserRequirement}s for this traversal. * * @return the features of a traverser that are required to execute properly in this traversal diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java index 91ef554..04fdf01 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java @@ -375,7 +375,7 @@ public interface TraversalSource extends Cloneable, AutoCloseable { /** * Configures the {@code TraversalSource} as a "remote" to issue the {@link Traversal} for execution elsewhere. - * Expects key for {@link #GREMLIN_REMOTE_CONNECTION_CLASS} as well as any configuration required by + * Expects key for {@link RemoteConnection#GREMLIN_REMOTE_CONNECTION_CLASS} as well as any configuration required by * the underlying {@link RemoteConnection} which will be instantiated. Note that the {@code Configuration} object * is passed down without change to the creation of the {@link RemoteConnection} instance. * 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 1343aab..37441eb 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 = this.traverserSetSupplier.get(); + final TraverserSet<S> barrier = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().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 a4d3458..e4ca430 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 = this.traverserSetSupplier.get(); + final TraverserSet<S> sampledSet = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().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 b8b8037..cc746c8 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 = this.traverserSetSupplier.get(); + final TraverserSet<S> barrier = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().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 f43ae4b..6de3970 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 @@ -91,7 +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.standardAlgorithmBarrier = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().get(); this.computedStartLabel = Helper.computeStartLabel(this.matchTraversals); } @@ -247,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 = this.traverserSetSupplier.get(); + clone.standardAlgorithmBarrier = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().get(); return clone; } 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 14421c9..d0a7d29 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 @@ -47,7 +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(); + this.barrier = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().get(); } @Override @@ -84,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 = this.traverserSetSupplier.get(); + this.barrier = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().get(); return temp; } } @@ -97,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 = this.traverserSetSupplier.get(); + clone.barrier = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().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 c7b7a40..9c2ea48 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 @@ -53,7 +53,7 @@ public final class AggregateStep<S> extends AbstractStep<S, S> implements SideEf public AggregateStep(final Traversal.Admin traversal, final String sideEffectKey) { super(traversal); this.sideEffectKey = sideEffectKey; - this.barrier = this.traverserSetSupplier.get(); + this.barrier = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().get(); this.getTraversal().getSideEffects().registerIfAbsent(this.sideEffectKey, (Supplier) BulkSetSupplier.instance(), Operator.addAll); } @@ -85,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 = this.traverserSetSupplier.get(); + clone.barrier = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().get(); if (null != this.aggregateTraversal) clone.aggregateTraversal = this.aggregateTraversal.clone(); return clone; @@ -144,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 = this.traverserSetSupplier.get(); + this.barrier = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().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 28d0b88..32d77e8 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 @@ -45,21 +45,13 @@ 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.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()); + this.starts = new ExpandableStepIterator<>(this, (TraverserSet<S>) traversal.getTraverserSetSupplier().get()); } @Override @@ -184,7 +176,7 @@ public abstract class AbstractStep<S, E> implements Step<S, E> { public AbstractStep<S, E> clone() { try { final AbstractStep<S, E> clone = (AbstractStep<S, E>) super.clone(); - clone.starts = new ExpandableStepIterator<>(clone); + clone.starts = new ExpandableStepIterator<>(clone, (TraverserSet<S>) traversal.getTraverserSetSupplier().get()); clone.previousStep = EmptyStep.instance(); clone.nextStep = EmptyStep.instance(); clone.nextEnd = null; @@ -215,18 +207,7 @@ public abstract class AbstractStep<S, E> implements Step<S, E> { 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) { + private Traverser.Admin<E> prepareTraversalForNextStep(final Traverser.Admin<E> traverser) { if (!this.traverserStepIdAndLabelsSetByChild) { traverser.setStepId(this.nextStep.getId()); traverser.addLabels(this.labels); 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 ebc3975..a2418e8 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 @@ -51,7 +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.traverserSet = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().get(); this.maxBarrierSize = maxBarrierSize; } @@ -87,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 = this.traverserSetSupplier.get(); + final TraverserSet<S> temp = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().get(); IteratorUtils.removeOnNext(this.traverserSet.iterator()).forEachRemaining(t -> { DetachedFactory.detach(t, true); // this should be dynamic temp.add(t); @@ -120,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 = this.traverserSetSupplier.get(); + clone.traverserSet = (TraverserSet<S>) this.traversal.getTraverserSetSupplier().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 d84e430..8978d38 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 @@ -34,8 +34,7 @@ public final class ExpandableStepIterator<S> implements Iterator<Traverser.Admin private final Step<S, ?> hostStep; public ExpandableStepIterator(final Step<S, ?> hostStep) { - this.hostStep = hostStep; - this.traverserSet = new TraverserSet<>(); + this(hostStep, new TraverserSet<>()); } public ExpandableStepIterator(final Step<S, ?> hostStep, final TraverserSet<S> traverserSet) { @@ -59,16 +58,6 @@ 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/process/traversal/util/DefaultTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversal.java index b7bf94d..87c585a 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversal.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversal.java @@ -64,8 +64,7 @@ public class DefaultTraversal<S, E> implements Traversal.Admin<S, E> { protected transient TraverserGenerator generator; protected Set<TraverserRequirement> requirements; protected boolean locked = false; - protected Bytecode bytecode; // TODO: perhaps make transient until 3.3.0? - + protected Bytecode bytecode; private DefaultTraversal(final Graph graph, final TraversalStrategies traversalStrategies, final Bytecode bytecode) { this.graph = graph; @@ -152,7 +151,6 @@ public class DefaultTraversal<S, E> implements Traversal.Admin<S, E> { @Override public Set<TraverserRequirement> getTraverserRequirements() { if (null == this.requirements) { - // if (!this.locked) this.applyStrategies(); this.requirements = EnumSet.noneOf(TraverserRequirement.class); for (final Step<?, ?> step : this.getSteps()) { this.requirements.addAll(step.getRequirements());
