[jbpm-commits] JBoss JBPM SVN: r7059 - in jbpm3/branches/jbpm-3.2-soa/core/src: main/java/org/jbpm/job/executor and 7 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Tue Feb 21 21:13:15 EST 2012


Author: marco.rietveld
Date: 2012-02-21 21:13:14 -0500 (Tue, 21 Feb 2012)
New Revision: 7059

Added:
   jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/Jbpm3430/
   jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/Jbpm3430/JBPM3430Test.java
   jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/job/executor/DispatcherAndJobExecutorMethodTest.java
   jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm3430/
   jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm3430/hibernate.postgresql.properties
   jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm3430/jbpm-3430.cfg.xml
   jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/spy.properties
Modified:
   jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/db/JobSession.java
   jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/job/executor/DispatcherThread.java
   jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/job/executor/JobExecutor.java
   jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/job/executor/JobExecutorThread.java
   jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/org/jbpm/db/hibernate.queries.hbm.xml
Log:
JBPM-3430: rewrite queries for calculating due date, clean up Job executor/dispatcher code. 

Modified: jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/db/JobSession.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/db/JobSession.java	2012-02-22 02:06:32 UTC (rev 7058)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/db/JobSession.java	2012-02-22 02:13:14 UTC (rev 7059)
@@ -21,7 +21,7 @@
  */
 package org.jbpm.db;
 
-import java.util.Collection;
+import java.sql.Timestamp;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
@@ -30,15 +30,27 @@
 import org.hibernate.LockMode;
 import org.hibernate.Query;
 import org.hibernate.Session;
-import org.hibernate.criterion.Restrictions;
-
+import org.jbpm.command.ExecuteJobsCommand;
 import org.jbpm.graph.def.Action;
 import org.jbpm.graph.exe.ProcessInstance;
 import org.jbpm.graph.exe.Token;
 import org.jbpm.job.Job;
 import org.jbpm.job.Timer;
+import org.jbpm.job.executor.JobExecutor;
 import org.jbpm.persistence.JbpmPersistenceException;
 
+/**
+ * This is the utility class that deals with Job persistence. 
+ * It has a bunch of methods that have been grouped according to who uses the methods: 
+ * <ul>
+ *   <li>General use</li>
+ *   <li>DispatcherThread, {@link JobExecutor}, etc.</li>
+ *   <li>Service</li>
+ *   <li>{@link Token}</li>
+ *   <li>{@link ProcessInstance}</li>
+ *   <li>Various commands, including the {@link ExecuteJobsCommand}</li>
+ * </ul>
+ */
 public class JobSession {
 
   private final Session session;
@@ -47,71 +59,7 @@
     this.session = session;
   }
 
-  public Job getFirstAcquirableJob(String lockOwner) {
-    try {
-      Query query;
-      if (lockOwner == null) {
-        query = session.getNamedQuery("JobSession.getFirstUnownedAcquirableJob");
-      }
-      else {
-        query = session.getNamedQuery("JobSession.getFirstAcquirableJob")
-          .setString("lockOwner", lockOwner);
-      }
-      return (Job) query.setTimestamp("now", new Date()).setMaxResults(1).uniqueResult();
-    }
-    catch (HibernateException e) {
-      throw new JbpmPersistenceException("could not get first acquirable job", e);
-    }
-  }
-
-  public List findExclusiveJobs(String lockOwner, ProcessInstance processInstance) {
-    try {
-      return session.getNamedQuery("JobSession.findExclusiveJobs")
-        .setString("lockOwner", lockOwner)
-        .setTimestamp("now", new Date())
-        .setParameter("processInstance", processInstance)
-        .list();
-    }
-    catch (HibernateException e) {
-      throw new JbpmPersistenceException("could not find exclusive jobs owned by '" + lockOwner
-        + "' for " + processInstance, e);
-    }
-  }
-
-  public List findJobsByToken(Token token) {
-    try {
-      return session.getNamedQuery("JobSession.findJobsByToken")
-        .setParameter("token", token)
-        .list();
-    }
-    catch (HibernateException e) {
-      throw new JbpmPersistenceException("could not find jobs for " + token, e);
-    }
-  }
-
-  public Job getFirstDueJob(String lockOwner, Collection monitoredJobs) {
-    try {
-      Query query;
-      if (lockOwner == null) {
-        query = session.getNamedQuery("JobSession.getFirstUnownedDueJob");
-      }
-      else if (monitoredJobs == null || monitoredJobs.isEmpty()) {
-        query = session.getNamedQuery("JobSession.getFirstDueJob")
-          .setString("lockOwner", lockOwner);
-      }
-      else {
-        query = session.getNamedQuery("JobSession.getFirstDueJobExcludingMonitoredJobs")
-          .setString("lockOwner", lockOwner)
-          .setParameterList("monitoredJobIds", monitoredJobs);
-      }
-      return (Job) query.setMaxResults(1).uniqueResult();
-    }
-    catch (HibernateException e) {
-      throw new JbpmPersistenceException("could not get first due job owned by '" + lockOwner
-        + "' ignoring jobs " + monitoredJobs, e);
-    }
-  }
-
+  // Services
   public void saveJob(Job job) {
     try {
       session.save(job);
@@ -119,7 +67,8 @@
         Timer timer = (Timer) job;
         Action action = timer.getAction();
         // if action is transient, save it
-        if (action != null && action.getId() == 0L) session.save(action);
+        if (action != null && action.getId() == 0L) 
+          session.save(action);
       }
     }
     catch (HibernateException e) {
@@ -127,6 +76,7 @@
     }
   }
 
+  // EVERYTHING
   public void deleteJob(Job job) {
     try {
       session.delete(job);
@@ -136,21 +86,13 @@
     }
   }
 
-  public Job loadJob(long jobId) {
-    try {
-      return (Job) session.load(Job.class, new Long(jobId));
-    }
-    catch (HibernateException e) {
-      throw new JbpmPersistenceException("could not load job " + jobId, e);
-    }
-  }
-
   /**
    * Reattach job originally loaded in a previous session.
    * 
    * @param job a detached job
    * @see <a href="http://tinyurl.com/kjss69">Detached objects and automatic versioning</a>
    */
+  // JobExecutor, ExecuteJobsCommand
   public void reattachJob(Job job) {
     try {
       session.lock(job, LockMode.NONE);
@@ -160,24 +102,72 @@
     }
   }
 
-  public Timer loadTimer(long timerId) {
+  // Services
+  public void deleteTimersByName(String name, Token token) {
     try {
-      return (Timer) session.load(Timer.class, new Long(timerId));
+      // delete unowned timers
+      session.getNamedQuery("JobSession.deleteTimersByName")
+        .setString("name", name)
+        .setParameter("token", token)
+        .executeUpdate();
+  
+      // prevent further repetitions
+      List timers = session.getNamedQuery("JobSession.findRepeatingTimersByName")
+        .setString("name", name)
+        .setParameter("token", token)
+        .list();
+      preventFurtherRepetitions(timers);
     }
     catch (HibernateException e) {
-      throw new JbpmPersistenceException("could not load timer " + timerId, e);
+      throw new JbpmPersistenceException("could not delete timers by name '" + name + "' for "
+        + token, e);
     }
   }
 
-  public Job getJob(long jobId) {
+  // Job Executor
+  public Job getFirstAcquirableJob(String lockOwner) {
     try {
-      return (Job) session.get(Job.class, new Long(jobId));
+      Query query;
+      if (lockOwner == null) {
+        query = session.getNamedQuery("JobSession.getFirstUnownedAcquirableJob");
+      }
+      else {
+        query = session.getNamedQuery("JobSession.getFirstAcquirableJob")
+          .setString("lockOwner", lockOwner);
+      }
+      return (Job) query.setTimestamp("now", new Date()).setMaxResults(1).uniqueResult();
     }
     catch (HibernateException e) {
-      throw new JbpmPersistenceException("could not get job " + jobId, e);
+      throw new JbpmPersistenceException("could not get first acquirable job", e);
     }
   }
+  
+  // Job Executor
+  public Date getNextUnownedDueJobDueDate(Date wakeUpDate) { 
+    try {
+      Query query = session.getNamedQuery("JobSession.getNextUnownedDueJobDueDate")
+                           .setTimestamp("wakeUpDate", wakeUpDate);
+      return (Timestamp) query.uniqueResult();
+    }
+    catch (HibernateException e) {
+      throw new JbpmPersistenceException("could not get next job due.");
+    }
+  }
 
+  // used by the LockMonitorThread
+  public List findJobsWithOverdueLockTime(Date threshold) {
+    try {
+      return session.getNamedQuery("JobSession.findJobsWithOverdueLockTime")
+        .setTimestamp("threshold", threshold)
+        .list();
+    }
+    catch (HibernateException e) {
+      throw new JbpmPersistenceException("could not find jobs with lock time over " + threshold,
+        e);
+    }
+  }
+
+  // Token
   public void suspendJobs(Token token) {
     try {
       session.getNamedQuery("JobSession.suspendJobs")
@@ -189,6 +179,7 @@
     }
   }
 
+  // Token
   public void resumeJobs(Token token) {
     try {
       session.getNamedQuery("JobSession.resumeJobs")
@@ -200,27 +191,7 @@
     }
   }
 
-  public void deleteTimersByName(String name, Token token) {
-    try {
-      // delete unowned timers
-      session.getNamedQuery("JobSession.deleteTimersByName")
-        .setString("name", name)
-        .setParameter("token", token)
-        .executeUpdate();
-
-      // prevent further repetitions
-      List timers = session.getNamedQuery("JobSession.findRepeatingTimersByName")
-        .setString("name", name)
-        .setParameter("token", token)
-        .list();
-      preventFurtherRepetitions(timers);
-    }
-    catch (HibernateException e) {
-      throw new JbpmPersistenceException("could not delete timers by name '" + name + "' for "
-        + token, e);
-    }
-  }
-
+  // ProcessInstance
   public int countDeletableJobsForProcessInstance(ProcessInstance processInstance) {
     Number jobCount = (Number) session.getNamedQuery("JobSession.countDeletableJobsForProcessInstance")
       .setParameter("processInstance", processInstance)
@@ -228,6 +199,7 @@
     return jobCount.intValue();
   }
 
+  // ProcessInstance
   public void deleteJobsForProcessInstance(ProcessInstance processInstance) {
     try {
       // delete unowned node-execute-jobs and timers
@@ -255,24 +227,51 @@
     }
   }
 
-  public List findJobsWithOverdueLockTime(Date threshold) {
+  // Change Process Instance Command
+  public List findJobsByToken(Token token) {
     try {
-      return session.getNamedQuery("JobSession.findJobsWithOverdueLockTime")
-        .setTimestamp("threshold", threshold)
+      return session.getNamedQuery("JobSession.findJobsByToken")
+        .setParameter("token", token)
         .list();
     }
     catch (HibernateException e) {
-      throw new JbpmPersistenceException("could not find jobs with lock time over " + threshold,
-        e);
+      throw new JbpmPersistenceException("could not find jobs for " + token, e);
     }
   }
 
-  public List loadJobs(long[] jobIds) {
-    int jobCount = jobIds.length;
-    Long[] jobs = new Long[jobCount];
-    for (int i = 0; i < jobCount; i++) {
-      jobs[i] = new Long(jobIds[i]);
+  // ExecuteJobCommand
+  public Job getJob(long jobId) {
+    try {
+      return (Job) session.get(Job.class, new Long(jobId));
     }
-    return session.createCriteria(Job.class).add(Restrictions.in("id", jobs)).list();
+    catch (HibernateException e) {
+      throw new JbpmPersistenceException("could not get job " + jobId, e);
+    }
   }
+
+  // ExecuteJobCommand & tests
+  public Timer loadTimer(long timerId) {
+    try {
+      return (Timer) session.load(Timer.class, new Long(timerId));
+    }
+    catch (HibernateException e) {
+      throw new JbpmPersistenceException("could not load timer " + timerId, e);
+    }
+  }
+
+  // Execute Jobs Command
+  public List findExclusiveJobs(String lockOwner, ProcessInstance processInstance) {
+    try {
+      return session.getNamedQuery("JobSession.findExclusiveJobs")
+        .setString("lockOwner", lockOwner)
+        .setTimestamp("now", new Date())
+        .setParameter("processInstance", processInstance)
+        .list();
+    }
+    catch (HibernateException e) {
+      throw new JbpmPersistenceException("could not find exclusive jobs owned by '" + lockOwner
+        + "' for " + processInstance, e);
+    }
+  }
+
 }

Modified: jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/job/executor/DispatcherThread.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/job/executor/DispatcherThread.java	2012-02-22 02:06:32 UTC (rev 7058)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/job/executor/DispatcherThread.java	2012-02-22 02:13:14 UTC (rev 7059)
@@ -21,18 +21,17 @@
  */
 package org.jbpm.job.executor;
 
+import java.util.Calendar;
 import java.util.Date;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-
 import org.jbpm.JbpmContext;
 import org.jbpm.job.Job;
 
 /**
  * Acquires jobs and then dispatches them to the job executor thread pool.
  * 
- * @author Alejandro Guizar
  */
 class DispatcherThread extends Thread implements Deactivable {
 
@@ -66,12 +65,15 @@
       // if still active, wait or sleep
       if (active) {
         try {
+          int currentIdleInterval = jobExecutor.getIdleInterval();
           // wait for next due job
-          long waitPeriod = getWaitPeriod(jobExecutor.getIdleInterval());
+          Date nextDueDate = getNextDueDateWithinIdleInterval(currentIdleInterval);
+          long waitPeriod = getWaitPeriod(currentIdleInterval, nextDueDate);
           if (waitPeriod > 0) {
             synchronized (jobExecutor) {
-              if (active)
+              if (active) {
                 jobExecutor.wait(waitPeriod);
+              }
             }
           }
         }
@@ -79,7 +81,9 @@
           if (log.isDebugEnabled()) log.debug(getName() + " got interrupted");
         }
       }
-    }
+      
+    } // while(active)
+    
     log.info(getName() + " leaves cyberspace");
   }
 
@@ -165,28 +169,35 @@
     }
   }
 
-  private long getWaitPeriod(int currentIdleInterval) {
-    Date nextDueDate = getNextDueDate();
+  static long getWaitPeriod(int currentIdleInterval, Date nextDueDate) {
+    // Have we found a job that should be called before now + current idle interval? 
     if (nextDueDate != null) {
       long waitPeriod = nextDueDate.getTime() - System.currentTimeMillis();
-      if (waitPeriod < currentIdleInterval) return waitPeriod;
+      
+      // next due date > now
+      if (waitPeriod < currentIdleInterval) { 
+        return waitPeriod;
+      }
     }
     return currentIdleInterval;
   }
 
-  private Date getNextDueDate() {
+  private Date getNextDueDateWithinIdleInterval(int currentIdleInterval) { 
     Date nextDueDate = null;
     JbpmContext jbpmContext = jobExecutor.getJbpmConfiguration().createJbpmContext();
     try {
-      Job job = jbpmContext.getJobSession().getFirstDueJob(null, null);
-      if (job != null) {
-        nextDueDate = job.getDueDate();
+      Calendar cal = Calendar.getInstance();
+      cal.add(Calendar.MILLISECOND, currentIdleInterval);
+      Date wakeUpDate = cal.getTime();
+      
+      nextDueDate = jbpmContext.getJobSession().getNextUnownedDueJobDueDate(wakeUpDate);
+      if (log.isDebugEnabled() && nextDueDate == null) { 
+        log.debug("no next waiting due job found before wake up date: possible future jobs after sleep");
       }
-      else if (log.isDebugEnabled()) log.debug("no due job found");
     }
     catch (RuntimeException e) {
       jbpmContext.setRollbackOnly();
-      if (log.isDebugEnabled()) log.debug("failed to determine next due date", e);
+      if (log.isDebugEnabled()) log.debug("failed to retrieve next waiting due job", e);
     }
     catch (Error e) {
       jbpmContext.setRollbackOnly();
@@ -198,7 +209,7 @@
       }
       catch (RuntimeException e) {
         nextDueDate = null;
-        if (log.isDebugEnabled()) log.debug("failed to determine next due date", e);
+        if (log.isDebugEnabled()) log.debug("failed to retrieve next waiting due job", e);
       }
     }
     return nextDueDate;

Modified: jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/job/executor/JobExecutor.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/job/executor/JobExecutor.java	2012-02-22 02:06:32 UTC (rev 7058)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/job/executor/JobExecutor.java	2012-02-22 02:13:14 UTC (rev 7059)
@@ -4,7 +4,6 @@
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -17,7 +16,6 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-
 import org.jbpm.JbpmConfiguration;
 import org.jbpm.job.Job;
 
@@ -35,13 +33,9 @@
   protected int idleInterval;
   protected int maxIdleInterval;
   private int retryInterval;
-  /** @deprecated property has no effect */
-  protected int historyMaxSize;
 
   protected int maxLockTime;
   protected int lockMonitorInterval;
-  /** @deprecated property has no effect */
-  protected int lockBufferTime;
 
   private ThreadGroup threadGroup;
   private int waitingExecutorCount ;
@@ -52,17 +46,15 @@
   private Condition waitingDispatcherCondition = waitingExecutorLock.newCondition() ;
   private LinkedList dispatchedJobs = new LinkedList();
 
-  /** @deprecated call {@link #getThreads()} instead */
-  protected Map threads;
-  /** @deprecated call {@link #getThreads()} instead */
-  protected LockMonitorThread lockMonitorThread;
-
   protected Map monitoredJobIds = new Hashtable();
   protected boolean isStarted;
 
-  /** @deprecated this field was just an aid for generating thread names */
-  protected static String hostName;
-
+  /**
+   * Starts all the threads needed. 
+   * 
+   * This method has been split into smaller methods
+   *  in order to make the logic testable.
+   */
   public synchronized void start() {
     if (!isStarted) {
       log.info("starting " + name);
@@ -99,7 +91,7 @@
       log.debug("ignoring start: " + name + " already started");
     }
   }
-
+    
   /**
    * tells all threads in this job executor to stop. Threads may be in the middle of processing
    * a job and they will finish that first. Use {@link #stopAndJoin()} in case you want a method
@@ -177,11 +169,6 @@
     return name + '@' + getHostAddress() + ":Executor-" + index;
   }
 
-  /** @deprecated no longer invoked */
-  protected void startThread() {
-    startThread(getNextThreadName());
-  }
-
   protected void startThread(String threadName) {
     Thread thread = createThread(threadName);
 
@@ -193,35 +180,6 @@
     return new JobExecutorThread(threadName, this);
   }
 
-  /** @deprecated no longer invoked */
-  protected String getNextThreadName() {
-    return getThreadName(threadGroup.activeCount() + 1);
-  }
-
-  /** @deprecated no longer invoked */
-  protected String getLastThreadName() {
-    Map threads = getThreads();
-    for (int i = nbrOfThreads; i > 0; i--) {
-      String threadName = getThreadName(i);
-      if (threads.containsKey(threadName)) return threadName;
-    }
-    return null;
-  }
-
-  /** @deprecated no longer invoked */
-  protected synchronized Thread stopThread() {
-    Map threads = getThreads();
-    for (int i = nbrOfThreads; i > 0; i--) {
-      String threadName = getThreadName(i);
-      JobExecutorThread executorThread = (JobExecutorThread) threads.get(threadName);
-      if (executorThread != null) {
-        executorThread.deactivate();
-        return executorThread;
-      }
-    }
-    return null;
-  }
-
   private String getDispatcherThreadName() {
     return name + '@' + getHostAddress() + ':' + DispatcherThread.DEFAULT_NAME;
   }
@@ -267,25 +225,6 @@
     monitoredJobIds.remove(threadName);
   }
 
-  /**
-   * Method has no effect.
-   * 
-   * @deprecated call {@link #addMonitoredJobId(String, long)} or
-   * {@link #removeMonitoredJobId(String)} to manipulate the set of monitored jobs
-   */
-  public void setMonitoredJobIds(Map monitoredJobIds) {
-  }
-
-  /** @deprecated property has no effect */
-  public int getHistoryMaxSize() {
-    return historyMaxSize;
-  }
-
-  /** @deprecated property has no effect */
-  public void setHistoryMaxSize(int historyMaxSize) {
-    this.historyMaxSize = historyMaxSize;
-  }
-
   public int getIdleInterval() {
     return idleInterval;
   }
@@ -304,14 +243,6 @@
     return isStarted;
   }
 
-  /**
-   * This method has no effect.
-   * 
-   * @deprecated call {@link #start()} or {@link #stop()} to control this job executor.
-   */
-  public void setStarted(boolean isStarted) {
-  }
-
   public JbpmConfiguration getJbpmConfiguration() {
     return jbpmConfiguration;
   }
@@ -350,20 +281,6 @@
     this.name = name;
   }
 
-  /**
-   * @deprecated replaced by {@link #getNbrOfThreads()}
-   */
-  public int getSize() {
-    return nbrOfThreads;
-  }
-
-  /**
-   * @deprecated replaced by {@link #setNbrOfThreads(int)}
-   */
-  public void setSize(int nbrOfThreads) {
-    this.nbrOfThreads = nbrOfThreads;
-  }
-
   public Map getThreads() {
     // fetch active threads
     Thread[] activeThreads = new Thread[nbrOfThreads + 2];
@@ -378,14 +295,6 @@
     return threadMap;
   }
 
-  /**
-   * This method has no effect.
-   * 
-   * @deprecated this job executor manages its own thread pool
-   */
-  public void setThreads(Map threads) {
-  }
-
   public int getMaxLockTime() {
     return maxLockTime;
   }
@@ -397,16 +306,6 @@
     this.maxLockTime = maxLockTime;
   }
 
-  /** @deprecated property has no effect */
-  public int getLockBufferTime() {
-    return lockBufferTime;
-  }
-
-  /** @deprecated property has no effect */
-  public void setLockBufferTime(int lockBufferTime) {
-    this.lockBufferTime = lockBufferTime;
-  }
-
   public int getLockMonitorInterval() {
     return lockMonitorInterval;
   }
@@ -431,12 +330,13 @@
 
   private boolean hasFreeExecutor() {
     waitingExecutorLock.lock() ;
-	try {
+    try {
       return (waitingExecutorCount > dispatchedJobs.size()) ;
     } finally {
       waitingExecutorLock.unlock() ;
     }
   }
+
   // return false when interrupted
   boolean waitForFreeExecutorThread() {
     waitingExecutorLock.lock() ;
@@ -483,9 +383,9 @@
   }
   
   boolean submitJob(final Job job) {
-	waitingExecutorLock.lock() ;
-	try {
-	  if (hasFreeExecutor()) {
+    waitingExecutorLock.lock() ;
+    try {
+      if (hasFreeExecutor()) {
         dispatchedJobs.add(job) ;
         waitingExecutorCondition.signal() ;
         return true ;
@@ -514,4 +414,5 @@
   }
   
   private static Log log = LogFactory.getLog(JobExecutor.class);
+  
 }

Modified: jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/job/executor/JobExecutorThread.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/job/executor/JobExecutorThread.java	2012-02-22 02:06:32 UTC (rev 7058)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/job/executor/JobExecutorThread.java	2012-02-22 02:13:14 UTC (rev 7059)
@@ -2,17 +2,11 @@
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.util.Collection;
-import java.util.Collections;
 import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Random;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-
-import org.jbpm.JbpmConfiguration;
 import org.jbpm.JbpmContext;
 import org.jbpm.db.JobSession;
 import org.jbpm.graph.exe.ProcessInstance;
@@ -31,16 +25,6 @@
     this.jobExecutor = jobExecutor;
   }
 
-  /**
-   * @deprecated use {@link #JobExecutorThread(String, JobExecutor)} instead
-   */
-  public JobExecutorThread(String name, JobExecutor jobExecutor,
-    JbpmConfiguration jbpmConfiguration, int idleInterval, int maxIdleInterval,
-    long maxLockTime, int maxHistory) {
-    super(jobExecutor.getThreadGroup(), name);
-    this.jobExecutor = jobExecutor;
-  }
-
   public void run() {
     while (active) {
       // take on next job
@@ -66,68 +50,6 @@
     log.info(getName() + " leaves cyberspace");
   }
 
-  /** @deprecated responsibility moved to DispatcherThread **/
-  protected Collection acquireJobs() {
-    Collection jobs = Collections.EMPTY_LIST;
-    boolean debug = log.isDebugEnabled();
-    JbpmContext jbpmContext = jobExecutor.getJbpmConfiguration().createJbpmContext();
-    try {
-      // search for available job
-      String lockOwner = getName();
-      JobSession jobSession = jbpmContext.getJobSession();
-      Job firstJob = jobSession.getFirstAcquirableJob(lockOwner);
-      // is there a job?
-      if (firstJob != null) {
-        // is job exclusive?
-        if (firstJob.isExclusive()) {
-          // find other exclusive jobs
-          ProcessInstance processInstance = firstJob.getProcessInstance();
-          List exclusiveJobs = jobSession.findExclusiveJobs(lockOwner, processInstance);
-
-          if (debug) log.debug("acquiring " + exclusiveJobs + " for " + processInstance);
-          Date lockTime = new Date();
-          for (Iterator i = exclusiveJobs.iterator(); i.hasNext();) {
-            Job exclusiveJob = (Job) i.next();
-            exclusiveJob.setLockOwner(lockOwner);
-            exclusiveJob.setLockTime(lockTime);
-          }
-
-          // deliver result
-          if (debug) log.debug("acquired " + exclusiveJobs);
-          jobs = exclusiveJobs;
-        }
-        else {
-          if (debug) log.debug("acquiring " + firstJob);
-          firstJob.setLockOwner(lockOwner);
-          firstJob.setLockTime(new Date());
-
-          // deliver result
-          if (debug) log.debug("acquired " + firstJob);
-          jobs = Collections.singletonList(firstJob);
-        }
-      }
-      else if (debug) log.debug("no acquirable job found");
-    }
-    catch (RuntimeException e) {
-      jbpmContext.setRollbackOnly();
-      if (debug) log.debug("failed to acquire jobs", e);
-    }
-    catch (Error e) {
-      jbpmContext.setRollbackOnly();
-      throw e;
-    }
-    finally {
-      try {
-        jbpmContext.close();
-      }
-      catch (RuntimeException e) {
-        jobs = Collections.EMPTY_LIST;
-        if (debug) log.debug("failed to acquire jobs", e);
-      }
-    }
-    return jobs;
-  }
-
   protected void executeJob(Job job) throws Exception {
     JbpmContext jbpmContext = jobExecutor.getJbpmConfiguration().createJbpmContext();
     try {
@@ -164,8 +86,7 @@
   private void saveJobException(Job job, Exception exception) {
     // if this is a locking exception, keep it quiet
     if (DbPersistenceService.isLockingException(exception)) {
-      StaleObjectLogConfigurer.getStaleObjectExceptionsLog()
-        .error("failed to execute " + job, exception);
+      StaleObjectLogConfigurer.getStaleObjectExceptionsLog().error("failed to execute " + job, exception);
     }
     else {
       log.error("failed to execute " + job, exception);
@@ -247,57 +168,6 @@
     }
   }
 
-  /** @deprecated responsibility moved to DispatcherThread */
-  protected long getWaitPeriod(int currentIdleInterval) {
-    Date nextDueDate = getNextDueDate();
-    if (nextDueDate != null) {
-      long waitPeriod = nextDueDate.getTime() - System.currentTimeMillis();
-      if (waitPeriod < currentIdleInterval) return waitPeriod;
-    }
-    return currentIdleInterval;
-  }
-
-  /** @deprecated responsibility moved to DispatcherThread */
-  protected Date getNextDueDate() {
-    Date nextDueDate = null;
-    JbpmContext jbpmContext = jobExecutor.getJbpmConfiguration().createJbpmContext();
-    try {
-      String lockOwner = getName();
-      Job job = jbpmContext.getJobSession()
-        .getFirstDueJob(lockOwner, jobExecutor.getMonitoredJobIds());
-      if (job != null) {
-        jobExecutor.addMonitoredJobId(lockOwner, job.getId());
-        nextDueDate = job.getDueDate();
-      }
-      else if (log.isDebugEnabled()) log.debug("no due job found");
-    }
-    catch (RuntimeException e) {
-      jbpmContext.setRollbackOnly();
-      if (log.isDebugEnabled()) log.debug("failed to determine next due date", e);
-    }
-    catch (Error e) {
-      jbpmContext.setRollbackOnly();
-      throw e;
-    }
-    finally {
-      try {
-        jbpmContext.close();
-      }
-      catch (RuntimeException e) {
-        nextDueDate = null;
-        if (log.isDebugEnabled()) log.debug("failed to determine next due date", e);
-      }
-    }
-    return nextDueDate;
-  }
-
-  /**
-   * @deprecated As of jBPM 3.2.3, replaced by {@link #deactivate()}
-   */
-  public void setActive(boolean isActive) {
-    if (isActive == false) deactivate();
-  }
-
   public void deactivate() {
     if (active) {
       active = false;

Modified: jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/org/jbpm/db/hibernate.queries.hbm.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/org/jbpm/db/hibernate.queries.hbm.xml	2012-02-22 02:06:32 UTC (rev 7058)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/org/jbpm/db/hibernate.queries.hbm.xml	2012-02-22 02:13:14 UTC (rev 7059)
@@ -250,6 +250,7 @@
   <!-- JobSession                  -->
   <!-- ########################### -->
 
+  <!-- : DISPATCHER THREAD -->
   <query name="JobSession.getFirstAcquirableJob">
     <![CDATA[
       select job
@@ -274,54 +275,34 @@
     ]]>
   </query>
 
-  <query name="JobSession.findExclusiveJobs">
+  <!-- Used to calculate the next time that a job should run
+       there are possibly multiple jobs with the same due date -->
+  <query name="JobSession.getNextUnownedDueJobDueDate">
     <![CDATA[
-      select job
+      select min(job.dueDate)
       from org.jbpm.job.Job job
-      where (job.lockOwner is null or job.lockOwner = :lockOwner)
+      where job.dueDate <= :wakeUpDate
+      and job.lockOwner is null
       and job.retries > 0
-      and job.dueDate <= :now
-      and job.processInstance = :processInstance
-      and job.isExclusive = true
       and job.isSuspended = false
-      order by job.dueDate asc
     ]]>
   </query>
 
-  <query name="JobSession.getFirstDueJob">
+  <!-- : EXECUTE JOBS COMMAND -->
+  <query name="JobSession.findExclusiveJobs">
     <![CDATA[
       select job
       from org.jbpm.job.Job job
       where (job.lockOwner is null or job.lockOwner = :lockOwner)
       and job.retries > 0
+      and job.dueDate <= :now
+      and job.processInstance = :processInstance
+      and job.isExclusive = true
       and job.isSuspended = false
       order by job.dueDate asc
     ]]>
   </query>
 
-  <query name="JobSession.getFirstDueJobExcludingMonitoredJobs">
-    <![CDATA[
-      select job
-      from org.jbpm.job.Job job
-      where (job.lockOwner is null or job.lockOwner = :lockOwner)
-      and job.id not in (:monitoredJobIds)
-      and job.retries > 0
-      and job.isSuspended = false
-      order by job.dueDate asc
-    ]]>
-  </query>
-
-  <query name="JobSession.getFirstUnownedDueJob">
-    <![CDATA[
-      select job
-      from org.jbpm.job.Job job
-      where job.lockOwner is null
-      and job.retries > 0
-      and job.isSuspended = false
-      order by job.dueDate asc
-    ]]>
-  </query>
-
   <query name="JobSession.suspendJobs">
     <![CDATA[
       update org.jbpm.job.Job job

Added: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/Jbpm3430/JBPM3430Test.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/Jbpm3430/JBPM3430Test.java	                        (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/Jbpm3430/JBPM3430Test.java	2012-02-22 02:13:14 UTC (rev 7059)
@@ -0,0 +1,305 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, 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.Jbpm3430;
+
+import java.lang.reflect.Field;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.hibernate.cfg.Configuration;
+import org.jbpm.JbpmConfiguration;
+import org.jbpm.db.AbstractDbTestCase;
+import org.jbpm.db.JbpmSchema;
+import org.jbpm.db.hibernate.HibernateHelper;
+import org.jbpm.graph.def.ActionHandler;
+import org.jbpm.graph.def.Event;
+import org.jbpm.graph.def.EventCallback;
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.graph.exe.ExecutionContext;
+import org.jbpm.graph.exe.ProcessInstance;
+import org.jbpm.job.Timer;
+import org.jbpm.jpdl.JpdlException;
+import org.jbpm.jpdl.xml.Problem;
+import org.jbpm.persistence.db.DbPersistenceServiceFactory;
+import org.jbpm.scheduler.db.DbSchedulerService;
+import org.jbpm.svc.Services;
+
+/**
+ * JobSession.getFirstDueJob was not performing due to the queries having to sort the duedate
+ * field without an index.
+ * 
+ * Which led me to look at the queries, and to discover that the queries were not at all matched
+ * with what they were being used for.
+ * 
+ * The queries where written to retrieve the first due job (and possibly the first due job w/
+ * lock owner, or etc.). They were being used to retrieve the next due date.
+ * 
+ * So I rewrote the queries.
+ * 
+ * (Needs the postgresql jdbc driver jar to be attached to the build path
+ * to work, as well as a local postgresql db, of course.)
+ */
+public class JBPM3430Test extends AbstractDbTestCase {
+
+  private static final String PROCESS_NAME = "jbpm3430";
+
+  protected void setUp() throws Exception {
+    super.setUp();
+    
+    setUpAndEnsureCleanDatabase();
+    setupTimerDueDates();
+
+    ProcessDefinition processDefinition = null;
+    try { 
+      processDefinition = ProcessDefinition.parseXmlString(getProcessDefinitionString());
+    } catch( JpdlException je ) { 
+      Iterator iter = je.getProblems().iterator();
+      while( iter.hasNext() ) { 
+        Problem prob = (Problem) iter.next();
+        log.error( prob.getDescription() );
+      }
+      fail( je.getMessage() );
+    }
+    
+    deployProcessDefinition(processDefinition);
+  }
+  
+  /**
+   * What do we want? 
+   * 
+   * 1. The job executor and dispatcher threads start. 
+   *   - no jobs available, 
+   */
+  private void setupTimerDueDates() { 
+    jobExecutor = getJbpmConfiguration().getJobExecutor();
+    dispatcherIdleInterval = jobExecutor.getIdleInterval();
+    assertTrue( "Idle interval is too small: " + dispatcherIdleInterval, dispatcherIdleInterval > 2500 );
+    
+    withinIdleSeconds = (int) (3 * ((double) dispatcherIdleInterval)/(4 * 1000) + ((double) dispatcherIdleInterval/1000));
+    afterIdleSeconds = (int) (3 * ((double) dispatcherIdleInterval)/1000 + 1);
+    assertTrue( "Within idle timer duration not larger than 0", withinIdleSeconds > 0 );
+    assertTrue( "Within idle timer duration equal to idle interval. [" + withinIdleSeconds + " >= " + dispatcherIdleInterval/1000 + "]", (withinIdleSeconds % (dispatcherIdleInterval/1000)-1) > 0 );
+  }
+  
+  private String postgresDatabaseProperties = "org/jbpm/jbpm3235/hibernate.postgresql.properties";
+  
+  private void setUpAndEnsureCleanDatabase() {
+    String propertiesResource = postgresDatabaseProperties;
+    
+    /**
+     * Postgresql/other database setup
+     */
+    // Ensure that the hibernate session uses the properties we configured (see propertiesResource above)
+    Configuration configuration = HibernateHelper.createConfiguration(null, propertiesResource);
+    
+    DbPersistenceServiceFactory persistenceServiceFactory = (DbPersistenceServiceFactory) getJbpmConfiguration().getServiceFactory(Services.SERVICENAME_PERSISTENCE);
+    if (persistenceServiceFactory == null) fail("Expected to be able to configure persistence, but no peristence service factory can be found.");
+    persistenceServiceFactory.setConfiguration(configuration);
+  
+    /**
+     * Clean up jbpm schema in database
+     */
+    boolean hasLeftOvers = false;
+    JbpmSchema jbpmSchema = new JbpmSchema(configuration);
+  
+    for (Iterator i = jbpmSchema.getRowsPerTable().entrySet().iterator(); i.hasNext();) {
+      Map.Entry entry = (Map.Entry) i.next();
+      Long count = (Long) entry.getValue();
+      if (count.intValue() != 0) {
+        hasLeftOvers = true;
+        log.debug(getName() + " left " + count + " records in " + entry.getKey());
+      }
+    }
+  
+    if (hasLeftOvers) {
+      jbpmSchema.cleanSchema();
+    }
+  }
+
+//  protected void startJobExecutor() { 
+//    jobExecutor.start();
+//  }
+    
+  protected void tearDown() throws Exception {
+    stopJobExecutor();
+    EventCallback.clear();
+    
+    log.info("### END " + getName() + " ####################");
+  }
+  
+  protected JbpmConfiguration getJbpmConfiguration() {
+    if (jbpmConfiguration == null) {
+      // use postgresql properties
+      jbpmConfiguration = JbpmConfiguration.getInstance("org/jbpm/jbpm3430/jbpm-3430.cfg.xml");
+    }
+    return jbpmConfiguration;
+  } 
+
+  // ACTUAL TEST
+  
+  
+  private static HashMap timerActionDates = new HashMap();
+  
+  private static long dispatcherIdleInterval;
+  private static int withinIdleSeconds;
+  private static int afterIdleSeconds;
+  private static final String overdueTimerDate = "overDueDate";
+
+  private static final String overdueTimer = "overdue-timer";
+  private static final String withinIdleTimer = "pre-idle-timer";
+  private static final String afterIdleTimer = "after-idle-timer";
+  
+  // DBG 
+  private static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss,SSS");
+  
+  boolean doNotRunUnlessManually = true;
+  
+  public void testTimerScheduling() throws Exception {
+    if( doNotRunUnlessManually ) { 
+      return;
+    }
+    
+    // multiple job executors not supported on hsql
+    if (getHibernateDialect().indexOf("HSQL") != -1) { 
+      return;
+    }
+
+    ProcessInstance processInstance = jbpmContext.newProcessInstanceForUpdate(PROCESS_NAME);
+    processInstance.getContextInstance().setVariable("eventCallback", new EventCallback());
+    
+    Calendar overDueDateCal = Calendar.getInstance();
+    overDueDateCal.clear(Calendar.MILLISECOND);
+    overDueDateCal.add(Calendar.HOUR, -1);
+    processInstance.getContextInstance().setVariable(overdueTimerDate, overDueDateCal.getTime());
+   
+    // start dispatcher, job executor and lock monitor threads
+    startJobExecutor();
+    
+    // kick off process instance
+    processInstance.signal();
+
+    // Make sure that the jobExecutor is not notified
+    DbSchedulerService schedulerService = (DbSchedulerService) jbpmContext.getServices().getSchedulerService();
+    Field hasProducedTimersField = DbSchedulerService.class.getDeclaredField("hasProducedTimers");
+    hasProducedTimersField.setAccessible(true);
+    hasProducedTimersField.setBoolean(schedulerService, false);
+    
+    closeJbpmContext();
+    try {
+      EventCallback.waitForEvent(Event.EVENTTYPE_PROCESS_END);
+    }
+    finally {
+      createJbpmContext();
+    }
+
+    assertTrue(timerActionDates.size() == 4);
+    
+    long startTime = ((Long) timerActionDates.get("start")).longValue();
+    { long overdueTime = ((Long) timerActionDates.get(overdueTimer)).longValue();
+       assertTrue( "Overdue job ran " + ((double) overdueTime-startTime)/1000 + " secs after process started [ < " + ((double) dispatcherIdleInterval)/1000 + "]", startTime+dispatcherIdleInterval + 500 > overdueTime );
+    }
+    
+    { long withinIdleTime = ((Long) timerActionDates.get(withinIdleTimer)).longValue();
+      assertTrue( "Pre idle job did not run " + withinIdleSeconds + " seconds after start [" + ((double) startTime-withinIdleTime)/1000 + "]", isWithin1SecondOf(startTime + withinIdleSeconds*1000, withinIdleTime) );
+    }
+    
+    { long afterIdleTime = ((Long) timerActionDates.get(afterIdleTimer)).longValue();
+      assertTrue( "After idle job did not run " + afterIdleSeconds + " seconds after start [" + ((double) startTime-afterIdleTime)/1000 + "]", isWithin1SecondOf(startTime + afterIdleSeconds*1000, afterIdleTime) );
+    }
+  }
+
+  // ACTUAL TESTS
+  //
+
+  boolean isWithin1SecondOf(long compare, long expected) { 
+    boolean withinOneSecond = false;
+    
+    double thisSeconds = ((double) compare)/1000;
+    double thatSeconds = ((double) expected)/1000;
+   
+    if( thatSeconds - 0.5d <= thisSeconds && thisSeconds <= thatSeconds + 0.5 ) { 
+      withinOneSecond = true;
+    }
+    
+    return withinOneSecond;
+  }
+
+
+  public static class TimerAction implements ActionHandler {
+
+    private static final long serialVersionUID = -1723705242334355414L;
+
+    public void execute(ExecutionContext executionContext) throws Exception {
+      Timer timer = executionContext.getTimer();
+      String timerName = timer.getName();
+      
+      System.out.println("--> " + timerName  + " [" + sdf.format(new Date()) + " <> " + sdf.format(timer.getDueDate()) + "]" );
+      
+      timerActionDates.put(timerName, new Long(new Date().getTime()));
+    }
+  }
+
+  
+  public static class StartAction implements ActionHandler {
+
+    private static final long serialVersionUID = -8083148121782750200L;
+
+    public void execute(ExecutionContext executionContext) throws Exception {
+      System.out.println("START: " + sdf.format(new Date()));
+      timerActionDates.put("start", new Long(new Date().getTime()));
+    } 
+    
+  }
+  
+  private String getProcessDefinitionString() { 
+    return 
+      "<?xml version='1.0' encoding='UTF-8'?>" + 
+      "<process-definition name='jbpm3430' xmlns='urn:jbpm.org:jpdl-3.2'>" + 
+      "  <event type='process-end'>" + 
+      "    <action expression='#{eventCallback.processEnd}' />" + 
+      "  </event>" + 
+      ""   + 
+      "  <start-state>" + 
+      "    <transition to='timers'>" + 
+      "      <action class='" + StartAction.class.getName() + "'/>" + 
+      "    </transition>" + 
+      " </start-state>" + 
+      "" + 
+      "  <state name='timers'>" + 
+      "    <event type='timer'>" + 
+      "      <action class='" + TimerAction.class.getName() + "'/>" + 
+      "    </event>" + 
+      "    <timer duedate='#{" + overdueTimerDate + "}' name='" + overdueTimer + "' />" + 
+      "    <timer duedate='" + withinIdleSeconds + " seconds' name='" + withinIdleTimer + "' />" + 
+      "    <timer duedate='" + afterIdleSeconds + " seconds' name='" + afterIdleTimer + "' transition='done' />" + 
+      "    <transition to='end' name='done' />" + 
+      "  </state>" + 
+      "" + 
+      "  <end-state name='end' />" + 
+      "</process-definition>";
+  }
+  
+}


Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/Jbpm3430/JBPM3430Test.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Added: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/job/executor/DispatcherAndJobExecutorMethodTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/job/executor/DispatcherAndJobExecutorMethodTest.java	                        (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/job/executor/DispatcherAndJobExecutorMethodTest.java	2012-02-22 02:13:14 UTC (rev 7059)
@@ -0,0 +1,55 @@
+package org.jbpm.job.executor;
+
+
+import java.util.Calendar;
+import java.util.Date;
+
+import junit.framework.TestCase;
+
+public class DispatcherAndJobExecutorMethodTest extends TestCase {
+
+  private DispatcherThread dispatcherThread = null;
+  private JobExecutor jobExecutor = null;
+  private JobExecutorThread jobExecutorThread = null;
+  
+  public void setUp() { 
+    jobExecutor = new JobExecutor();
+    dispatcherThread = new DispatcherThread("Test-Dispatcher", jobExecutor);
+    jobExecutorThread = new JobExecutorThread("Test-JobExecutorThread", jobExecutor);
+  }
+  
+  public void tearDown() { 
+    jobExecutor = null;
+    dispatcherThread = null;
+    jobExecutorThread = null;
+  }
+ 
+  public void testGetWaitPeriod() { 
+    long currentIdleInterval = 20 * 1000;
+    
+    Calendar cal = Calendar.getInstance();
+    cal.add(Calendar.SECOND, -10);
+    Date nextDueDate = cal.getTime();
+    
+    long waitPeriod = DispatcherThread.getWaitPeriod((int) currentIdleInterval, nextDueDate);
+    assertTrue( "The due date has passed, we expect no wait period, not " + waitPeriod/1000, waitPeriod <= 0 );
+    
+    cal = Calendar.getInstance();
+    cal.add(Calendar.SECOND, 30);
+    nextDueDate = cal.getTime();
+    
+    waitPeriod = DispatcherThread.getWaitPeriod((int) currentIdleInterval, nextDueDate);
+    assertTrue( "The due date is past the idle interval, we expect a wait period of " + currentIdleInterval + " not " + waitPeriod,
+      waitPeriod == currentIdleInterval );
+    
+    cal = Calendar.getInstance();
+    cal.add(Calendar.SECOND, 10);
+    nextDueDate = cal.getTime();
+    
+    waitPeriod = DispatcherThread.getWaitPeriod((int) currentIdleInterval, nextDueDate);
+    assertTrue( "The due date is past the idle interval, we expect a wait period of approximately " + 10 * 1000 + " not " + waitPeriod,
+      9 * 1000 <= waitPeriod && waitPeriod <= 11 * 1000 );
+  }
+  
+}
+


Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/job/executor/DispatcherAndJobExecutorMethodTest.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Added: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm3430/hibernate.postgresql.properties
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm3430/hibernate.postgresql.properties	                        (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm3430/hibernate.postgresql.properties	2012-02-22 02:13:14 UTC (rev 7059)
@@ -0,0 +1,11 @@
+hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
+
+hibernate.connection.driver_class=org.postgresql.Driver
+# hibernate.connection.driver_class=com.p6spy.engine.spy.P6SpyDriver
+hibernate.connection.url=jdbc\:postgresql\://localhost\:5432/jbpm3
+hibernate.connection.username=jbpm3
+hibernate.connection.password=jbpm3
+
+hibernate.hbm2ddl.auto=update
+hibernate.show_sql=false
+


Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm3430/hibernate.postgresql.properties
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Added: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm3430/jbpm-3430.cfg.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm3430/jbpm-3430.cfg.xml	                        (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm3430/jbpm-3430.cfg.xml	2012-02-22 02:13:14 UTC (rev 7059)
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jbpm-configuration>
+  <string name="resource.hibernate.properties" value="org/jbpm/jbpm3430/hibernate.postgresql.properties" />
+  
+  <bean name="jbpm.job.executor" class="org.jbpm.job.executor.JobExecutor">
+    <field name="jbpmConfiguration"><ref bean="jbpmConfiguration" /></field>
+    <field name="name"><string value="Jbpm3430JobExector" /></field>
+    <field name="nbrOfThreads"><int value="1" /></field>
+    
+    <field name="idleInterval"><int value="3000" /></field> <!-- 3 secs -->
+    <field name="maxIdleInterval"><int value="3600000" /></field> <!-- 1 hour -->
+    <field name="retryInterval"><int value="10000" /></field> 
+    
+    <field name="maxLockTime"><int value="600000" /></field> <!-- 10 minutes -->
+    <field name="lockMonitorInterval"><int value="60000" /></field> <!-- 1 minute -->
+  </bean>
+  
+</jbpm-configuration>


Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm3430/jbpm-3430.cfg.xml
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Added: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/spy.properties
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/spy.properties	                        (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/spy.properties	2012-02-22 02:13:14 UTC (rev 7059)
@@ -0,0 +1,249 @@
+#################################################################
+# P6Spy 2.0-SNAPSHOT Options File                               #
+# See documentation for detailed instructions                   #
+#                                                               #
+# PLACE IN src/test/resources when using!!!                     #
+#                                                               #
+#################################################################
+
+#################################################################
+# MODULES                                                       #
+#                                                               #
+# Modules provide the P6Spy functionality.  If a module, such   #
+# as module_log is commented out, that functionality will not   #
+# be available.  If it is not commented out (if it is active),  #
+# the functionality will be active.                             #
+#                                                               #
+# Values set in Modules cannot be reloaded using the            #
+# reloadproperties variable.  Once they are loaded, they remain #
+# in memory until the application is restarted.                 #
+#                                                               #
+#################################################################
+
+module.log=com.p6spy.engine.logging.P6LogFactory
+#module.outage=com.p6spy.engine.outage.P6OutageFactory
+
+#################################################################
+# REALDRIVER(s)                                                 #
+#                                                               #
+# In your application server configuration file you replace the #
+# "real driver" name with com.p6spy.engine.spy.P6SpyDriver. This#
+# is where you put the name of your real driver P6Spy can find  #
+# and register your real driver to do the database work.        #
+#                                                               #
+# If your application uses several drivers specify them in      #
+# realdriver2, realdriver3.  See the documentation for more     #
+# details.                                                      #
+#                                                               #
+# Values set in REALDRIVER(s) cannot be reloaded using the      #
+# reloadproperties variable.  Once they are loaded, they remain #
+# in memory until the application is restarted.                 #
+#                                                               #
+#################################################################
+
+# oracle driver
+# realdriver=oracle.jdbc.driver.OracleDriver
+
+# mysql Connector/J driver
+# realdriver=com.mysql.jdbc.Driver
+
+# informix driver
+# realdriver=com.informix.jdbc.IfxDriver
+
+# ibm db2 driver
+# realdriver=COM.ibm.db2.jdbc.net.DB2Driver
+
+# the mysql open source driver
+realdriver=org.hsqldb.jdbcDriver
+#realdriver=org.postgresql.Driver
+
+#specifies another driver to use
+realdriver2=
+#specifies a third driver to use
+realdriver3=
+
+#the DriverManager class sequentially tries every driver that is
+#registered to find the right driver.  In some instances, it's possible to
+#load up the realdriver before the p6spy driver, in which case your connections
+#will not get wrapped as the realdriver will "steal" the connection before
+#p6spy sees it.  Set the following property to "true" to cause p6spy to
+#explicitily deregister the realdrivers
+deregisterdrivers=true
+
+################################################################
+# P6LOG SPECIFIC PROPERTIES                                    #
+################################################################
+# no properties currently available
+
+################################################################
+# EXECUTION THRESHOLD PROPERTIES                               #
+################################################################
+# This feature applies to the standard logging of P6Spy.       # 
+# While the standard logging logs out every statement          #
+# regardless of its execution time, this feature puts a time   # 
+# condition on that logging.  Only statements that have taken  # 
+# longer than the time specified (in milliseconds) will be     #
+# logged.  This way it is possible to see only statements that #
+# have exceeded some high water mark.                          #
+# This time is reloadable.                                     #
+#
+# executionthreshold=integer time (milliseconds)
+#
+executionthreshold=
+
+################################################################
+# P6OUTAGE SPECIFIC PROPERTIES                                 #
+################################################################
+# Outage Detection
+#
+# This feature detects long-running statements that may be indicative of
+# a database outage problem. If this feature is turned on, it will log any
+# statement that surpasses the configurable time boundary during its execution.
+# When this feature is enabled, no other statements are logged except the long
+# running statements. The interval property is the boundary time set in seconds.
+# For example, if this is set to 2, then any statement requiring at least 2 
+# seconds will be logged. Note that the same statement will continue to be logged
+# for as long as it executes. So if the interval is set to 2, and the query takes
+# 11 seconds, it will be logged 5 times (at the 2, 4, 6, 8, 10 second intervals).
+#
+# outagedetection=true|false
+# outagedetectioninterval=integer time (seconds)
+#
+outagedetection=false
+outagedetectioninterval=
+
+################################################################
+# COMMON PROPERTIES                                            #
+################################################################
+
+# filter what is logged
+filter=true
+
+# comma separated list of tables to include when filtering
+include=JBPM_JOB
+# comma separated list of tables to exclude when filtering
+exclude=
+
+# sql expression to evaluate if using regex filtering
+sqlexpression = 
+
+
+# turn on tracing
+autoflush   = true
+
+# sets the date format using Java's SimpleDateFormat routine
+dateformat=HH:mm:ss,SSS
+
+#list of categories to explicitly include 
+includecategories=
+
+#list of categories to exclude: error, info, batch, debug, statement, resultset
+#commit, rollback and result are valid values
+#excludecategories=info,debug,result,batch
+excludecategories=debug,resultset,result
+
+
+#allows you to use a regex engine or your own matching engine to determine 
+#which statements to log
+#
+#stringmatcher=com.p6spy.engine.common.GnuRegexMatcher
+#stringmatcher=com.p6spy.engine.common.JakartaRegexMatcher
+stringmatcher=
+
+# prints a stack trace for every statement logged
+stacktrace=false
+# if stacktrace=true, specifies the stack trace to print
+stacktraceclass=
+
+# determines if property file should be reloaded
+reloadproperties=false
+# determines how often should be reloaded in seconds
+reloadpropertiesinterval=60
+
+#if=true then url must be prefixed with p6spy:
+useprefix=false
+
+#specifies the appender to use for logging
+#appender=com.p6spy.engine.logging.appender.Log4jLogger
+appender=com.p6spy.engine.logging.appender.StdoutLogger
+
+# name of logfile to use, note Windows users should make sure to use forward slashes in their pathname (e:/test/spy.log) (used for file logger only)
+logfile     = spy.log
+
+# append to  the p6spy log file.  if this is set to false the
+# log file is truncated every time.  (file logger only)
+append=true
+
+#The following are for log4j logging only
+log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
+log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
+log4j.appender.STDOUT.layout.ConversionPattern=p6spy - %m%n
+
+#log4j.appender.CHAINSAW_CLIENT=org.apache.log4j.net.SocketAppender
+#log4j.appender.CHAINSAW_CLIENT.RemoteHost=localhost
+#log4j.appender.CHAINSAW_CLIENT.Port=4445
+#log4j.appender.CHAINSAW_CLIENT.LocationInfo=true
+
+log4j.logger.p6spy=INFO,STDOUT
+
+
+#################################################################
+# DataSource replacement                                        #
+#                                                               #
+# Replace the real DataSource class in your application server  #
+# configuration with the name com.p6spy.engine.spy.P6DataSource,#
+# then add the JNDI name and class name of the real     #
+# DataSource here                     #
+#                                                               #
+# Values set in this item cannot be reloaded using the          #
+# reloadproperties variable.  Once it is loaded, it remains     #
+# in memory until the application is restarted.                 #
+#                                                               #
+#################################################################
+#realdatasource=/RealMySqlDS
+#realdatasourceclass=com.mysql.jdbc.jdbc2.optional.MysqlDataSource
+
+#################################################################
+# DataSource properties                                         #
+#                                                               #
+# If you are using the DataSource support to intercept calls    # 
+# to a DataSource that requires properties for proper setup,    #
+# define those properties here. Use name value pairs, separate  #
+# the name and value with a semicolon, and separate the         #
+# pairs with commas.                                            #
+#                                   #
+# The example shown here is for mysql                           #
+#                                                               #
+#################################################################
+#realdatasourceproperties=port;3306,serverName;ibmhost,databaseName;mydb
+
+
+#################################################################
+# JNDI DataSource lookup                                        #
+#                                                               #
+# If you are using the DataSource support outside of an app     #
+# server, you will probably need to define the JNDI Context     #
+# environment.                                                  #
+#                                                               #
+# If the P6Spy code will be executing inside an app server then #
+# do not use these properties, and the DataSource lookup will   #
+# use the naming context defined by the app server.             #
+#                                                               #
+# The two standard elements of the naming environment are #
+# jndicontextfactory and jndicontextproviderurl. If you need    #
+# additional elements, use the jndicontextcustom property.      #
+# You can define multiple properties in jndicontextcustom,      #
+# in name value pairs. Separate the name and value with a       #
+# semicolon, and separate the pairs with commas.                #
+#                                                               #
+# The example shown here is for a standalone program running on #
+# a machine that is also running JBoss, so the JDNI context     #
+# is configured for JBoss (3.0.4).                              #
+#                                                               #
+#################################################################
+#jndicontextfactory=org.jnp.interfaces.NamingContextFactory
+#jndicontextproviderurl=localhost:1099
+#jndicontextcustom=java.naming.factory.url.pkgs;org.jboss.nameing:org.jnp.interfaces
+
+#jndicontextfactory=com.ibm.websphere.naming.WsnInitialContextFactory
+#jndicontextproviderurl=iiop://localhost:900


Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/spy.properties
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native



More information about the jbpm-commits mailing list