Package org.jbpm.jobexecutor

Source Code of org.jbpm.jobexecutor.JobExecutor

/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jbpm.jobexecutor;

import java.io.Serializable;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Logger;

import org.jbpm.PvmException;
import org.jbpm.client.Command;
import org.jbpm.client.CommandService;

/** manager for job execution threads and their configuration.
*
* @author Tom Baeyens, Guillaume Porcher
*/
public class JobExecutor implements Serializable {
  private static final Logger log = Logger.getLogger(JobExecutor.class.getName());

  private static final long serialVersionUID = 1L;

  // configuration parameters
 
  CommandService commandService;
  String name = "JobExecutor-"+getHostName();
  int nbrOfThreads = 3;
  int idleMillis = 5000; // default normal poll interval is 5 seconds
  int idleMillisMax = 1000*60*2; // default max poll interval in case of continuous exceptions is 2 minutes
  int historySize = 200;
  int lockMillis = 1000*60*30; // default max lock time is 30 minutes
  // after jobs are executed, the job executor checks if the locktimout has passed.
  // if that is the case, the tx will be rolled back.  potentially there could be a
  // small racecondition between the moment that the job executor thread checks for the
  // lock time out and the moment that the dispatcher thread 'sees' the job because the
  // lock timeout has passed.  the lock buffer time is added to the lock time in the query
  // that scans for jobs to acquire.
  int lockMillisBuffer = 5000; // 5 seconds

  // runtime state

  Command acquireJobsCommand;
  Command nextDueDateCommand;
 
  boolean isActive = false;

  JobExecutorThreadPool jobExecutorThreadPool;
 
  DispatcherThread dispatcherThread = null;
 
  /** queue to dispatch collections of jobDbids to the JobExecutorThreads, which are
   * competing readers. */
  BlockingQueue<Collection<Long>> jobDbidsQueue = null;

  List<JobHistoryEntry> history = new ArrayList<JobHistoryEntry>();
 
  /** starts the {@link DispatcherThread} and {@link JobExecutorThread}s for this job executor */
  public synchronized void start() {
    if (commandService==null) {
      throw new PvmException("no command executor available in job executor");
    }
    if (! isActive) {
      acquireJobsCommand = new AcquireJobs(this);
      nextDueDateCommand = new NextDueDate(this);
     
      // the max capacity of the jobDbidsQueue is set to nbrOfJobExecutorThreads. 
      // That way, the distpatcher thread will be stalled if enough jobs are acquired.
      jobDbidsQueue = new ArrayBlockingQueue<Collection<Long>>(nbrOfThreads, true);

      isActive = true;
      log.finest("starting job executor threads for job executor '"+name+"'...");
      jobExecutorThreadPool = new JobExecutorThreadPool(this);
      jobExecutorThreadPool.start();

      log.finest("starting dispatcher thread for job executor '"+name+"'...");
      dispatcherThread = new DispatcherThread(this);
      dispatcherThread.start();
     
    } else {
      log.finest("ignoring start: job executor '"+name+"' is already started'");
    }
  }
 
  /** stops with join set to false.
   * @see #stop(boolean) */
  public synchronized void stop() {
    stop(false);
  }
 
  /** signals to all threads managed by this job executor to stop.  Stopping the
   * dispatcher thread is blocking till the dispatcher is no more alive.  If join is set to true,
   * this method will block until all job executor threads
   * are joined and actually dead. If join is false, the job executor threads are only told to
   * stop, without waiting till they are actually stopped. It may be that job executor threads
   * are in the middle of executing a job and they may finish after this method returned.
   */
  public synchronized void stop(boolean join) {
    log.fine("stopping job executor");
    if (isActive) {
      isActive = false;
      dispatcherThread.deactivate(true);
      waitTillQueueEmpty();
      jobExecutorThreadPool.deactivate(join);
    } else {
      log.finest("ignoring stop: job executor '"+name+"' not started");
    }
  }

  protected void waitTillQueueEmpty() {
    while (! jobDbidsQueue.isEmpty()) {
      log.finest("waiting for job-id-queue to become empty");
      try {
        Thread.sleep(200);
      } catch (InterruptedException e) {
        log.finest("waiting for job-id-queue to become empty got interrupted");
      }
    }
  }

  public void jobWasAdded() {
    if ( (dispatcherThread!=null)
         && (dispatcherThread.isActive())
       ) {
      dispatcherThread.jobWasAdded();
    }
  }

  protected static String getHostName() {
    try {
      return InetAddress.getLocalHost().getHostAddress();
    } catch (Exception e) {
      return "unknown";
    }
  }

  protected BlockingQueue<Collection<Long>> getJobDbidsQueue() {
    return jobDbidsQueue;
  }

  // getters //////////////////////////////////////////////////////////////////
 
  public String getName() {
    return name;
  }
  public int getHistorySize() {
    return historySize;
  }
  public int getIdleMillis() {
    return idleMillis;
  }
  public boolean isActive() {
    return isActive;
  }
  public int getIdleMillisMax() {
    return idleMillisMax;
  }
  public int getLockMillis() {
    return lockMillis;
  }
  public int getLockMillisBuffer() {
    return lockMillisBuffer;
  }
  public int getNbrOfThreads() {
    return nbrOfThreads;
  }
  public CommandService getCommandExecutor() {
    return commandService;
  }
  public Command getAcquireJobsCommand() {
    return acquireJobsCommand;
  }
  public Command getNextDueDateCommand() {
    return nextDueDateCommand;
  }
  public DispatcherThread getDispatcherThread() {
    return dispatcherThread;
  }
  public List<JobHistoryEntry> getHistory() {
    return history;
  }

  // configuration setters ////////////////////////////////////////////////////

  public void setCommandExecutor(CommandService commandService) {
    this.commandService = commandService;
  }
  public void setName(String name) {
    this.name = name;
  }
  public void setNbrOfJobExecutorThreads(int nbrOfJobExecutorThreads) {
    this.nbrOfThreads = nbrOfJobExecutorThreads;
  }
  public void setIdleInterval(int idleInterval) {
    this.idleMillis = idleInterval;
  }
  public void setMaxIdleInterval(int maxIdleInterval) {
    this.idleMillisMax = maxIdleInterval;
  }
  public void setHistoryMaxSize(int historyMaxSize) {
    this.historySize = historyMaxSize;
  }
  public void setMaxLockTime(int maxLockTime) {
    this.lockMillis = maxLockTime;
  }
  public void setLockBufferPeriod(int lockBufferPeriod) {
    this.lockMillisBuffer = lockBufferPeriod;
  }
}
TOP

Related Classes of org.jbpm.jobexecutor.JobExecutor

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.