// This software is released into the Public Domain. See copying.txt for details.
package org.openstreetmap.osmosis.core.pipeline.common;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openstreetmap.osmosis.core.OsmosisRuntimeException;
/**
* Manages a processing pipeline from parsing of arguments, to creating and
* instantiating tasks, running of the pipeline, and waiting until pipeline
* completion.
*
* @author Brett Henderson
*/
public class Pipeline {
private static final Logger LOG = Logger.getLogger(Pipeline.class.getName());
private TaskManagerFactoryRegister factoryRegister;
private List<TaskManager> taskManagers;
/**
* Creates a new instance.
*
* @param factoryRegister
* The register containing all known task manager factories.
*/
public Pipeline(TaskManagerFactoryRegister factoryRegister) {
this.factoryRegister = factoryRegister;
taskManagers = new ArrayList<TaskManager>();
}
/**
* Creates a new node in the pipeline. The node will be created with the
* correct task with all task parameters set. The tasks will not be
* connected together.
*
* @param taskInfoList
* The list of task information objects.
*/
private void buildTasks(List<TaskConfiguration> taskInfoList) {
for (TaskConfiguration taskConfig : taskInfoList) {
// Create the new task manager and add to the pipeline.
taskManagers.add(
factoryRegister.getInstance(taskConfig.getType()).createTaskManager(taskConfig)
);
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("Created task \"" + taskConfig.getId() + "\"");
}
}
}
/**
* Uses the pipe arguments specified for each task to connect the tasks appropriately.
*/
private void connectTasks() {
PipeTasks pipeTasks;
// Create a container to map between the pipe name and the task that has
// last written to it.
pipeTasks = new PipeTasks();
// Request each node to perform connection, each node will update the
// pipe tasks as it provides and consumes pipes.
for (TaskManager taskManager : taskManagers) {
taskManager.connect(pipeTasks);
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("Connected task \"" + taskManager.getTaskId() + "\"");
}
}
// Validate that no pipes are left without sinks.
if (pipeTasks.size() > 0) {
StringBuilder namedPipes;
// Build a list of pipes to include in the error.
namedPipes = new StringBuilder();
for (String pipeName : pipeTasks.getPipeNames()) {
if (namedPipes.length() > 0) {
namedPipes.append(", ");
}
namedPipes.append(pipeName);
}
throw new OsmosisRuntimeException(
"The following named pipes (" + namedPipes + ") and "
+ pipeTasks.defaultTaskSize()
+ " default pipes have not been terminated with appropriate output sinks."
);
}
}
/**
* Instantiates and configures all tasks within the pipeline.
*
* @param taskInfoList
* The list of task information objects.
*/
public void prepare(List<TaskConfiguration> taskInfoList) {
// Process the command line arguments to build all tasks in the pipeline.
LOG.fine("Building tasks.");
buildTasks(taskInfoList);
// Connect the nodes in the pipeline.
LOG.fine("Connecting tasks.");
connectTasks();
}
/**
* Launches the execution of the tasks within the pipeline.
*/
public void execute() {
// Initiate execution of all nodes.
for (TaskManager taskManager : taskManagers) {
taskManager.execute();
}
}
/**
* Waits for all tasks within the pipeline to complete.
*/
public void waitForCompletion() {
boolean successful;
// Wait for completion of all nodes.
successful = true;
for (TaskManager taskManager : taskManagers) {
if (!taskManager.waitForCompletion()) {
successful = false;
}
}
if (!successful) {
throw new OsmosisRuntimeException("One or more tasks failed.");
}
}
}