blob: 63d0bc699d2fdc040ff30c25cf6c38e5085d17e6 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.wayang.core.plan.wayangplan;
import java.util.Collection;
import org.apache.wayang.core.api.Configuration;
import org.apache.wayang.core.optimizer.cardinality.CardinalityPusher;
import org.apache.wayang.core.optimizer.cardinality.DefaultCardinalityPusher;
/**
* Head of a {@link LoopSubplan}.
*/
public interface LoopHeadOperator extends Operator {
/**
* If this instance is the head of a loop, then return these {@link OutputSlot}s that go into the loop body (as
* opposed to the {@link OutputSlot}s that form the final result of the iteration).
*
* @return the loop body-bound {@link OutputSlot}s
*/
Collection<OutputSlot<?>> getLoopBodyOutputs();
/**
* If this instance is the head of a loop, then return these {@link OutputSlot}s that form the final result of
* the iteration.
*
* @return the loop-terminal {@link OutputSlot}s
*/
Collection<OutputSlot<?>> getFinalLoopOutputs();
/**
* If this instance is the head of a loop, then return these {@link InputSlot}s that are fed from the loop body (as
* opposed to the {@link InputSlot}s that initialize the loop).
*
* @return the loop body-bound {@link InputSlot}s
*/
Collection<InputSlot<?>> getLoopBodyInputs();
/**
* If this instance is the head of a loop, then return these {@link InputSlot}s that initialize the loop.
*
* @return the initialization {@link InputSlot}s
*/
Collection<InputSlot<?>> getLoopInitializationInputs();
/**
* Retrieve those {@link InputSlot}s that are required to evaluate the loop condition.
*
* @return the condition {@link InputSlot}s
*/
Collection<InputSlot<?>> getConditionInputSlots();
/**
* Retrieve those {@link OutputSlot}s that forward the {@link #getConditionInputSlots()}.
*
* @return the condition {@link OutputSlot}s
*/
Collection<OutputSlot<?>> getConditionOutputSlots();
/**
* @return a number of expected iterations; not necessarily the actual value
*/
int getNumExpectedIterations();
/**
* Get the {@link CardinalityPusher} implementation for the intermediate iterations.
*/
@Override
default CardinalityPusher getCardinalityPusher(final Configuration configuration) {
return new DefaultCardinalityPusher(this,
Slot.toIndices(this.getLoopBodyInputs()),
Slot.toIndices(this.getLoopBodyOutputs()),
configuration.getCardinalityEstimatorProvider());
}
/**
* Get the {@link CardinalityPusher} implementation for the initial iteration.
*/
default CardinalityPusher getInitializationPusher(Configuration configuration) {
return new DefaultCardinalityPusher(this,
Slot.toIndices(this.getLoopInitializationInputs()),
Slot.toIndices(this.getLoopBodyOutputs()),
configuration.getCardinalityEstimatorProvider());
}
/**
* Get the {@link CardinalityPusher} implementation for the final iteration.
*/
default CardinalityPusher getFinalizationPusher(Configuration configuration) {
return new DefaultCardinalityPusher(this,
Slot.toIndices(this.getLoopBodyInputs()),
Slot.toIndices(this.getFinalLoopOutputs()),
configuration.getCardinalityEstimatorProvider());
}
/**
* <i>Optional operation. Only {@link ExecutionOperator}s need to implement this method.</i>
* @return the current {@link State} of this instance
*/
default State getState() {
assert !this.isExecutionOperator();
throw new UnsupportedOperationException();
}
/**
* <i>Optional operation. Only {@link ExecutionOperator}s need to implement this method.</i> Sets the {@link State} of this instance.
*/
default void setState(State state) {
assert !this.isExecutionOperator();
throw new UnsupportedOperationException();
}
/**
* {@link LoopHeadOperator}s can be stateful because they might be executed mulitple times. This {@code enum}
* expresses this state.
*/
enum State {
/**
* The {@link LoopHeadOperator} has not been executed yet.
*/
NOT_STARTED,
/**
* The {@link LoopHeadOperator} has been executed. However, the last execution was not the ultimate one.
*/
RUNNING,
/**
* The {@link LoopHeadOperator} has been executed ultimately.
*/
FINISHED
}
}