Package org.jbpm.jobexecutor

Source Code of org.jbpm.jobexecutor.DispatcherThread

/*
* 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.util.Collection;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

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

/** this thread is responsible for acquiring jobs in the job that need to be
* executed and then let the JobExecutor dispatch the acquired ids to one of the
* JobExecutorThreads in the pool.  There is only one dispatcher thread per
* JobExecutor. 
*
* @author Tom Baeyens, Guillaume Porcher
*/
public class DispatcherThread extends Thread {

  private static final Logger log = Logger.getLogger(DispatcherThread.class.getName());
 
  JobExecutor jobExecutor;
  boolean isActive;
  boolean checkForNewJobs;
  int currentIdleInterval;
  Object semaphore = new Object();

  DispatcherThread(JobExecutor jobExecutor) {
    this(jobExecutor, "DispatcherThread");
  }

  DispatcherThread(JobExecutor jobExecutor, String name) {
    super(name);
    this.jobExecutor = jobExecutor;
  }

  public void run() {
    log.info("starting...");
    isActive = true;
    currentIdleInterval = jobExecutor.getIdleMillis();
    try {
      while (isActive) {
        try {
          // checkForNewJobs is set to true in jobWasAdded() below
          checkForNewJobs = false;

          // try to acquire jobs
          Collection<Long> acquiredJobDbids = acquireJobs();

          // no exception so resetting the currentIdleInterval
          currentIdleInterval = jobExecutor.getIdleMillis();

          if ((acquiredJobDbids != null) && (!acquiredJobDbids.isEmpty())) {
            putAcquiredJobDbidsOnQueue(acquiredJobDbids);
            log.info("added jobs "+acquiredJobDbids+" to the queue");

          } else if (isActive) {
            long waitPeriod = getWaitPeriod();
            if (waitPeriod > 0) {
              synchronized (semaphore) {
                if (!checkForNewJobs) {
                  log.fine(getName()+" will wait for max "+waitPeriod+"ms on "+jobExecutor);
                  semaphore.wait(waitPeriod);
                  log.fine(getName()+" woke up");
                } else {
                  log.fine("skipped wait because new message arrived");
                }
              }
            }
          }

        } catch (InterruptedException e) {
          log.info((isActive ? "active" : "inactivated") + " job dispatcher thread '" + getName() + "' got interrupted");
        } catch (Exception e) {
          log.log(Level.SEVERE, "exception in job executor thread. waiting " + currentIdleInterval + " milliseconds", e);
          try {
            synchronized (semaphore) {
              semaphore.wait(currentIdleInterval);
            }
          } catch (InterruptedException e2) {
            log.log(Level.FINEST, "delay after exception got interrupted", e2);
          }
          // after an exception, the current idle interval is doubled to prevent
          // continuous exception generation when e.g. the db is unreachable
          currentIdleInterval = currentIdleInterval * 2;
        }
      }
    } catch (Throwable t) {
      t.printStackTrace();
    } finally {
      log.info(getName() + " leaves cyberspace");
    }
  }

  protected void putAcquiredJobDbidsOnQueue(Collection<Long> acquiredJobDbids) {
    log.fine("pushing jobs on the queue "+acquiredJobDbids);
    while (acquiredJobDbids!=null) {
      try {
        jobExecutor.getJobDbidsQueue().put(acquiredJobDbids);
        log.finest("jobs "+acquiredJobDbids+" were put on the queue");
        acquiredJobDbids = null;
      } catch (InterruptedException e) {
        log.finest("putting acquired job dbids got interrupted. retrying...");
      }
    }
  }

  protected Collection<Long> acquireJobs() {
    CommandService commandService = jobExecutor.getCommandExecutor();
    Command acquireJobsCommand = jobExecutor.getAcquireJobsCommand();
    return (Collection<Long>) commandService.execute(acquireJobsCommand);
  }

  protected Date getNextDueDate() {
    CommandService commandService = jobExecutor.getCommandExecutor();
    Command getNextDueDate = jobExecutor.getNextDueDateCommand();
    return (Date) commandService.execute(getNextDueDate);
  }

  protected long getWaitPeriod() {
    long interval = jobExecutor.getIdleMillis();
    Date nextDueDate = getNextDueDate();
    if (nextDueDate != null) {
      long currentTimeMillis = System.currentTimeMillis();
      long nextDueDateTime = nextDueDate.getTime();
      if (nextDueDateTime < currentTimeMillis + currentIdleInterval) {
        interval = nextDueDateTime - currentTimeMillis;
      }
    }
    if (interval < 0) {
      interval = 0;
    }
    return interval;
  }

  public void deactivate() {
    deactivate(false);
  }
 
  public void deactivate(boolean join) {
    if (isActive) {
      log.fine("deactivating "+getName());
      isActive = false;
      interrupt();
      if (join) {
        while (isAlive()) {
          try {
            log.fine("joining "+getName());
            join();
          } catch (InterruptedException e) {
            log.finest("joining "+getName()+" got interrupted");
          }
        }
      }
    } else {
      log.finest("ignoring deactivate: "+getName()+" is not active");
    }
  }

  public void jobWasAdded() {
    log.finest("notifying job executor dispatcher thread of new job");
    synchronized (semaphore) {
      checkForNewJobs = true;
      semaphore.notify();
    }
  }

  public boolean isActive() {
    return isActive;
  }
}
TOP

Related Classes of org.jbpm.jobexecutor.DispatcherThread

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.