// connect the initial solution set now.
if (node instanceof WorksetIterationPlanNode) {
// connect the initial solution set
WorksetIterationPlanNode wsNode = (WorksetIterationPlanNode) node;
AbstractJobVertex headVertex = this.iterations.get(wsNode).getHeadTask();
TaskConfig headConfig = new TaskConfig(headVertex.getConfiguration());
int inputIndex = headConfig.getDriverStrategy().getNumInputs();
headConfig.setIterationHeadSolutionSetInputIndex(inputIndex);
translateChannel(wsNode.getInitialSolutionSetInput(), inputIndex, headVertex, headConfig, false);
}
return;
}
final AbstractJobVertex targetVertex = this.vertices.get(node);
// --------- Main Path: Translation of channels ----------
//
// There are two paths of translation: One for chained tasks (or merged tasks in general),
// which do not have their own task vertex. The other for tasks that have their own vertex,
// or are the primary task in a vertex (to which the others are chained).
// check whether this node has its own task, or is merged with another one
if (targetVertex == null) {
// node's task is merged with another task. it is either chained, of a merged head vertex
// from an iteration
final TaskInChain chainedTask;
if ((chainedTask = this.chainedTasks.get(node)) != null) {
// Chained Task. Sanity check first...
final Iterator<Channel> inConns = node.getInputs().iterator();
if (!inConns.hasNext()) {
throw new CompilerException("Bug: Found chained task with no input.");
}
final Channel inConn = inConns.next();
if (inConns.hasNext()) {
throw new CompilerException("Bug: Found a chained task with more than one input!");
}
if (inConn.getLocalStrategy() != null && inConn.getLocalStrategy() != LocalStrategy.NONE) {
throw new CompilerException("Bug: Found a chained task with an input local strategy.");
}
if (inConn.getShipStrategy() != null && inConn.getShipStrategy() != ShipStrategyType.FORWARD) {
throw new CompilerException("Bug: Found a chained task with an input ship strategy other than FORWARD.");
}
AbstractJobVertex container = chainedTask.getContainingVertex();
if (container == null) {
final PlanNode sourceNode = inConn.getSource();
container = this.vertices.get(sourceNode);
if (container == null) {
// predecessor is itself chained
container = this.chainedTasks.get(sourceNode).getContainingVertex();
if (container == null) {
throw new IllegalStateException("Bug: Chained task predecessor has not been assigned its containing vertex.");
}
} else {
// predecessor is a proper task job vertex and this is the first chained task. add a forward connection entry.
new TaskConfig(container.getConfiguration()).addOutputShipStrategy(ShipStrategyType.FORWARD);
}
chainedTask.setContainingVertex(container);
}
// add info about the input serializer type
chainedTask.getTaskConfig().setInputSerializer(inConn.getSerializer(), 0);
// update name of container task
String containerTaskName = container.getName();
if(containerTaskName.startsWith("CHAIN ")) {
container.setName(containerTaskName+" -> "+chainedTask.getTaskName());
} else {
container.setName("CHAIN "+containerTaskName+" -> "+chainedTask.getTaskName());
}
this.chainedTasksInSequence.add(chainedTask);
return;
}
else if (node instanceof BulkPartialSolutionPlanNode ||
node instanceof WorksetPlanNode)
{
// merged iteration head task. the task that the head is merged with will take care of it
return;
} else {
throw new CompilerException("Bug: Unrecognized merged task vertex.");
}
}
// -------- Here, we translate non-chained tasks -------------
if (this.currentIteration != null) {
AbstractJobVertex head = this.iterations.get(this.currentIteration).getHeadTask();
// the head may still be null if we descend into the static parts first
if (head != null) {
targetVertex.setStrictlyCoLocatedWith(head);
}
}
// create the config that will contain all the description of the inputs
final TaskConfig targetVertexConfig = new TaskConfig(targetVertex.getConfiguration());
// get the inputs. if this node is the head of an iteration, we obtain the inputs from the
// enclosing iteration node, because the inputs are the initial inputs to the iteration.
final Iterator<Channel> inConns;
if (node instanceof BulkPartialSolutionPlanNode) {
inConns = ((BulkPartialSolutionPlanNode) node).getContainingIterationNode().getInputs().iterator();
// because the partial solution has its own vertex, is has only one (logical) input.
// note this in the task configuration
targetVertexConfig.setIterationHeadPartialSolutionOrWorksetInputIndex(0);
} else if (node instanceof WorksetPlanNode) {
WorksetPlanNode wspn = (WorksetPlanNode) node;
// input that is the initial workset
inConns = Collections.singleton(wspn.getContainingIterationNode().getInput2()).iterator();
// because we have a stand-alone (non-merged) workset iteration head, the initial workset will
// be input 0 and the solution set will be input 1
targetVertexConfig.setIterationHeadPartialSolutionOrWorksetInputIndex(0);
targetVertexConfig.setIterationHeadSolutionSetInputIndex(1);
} else {
inConns = node.getInputs().iterator();
}
if (!inConns.hasNext()) {
throw new CompilerException("Bug: Found a non-source task with no input.");
}
int inputIndex = 0;
while (inConns.hasNext()) {
Channel input = inConns.next();
inputIndex += translateChannel(input, inputIndex, targetVertex, targetVertexConfig, false);
}
// broadcast variables
int broadcastInputIndex = 0;
for (NamedChannel broadcastInput: node.getBroadcastInputs()) {
int broadcastInputIndexDelta = translateChannel(broadcastInput, broadcastInputIndex, targetVertex, targetVertexConfig, true);
targetVertexConfig.setBroadcastInputName(broadcastInput.getName(), broadcastInputIndex);
targetVertexConfig.setBroadcastInputSerializer(broadcastInput.getSerializer(), broadcastInputIndex);
broadcastInputIndex += broadcastInputIndexDelta;
}
} catch (Exception e) {
throw new CompilerException(
"An error occurred while translating the optimized plan to a nephele JobGraph: " + e.getMessage(), e);