package com.yahoo.dtf.actions.flowcontrol; import com.yahoo.dtf.actions.flowcontrol.Loop; import com.yahoo.dtf.actions.flowcontrol.Sequence; 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.range.Range; import com.yahoo.dtf.range.RangeFactory; import com.yahoo.dtf.state.DTFState; /** * @dtf.tag parallelloop * * @dtf.since 1.0 * @dtf.author Rodney Gomes * * @dtf.tag.desc The parallelloop tag will take the child tag and spawn as many * times as the number of items in the range expression and execute * those in parallel. * * @dtf.tag.example * <parallelloop property="j" range="[1..6]"> * <parallelloop property="k" range="[1..6]"> * <log>Creating property property.${j}.${k}</log> * <property name="property.${j}.${k}" value="${j}-${k}"/> * </parallelloop> * </parallelloop> * * @dtf.tag.example * <parallelloop property="var1" range="[1,2,3,4,5,6]"> * <log>Looping on ${var1}</log> * </parallelloop> */ public class Parallelloop extends Loop { public Parallelloop() { } public void execute() throws DTFException { Range range = RangeFactory.getRange(getRange()); int workerCount = range.size(); Sequence children = new Sequence(); children.addActions(children()); Worker[] workers = new Worker[workerCount]; int i = 0; while (range.hasMoreElements()) { String value = range.nextElement(); DTFState state = getState().duplicate(); state.getConfig().setProperty(getProperty(), value); workers[i++] = new Worker(children, state, value); } for(i = 0; i < workerCount; i++) workers[i].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 < workers.length; index++) { try { workers[index].waitFor(); } catch (InterruptionException e) { if ( getLogger().isDebugEnabled() ) { getLogger().debug("Thread interrupted [" + workers[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; } }