org.workflow.WorkflowParser.java Source code

Java tutorial

Introduction

Here is the source code for org.workflow.WorkflowParser.java

Source

/**
 * Copyright 2012-2013 University Of Southern California
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.workflow;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.cloudbus.cloudsim.Log;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.workflow.scheduling.BaseClusterSimWorkflow;
import org.workflow.scheduling.ClusterSimWorkflow;
import org.workflow.scheduling.algorithms.WorkflowSchedulingAlgorithm;
import org.workflow.scheduling.algorithms.WorkflowSchedulingAlgorithmType;
import org.workflow.scheduling.factory.WorkflowSchedulingAlgorithmFactory;
import org.workflowsim.FileItem;
import org.workflowsim.utils.Parameters;
import org.workflowsim.utils.Parameters.FileType;
import org.workflowsim.utils.ReplicaCatalog;

/**
 * WorkflowParser parse a DAX into tasks so that WorkflowSim can manage them
 *
 * @author Weiwei Chen
 * @since WorkflowSim Toolkit 1.0
 * @date Aug 23, 2013
 * @date Nov 9, 2014
 */
public final class WorkflowParser {

    /**
     * The path to DAX file.
     */
    private final String daxPath;
    /**
     * The path to DAX files.
     */
    private final List<String> daxPaths;
    /**
     * All tasks.
     */
    private List<Task> taskList;
    /**
     * User id. used to create a new task.
     */
    private final int userId;

    private WorkflowSchedulingAlgorithmType workflowSchedulingAlgorithmType = WorkflowSchedulingAlgorithmType.FCFS;

    /**
     * current job id. In case multiple workflow submission
     */
    private int jobIdStartsFrom;

    private List<ClusterSimWorkflow> workflows;

    public static void main(String[] args) {
        WorkflowParser parser = new WorkflowParser(2);
        parser.modifyXmlFile("CyberShake_100.xml");
    }

    private void modifyXmlFile(String path) {
        try {

            SAXBuilder builder = new SAXBuilder();
            //parse using builder to get DOM representation of the XML file
            Document dom = builder.build(new File(path));
            Element root = dom.getRootElement();
            List<Element> list = root.getChildren();
            for (Element node : list) {
                switch (node.getName().toLowerCase()) {

                case "job":
                    double runtime;
                    if (node.getAttributeValue("runtime") != null) {
                        Attribute att = node.getAttribute("runtime");
                        att.setValue("20");
                        node.removeAttribute("runtime");
                        node.setAttribute(att);
                    }
                    break;
                default:
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public List<ClusterSimWorkflow> getWorkflows() {
        return this.workflows;
    }

    public void setWorkflows(final List<ClusterSimWorkflow> workflows) {
        this.workflows = workflows;
    }

    public void setWorkflowSchedulingAlgorithmType(
            WorkflowSchedulingAlgorithmType workflowSchedulingAlgorithmType) {
        this.workflowSchedulingAlgorithmType = workflowSchedulingAlgorithmType;
    }

    public WorkflowSchedulingAlgorithmType getWorkflowSchedulingAlgorithmType() {
        return this.workflowSchedulingAlgorithmType;
    }

    /**
     * Gets the task list
     *
     * @return the task list
     */
    @SuppressWarnings("unchecked")
    public List<Task> getTaskList() {
        return taskList;
    }

    /**
     * Sets the task list
     *
     * @param taskList the task list
     */
    protected void setTaskList(List<Task> taskList) {
        this.taskList = taskList;
    }

    /**
     * Map from task name to task.
     */
    protected Map<String, Task> mName2Task;

    /**
     * Initialize a WorkflowParser
     *
     * @param userId the user id. Currently we have just checked single user
     * mode
     */
    public WorkflowParser(int userId) {
        this.userId = userId;
        this.mName2Task = new HashMap<>();
        this.daxPath = Parameters.getDaxPath();
        this.daxPaths = Parameters.getDAXPaths();
        this.jobIdStartsFrom = 1;

        setTaskList(new ArrayList<Task>());
    }

    /**
     * Start to parse a workflow which is a xml file(s).
     */
    public void parse() {
        if (this.daxPath != null) {
            parseXmlFile(this.daxPath);
        } else if (this.daxPaths != null) {
            List<ClusterSimWorkflow> workflows = new ArrayList<>();
            for (String path : this.daxPaths) {
                workflows.add(parseWorkflow(path));
            }
            addTasksFromWorkflowToTaskList(workflows);
        }
    }

    private void addTasksFromWorkflowToTaskList(final List<ClusterSimWorkflow> workflows) {
        WorkflowSchedulingAlgorithm algorithm = (new WorkflowSchedulingAlgorithmFactory())
                .getWorkflowSchedulingAlgorithm(getWorkflowSchedulingAlgorithmType());
        List<ClusterSimWorkflow> orderedWorkflows = algorithm.scheduleWorkflows(workflows);
        for (ClusterSimWorkflow workflow : orderedWorkflows) {
            BaseClusterSimWorkflow baseWorkflow = (BaseClusterSimWorkflow) workflow;
            List<Task> tasksInWorkflow = baseWorkflow.getTasks();
            for (Task taskSingle : tasksInWorkflow) {
                this.getTaskList().add(taskSingle);
            }
        }
    }

    /**
     * Sets the depth of a task
     *
     * @param task the task
     * @param depth the depth
     */
    private void setDepth(Task task, int depth) {
        if (depth > task.getDepth()) {
            task.setDepth(depth);
        }
        for (Task cTask : task.getChildList()) {
            setDepth(cTask, task.getDepth() + 1);
        }
    }

    private ClusterSimWorkflow parseWorkflow(final String path) {
        return parseSingleWorkflow(path);
    }

    private ClusterSimWorkflow parseSingleWorkflow(final String path) {
        ClusterSimWorkflow workflow = this.parseWorkflowFromXmlFile(path);
        return workflow;
    }

    private ClusterSimWorkflow parseWorkflowFromXmlFile(final String path) {
        BaseClusterSimWorkflow parsedWorkflow = new BaseClusterSimWorkflow(path);
        List<Task> tasks = new ArrayList<>();
        try {

            SAXBuilder builder = new SAXBuilder();
            //parse using builder to get DOM representation of the XML file
            Document dom = builder.build(new File(path));
            Element root = dom.getRootElement();
            List<Element> list = root.getChildren();
            for (Element node : list) {
                switch (node.getName().toLowerCase()) {
                case "arrivalTime":
                    //String actualArrivalTime = node.getAttributeValue("actualarrivaltime");
                    parsedWorkflow.setArrivalTime(System.currentTimeMillis());
                    break;
                case "deadline":
                    //String acutualDeadline = node.getAttributeValue("actualdeadline");
                    //parsedWorkflow.setDeadline(Long.parseLong(acutualDeadline));
                    break;
                case "job":
                    long length = 0;
                    String nodeName = node.getAttributeValue("id");
                    String nodeType = node.getAttributeValue("name");
                    /**
                     * capture runtime. If not exist, by default the runtime
                     * is 0.1. Otherwise CloudSim would ignore this task.
                     * BUG/#11
                     */
                    double runtime;
                    if (node.getAttributeValue("runtime") != null) {
                        String nodeTime = node.getAttributeValue("runtime");
                        runtime = 1000 * Double.parseDouble(nodeTime);
                        if (runtime < 100) {
                            runtime = 100;
                        }
                        length = (long) runtime;
                    } else {
                        Log.printLine("Cannot find runtime for " + nodeName + ",set it to be 0");
                    } //multiple the scale, by default it is 1.0
                    length *= Parameters.getRuntimeScale();
                    List<Element> fileList = node.getChildren();
                    List<FileItem> mFileList = new ArrayList<>();
                    for (Element file : fileList) {
                        if (file.getName().toLowerCase().equals("uses")) {
                            String fileName = file.getAttributeValue("name");//DAX version 3.3
                            if (fileName == null) {
                                fileName = file.getAttributeValue("file");//DAX version 3.0
                            }
                            if (fileName == null) {
                                Log.print("Error in parsing xml");
                            }

                            String inout = file.getAttributeValue("link");
                            double size = 0.0;

                            String fileSize = file.getAttributeValue("size");
                            if (fileSize != null) {
                                size = Double.parseDouble(fileSize) /*/ 1024*/;
                            } else {
                                Log.printLine("File Size not found for " + fileName);
                            }

                            /**
                             * a bug of cloudsim, size 0 causes a problem. 1
                             * is ok.
                             */
                            if (size == 0) {
                                size++;
                            }
                            /**
                             * Sets the file type 1 is input 2 is output
                             */
                            FileType type = FileType.NONE;
                            switch (inout) {
                            case "input":
                                type = FileType.INPUT;
                                break;
                            case "output":
                                type = FileType.OUTPUT;
                                break;
                            default:
                                Log.printLine("Parsing Error");
                                break;
                            }
                            FileItem tFile;
                            /*
                             * Already exists an input file (forget output file)
                             */
                            if (size < 0) {
                                /*
                                 * Assuming it is a parsing error
                                 */
                                size = 0 - size;
                                Log.printLine("Size is negative, I assume it is a parser error");
                            }
                            /*
                             * Note that CloudSim use size as MB, in this case we use it as Byte
                             */
                            if (type == FileType.OUTPUT) {
                                /**
                                 * It is good that CloudSim does tell
                                 * whether a size is zero
                                 */
                                tFile = new FileItem(fileName, size);
                            } else if (ReplicaCatalog.containsFile(fileName)) {
                                tFile = ReplicaCatalog.getFile(fileName);
                            } else {

                                tFile = new FileItem(fileName, size);
                                ReplicaCatalog.setFile(fileName, tFile);
                            }

                            tFile.setType(type);
                            mFileList.add(tFile);

                        }
                    }
                    Task task;
                    //In case of multiple workflow submission. Make sure the jobIdStartsFrom is consistent.
                    synchronized (this) {
                        task = new Task(this.jobIdStartsFrom, length);
                        this.jobIdStartsFrom++;
                    }
                    task.setType(nodeType);
                    task.setUserId(userId);
                    mName2Task.put(nodeName, task);
                    for (FileItem file : mFileList) {
                        task.addRequiredFile(file.getName());
                    }
                    task.setFileList(mFileList);
                    tasks.add(task);

                    /**
                     * Add dependencies info.
                     */
                    break;
                case "child":
                    List<Element> pList = node.getChildren();
                    String childName = node.getAttributeValue("ref");
                    if (mName2Task.containsKey(childName)) {

                        Task childTask = (Task) mName2Task.get(childName);

                        for (Element parent : pList) {
                            String parentName = parent.getAttributeValue("ref");
                            if (mName2Task.containsKey(parentName)) {
                                Task parentTask = (Task) mName2Task.get(parentName);
                                parentTask.addChild(childTask);
                                childTask.addParent(parentTask);
                            }
                        }
                    }
                    break;
                }
            }
            /**
             * If a task has no parent, then it is root task.
             */
            ArrayList roots = new ArrayList<>();
            for (Task task : mName2Task.values()) {
                task.setDepth(0);
                if (task.getParentList().isEmpty()) {
                    roots.add(task);
                }
            }

            /**
             * Add depth from top to bottom.
             */
            for (Iterator it = roots.iterator(); it.hasNext();) {
                Task task = (Task) it.next();
                setDepth(task, 1);
            }
            /**
             * Clean them so as to save memory. Parsing workflow may take much
             * memory
             */
            this.mName2Task.clear();

        } catch (JDOMException jde) {
            Log.printLine("JDOM Exception;Please make sure your dax file is valid");

        } catch (IOException ioe) {
            Log.printLine("IO Exception;Please make sure dax.path is correctly set in your config file");

        } catch (Exception e) {
            e.printStackTrace();
            Log.printLine("Parsing Exception");
        }
        parsedWorkflow.setTasks(tasks);
        parsedWorkflow.setDeadline(System.currentTimeMillis() + 30 * tasks.size());
        return parsedWorkflow;
    }

    /**
     * Parse a DAX file with jdom
     */
    private void parseXmlFile(String path) {

        try {

            SAXBuilder builder = new SAXBuilder();
            //parse using builder to get DOM representation of the XML file
            Document dom = builder.build(new File(path));
            Element root = dom.getRootElement();
            List<Element> list = root.getChildren();
            for (Element node : list) {
                switch (node.getName().toLowerCase()) {
                case "job":
                    long length = 0;
                    String nodeName = node.getAttributeValue("id");
                    String nodeType = node.getAttributeValue("name");
                    /**
                     * capture runtime. If not exist, by default the runtime
                     * is 0.1. Otherwise CloudSim would ignore this task.
                     * BUG/#11
                     */
                    double runtime;
                    if (node.getAttributeValue("runtime") != null) {
                        String nodeTime = node.getAttributeValue("runtime");
                        runtime = 1000 * Double.parseDouble(nodeTime);
                        if (runtime < 100) {
                            runtime = 100;
                        }
                        length = (long) runtime;
                    } else {
                        Log.printLine("Cannot find runtime for " + nodeName + ",set it to be 0");
                    } //multiple the scale, by default it is 1.0
                    length *= Parameters.getRuntimeScale();
                    List<Element> fileList = node.getChildren();
                    List<FileItem> mFileList = new ArrayList<>();
                    for (Element file : fileList) {
                        if (file.getName().toLowerCase().equals("uses")) {
                            String fileName = file.getAttributeValue("name");//DAX version 3.3
                            if (fileName == null) {
                                fileName = file.getAttributeValue("file");//DAX version 3.0
                            }
                            if (fileName == null) {
                                Log.print("Error in parsing xml");
                            }

                            String inout = file.getAttributeValue("link");
                            double size = 0.0;

                            String fileSize = file.getAttributeValue("size");
                            if (fileSize != null) {
                                size = Double.parseDouble(fileSize) /*/ 1024*/;
                            } else {
                                Log.printLine("File Size not found for " + fileName);
                            }

                            /**
                             * a bug of cloudsim, size 0 causes a problem. 1
                             * is ok.
                             */
                            if (size == 0) {
                                size++;
                            }
                            /**
                             * Sets the file type 1 is input 2 is output
                             */
                            FileType type = FileType.NONE;
                            switch (inout) {
                            case "input":
                                type = FileType.INPUT;
                                break;
                            case "output":
                                type = FileType.OUTPUT;
                                break;
                            default:
                                Log.printLine("Parsing Error");
                                break;
                            }
                            FileItem tFile;
                            /*
                             * Already exists an input file (forget output file)
                             */
                            if (size < 0) {
                                /*
                                 * Assuming it is a parsing error
                                 */
                                size = 0 - size;
                                Log.printLine("Size is negative, I assume it is a parser error");
                            }
                            /*
                             * Note that CloudSim use size as MB, in this case we use it as Byte
                             */
                            if (type == FileType.OUTPUT) {
                                /**
                                 * It is good that CloudSim does tell
                                 * whether a size is zero
                                 */
                                tFile = new FileItem(fileName, size);
                            } else if (ReplicaCatalog.containsFile(fileName)) {
                                tFile = ReplicaCatalog.getFile(fileName);
                            } else {

                                tFile = new FileItem(fileName, size);
                                ReplicaCatalog.setFile(fileName, tFile);
                            }

                            tFile.setType(type);
                            mFileList.add(tFile);

                        }
                    }
                    Task task;
                    //In case of multiple workflow submission. Make sure the jobIdStartsFrom is consistent.
                    synchronized (this) {
                        task = new Task(this.jobIdStartsFrom, length);
                        this.jobIdStartsFrom++;
                    }
                    task.setType(nodeType);
                    task.setUserId(userId);
                    mName2Task.put(nodeName, task);
                    for (FileItem file : mFileList) {
                        task.addRequiredFile(file.getName());
                    }
                    task.setFileList(mFileList);
                    this.getTaskList().add(task);

                    /**
                     * Add dependencies info.
                     */
                    break;
                case "child":
                    List<Element> pList = node.getChildren();
                    String childName = node.getAttributeValue("ref");
                    if (mName2Task.containsKey(childName)) {

                        Task childTask = (Task) mName2Task.get(childName);

                        for (Element parent : pList) {
                            String parentName = parent.getAttributeValue("ref");
                            if (mName2Task.containsKey(parentName)) {
                                Task parentTask = (Task) mName2Task.get(parentName);
                                parentTask.addChild(childTask);
                                childTask.addParent(parentTask);
                            }
                        }
                    }
                    break;
                }
            }
            /**
             * If a task has no parent, then it is root task.
             */
            ArrayList roots = new ArrayList<>();
            for (Task task : mName2Task.values()) {
                task.setDepth(0);
                if (task.getParentList().isEmpty()) {
                    roots.add(task);
                }
            }

            /**
             * Add depth from top to bottom.
             */
            for (Iterator it = roots.iterator(); it.hasNext();) {
                Task task = (Task) it.next();
                setDepth(task, 1);
            }
            /**
             * Clean them so as to save memory. Parsing workflow may take much
             * memory
             */
            this.mName2Task.clear();

        } catch (JDOMException jde) {
            Log.printLine("JDOM Exception;Please make sure your dax file is valid");

        } catch (IOException ioe) {
            Log.printLine("IO Exception;Please make sure dax.path is correctly set in your config file");

        } catch (Exception e) {
            e.printStackTrace();
            Log.printLine("Parsing Exception");
        }
    }
}