/** * Determine if the traversal has a step of an assignable class in the current {@link Traversal} and its * local and global child traversals. * * @param stepClass the step class to look for * @param traversal the traversal in which to look for the given step class * @return <code>true</code> if any step in the given traversal (and its child traversals) is an instance of the * given <code>stepClass</code>, otherwise <code>false</code>. */ public static boolean hasStepOfAssignableClassRecursively(final Class stepClass, final Traversal.Admin<?, ?> traversal) { return hasStepOfAssignableClassRecursively(null, stepClass, traversal); }
/** * Determine if the traversal has any of the supplied steps of an assignable class in the current {@link Traversal} * and its global or local child traversals. * * @param stepClasses the step classes to look for * @param traversal the traversal in which to look for the given step classes * @return <code>true</code> if any step in the given traversal (and its child traversals) is an instance of a class * provided in <code>stepClasses</code>, otherwise <code>false</code>. */ public static boolean hasStepOfAssignableClassRecursively(final Collection<Class> stepClasses, final Traversal.Admin<?, ?> traversal) { return hasStepOfAssignableClassRecursively(null, stepClasses, traversal); }
return hasStepOfAssignableClassRecursively(stepClasses.iterator().next(), traversal); for (final Step<?, ?> step : traversal.getSteps()) { if (IteratorUtils.anyMatch(stepClasses.iterator(), stepClass -> stepClass.isAssignableFrom(step.getClass()))) { if (null == scope || Scope.local.equals(scope)) { for (final Traversal.Admin<?, ?> localChild : ((TraversalParent) step).getLocalChildren()) { if (hasStepOfAssignableClassRecursively(stepClasses, localChild)) return true; if (hasStepOfAssignableClassRecursively(stepClasses, globalChild)) return true;
/** * Determine if the traversal has a step of an assignable class in the current {@link Traversal} and its * {@link Scope} child traversals. * * @param scope the child traversal scope to check * @param stepClass the step class to look for * @param traversal the traversal in which to look for the given step class * @return <code>true</code> if any step in the given traversal (and its child traversals) is an instance of the * given <code>stepClass</code>, otherwise <code>false</code>. */ public static boolean hasStepOfAssignableClassRecursively(final Scope scope, final Class stepClass, final Traversal.Admin<?, ?> traversal) { for (final Step<?, ?> step : traversal.getSteps()) { if (stepClass.isAssignableFrom(step.getClass())) { return true; } if (step instanceof TraversalParent) { if (null == scope || Scope.local.equals(scope)) { for (final Traversal.Admin<?, ?> localChild : ((TraversalParent) step).getLocalChildren()) { if (hasStepOfAssignableClassRecursively(stepClass, localChild)) return true; } } if (null == scope || Scope.global.equals(scope)) { for (final Traversal.Admin<?, ?> globalChild : ((TraversalParent) step).getGlobalChildren()) { if (hasStepOfAssignableClassRecursively(stepClass, globalChild)) return true; } } } } return false; }
protected static Traversal.Admin<Vertex, Edge> getEdgeFilter(final Traversal.Admin<?, ?> traversal) { if (traversal.getStartStep() instanceof GraphStep && ((GraphStep) traversal.getStartStep()).returnsEdge()) return null; // if the traversal is an edge traversal, don't filter (this can be made less stringent) if (TraversalHelper.hasStepOfAssignableClassRecursively(LambdaHolder.class, traversal)) return null; // if the traversal contains lambdas, don't filter as you don't know what is being accessed by the lambdas final Map<Direction, Set<String>> directionLabels = new EnumMap<>(Direction.class);
@Override public void apply(final Traversal.Admin<?, ?> traversal) { if ((traversal.getParent() instanceof EmptyStep || traversal.getParent() instanceof VertexProgramStep) && TraversalHelper.hasStepOfAssignableClassRecursively(ProfileSideEffectStep.class, traversal)) TraversalHelper.applyTraversalRecursively(t -> t.getEndStep().addLabel(MARKER), traversal); if (traversal.getEndStep().getLabels().contains(MARKER)) { traversal.getEndStep().removeLabel(MARKER); // Add .profile() step after every pre-existing step. final List<Step> steps = traversal.getSteps(); final int numSteps = steps.size(); for (int i = 0; i < numSteps; i++) { // Do not inject profiling after ProfileSideEffectStep as this will be the last step on the root traversal. if (steps.get(i * 2) instanceof ProfileSideEffectStep) break; // Create and inject ProfileStep traversal.addStep((i * 2) + 1, new ProfileStep(traversal)); } } }
@Override public void apply(final Traversal.Admin<?, ?> traversal) { // using a hidden label marker to denote whether the traversal should not be processed by this strategy if ((traversal.getParent() instanceof EmptyStep || traversal.getParent() instanceof VertexProgramStep) && TraversalHelper.hasStepOfAssignableClassRecursively(INVALIDATING_STEP_CLASSES, traversal)) TraversalHelper.applyTraversalRecursively(t -> t.getStartStep().addLabel(MARKER), traversal); if (traversal.getStartStep().getLabels().contains(MARKER)) { traversal.getStartStep().removeLabel(MARKER); return; } //////////////////////////////////////////////////////////////////////////// final Collection<Pair<VertexStep, Step>> stepsToReplace = new ArrayList<>(); Step prev = null; for (final Step curr : traversal.getSteps()) { if (curr instanceof TraversalParent) { ((TraversalParent) curr).getLocalChildren().forEach(this::apply); ((TraversalParent) curr).getGlobalChildren().forEach(this::apply); } if (isOptimizable(prev, curr)) { stepsToReplace.add(Pair.with((VertexStep) prev, curr)); } prev = curr; } if (!stepsToReplace.isEmpty()) { for (final Pair<VertexStep, Step> pair : stepsToReplace) { optimizeSteps(traversal, pair.getValue0(), pair.getValue1()); } } }
if (null == repeatStep.getEmitTraversal() && null != repeatStep.getRepeatTraversal() && repeatStep.getUntilTraversal() instanceof LoopTraversal && ((LoopTraversal) repeatStep.getUntilTraversal()).getMaxLoops() > 0 && !TraversalHelper.hasStepOfAssignableClassRecursively(Scope.global, DedupGlobalStep.class, repeatStep.getRepeatTraversal()) && !TraversalHelper.hasStepOfAssignableClassRecursively(INVALIDATING_STEPS, repeatStep.getRepeatTraversal())) { final Traversal.Admin<?, ?> repeatTraversal = repeatStep.getGlobalChildren().get(0); repeatTraversal.removeStep(repeatTraversal.getSteps().size() - 1); // removes the RepeatEndStep
@Override public void apply(final Traversal.Admin<?, ?> traversal) { if (!TraversalHelper.onGraphComputer(traversal)) return; if (traversal.getParent() instanceof TraversalVertexProgramStep) { if (TraversalHelper.getStepsOfAssignableClassRecursively(GraphStep.class, traversal).size() > 1) throw new VerificationException("Mid-traversal V()/E() is currently not supported on GraphComputer", traversal); if (TraversalHelper.hasStepOfAssignableClassRecursively(ProfileStep.class, traversal) && TraversalHelper.getStepsOfAssignableClass(VertexProgramStep.class, TraversalHelper.getRootTraversal(traversal)).size() > 1) throw new VerificationException("Profiling a multi-VertexProgramStep traversal is currently not supported on GraphComputer", traversal); } // this is a problem because sideEffect.merge() is transient on the OLAP reduction if (TraversalHelper.getRootTraversal(traversal).getTraverserRequirements().contains(TraverserRequirement.ONE_BULK)) throw new VerificationException("One bulk is currently not supported on GraphComputer: " + traversal, traversal); // you can not traverse past the local star graph with localChildren (e.g. by()-modulators). if (!TraversalHelper.isGlobalChild(traversal) && !TraversalHelper.isLocalStarGraph(traversal)) throw new VerificationException("Local traversals may not traverse past the local star-graph on GraphComputer: " + traversal, traversal); for (final Step<?, ?> step : traversal.getSteps()) { if (step instanceof PathProcessor && ((PathProcessor) step).getMaxRequirement() != PathProcessor.ElementRequirement.ID) throw new VerificationException("It is not possible to access more than a path element's id on GraphComputer: " + step + " requires " + ((PathProcessor) step).getMaxRequirement(), traversal); if (UNSUPPORTED_STEPS.stream().filter(c -> c.isAssignableFrom(step.getClass())).findFirst().isPresent()) throw new VerificationException("The following step is currently not supported on GraphComputer: " + step, traversal); } Step<?, ?> nextParentStep = traversal.getParent().asStep(); while (!(nextParentStep instanceof EmptyStep)) { if (nextParentStep instanceof PathProcessor && ((PathProcessor) nextParentStep).getMaxRequirement() != PathProcessor.ElementRequirement.ID) throw new VerificationException("The following path processor step requires more than the element id on GraphComputer: " + nextParentStep + " requires " + ((PathProcessor) nextParentStep).getMaxRequirement(), traversal); nextParentStep = nextParentStep.getNextStep(); } }
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 if (computerTraversal.getSteps().size() > 1 && !(computerTraversal.getStartStep().getNextStep() instanceof Barrier) && TraversalHelper.hasStepOfAssignableClassRecursively(Arrays.asList(VertexStep.class, EdgeVertexStep.class), computerTraversal) && TraversalHelper.isLocalStarGraph(computerTraversal)) { final Step barrier = (Step) TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, computerTraversal).orElse(null);
/** * Determine if the traversal has a step of an assignable class in the current {@link Traversal} and its * local and global child traversals. * * @param stepClass the step class to look for * @param traversal the traversal in which to look for the given step class * @return <code>true</code> if any step in the given traversal (and its child traversals) is an instance of the * given <code>stepClass</code>, otherwise <code>false</code>. */ public static boolean hasStepOfAssignableClassRecursively(final Class stepClass, final Traversal.Admin<?, ?> traversal) { return hasStepOfAssignableClassRecursively(null, stepClass, traversal); }
/** * Determine if the traversal has any of the supplied steps of an assignable class in the current {@link Traversal} * and its global or local child traversals. * * @param stepClasses the step classes to look for * @param traversal the traversal in which to look for the given step classes * @return <code>true</code> if any step in the given traversal (and its child traversals) is an instance of a class * provided in <code>stepClasses</code>, otherwise <code>false</code>. */ public static boolean hasStepOfAssignableClassRecursively(final Collection<Class> stepClasses, final Traversal.Admin<?, ?> traversal) { return hasStepOfAssignableClassRecursively(null, stepClasses, traversal); }
@Override public void apply(final Traversal.Admin<?, ?> traversal) { final Graph graph = traversal.getGraph().orElse(EmptyGraph.instance()); // best guess at what the graph will be as its dynamically determined for (final TraversalVertexProgramStep step : TraversalHelper.getStepsOfClass(TraversalVertexProgramStep.class, traversal)) { final Traversal.Admin<?, ?> computerTraversal = step.generateProgram(graph, EmptyMemory.instance()).getTraversal().get().clone(); if (!computerTraversal.isLocked()) computerTraversal.applyStrategies(); /// boolean doesMessagePass = TraversalHelper.hasStepOfAssignableClassRecursively(Scope.global, MULTI_ITERATION_CLASSES, computerTraversal); if (!doesMessagePass) { for (final VertexStep vertexStep : TraversalHelper.getStepsOfAssignableClassRecursively(Scope.global, VertexStep.class, computerTraversal)) { if (vertexStep.returnsVertex() || !vertexStep.getDirection().equals(Direction.OUT)) { // in-edges require message pass in OLAP doesMessagePass = true; break; } } } if (!doesMessagePass && !MessagePassingReductionStrategy.endsWithElement(computerTraversal.getEndStep()) && !(computerTraversal.getTraverserRequirements().contains(TraverserRequirement.LABELED_PATH) || // TODO: remove this when dynamic detachment is available in 3.3.0 computerTraversal.getTraverserRequirements().contains(TraverserRequirement.PATH))) { // TODO: remove this when dynamic detachment is available in 3.3.0 step.setComputer(step.getComputer() // if no message passing, don't partition the loaded graph .configure(Constants.GREMLIN_SPARK_SKIP_PARTITIONER, true) // if no message passing, don't cache the loaded graph .configure(Constants.GREMLIN_SPARK_SKIP_GRAPH_CACHE, true)); } } }
if (!TraversalHelper.onGraphComputer(traversal) || !TraversalHelper.isGlobalChild(traversal) || TraversalHelper.hasStepOfAssignableClassRecursively(INVALIDATING_STEP_CLASSES, TraversalHelper.getRootTraversal(traversal))) // TODO: use the MARKER model when that PR is merged return;
checkResults(Arrays.asList("purcellville", "baltimore", "oakland", "seattle", "aachen"), sg.V().values("location")); if (sg.getStrategies().getStrategy(InlineFilterStrategy.class).isPresent()) assertFalse(TraversalHelper.hasStepOfAssignableClassRecursively(TraversalFilterStep.class, sg.V().properties("location").value().iterate().asAdmin())); checkResults(Arrays.asList("purcellville", "baltimore", "oakland", "seattle", "aachen"), sg.V().as("a").values("location").as("b").select("a").outE().properties().select("b").dedup()); if (sg.getStrategies().getStrategy(InlineFilterStrategy.class).isPresent()) assertFalse(TraversalHelper.hasStepOfAssignableClassRecursively(TraversalFilterStep.class, sg.V().as("a").values("location").as("b").select("a").outE().properties().select("b").dedup().iterate().asAdmin()));
/** * Determine if the traversal has a step of an assignable class in the current {@link Traversal} and its * {@link Scope} child traversals. * * @param scope the child traversal scope to check * @param stepClass the step class to look for * @param traversal the traversal in which to look for the given step class * @return <code>true</code> if any step in the given traversal (and its child traversals) is an instance of the * given <code>stepClass</code>, otherwise <code>false</code>. */ public static boolean hasStepOfAssignableClassRecursively(final Scope scope, final Class stepClass, final Traversal.Admin<?, ?> traversal) { for (final Step<?, ?> step : traversal.getSteps()) { if (stepClass.isAssignableFrom(step.getClass())) { return true; } if (step instanceof TraversalParent) { if (null == scope || Scope.local.equals(scope)) { for (final Traversal.Admin<?, ?> localChild : ((TraversalParent) step).getLocalChildren()) { if (hasStepOfAssignableClassRecursively(stepClass, localChild)) return true; } } if (null == scope || Scope.global.equals(scope)) { for (final Traversal.Admin<?, ?> globalChild : ((TraversalParent) step).getGlobalChildren()) { if (hasStepOfAssignableClassRecursively(stepClass, globalChild)) return true; } } } } return false; }
@Override public void apply(final Traversal.Admin<?, ?> traversal) { if ((traversal.getParent() instanceof EmptyStep || traversal.getParent() instanceof VertexProgramStep) && TraversalHelper.hasStepOfAssignableClassRecursively(ProfileSideEffectStep.class, traversal)) TraversalHelper.applyTraversalRecursively(t -> t.getEndStep().addLabel(MARKER), traversal); if (traversal.getEndStep().getLabels().contains(MARKER)) { traversal.getEndStep().removeLabel(MARKER); // Add .profile() step after every pre-existing step. final List<Step> steps = traversal.getSteps(); final int numSteps = steps.size(); for (int i = 0; i < numSteps; i++) { // Do not inject profiling after ProfileSideEffectStep as this will be the last step on the root traversal. if (steps.get(i * 2) instanceof ProfileSideEffectStep) break; // Create and inject ProfileStep traversal.addStep((i * 2) + 1, new ProfileStep(traversal)); } } }
@Override public void apply(final Traversal.Admin<?, ?> traversal) { // using a hidden label marker to denote whether the traversal should not be processed by this strategy if ((traversal.getParent() instanceof EmptyStep || traversal.getParent() instanceof VertexProgramStep) && TraversalHelper.hasStepOfAssignableClassRecursively(INVALIDATING_STEP_CLASSES, traversal)) TraversalHelper.applyTraversalRecursively(t -> t.getStartStep().addLabel(MARKER), traversal); if (traversal.getStartStep().getLabels().contains(MARKER)) { traversal.getStartStep().removeLabel(MARKER); return; } //////////////////////////////////////////////////////////////////////////// final Collection<Pair<VertexStep, Step>> stepsToReplace = new ArrayList<>(); Step prev = null; for (final Step curr : traversal.getSteps()) { if (curr instanceof TraversalParent) { ((TraversalParent) curr).getLocalChildren().forEach(this::apply); ((TraversalParent) curr).getGlobalChildren().forEach(this::apply); } if (isOptimizable(prev, curr)) { stepsToReplace.add(Pair.with((VertexStep) prev, curr)); } prev = curr; } if (!stepsToReplace.isEmpty()) { for (final Pair<VertexStep, Step> pair : stepsToReplace) { optimizeSteps(traversal, pair.getValue0(), pair.getValue1()); } } }
@Override public void apply(final Traversal.Admin<?, ?> traversal) { if (!TraversalHelper.onGraphComputer(traversal)) return; if (traversal.getParent() instanceof TraversalVertexProgramStep) { if (TraversalHelper.getStepsOfAssignableClassRecursively(GraphStep.class, traversal).size() > 1) throw new VerificationException("Mid-traversal V()/E() is currently not supported on GraphComputer", traversal); if (TraversalHelper.hasStepOfAssignableClassRecursively(ProfileStep.class, traversal) && TraversalHelper.getStepsOfAssignableClass(VertexProgramStep.class, TraversalHelper.getRootTraversal(traversal)).size() > 1) throw new VerificationException("Profiling a multi-VertexProgramStep traversal is currently not supported on GraphComputer", traversal); } // this is a problem because sideEffect.merge() is transient on the OLAP reduction if (TraversalHelper.getRootTraversal(traversal).getTraverserRequirements().contains(TraverserRequirement.ONE_BULK)) throw new VerificationException("One bulk is currently not supported on GraphComputer: " + traversal, traversal); // you can not traverse past the local star graph with localChildren (e.g. by()-modulators). if (!TraversalHelper.isGlobalChild(traversal) && !TraversalHelper.isLocalStarGraph(traversal)) throw new VerificationException("Local traversals may not traverse past the local star-graph on GraphComputer: " + traversal, traversal); for (final Step<?, ?> step : traversal.getSteps()) { if (step instanceof PathProcessor && ((PathProcessor) step).getMaxRequirement() != PathProcessor.ElementRequirement.ID) throw new VerificationException("It is not possible to access more than a path element's id on GraphComputer: " + step + " requires " + ((PathProcessor) step).getMaxRequirement(), traversal); if (UNSUPPORTED_STEPS.stream().filter(c -> c.isAssignableFrom(step.getClass())).findFirst().isPresent()) throw new VerificationException("The following step is currently not supported on GraphComputer: " + step, traversal); } Step<?, ?> nextParentStep = traversal.getParent().asStep(); while (!(nextParentStep instanceof EmptyStep)) { if (nextParentStep instanceof PathProcessor && ((PathProcessor) nextParentStep).getMaxRequirement() != PathProcessor.ElementRequirement.ID) throw new VerificationException("The following path processor step requires more than the element id on GraphComputer: " + nextParentStep + " requires " + ((PathProcessor) nextParentStep).getMaxRequirement(), traversal); nextParentStep = nextParentStep.getNextStep(); } }
@Override public void apply(final Traversal.Admin<?, ?> traversal) { final Graph graph = traversal.getGraph().orElse(EmptyGraph.instance()); // best guess at what the graph will be as its dynamically determined for (final TraversalVertexProgramStep step : TraversalHelper.getStepsOfClass(TraversalVertexProgramStep.class, traversal)) { final Traversal.Admin<?, ?> computerTraversal = step.generateProgram(graph, EmptyMemory.instance()).getTraversal().get().clone(); if (!computerTraversal.isLocked()) computerTraversal.applyStrategies(); /// boolean doesMessagePass = TraversalHelper.hasStepOfAssignableClassRecursively(Scope.global, MULTI_ITERATION_CLASSES, computerTraversal); if (!doesMessagePass) { for (final VertexStep vertexStep : TraversalHelper.getStepsOfAssignableClassRecursively(Scope.global, VertexStep.class, computerTraversal)) { if (vertexStep.returnsVertex() || !vertexStep.getDirection().equals(Direction.OUT)) { // in-edges require message pass in OLAP doesMessagePass = true; break; } } } if (!doesMessagePass && !MessagePassingReductionStrategy.endsWithElement(computerTraversal.getEndStep()) && !(computerTraversal.getTraverserRequirements().contains(TraverserRequirement.LABELED_PATH) || // TODO: remove this when dynamic detachment is available in 3.3.0 computerTraversal.getTraverserRequirements().contains(TraverserRequirement.PATH))) { // TODO: remove this when dynamic detachment is available in 3.3.0 step.setComputer(step.getComputer() // if no message passing, don't partition the loaded graph .configure(Constants.GREMLIN_SPARK_SKIP_PARTITIONER, true) // if no message passing, don't cache the loaded graph .configure(Constants.GREMLIN_SPARK_SKIP_GRAPH_CACHE, true)); } } }