/** * Checks if the given {@code channel} is a feedforward to {@code task} (i.e., it constitutes the beginning of a data flow cycle). */ private boolean checkIfFeedforwardChannel(ExecutionTask task, Channel channel) { if (!task.getOperator().isLoopHead()) return false; final OutputSlot<?> output = task.getOutputSlotFor(channel); return output != null && output.isFeedforward(); } }
/** * Determine the producing {@link OutputSlot} of this {@link Channel} that lies within a {@link RheemPlan}. * We follow non-RheemPlan {@link ExecutionOperator}s because they should merely forward data. */ public static OutputSlot<?> findRheemPlanOutputSlotFor(Channel openChannel) { OutputSlot<?> producerOutput = null; Channel tracedChannel = openChannel; do { final ExecutionTask producer = tracedChannel.getProducer(); final ExecutionOperator producerOperator = producer.getOperator(); if (!producerOperator.isAuxiliary()) { producerOutput = producer.getOutputSlotFor(tracedChannel); } else { assert producer.getNumInputChannels() == 1; tracedChannel = producer.getInputChannel(0); } } while (producerOutput == null); return producerOutput; }
/** * Determine the {@link ExecutionStageLoop} the given {@link Channel} belongs to. * * @param channel the {@link Channel} * @return the {@link ExecutionStageLoop} or {@code null} if none */ private static ExecutionStageLoop getExecutionStageLoop(Channel channel) { final ExecutionStage producerStage = channel.getProducer().getStage(); if (producerStage.getLoop() == null) return null; final OutputSlot<?> output = channel.getProducer().getOutputSlotFor(channel); if (output != null && output.getOwner().isLoopHead() && ((LoopHeadOperator) output.getOwner()).getFinalLoopOutputs().contains(output)) { return null; } return producerStage.getLoop(); }