in gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/optimization/MessagePassingReductionStrategy.java [78:135]
public void apply(final Traversal.Admin<?, ?> traversal) {
// only process the first traversal step in an OLAP chain
TraversalHelper.getFirstStepOfAssignableClass(TraversalVertexProgramStep.class, traversal).ifPresent(step -> {
final Graph graph = traversal.getGraph().orElse(EmptyGraph.instance()); // best guess at what the graph will be as its dynamically determined
final Traversal.Admin<?, ?> compiledComputerTraversal = step.generateProgram(graph, EmptyMemory.instance()).getTraversal().get().clone();
if (!compiledComputerTraversal.isLocked())
compiledComputerTraversal.applyStrategies();
if (!TraversalHelper.hasStepOfAssignableClassRecursively(Arrays.asList(LocalStep.class, LambdaHolder.class), compiledComputerTraversal) && // don't do anything with lambdas or locals as this leads to unknown adjacencies
!compiledComputerTraversal.getTraverserRequirements().contains(TraverserRequirement.PATH) && // when dynamic detachment is provided in 3.3.0, remove this (TODO)
!compiledComputerTraversal.getTraverserRequirements().contains(TraverserRequirement.LABELED_PATH) && // when dynamic detachment is provided in 3.3.0, remove this (TODO)
!(TraversalHelper.getStepsOfAssignableClass(TraversalParent.class, compiledComputerTraversal). // this is a strict precaution that could be loosed with deeper logic on barriers in global children
stream().
filter(parent -> !parent.getGlobalChildren().isEmpty()).findAny().isPresent())) {
final Traversal.Admin<?, ?> computerTraversal = step.computerTraversal.get().clone();
if (computerTraversal.getSteps().size() > 1 &&
!(computerTraversal.getStartStep().getNextStep() instanceof Barrier) &&
TraversalHelper.hasStepOfAssignableClassRecursively(Arrays.asList(VertexStep.class, EdgeVertexStep.class), computerTraversal) &&
TraversalHelper.isLocalStarGraph(computerTraversal)) {
Step barrier = (Step) TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, computerTraversal).orElse(null);
// if the barrier isn't present gotta check for uncapped profile() which can happen if you do
// profile("metrics") - see below for more worries
if (null == barrier) {
final ProfileSideEffectStep pses = TraversalHelper.getFirstStepOfAssignableClass(ProfileSideEffectStep.class, computerTraversal).orElse(null);
if (pses != null)
barrier = pses.getPreviousStep();
}
// if the barrier is a profile() then we'll mess stuff up if we wrap that in a local() as in:
// local(..., ProfileSideEffectStep)
// which won't compute right on OLAP (or anything??). By stepping back we cut things off at
// just before the ProfileSideEffectStep to go inside the local() so that ProfileSideEffectStep
// shows up just after it
//
// why does this strategy need to know so much about profile!?!
if (barrier != null && barrier.getPreviousStep() instanceof ProfileSideEffectStep)
barrier = barrier.getPreviousStep().getPreviousStep();
if (MessagePassingReductionStrategy.insertElementId(barrier)) // out().count() -> out().id().count()
TraversalHelper.insertBeforeStep(new IdStep(computerTraversal), barrier, computerTraversal);
if (!(MessagePassingReductionStrategy.endsWithElement(null == barrier ? computerTraversal.getEndStep() : barrier))) {
Traversal.Admin newChildTraversal = new DefaultGraphTraversal<>();
TraversalHelper.removeToTraversal(computerTraversal.getStartStep() instanceof GraphStep ?
computerTraversal.getStartStep().getNextStep() :
(Step) computerTraversal.getStartStep(), null == barrier ?
EmptyStep.instance() :
barrier, newChildTraversal);
newChildTraversal = newChildTraversal.getSteps().size() > 1 ? (Traversal.Admin) __.local(newChildTraversal) : newChildTraversal;
if (null == barrier)
TraversalHelper.insertTraversal(0, newChildTraversal, computerTraversal);
else
TraversalHelper.insertTraversal(barrier.getPreviousStep(), newChildTraversal, computerTraversal);
}
}
step.setComputerTraversal(computerTraversal);
}
});
}