Package org.apache.oodt.cas.workflow.engine

Source Code of org.apache.oodt.cas.workflow.engine.ThreadPoolWorkflowEngine

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.oodt.cas.workflow.engine;

//OODT imports
import org.apache.oodt.cas.metadata.Metadata;
import org.apache.oodt.cas.resource.system.XmlRpcResourceManagerClient;
import org.apache.oodt.cas.workflow.structs.Workflow;
import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
import org.apache.oodt.cas.workflow.structs.WorkflowStatus;
import org.apache.oodt.cas.workflow.structs.WorkflowTask;
import org.apache.oodt.cas.workflow.structs.exceptions.EngineException;
import org.apache.oodt.cas.workflow.structs.exceptions.InstanceRepositoryException;
import org.apache.oodt.cas.workflow.engine.IterativeWorkflowProcessorThread;
import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
import org.apache.oodt.commons.util.DateConvert;

//JDK imports
import java.net.URL;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

//java.util.concurrent imports
import EDU.oswego.cs.dl.util.concurrent.BoundedBuffer;
import EDU.oswego.cs.dl.util.concurrent.Channel;
import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;

/**
* @author mattmann
* @version $Revsion$
*
* <p>
* The ThreadPooling portion of the WorkflowEngine. This class is meant to be an
* extension point for WorkflowEngines that want to implement ThreadPooling.
* This WorkflowEngine provides everything needed to manage a ThreadPool using
* Doug Lea's wonderful java.util.concurrent package that made it into JDK5.
* </p>
*/
public class ThreadPoolWorkflowEngine implements WorkflowEngine, WorkflowStatus {

    /* our thread pool */
    private PooledExecutor pool = null;

    /* our worker thread hash mapping worker threads to workflow instance ids */
    private HashMap workerMap = null;

    /* our log stream */
    private static final Logger LOG = Logger
            .getLogger(ThreadPoolWorkflowEngine.class.getName());

    /* our instance repository */
    private WorkflowInstanceRepository instRep = null;

    /* our resource manager client */
    private XmlRpcResourceManagerClient rClient = null;

    /* the URL pointer to the parent Workflow Manager */
    private URL wmgrUrl = null;

    /**
     * Default Constructor.
     *
     * @param instRep
     *            The WorkflowInstanceRepository to be used by this engine.
     * @param queueSize
     *            The size of the queue that the workflow engine should use
     *            (irrelevant if unlimitedQueue is set to true)
     * @param maxPoolSize
     *            The minimum thread pool size.
     * @param minPoolSize
     *            The maximum thread pool size.
     * @param threadKeepAliveTime
     *            The amount of minutes that each thread in the pool should be
     *            kept alive.
     * @param unlimitedQueue
     *            Whether or not to use a queue whose bounds are dictated by the
     *            physical memory of the underlying hardware.
     * @param resUrl
     *            A URL pointer to a resource manager. If this is set Tasks will
     *            be wrapped as Resource Manager {@link Job}s and sent through
     *            the Resource Manager. If this parameter is not set, local
     *            execution (the default) will be used
     */
    public ThreadPoolWorkflowEngine(WorkflowInstanceRepository instRep,
            int queueSize, int maxPoolSize, int minPoolSize,
            long threadKeepAliveTime, boolean unlimitedQueue, URL resUrl) {

        this.instRep = instRep;
        Channel c = null;
        if (unlimitedQueue) {
            c = new LinkedQueue();
        } else {
            c = new BoundedBuffer(queueSize);
        }

        pool = new PooledExecutor(c, maxPoolSize);
        pool.setMinimumPoolSize(minPoolSize);
        pool.setKeepAliveTime(1000 * 60 * threadKeepAliveTime);

        workerMap = new HashMap();

        if (resUrl != null)
            rClient = new XmlRpcResourceManagerClient(resUrl);
    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.oodt.cas.workflow.engine.WorkflowEngine#pauseWorkflowInstance(java.lang.String)
     */
    public synchronized void pauseWorkflowInstance(String workflowInstId) {
        // okay, try and look up that worker thread in our hash map
        IterativeWorkflowProcessorThread worker = (IterativeWorkflowProcessorThread) workerMap
                .get(workflowInstId);
        if (worker == null) {
            LOG
                    .log(
                            Level.WARNING,
                            "WorkflowEngine: Attempt to pause workflow instance id: "
                                    + workflowInstId
                                    + ", however, this engine is not tracking its execution");
            return;
        }

        // otherwise, all good
        worker.pause();

    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.oodt.cas.workflow.engine.WorkflowEngine#resumeWorkflowInstance(java.lang.String)
     */
    public synchronized void resumeWorkflowInstance(String workflowInstId) {
        // okay, try and look up that worker thread in our hash map
        IterativeWorkflowProcessorThread worker = (IterativeWorkflowProcessorThread) workerMap
                .get(workflowInstId);
        if (worker == null) {
            LOG.log(Level.WARNING,
                    "WorkflowEngine: Attempt to resume workflow instance id: "
                            + workflowInstId + ", however, this engine is "
                            + "not tracking its execution");
            return;
        }

        // also check to make sure that the worker is currently paused
        // only can resume WorkflowInstances that are paused, right?
        if (!worker.isPaused()) {
            LOG.log(Level.WARNING,
                    "WorkflowEngine: Attempt to resume a workflow that "
                            + "isn't paused currently: instance id: "
                            + workflowInstId);
            return;
        }

        // okay, all good
        worker.resume();

    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.oodt.cas.workflow.engine.WorkflowEngine#startWorkflow(org.apache.oodt.cas.workflow.structs.Workflow,
     *      org.apache.oodt.cas.metadata.Metadata)
     */
    public synchronized WorkflowInstance startWorkflow(Workflow workflow,
            Metadata metadata) throws EngineException {
        // to start the workflow, we create a default workflow instance
        // populate it
        // persist it
        // add it to the worker map
        // start it

        WorkflowInstance wInst = new WorkflowInstance();
        wInst.setWorkflow(workflow);
        wInst.setCurrentTaskId(((WorkflowTask) workflow.getTasks().get(0))
                .getTaskId());
        wInst.setSharedContext(metadata);
        wInst.setStatus(CREATED);
        persistWorkflowInstance(wInst);

        IterativeWorkflowProcessorThread worker = new IterativeWorkflowProcessorThread(
                wInst, instRep, this.wmgrUrl);
        worker.setRClient(rClient);
        workerMap.put(wInst.getId(), worker);

        wInst.setStatus(QUEUED);
        persistWorkflowInstance(wInst);

        try {
            pool.execute(worker);
        } catch (InterruptedException e) {
            throw new EngineException(e);
        }

        return wInst;

    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.oodt.cas.workflow.engine.WorkflowEngine#getInstanceRepository()
     */
    public WorkflowInstanceRepository getInstanceRepository() {
        return this.instRep;
    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.oodt.cas.workflow.engine.WorkflowEngine#updateMetadata(java.lang.String,
     *      org.apache.oodt.cas.metadata.Metadata)
     */
    public synchronized boolean updateMetadata(String workflowInstId,
            Metadata met) {
        // okay, try and look up that worker thread in our hash map
        IterativeWorkflowProcessorThread worker = (IterativeWorkflowProcessorThread) workerMap
                .get(workflowInstId);
        if (worker == null) {
            LOG.log(Level.WARNING,
                    "WorkflowEngine: Attempt to update metadata context "
                            + "for workflow instance id: " + workflowInstId
                            + ", however, this engine is "
                            + "not tracking its execution");
            return false;
        }

        worker.getWorkflowInstance().setSharedContext(met);
        try {
            persistWorkflowInstance(worker.getWorkflowInstance());
        } catch (Exception e) {
            LOG.log(Level.WARNING, "Exception persisting workflow instance: ["
                    + worker.getWorkflowInstance().getId() + "]: Message: "
                    + e.getMessage());
            return false;
        }

        return true;
    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.oodt.cas.workflow.engine.WorkflowEngine#setWorkflowManagerUrl(java.net.URL)
     */
    public void setWorkflowManagerUrl(URL url) {
        this.wmgrUrl = url;
    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.oodt.cas.workflow.engine.WorkflowEngine#stopWorkflow(java.lang.String)
     */
    public synchronized void stopWorkflow(String workflowInstId) {
        // okay, try and look up that worker thread in our hash map
        IterativeWorkflowProcessorThread worker = (IterativeWorkflowProcessorThread) workerMap
                .get(workflowInstId);
        if (worker == null) {
            LOG.log(Level.WARNING,
                    "WorkflowEngine: Attempt to stop workflow instance id: "
                            + workflowInstId + ", however, this engine is "
                            + "not tracking its execution");
            return;
        }

        worker.stop();
    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.oodt.cas.workflow.engine.WorkflowEngine#getCurrentTaskWallClockMinutes(java.lang.String)
     */
    public double getCurrentTaskWallClockMinutes(String workflowInstId) {
        // get the workflow instance that we're talking about
        WorkflowInstance inst = safeGetWorkflowInstanceById(workflowInstId);
        return getCurrentTaskWallClockMinutes(inst);
    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.oodt.cas.workflow.engine.WorkflowEngine#getWorkflowInstanceMetadata(java.lang.String)
     */
    public Metadata getWorkflowInstanceMetadata(String workflowInstId) {
        // okay, try and look up that worker thread in our hash map
        IterativeWorkflowProcessorThread worker = (IterativeWorkflowProcessorThread) workerMap
                .get(workflowInstId);
        if (worker == null) {
            // try and get the metadata
            // from the workflow instance repository (as it was persisted)
            try {
                WorkflowInstance inst = instRep
                        .getWorkflowInstanceById(workflowInstId);
                return inst.getSharedContext();
            } catch (InstanceRepositoryException e) {
                LOG.log(Level.FINEST,
                        "WorkflowEngine: Attempt to get metadata "
                                + "for workflow instance id: " + workflowInstId
                                + ", however, this engine is "
                                + "not tracking its execution and the id: ["
                                + workflowInstId + "] "
                                + "was never persisted to "
                                + "the instance repository");
                e.printStackTrace();
                return new Metadata();
            }
        }

        return worker.getWorkflowInstance().getSharedContext();
    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.oodt.cas.workflow.engine.WorkflowEngine#getWallClockMinutes(java.lang.String)
     */
    public double getWallClockMinutes(String workflowInstId) {
        // get the workflow instance that we're talking about
        WorkflowInstance inst = safeGetWorkflowInstanceById(workflowInstId);
        return getWallClockMinutes(inst);
    }

    protected static double getWallClockMinutes(WorkflowInstance inst) {
        if (inst == null) {
            return 0.0;
        }

        Date currentDateOrStopTime = (inst.getEndDateTimeIsoStr() != null
                && !inst.getEndDateTimeIsoStr().equals("") && !inst
                .getEndDateTimeIsoStr().equals("null")) ? safeDateConvert(inst
                .getEndDateTimeIsoStr()) : new Date();

        Date workflowStartDateTime = null;

        if (inst.getStartDateTimeIsoStr() == null
                || (inst.getStartDateTimeIsoStr() != null && (inst
                        .getStartDateTimeIsoStr().equals("") || inst
                        .getStartDateTimeIsoStr().equals("null")))) {
            return 0.0;
        }

        try {
            workflowStartDateTime = DateConvert.isoParse(inst
                    .getStartDateTimeIsoStr());
        } catch (ParseException e) {
            return 0.0;
        }

        long diffMs = currentDateOrStopTime.getTime()
                - workflowStartDateTime.getTime();
        double diffSecs = (diffMs * 1.0 / 1000.0);
        double diffMins = diffSecs / 60.0;
        return diffMins;

    }

    protected static double getCurrentTaskWallClockMinutes(WorkflowInstance inst) {
        if (inst == null) {
            return 0.0;
        }

        Date currentDateOrStopTime = (inst.getCurrentTaskEndDateTimeIsoStr() != null
                && !inst.getCurrentTaskEndDateTimeIsoStr().equals("") && !inst
                .getCurrentTaskEndDateTimeIsoStr().equals("null")) ? safeDateConvert(inst
                .getCurrentTaskEndDateTimeIsoStr())
                : new Date();

        Date workflowTaskStartDateTime = null;

        if (inst.getCurrentTaskStartDateTimeIsoStr() == null
                || (inst.getCurrentTaskStartDateTimeIsoStr() != null && (inst
                        .getCurrentTaskStartDateTimeIsoStr().equals("") || inst
                        .getCurrentTaskStartDateTimeIsoStr().equals("null")))) {
            return 0.0;
        }

        try {
            workflowTaskStartDateTime = DateConvert.isoParse(inst
                    .getCurrentTaskStartDateTimeIsoStr());
        } catch (ParseException e) {
            return 0.0;
        }

        // should never be in this state, so return 0
        if (workflowTaskStartDateTime.after(currentDateOrStopTime)) {
            LOG.log(Level.WARNING, "Start date time: ["
                    + DateConvert.isoFormat(workflowTaskStartDateTime)
                    + " of workflow inst [" + inst.getId() + "] is AFTER "
                    + "End date time: ["
                    + DateConvert.isoFormat(currentDateOrStopTime)
                    + "] of workflow inst.");
            return 0.0;
        }

        long diffMs = currentDateOrStopTime.getTime()
                - workflowTaskStartDateTime.getTime();
        double diffSecs = (diffMs * 1.0 / 1000.0);
        double diffMins = diffSecs / 60.0;
        return diffMins;
    }

    private synchronized void persistWorkflowInstance(WorkflowInstance wInst)
            throws EngineException {

        try {
            if (wInst.getId() == null
                    || (wInst.getId() != null && wInst.getId().equals(""))) {
                // we have to persist it by adding it
                // rather than updating it
                instRep.addWorkflowInstance(wInst);

            } else {
                // persist by update
                instRep.updateWorkflowInstance(wInst);
            }
        } catch (InstanceRepositoryException e) {
            e.printStackTrace();
            throw new EngineException(e.getMessage());
        }

    }

    private WorkflowInstance safeGetWorkflowInstanceById(String workflowInstId) {
        try {
            return instRep.getWorkflowInstanceById(workflowInstId);
        } catch (Exception e) {
            return null;
        }
    }

    private static Date safeDateConvert(String isoTimeStr) {
        try {
            return DateConvert.isoParse(isoTimeStr);
        } catch (Exception ignore) {
            ignore.printStackTrace();
            return null;
        }
    }

}
TOP

Related Classes of org.apache.oodt.cas.workflow.engine.ThreadPoolWorkflowEngine

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.