Search in sources :

Example 1 with FlowError

use of org.ow2.proactive.scheduler.common.job.factories.FlowError in project scheduling by ow2-proactive.

the class FlowChecker method checkBlocks.

/**
 * Checks all declared blocks are correct
 *
 * @param job the job to check
 * @return a list of valid blocks
 * @throws FlowError
 */
private void checkBlocks() throws FlowError {
    Set<String> done = new HashSet<>();
    // detect blocks
    for (TaskTree tt : roots) {
        Stack<TaskTree> env = new Stack<>();
        Stack<TaskTree> join = new Stack<>();
        dfsBlocks(tt, done, env, join);
        if (env.size() > 0) {
            throw new FlowError("Unmatched start block", FlowErrorType.BLOCK, env.firstElement().element.getName());
        }
    }
    // check blocks
    for (Block b : blocks) {
        checkBlockDown(b.end, b.start);
        checkBlockUp(b.start, b.end);
    }
}
Also used : FlowBlock(org.ow2.proactive.scheduler.common.task.flow.FlowBlock) HashSet(java.util.HashSet) Stack(java.util.Stack)

Example 2 with FlowError

use of org.ow2.proactive.scheduler.common.job.factories.FlowError in project scheduling by ow2-proactive.

the class FlowChecker method checkReplicate.

/**
 * Checks the provided taskflow against rules specific to the REPLICATE control flow action
 *
 * @param job the job to check
 * @throws FlowError
 */
private void checkReplicate() throws FlowError {
    for (TaskTree tree : tasksFlat) {
        if (tree.element.getFlowScript() != null && tree.element.getFlowScript().getActionType().equals(FlowActionType.REPLICATE.toString())) {
            for (TaskTree child : tree.children) {
                if (child.parents.size() != 1) {
                    throw new FlowError("The Target of a REPLICATE must have only one dependency", FlowErrorType.REPLICATE, child.element.getName());
                }
                if (child.element.getFlowBlock().equals(FlowBlock.END)) {
                    throw new FlowError("The target of a REPLICATE cannot be the end of a task block", FlowErrorType.REPLICATE, child.element.getName());
                }
                Block block = null;
                for (Block b : this.blocks) {
                    if (b.start.element.getName().equals(child.element.getName())) {
                        block = b;
                    }
                }
                TaskTree endBlock = null;
                if (block != null) {
                    endBlock = block.end;
                } else {
                    endBlock = child;
                }
                if (endBlock.children.size() < 1) {
                    throw new FlowError("No merge point for REPLICATE block", FlowErrorType.REPLICATE, endBlock.element.getName());
                }
                if (endBlock.element.getFlowScript() != null) {
                    if (endBlock.element.getFlowScript().getActionType().equals(FlowActionType.REPLICATE.toString()) || endBlock.element.getFlowScript().getActionType().equals(FlowActionType.IF.toString())) {
                        throw new FlowError("Last action of a REPLICATE block cannot perform IF or REPLICATE action", FlowErrorType.REPLICATE, endBlock.element.getName());
                    }
                }
            }
        }
    }
}
Also used : FlowBlock(org.ow2.proactive.scheduler.common.task.flow.FlowBlock)

Example 3 with FlowError

use of org.ow2.proactive.scheduler.common.job.factories.FlowError in project scheduling by ow2-proactive.

the class FlowChecker method checkReachable.

/**
 * Check whether or not every tasks of the given tasks flow can be reached.
 * Happens with dependency cycles.
 *
 * @return FlowError
 */
private void checkReachable() throws FlowError {
    HashSet<Task> tasks = new HashSet<>();
    HashSet<Task> reached = new HashSet<>();
    for (Task t : job.getTasks()) {
        if (t.getDependencesList() == null) {
            reached.add(t);
        } else {
            tasks.add(t);
        }
    }
    boolean change;
    do {
        change = false;
        Iterator<Task> it = tasks.iterator();
        while (it.hasNext()) {
            Task t = it.next();
            if (reached.containsAll(t.getDependencesList())) {
                it.remove();
                reached.add(t);
                change = true;
            }
        }
    } while (change);
    if (reached.size() != job.getTasks().size()) {
        for (Task t : job.getTasks()) {
            if (!reached.contains(t)) {
                throw new FlowError("Unreachable task", FlowErrorType.UNREACHABLE, t.getName());
            }
        }
    }
}
Also used : Task(org.ow2.proactive.scheduler.common.task.Task) HashSet(java.util.HashSet)

Example 4 with FlowError

use of org.ow2.proactive.scheduler.common.job.factories.FlowError in project scheduling by ow2-proactive.

the class FlowChecker method checkIf.

/**
 * Checks the provided taskflow against rules specific to the IF control flow action
 *
 * @throws FlowError
 */
private void checkIf() throws FlowError {
    for (TaskTree tree : tasksFlat) {
        if (tree.element.getFlowScript() != null && tree.element.getFlowScript().getActionType().equals(FlowActionType.IF.toString())) {
            TaskTree targetIf = findTask(tree.element.getFlowScript().getActionTarget());
            TaskTree targetElse = findTask(tree.element.getFlowScript().getActionTargetElse());
            TaskTree targetJoin = findTask(tree.element.getFlowScript().getActionContinuation());
            if (targetIf == null) {
                throw new FlowError("IF action has no target", FlowErrorType.IF, tree.element.getName());
            }
            if (targetElse == null) {
                throw new FlowError("IF action has no ELSE target", FlowErrorType.IF, tree.element.getName());
            }
            if (targetIf.equals(targetElse)) {
                throw new FlowError("IF and ELSE targets are the same", FlowErrorType.IF, targetIf.element.getName());
            }
            // No join : IF and ELSE are /loose/ blocks
            if (targetJoin == null) {
                if (targetIf.parents.size() > 0) {
                    throw new FlowError("IF target task cannot have dependencies", FlowErrorType.IF, targetIf.element.getName());
                }
                if (targetElse.parents.size() > 0) {
                    throw new FlowError("IF target task ELSE cannot have dependencies", FlowErrorType.IF, targetElse.element.getName());
                }
                List<TaskTree> targets = new ArrayList<>(2);
                targets.add(targetIf);
                targets.add(targetElse);
                for (TaskTree target : targets) {
                    Map<String, TaskTree> ifTasks = new HashMap<>();
                    Stack<TaskTree> stack = new Stack<>();
                    stack.push(target);
                    while (stack.size() > 0) {
                        TaskTree cur = stack.pop();
                        if (ifTasks.containsKey(cur.element.getName())) {
                            continue;
                        } else {
                            ifTasks.put(cur.element.getName(), cur);
                            for (TaskTree t : cur.children) {
                                stack.push(t);
                            }
                            for (TaskTree t : cur.targets) {
                                stack.push(t);
                            }
                        }
                    }
                    for (TaskTree t : ifTasks.values()) {
                        if (t.element.getName().equals(target.element.getName())) {
                            continue;
                        }
                        try {
                            checkBlockUp(target, t);
                        } catch (FlowError e) {
                            throw new FlowError("IF block at " + target.element.getName() + " has external dependencies", FlowErrorType.IF, e.getTask());
                        }
                    }
                }
            } else // join : IF and ELSE are blocks
            {
                Block ifBlock = null;
                Block elseBlock = null;
                // detect blocks
                for (Block b : this.blocks) {
                    if (b.start.element.getName().equals(targetIf.element.getName())) {
                        ifBlock = b;
                    }
                    if (b.start.element.getName().equals(targetElse.element.getName())) {
                        elseBlock = b;
                    }
                }
                // if is a block or a single task
                if (ifBlock == null) {
                    if (!(targetIf.children.size() > 0 || targetIf.targets.size() > 0)) {
                        ifBlock = new Block(targetIf, targetIf);
                    } else {
                        throw new FlowError("IF action target is not a Task Block", FlowErrorType.IF, targetIf.element.getName());
                    }
                }
                // else is a block or a single task
                if (elseBlock == null) {
                    if (!(targetElse.children.size() > 0 || targetElse.targets.size() > 0)) {
                        elseBlock = new Block(targetElse, targetElse);
                    } else {
                        throw new FlowError("IF action ELSE target is not a Task Block", FlowErrorType.IF, targetElse.element.getName());
                    }
                }
                // join joins only one if
                if (targetJoin != null) {
                    for (TaskTree join : targetJoin.joins) {
                        String jN = join.element.getName();
                        if (!(jN.equals(ifBlock.end.element.getName()) || jN.equals(elseBlock.end.element.getName()))) {
                            throw new FlowError("JOIN task merges multiple IF actions", FlowErrorType.IF, targetJoin.element.getName());
                        }
                    }
                }
                if (ifBlock.start.parents.size() > 0) {
                    throw new FlowError("IF task block cannot have dependencies", FlowErrorType.IF, ifBlock.start.element.getName());
                }
                if (ifBlock.end.children.size() > 0) {
                    throw new FlowError("IF task block cannot have children", FlowErrorType.IF, ifBlock.end.element.getName());
                }
                if (elseBlock.start.parents.size() > 0) {
                    throw new FlowError("ELSE task block cannot have dependencies", FlowErrorType.IF, elseBlock.start.element.getName());
                }
                if (elseBlock.end.children.size() > 0) {
                    throw new FlowError("ELSE task block cannot have children", FlowErrorType.IF, elseBlock.end.element.getName());
                }
                if (targetJoin.parents.size() > 0) {
                    throw new FlowError("JOIN task cannot have dependencies", FlowErrorType.IF, targetJoin.element.getName());
                }
            }
        }
    }
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) FlowBlock(org.ow2.proactive.scheduler.common.task.flow.FlowBlock) Stack(java.util.Stack)

Example 5 with FlowError

use of org.ow2.proactive.scheduler.common.job.factories.FlowError in project scheduling by ow2-proactive.

the class FlowChecker method dfsBlocks.

/**
 * Find matching start and end blocks in a task tree using depth first search
 *
 * @param tree task tree to search
 * @param done already treated tasks; multiple dependencies: multiple passes
 * @param env accumulates the previously read start tags
 * @param join stacks previous join targets
 * @throws FlowError
 */
private void dfsBlocks(TaskTree tree, Set<String> done, Stack<TaskTree> env, Stack<TaskTree> join) throws FlowError {
    if (tree.joins.size() > 0 && !tree.joinTrigger) {
        return;
    }
    if (tree.targetOf != null && !done.contains(tree.targetOf.element.getName())) {
        return;
    }
    FlowBlock fb = tree.element.getFlowBlock();
    String name = tree.element.getName();
    if (done.contains(name)) {
        return;
    } else {
        done.add(name);
    }
    switch(fb) {
        case START:
            // push new opening tag in the environment
            env.push(tree);
            break;
        case END:
            // close the last opened block
            TaskTree start = null;
            try {
                start = env.pop();
            } catch (EmptyStackException e) {
                throw new FlowError("Unmatched end block", FlowErrorType.BLOCK, name);
            }
            Block blk = new Block(start, tree);
            blocks.add(blk);
            break;
        case NONE:
            break;
    }
    List<TaskTree> children = new ArrayList<>();
    children.addAll(tree.children);
    if (tree.children.size() == 0) {
        if (tree.element.getFlowScript() != null && tree.element.getFlowScript().getActionType().equals(FlowActionType.IF.toString())) {
            if (tree.targetJoin != null) {
                join.add(tree.targetJoin);
            }
            for (TaskTree t : tree.targets) {
                children.add(t);
            }
        } else if (join.size() > 0) {
            TaskTree pop = join.pop();
            children.add(pop);
            pop.joinTrigger = true;
        }
    }
    // recursive call
    for (TaskTree child : children) {
        dfsBlocks(child, done, env, join);
    }
}
Also used : EmptyStackException(java.util.EmptyStackException) FlowBlock(org.ow2.proactive.scheduler.common.task.flow.FlowBlock) ArrayList(java.util.ArrayList) FlowBlock(org.ow2.proactive.scheduler.common.task.flow.FlowBlock)

Aggregations

ArrayList (java.util.ArrayList)4 Task (org.ow2.proactive.scheduler.common.task.Task)4 FlowBlock (org.ow2.proactive.scheduler.common.task.flow.FlowBlock)4 Stack (java.util.Stack)3 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 FlowError (org.ow2.proactive.scheduler.common.job.factories.FlowError)2 EmptyStackException (java.util.EmptyStackException)1 LinkedHashMap (java.util.LinkedHashMap)1 JobCreationException (org.ow2.proactive.scheduler.common.exception.JobCreationException)1 FlowChecker (org.ow2.proactive.scheduler.common.job.factories.FlowChecker)1 JavaTask (org.ow2.proactive.scheduler.common.task.JavaTask)1 NativeTask (org.ow2.proactive.scheduler.common.task.NativeTask)1 ScriptTask (org.ow2.proactive.scheduler.common.task.ScriptTask)1 InternalForkedScriptTask (org.ow2.proactive.scheduler.task.internal.InternalForkedScriptTask)1 InternalScriptTask (org.ow2.proactive.scheduler.task.internal.InternalScriptTask)1 InternalTask (org.ow2.proactive.scheduler.task.internal.InternalTask)1