package com.yahoo.dtf.actions.flowcontrol;
import java.util.ArrayList;
import com.yahoo.dtf.actions.Action;
import com.yahoo.dtf.distribution.Worker;
import com.yahoo.dtf.exception.BreakException;
import com.yahoo.dtf.exception.DTFException;
import com.yahoo.dtf.exception.InterruptionException;
import com.yahoo.dtf.state.DTFState;
/**
* @dtf.tag parallel
*
* @dtf.since 1.0
* @dtf.author Rodney Gomes
*
* @dtf.tag.desc All of the direct children of this tag are executed in
* parallel, this tag only terminates its execution once all of
* the children have completed their executions.
*
* @dtf.tag.example
* <parallel>
* <component id="DTFA1">
* <echo>Echo a</echo>
* </component>
* <component id="DTFA2">
* <echo>Echo b</echo>
* </component>
* </parallel>
*
* @dtf.tag.example
* <parallel>
* <for property="i" range="1..100">
* <echo>Echo first thread ${i}</echo>
* </for>
* <for property="i" range="1..100">
* <echo>Echo second thread ${i}</echo>
* </for>
* </parallel>
*
*/
public class Parallel extends Action {
public Parallel() { }
public void execute() throws DTFException {
ArrayList<Action> children = children();
Worker[] actions = new Worker[children.size()];
for (int index = 0; index < actions.length; index++) {
DTFState state = getState().duplicate();
actions[index] = new Worker((Action) children.get(index),
state,
""+index);
}
for (int index = 0; index < actions.length; index++)
actions[index].start();
/*
* Wait for all underlying threads to terminate and log all of them
* except the last exception which we can throw to any parent tag to
* handle the error.
*/
DTFException lastexception = null;
boolean interrupted = false;
for (int index = 0; index < actions.length; index++) {
try {
actions[index].waitFor();
} catch (InterruptionException e) {
if ( getLogger().isDebugEnabled() ) {
getLogger().debug("Thread interrupted [" +
actions[index].getName() + "]",e);
}
interrupted = true;
} catch (BreakException e) {
// break point
if ( getLogger().isDebugEnabled() )
getLogger().debug("break point hit",e);
} catch (DTFException e) {
if ( lastexception != null )
getLogger().error("Child failed.", lastexception);
lastexception = e;
}
}
if ( interrupted && getLogger().isDebugEnabled() )
getLogger().debug("Execution interrupted.");
if ( lastexception != null )
throw lastexception;
}
}