/** * Checks if the given {@link Channel} (inbound to {@link #stage}), is entering an {@link ExecutionStageLoop} * when serving the {@link #stage}. * * @param inboundChannel {@link Channel} that is inbound to {@link #stage} and that might be a {@link ExecutionStageLoop} input * @return whether the {@link Channel} is a {@link ExecutionStageLoop} input, i.e., it is not produced in an {@link ExecutionStageLoop} * while this {@link #stage} is part of a {@link ExecutionStageLoop} */ private boolean checkIfIsLoopInput(Channel inboundChannel) { // NB: This code assumes no nested loops. return this.stage.getLoop() != null && this.stage.getLoop() != inboundChannel.getProducer().getStage().getLoop(); }
/** * Finds the single input {@link Channel} of the given {@code channel}'s producing {@link ExecutionTask}. * * @param channel whose predecessor is requested * @return the preceeding {@link Channel} */ public static Channel getPredecessorChannel(Channel channel) { final ExecutionTask producer = channel.getProducer(); assert producer != null && producer.getNumInputChannels() == 1; return producer.getInputChannel(0); }
/** * Inspect whether {@link ExecutionTask} is the {@link LoopHeadOperator} of the {@link #loopSubplan}. If so, * promote its {@link ExecutionStage} as the loop head. * * @param task to be checked */ public void update(ExecutionTask task) { if (this.headStageCache == null && this.isLoopHead(task)) { this.headStageCache = task.getStage(); } }
/** * Creates a new, hierarchical instance. Mimes the {@code original}'s properties except for the {@link #consumers}. * * @param original the original instance whose properties will be mimed */ protected Channel(Channel original) { this.descriptor = original.getDescriptor(); this.original = original.getOriginal(); assert this.original == null || !this.original.isCopy(); this.producer = original.getProducer(); this.producerSlot = original.getProducerSlot(); }
/** * Checks whether the given {@link Channel} is inside of a {@link ExecutionStageLoop}. * * @param channel the said {@link Channel} * @return whether the {@link Channel} is in a {@link ExecutionStageLoop} */ private static boolean checkIfIsInLoopChannel(Channel channel) { final ExecutionStageLoop producerLoop = channel.getProducer().getStage().getLoop(); return producerLoop != null && channel.getConsumers().stream().anyMatch( consumer -> consumer.getStage().getLoop() == producerLoop ); }
/** * Tells whether this instance is in a {@link ExecutionStageLoop} that has finished iterating. * * @return whether this instance is in a finished {@link ExecutionStageLoop} * @see #isLoopHead() */ public boolean isInFinishedLoop() { if (this.executionStageLoop == null) { return false; } final LoopHeadOperator loopHeadOperator = (LoopHeadOperator) this.executionStageLoop.getLoopHead().getLoopHeadTask().getOperator(); return loopHeadOperator.getState() == LoopHeadOperator.State.FINISHED; }
/** * Sets an output {@link Channel} for this instance. */ public void setOutputChannel(int index, Channel channel) { assert this.getOutputChannel(index) == null : String.format("Output channel %d of %s is already set to %s.", index, this, this.getOutputChannel(index)); this.getOutputChannels()[index] = channel; channel.setProducer(this); }
/** * Merges this instance into the original instance ({@link #getOriginal()}. * <p>The consumers of the original instance are cleared and replaced with the consumers of this instance. * For all other properties, the original and this instance should agree.</p> */ public void mergeIntoOriginal() { if (!this.isCopy()) return; this.getOriginal().copyConsumersFrom(this); this.getOriginal().adoptSiblings(this); }
/** * Create a new instance and register it with the given {@link PlatformExecution}. */ ExecutionStage(PlatformExecution platformExecution, ExecutionStageLoop executionStageLoop, int sequenceNumber) { this.platformExecution = platformExecution; this.sequenceNumber = sequenceNumber; this.executionStageLoop = executionStageLoop; if (this.executionStageLoop != null) { this.executionStageLoop.add(this); } this.platformExecution.addStage(this); }
public void addTask(ExecutionTask task) { task.setStage(this); this.updateLoop(task); }
/** * Copies the siblings of the given {@code channel} into this instance. */ private void adoptSiblings(Channel channel) { for (Channel newSibling : channel.siblings) { this.addSibling(newSibling); } channel.removeSiblings(); }
@Override public FileChannel.Descriptor getDescriptor() { return (FileChannel.Descriptor) super.getDescriptor(); }
/** * Determine if this instance is the loop head of its {@link ExecutionStageLoop}. * * @return {@code true} if the above condition is fulfilled or there is no {@link ExecutionStageLoop} */ public boolean isLoopHead() { return this.executionStageLoop != null && this.executionStageLoop.getLoopHead() == this; }
/** * Detaches this instance from all its {@link #siblings}. */ public void removeSiblings() { this.removeSiblingsWhere((channel) -> true); }
/** * Creates a {@link Stream} of this instance and its siblings. The sibling relationship must not be altered * while processing the {@link Stream}. * * @return the {@link Stream} */ public Stream<Channel> withSiblings() { return this.withSiblings(false); }
/** * Tells whether the producer of the given {@link Channel} (and its producers in turn) should be considered. */ private boolean shouldVisitProducerOf(Channel channel) { // We do not follow copied Channels, because they mark the border to already executed ExecutionTasks. return !channel.isCopy(); }
/** * Notify the {@link #executionStageLoop} that there is a new {@link ExecutionTask} in this instance, which might * comprise the {@link LoopHeadOperator}. * * @param task */ private void updateLoop(ExecutionTask task) { if (this.executionStageLoop != null) { this.executionStageLoop.update(task); } }
/** * Creates a {@link String} representation (not strictly ordered) of this instance. * * @return the {@link String} representation */ public String toExtensiveString() { return this.toExtensiveString(false); }
/** * Tells whether the given {@link Channel} lends itself to a {@link org.qcri.rheem.core.platform.Breakpoint}. In * that case, we might want to split an {@link ExecutionStage} here. * * @see StageSplittingCriterion#shouldSplit(ExecutionTask, Channel, ExecutionTask) */ private static boolean isSuitableForBreakpoint(ExecutionTask producer, Channel channel, ExecutionTask consumer) { return channel.isSuitableForBreakpoint(); }
/** * Prints the instance's {@link ExecutionTask}s and {@link Channel}s. * * @return a {@link String} containing the textual representation */ public String getPlanAsString() { return this.getPlanAsString(""); }