@Override public FileChannel.Descriptor getDescriptor() { return (FileChannel.Descriptor) super.getDescriptor(); }
/** * Declares whether this is not a read-once instance. * * @return whether this instance can have multiple consumers */ public boolean isReusable() { return this.getDescriptor().isReusable(); }
/** * Tells whether this instance lends itself for {@link Breakpoint}s. That is particularly the case if: * <ol> * <li>it is produced immediately by its producer ({@link #getProducer()};</li> * <li>the contained data are at rest;</li> * <li>and, as a bonus, the cardinality of the data can be observed.</li> * </ol> * * @return whether this instance lends itself for {@link Breakpoint}s */ public boolean isSuitableForBreakpoint() { return this.getDescriptor().isSuitableForBreakpoint(); }
/** * Find the supported {@link ChannelDescriptor}s for the given {@link InputSlot}. If the latter is a * "loop invariant" {@link InputSlot}, then require to only reusable {@link ChannelDescriptor}. * * @param input for which supported {@link ChannelDescriptor}s are requested * @return all eligible {@link ChannelDescriptor}s */ private Set<ChannelDescriptor> resolveSupportedChannels(final InputSlot<?> input) { final Channel existingChannel = this.existingDestinationChannels.get(input); if (existingChannel != null) { return Collections.singleton(existingChannel.getDescriptor()); } final ExecutionOperator owner = (ExecutionOperator) input.getOwner(); final List<ChannelDescriptor> supportedInputChannels = owner.getSupportedInputChannels(input.getIndex()); if (input.isLoopInvariant()) { // Loop input is needed in several iterations and must therefore be reusable. return supportedInputChannels.stream().filter(ChannelDescriptor::isReusable).collect(Collectors.toSet()); } else { return RheemCollections.asSet(supportedInputChannels); } }
/** * Find {@link ChannelDescriptor}s of {@link Channel}s that can be reached from the current * {@link ChannelDescriptor}. This is relevant only when there are {@link #existingChannels}. * * @param descriptor from which successor {@link ChannelDescriptor}s are requested * @return the successor {@link ChannelDescriptor}s or {@code null} if no restrictions apply */ private Set<ChannelDescriptor> getSuccessorChannelDescriptors(ChannelDescriptor descriptor) { final Channel channel = this.existingChannels.get(descriptor); if (channel == null || this.openChannelDescriptors.contains(descriptor)) return null; Set<ChannelDescriptor> result = new HashSet<>(); for (ExecutionTask consumer : channel.getConsumers()) { if (!consumer.getOperator().isAuxiliary()) continue; for (Channel successorChannel : consumer.getOutputChannels()) { result.add(successorChannel.getDescriptor()); } } return result; }
/** * 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(); }
/** * Traverse the given {@link Channel} downstream and collect any {@link Channel} that feeds some * {@link InputSlot} of a non-conversion {@link ExecutionOperator}. * * @param channel the {@link Channel} to traverse from * @see #existingChannels * @see #existingDestinationChannels */ private void collectExistingChannels(Channel channel) { this.existingChannels.put(channel.getDescriptor(), channel); for (ExecutionTask consumer : channel.getConsumers()) { final ExecutionOperator operator = consumer.getOperator(); if (!operator.isAuxiliary()) { final InputSlot<?> input = consumer.getInputSlotFor(channel); this.existingDestinationChannels.put(input, channel); int destIndex = 0; while (this.destInputs.get(destIndex) != input) destIndex++; this.existingDestinationChannelIndices.set(destIndex); } else { for (Channel outputChannel : consumer.getOutputChannels()) { if (outputChannel != null) this.collectExistingChannels(outputChannel); } } } }
this.sourceChannelDescriptor = sourceChannel.getDescriptor(); this.openChannelDescriptors = new HashSet<>(openChannels.size()); for (Channel openChannel : openChannels) { this.openChannelDescriptors.add(openChannel.getDescriptor()); for (Channel existingDestinationChannel : this.existingDestinationChannels.values()) { final Bitmask channelIndices = this.kernelDestChannelDescriptorsToIndices .get(existingDestinationChannel.getDescriptor()) .and(this.existingDestinationChannelIndices); while (true) { this.reachableExistingDestinationChannelIndices.compute( existingDestinationChannel.getDescriptor(), (k, v) -> v == null ? new Bitmask(channelIndices) : v.orInPlace(channelIndices) ); if (existingDestinationChannel.getDescriptor().equals(this.sourceChannelDescriptor)) break; existingDestinationChannel = OptimizationUtils.getPredecessorChannel(existingDestinationChannel);
if (!this.existingDestinationChannelIndices.get(index) && this.openChannelDescriptors.contains(baseChannel.getDescriptor())) { if (baseChannelCopy == null) baseChannelCopy = baseChannel.copy(); junction.setTargetChannel(index, baseChannelCopy); baseChannelCopy = this.openChannelDescriptors.contains(baseChannel.getDescriptor()) ? baseChannel.copy() : baseChannel;