Package org.quartz.impl.jdbcjobstore

Source Code of org.quartz.impl.jdbcjobstore.JobStoreSupport$ClusterManager

/*      */ package org.quartz.impl.jdbcjobstore;
/*      */
/*      */ import java.io.IOException;
/*      */ import java.lang.reflect.Constructor;
/*      */ import java.lang.reflect.InvocationTargetException;
/*      */ import java.sql.Connection;
/*      */ import java.sql.SQLException;
/*      */ import java.util.Date;
/*      */ import java.util.HashMap;
/*      */ import java.util.Iterator;
/*      */ import java.util.LinkedList;
/*      */ import java.util.List;
/*      */ import java.util.Set;
/*      */ import org.apache.commons.logging.Log;
/*      */ import org.apache.commons.logging.LogFactory;
/*      */ import org.quartz.Calendar;
/*      */ import org.quartz.CronTrigger;
/*      */ import org.quartz.JobDataMap;
/*      */ import org.quartz.JobDetail;
/*      */ import org.quartz.JobPersistenceException;
/*      */ import org.quartz.ObjectAlreadyExistsException;
/*      */ import org.quartz.SchedulerConfigException;
/*      */ import org.quartz.SchedulerException;
/*      */ import org.quartz.SimpleTrigger;
/*      */ import org.quartz.Trigger;
/*      */ import org.quartz.core.SchedulingContext;
/*      */ import org.quartz.spi.ClassLoadHelper;
/*      */ import org.quartz.spi.JobStore;
/*      */ import org.quartz.spi.SchedulerSignaler;
/*      */ import org.quartz.spi.TriggerFiredBundle;
/*      */ import org.quartz.utils.DBConnectionManager;
/*      */ import org.quartz.utils.Key;
/*      */ import org.quartz.utils.TriggerStatus;
/*      */
/*      */ public abstract class JobStoreSupport
/*      */   implements JobStore, Constants
/*      */ {
/*   76 */   protected static String LOCK_TRIGGER_ACCESS = "TRIGGER_ACCESS";
/*      */
/*   78 */   protected static String LOCK_JOB_ACCESS = "JOB_ACCESS";
/*      */
/*   80 */   protected static String LOCK_CALENDAR_ACCESS = "CALENDAR_ACCESS";
/*      */
/*   82 */   protected static String LOCK_STATE_ACCESS = "STATE_ACCESS";
/*      */
/*   84 */   protected static String LOCK_MISFIRE_ACCESS = "MISFIRE_ACCESS";
/*      */   protected String dsName;
/*      */   protected String tablePrefix;
/*      */   protected boolean useProperties;
/*      */   protected String instanceId;
/*      */   protected String instanceName;
/*      */   protected String delegateClassName;
/*      */   protected Class delegateClass;
/*      */   protected HashMap calendarCache;
/*      */   private DriverDelegate delegate;
/*      */   private long misfireThreshold;
/*      */   private boolean dontSetAutoCommitFalse;
/*      */   private boolean isClustered;
/*      */   private boolean useDBLocks;
/*      */   private boolean lockOnInsert;
/*      */   private Semaphore lockHandler;
/*      */   private String selectWithLockSQL;
/*      */   private long clusterCheckinInterval;
/*      */   private ClusterManager clusterManagementThread;
/*      */   private MisfireHandler misfireHandler;
/*      */   private ClassLoadHelper classLoadHelper;
/*      */   private SchedulerSignaler signaler;
/*      */   protected int maxToRecoverAtATime;
/*      */   private boolean setTxIsolationLevelSequential;
/*      */   private long dbRetryInterval;
/*      */   private int lastRecoverCount;
/* 1725 */   private static long ftrCtr = System.currentTimeMillis();
/*      */   protected boolean firstCheckIn;
/*      */   protected long lastCheckin;
/*      */
/*      */   public JobStoreSupport()
/*      */   {
/*   96 */     this.tablePrefix = "QRTZ_";
/*      */
/*   98 */     this.useProperties = false;
/*      */
/*  105 */     this.delegateClass = StdJDBCDelegate.class;
/*      */
/*  107 */     this.calendarCache = new HashMap();
/*      */
/*  111 */     this.misfireThreshold = 60000L;
/*      */
/*  113 */     this.dontSetAutoCommitFalse = false;
/*      */
/*  115 */     this.isClustered = false;
/*      */
/*  117 */     this.useDBLocks = false;
/*      */
/*  119 */     this.lockOnInsert = true;
/*      */
/*  121 */     this.lockHandler = null;
/*      */
/*  123 */     this.selectWithLockSQL = null;
/*      */
/*  125 */     this.clusterCheckinInterval = 7500L;
/*      */
/*  127 */     this.clusterManagementThread = null;
/*      */
/*  129 */     this.misfireHandler = null;
/*      */
/*  135 */     this.maxToRecoverAtATime = 20;
/*      */
/*  137 */     this.setTxIsolationLevelSequential = false;
/*      */
/*  139 */     this.dbRetryInterval = 10000L;
/*      */
/*  729 */     this.lastRecoverCount = 0;
/*      */
/* 2025 */     this.firstCheckIn = true;
/*      */
/* 2027 */     this.lastCheckin = System.currentTimeMillis();
/*      */   }
/*      */
/*      */   public void setDataSource(String dsName)
/*      */   {
/*  156 */     this.dsName = dsName;
/*      */   }
/*      */
/*      */   public String getDataSource()
/*      */   {
/*  166 */     return this.dsName;
/*      */   }
/*      */
/*      */   public void setTablePrefix(String prefix)
/*      */   {
/*  175 */     if (prefix == null) prefix = "";
/*      */
/*  177 */     this.tablePrefix = prefix;
/*      */   }
/*      */
/*      */   public String getTablePrefix()
/*      */   {
/*  186 */     return this.tablePrefix;
/*      */   }
/*      */
/*      */   public void setUseProperties(String useProp)
/*      */   {
/*  195 */     if (useProp == null) useProp = "false";
/*      */
/*  197 */     this.useProperties = Boolean.valueOf(useProp).booleanValue();
/*      */   }
/*      */
/*      */   public boolean canUseProperties()
/*      */   {
/*  206 */     return this.useProperties;
/*      */   }
/*      */
/*      */   public void setInstanceId(String instanceId)
/*      */   {
/*  215 */     this.instanceId = instanceId;
/*      */   }
/*      */
/*      */   public String getInstanceId()
/*      */   {
/*  225 */     return this.instanceId;
/*      */   }
/*      */
/*      */   public void setInstanceName(String instanceName)
/*      */   {
/*  234 */     this.instanceName = instanceName;
/*      */   }
/*      */
/*      */   public String getInstanceName()
/*      */   {
/*  244 */     return this.instanceName;
/*      */   }
/*      */
/*      */   public void setIsClustered(boolean isClustered)
/*      */   {
/*  253 */     this.isClustered = isClustered;
/*      */   }
/*      */
/*      */   public boolean isClustered()
/*      */   {
/*  262 */     return this.isClustered;
/*      */   }
/*      */
/*      */   public long getClusterCheckinInterval()
/*      */   {
/*  273 */     return this.clusterCheckinInterval;
/*      */   }
/*      */
/*      */   public void setClusterCheckinInterval(long l)
/*      */   {
/*  284 */     this.clusterCheckinInterval = l;
/*      */   }
/*      */
/*      */   public int getMaxMisfiresToHandleAtATime()
/*      */   {
/*  295 */     return this.maxToRecoverAtATime;
/*      */   }
/*      */
/*      */   public void setMaxMisfiresToHandleAtATime(int maxToRecoverAtATime)
/*      */   {
/*  306 */     this.maxToRecoverAtATime = maxToRecoverAtATime;
/*      */   }
/*      */
/*      */   public long getDbRetryInterval()
/*      */   {
/*  313 */     return this.dbRetryInterval;
/*      */   }
/*      */
/*      */   public void setDbRetryInterval(long dbRetryInterval)
/*      */   {
/*  319 */     this.dbRetryInterval = dbRetryInterval;
/*      */   }
/*      */
/*      */   public void setUseDBLocks(boolean useDBLocks)
/*      */   {
/*  329 */     this.useDBLocks = useDBLocks;
/*      */   }
/*      */
/*      */   public boolean getUseDBLocks()
/*      */   {
/*  339 */     return this.useDBLocks;
/*      */   }
/*      */
/*      */   public boolean isLockOnInsert() {
/*  343 */     return this.lockOnInsert;
/*      */   }
/*      */
/*      */   public void setLockOnInsert(boolean lockOnInsert)
/*      */   {
/*  359 */     this.lockOnInsert = lockOnInsert;
/*      */   }
/*      */
/*      */   public long getMisfireThreshold() {
/*  363 */     return this.misfireThreshold;
/*      */   }
/*      */
/*      */   public void setMisfireThreshold(long misfireThreshold)
/*      */   {
/*  374 */     if (misfireThreshold < 1L) {
/*  375 */       throw new IllegalArgumentException("Misfirethreashold must be larger than 0");
/*      */     }
/*  377 */     this.misfireThreshold = misfireThreshold;
/*      */   }
/*      */
/*      */   public boolean isDontSetAutoCommitFalse() {
/*  381 */     return this.dontSetAutoCommitFalse;
/*      */   }
/*      */
/*      */   public void setDontSetAutoCommitFalse(boolean b)
/*      */   {
/*  392 */     this.dontSetAutoCommitFalse = b;
/*      */   }
/*      */
/*      */   public boolean isTxIsolationLevelSerializable() {
/*  396 */     return this.setTxIsolationLevelSequential;
/*      */   }
/*      */
/*      */   public void setTxIsolationLevelSerializable(boolean b)
/*      */   {
/*  405 */     this.setTxIsolationLevelSequential = b;
/*      */   }
/*      */
/*      */   public void setDriverDelegateClass(String delegateClassName)
/*      */     throws InvalidConfigurationException
/*      */   {
/*  419 */     this.delegateClassName = delegateClassName;
/*      */   }
/*      */
/*      */   public String getDriverDelegateClass()
/*      */   {
/*  430 */     return this.delegateClassName;
/*      */   }
/*      */
/*      */   public String getSelectWithLockSQL() {
/*  434 */     return this.selectWithLockSQL;
/*      */   }
/*      */
/*      */   public void setSelectWithLockSQL(String string)
/*      */   {
/*  446 */     this.selectWithLockSQL = string;
/*      */   }
/*      */
/*      */   protected ClassLoadHelper getClassLoadHelper() {
/*  450 */     return this.classLoadHelper;
/*      */   }
/*      */
/*      */   Log getLog()
/*      */   {
/*  458 */     return LogFactory.getLog(getClass());
/*      */   }
/*      */
/*      */   public void initialize(ClassLoadHelper loadHelper, SchedulerSignaler signaler)
/*      */     throws SchedulerConfigException
/*      */   {
/*  470 */     if (this.dsName == null) throw new SchedulerConfigException("DataSource name not set.");
/*      */
/*  473 */     this.classLoadHelper = loadHelper;
/*  474 */     this.signaler = signaler;
/*      */
/*  476 */     if ((!getUseDBLocks()) && (!isClustered())) {
/*  477 */       getLog().info("Using thread monitor-based data access locking (synchronization).");
/*      */
/*  480 */       this.lockHandler = new SimpleSemaphore();
/*      */     } else {
/*  482 */       getLog().info("Using db table-based data access locking (synchronization).");
/*      */
/*  485 */       this.lockHandler = new StdRowLockSemaphore(getTablePrefix(), getSelectWithLockSQL());
/*      */     }
/*      */
/*  489 */     if (!isClustered())
/*      */       try {
/*  491 */         cleanVolatileTriggerAndJobs();
/*      */       } catch (SchedulerException se) {
/*  493 */         throw new SchedulerConfigException("Failure occured during job recovery.", se);
/*      */       }
/*      */   }
/*      */
/*      */   public void schedulerStarted()
/*      */     throws SchedulerException
/*      */   {
/*  504 */     if (isClustered()) {
/*  505 */       this.clusterManagementThread = new ClusterManager(this);
/*  506 */       this.clusterManagementThread.initialize();
/*      */     }
/*      */     else {
/*      */       try {
/*  510 */         recoverJobs();
/*      */       } catch (SchedulerException se) {
/*  512 */         throw new SchedulerConfigException("Failure occured during job recovery.", se);
/*      */       }
/*      */
/*      */     }
/*      */
/*  517 */     this.misfireHandler = new MisfireHandler(this);
/*  518 */     this.misfireHandler.initialize();
/*      */   }
/*      */
/*      */   public void shutdown()
/*      */   {
/*  529 */     if (this.clusterManagementThread != null) {
/*  530 */       this.clusterManagementThread.shutdown();
/*      */     }
/*  532 */     if (this.misfireHandler != null) this.misfireHandler.shutdown();
/*      */     try
/*      */     {
/*  535 */       DBConnectionManager.getInstance().shutdown(getDataSource());
/*      */     } catch (SQLException sqle) {
/*  537 */       getLog().warn("Database connection shutdown unsuccessful.", sqle);
/*      */     }
/*      */   }
/*      */
/*      */   public boolean supportsPersistence() {
/*  542 */     return true;
/*      */   }
/*      */
/*      */   protected Connection getConnection()
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/*  553 */       Connection conn = DBConnectionManager.getInstance().getConnection(getDataSource());
/*      */
/*  556 */       if (conn == null) throw new SQLException("Could not get connection from DataSource '" + getDataSource() + "'");
/*      */
/*      */       try
/*      */       {
/*  561 */         if (!isDontSetAutoCommitFalse()) conn.setAutoCommit(false);
/*      */
/*  563 */         if (isTxIsolationLevelSerializable())
/*  564 */           conn.setTransactionIsolation(8);
/*      */       } catch (SQLException ingore) {
/*      */       } catch (Exception e) {
/*  567 */         if (conn != null) try {
/*  568 */             conn.close(); } catch (Throwable tt) {
/*      */           } throw new JobPersistenceException("Failure setting up connection.", e);
/*      */       }
/*      */
/*  573 */       return conn;
/*      */     } catch (SQLException sqle) {
/*  575 */       throw new JobPersistenceException("Failed to obtain DB connection from data source '" + getDataSource() + "': " + sqle.toString(), sqle);
/*      */     }
/*      */     catch (Exception e) {
/*      */     }
/*  579 */     throw new JobPersistenceException("Failed to obtain DB connection from data source '" + getDataSource() + "': " + e.toString(), e, 499);
/*      */   }
/*      */
/*      */   protected void releaseLock(Connection conn, String lockName, boolean doIt)
/*      */   {
/*  587 */     if ((doIt) && (conn != null))
/*      */       try {
/*  589 */         getLockHandler().releaseLock(conn, lockName);
/*      */       } catch (LockException le) {
/*  591 */         getLog().error("Error returning lock: " + le.getMessage(), le);
/*      */       }
/*      */   }
/*      */
/*      */   protected abstract void cleanVolatileTriggerAndJobs()
/*      */     throws JobPersistenceException;
/*      */
/*      */   protected void cleanVolatileTriggerAndJobs(Connection conn)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/*  620 */       Key[] volatileTriggers = getDelegate().selectVolatileTriggers(conn);
/*  621 */       Key[] volatileJobs = getDelegate().selectVolatileJobs(conn);
/*      */
/*  623 */       for (int i = 0; i < volatileTriggers.length; i++) {
/*  624 */         removeTrigger(conn, null, volatileTriggers[i].getName(), volatileTriggers[i].getGroup());
/*      */       }
/*      */
/*  627 */       getLog().info("Removed " + volatileTriggers.length + " Volatile Trigger(s).");
/*      */
/*  631 */       for (int i = 0; i < volatileJobs.length; i++) {
/*  632 */         removeJob(conn, null, volatileJobs[i].getName(), volatileJobs[i].getGroup(), true);
/*      */       }
/*      */
/*  635 */       getLog().info("Removed " + volatileJobs.length + " Volatile Job(s).");
/*      */
/*  639 */       getDelegate().deleteVolatileFiredTriggers(conn);
/*      */     }
/*      */     catch (Exception e) {
/*  642 */       throw new JobPersistenceException("Couldn't clean volatile data: " + e.getMessage(), e);
/*      */     }
/*      */   }
/*      */
/*      */   protected abstract void recoverJobs()
/*      */     throws JobPersistenceException;
/*      */
/*      */   protected void recoverJobs(Connection conn)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/*  670 */       int rows = getDelegate().updateTriggerStatesFromOtherStates(conn, "WAITING", "ACQUIRED", "BLOCKED");
/*      */
/*  673 */       rows += getDelegate().updateTriggerStatesFromOtherStates(conn, "PAUSED", "PAUSED_BLOCKED", "PAUSED_BLOCKED");
/*      */
/*  676 */       getLog().info("Freed " + rows + " triggers from 'acquired' / 'blocked' state.");
/*      */
/*  681 */       getDelegate().updateTriggerStateFromOtherStatesBeforeTime(conn, "MISFIRED", "WAITING", "WAITING", getMisfireTime());
/*      */
/*  684 */       recoverMisfiredJobs(conn, true);
/*      */
/*  687 */       Trigger[] recoveringJobTriggers = getDelegate().selectTriggersForRecoveringJobs(conn);
/*      */
/*  689 */       getLog().info("Recovering " + recoveringJobTriggers.length + " jobs that were in-progress at the time of the last shut-down.");
/*      */
/*  695 */       for (int i = 0; i < recoveringJobTriggers.length; i++) {
/*  696 */         if (!jobExists(conn, recoveringJobTriggers[i].getJobName(), recoveringJobTriggers[i].getJobGroup()))
/*      */           continue;
/*  698 */         recoveringJobTriggers[i].computeFirstFireTime(null);
/*  699 */         storeTrigger(conn, null, recoveringJobTriggers[i], null, false, "WAITING", false, true);
/*      */       }
/*      */
/*  703 */       getLog().info("Recovery complete.");
/*      */
/*  706 */       Key[] ct = getDelegate().selectTriggersInState(conn, "COMPLETE");
/*  707 */       for (int i = 0; (ct != null) && (i < ct.length); i++)
/*  708 */         removeTrigger(conn, null, ct[i].getName(), ct[i].getGroup());
/*  709 */       getLog().info("Removed " + ct.length + " 'complete' triggers.");
/*      */
/*  714 */       int n = getDelegate().deleteFiredTriggers(conn);
/*  715 */       getLog().info("Removed " + n + " stale fired job entries.");
/*      */     } catch (Exception e) {
/*  717 */       throw new JobPersistenceException("Couldn't recover jobs: " + e.getMessage(), e);
/*      */     }
/*      */   }
/*      */
/*      */   protected long getMisfireTime()
/*      */   {
/*  723 */     long misfireTime = System.currentTimeMillis();
/*  724 */     if (getMisfireThreshold() > 0L) misfireTime -= getMisfireThreshold();
/*      */
/*  726 */     return misfireTime;
/*      */   }
/*      */
/*      */   protected boolean recoverMisfiredJobs(Connection conn, boolean recovering)
/*      */     throws JobPersistenceException, NoSuchDelegateException, SQLException, ClassNotFoundException, IOException
/*      */   {
/*  735 */     Key[] misfiredTriggers = getDelegate().selectTriggersInState(conn, "MISFIRED");
/*      */
/*  738 */     if ((misfiredTriggers.length > 0) && (misfiredTriggers.length > getMaxMisfiresToHandleAtATime())) {
/*  739 */       getLog().info("Handling " + getMaxMisfiresToHandleAtATime() + " of " + misfiredTriggers.length + " triggers that missed their scheduled fire-time.");
/*      */     }
/*  746 */     else if (misfiredTriggers.length > 0) getLog().info("Handling " + misfiredTriggers.length + " triggers that missed their scheduled fire-time.");
/*      */     else
/*      */     {
/*  750 */       getLog().debug("Found 0 triggers that missed their scheduled fire-time.");
/*      */     }
/*      */
/*  753 */     this.lastRecoverCount = misfiredTriggers.length;
/*      */
/*  755 */     for (int i = 0; (i < misfiredTriggers.length) && (i < getMaxMisfiresToHandleAtATime()); i++) {
/*  756 */       Trigger trig = getDelegate().selectTrigger(conn, misfiredTriggers[i].getName(), misfiredTriggers[i].getGroup());
/*      */
/*  760 */       if (trig == null)
/*      */         continue;
/*  762 */       Calendar cal = null;
/*  763 */       if (trig.getCalendarName() != null) {
/*  764 */         cal = retrieveCalendar(conn, null, trig.getCalendarName());
/*      */       }
/*  766 */       String[] listeners = getDelegate().selectTriggerListeners(conn, trig.getName(), trig.getGroup());
/*      */
/*  768 */       for (int l = 0; l < listeners.length; l++) {
/*  769 */         trig.addTriggerListener(listeners[l]);
/*      */       }
/*      */
/*  772 */       this.signaler.notifyTriggerListenersMisfired(trig);
/*      */
/*  774 */       trig.updateAfterMisfire(cal);
/*      */
/*  776 */       if (trig.getNextFireTime() == null) {
/*  777 */         storeTrigger(conn, null, trig, null, true, "COMPLETE", false, recovering);
/*      */       }
/*      */       else {
/*  780 */         storeTrigger(conn, null, trig, null, true, "WAITING", false, recovering);
/*      */       }
/*      */     }
/*      */
/*  784 */     return misfiredTriggers.length > getMaxMisfiresToHandleAtATime();
/*      */   }
/*      */
/*      */   protected boolean updateMisfiredTrigger(Connection conn, SchedulingContext ctxt, String triggerName, String groupName, String newStateIfNotComplete, boolean forceState)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/*  797 */       Trigger trig = getDelegate().selectTrigger(conn, triggerName, groupName);
/*      */
/*  800 */       long misfireTime = System.currentTimeMillis();
/*  801 */       if (getMisfireThreshold() > 0L) {
/*  802 */         misfireTime -= getMisfireThreshold();
/*      */       }
/*  804 */       if (trig.getNextFireTime().getTime() > misfireTime) return false;
/*      */
/*  806 */       Calendar cal = null;
/*  807 */       if (trig.getCalendarName() != null) {
/*  808 */         cal = retrieveCalendar(conn, ctxt, trig.getCalendarName());
/*      */       }
/*  810 */       this.signaler.notifyTriggerListenersMisfired(trig);
/*      */
/*  812 */       trig.updateAfterMisfire(cal);
/*      */
/*  814 */       if (trig.getNextFireTime() == null) storeTrigger(conn, ctxt, trig, null, true, "COMPLETE", forceState, false);
/*      */       else
/*      */       {
/*  817 */         storeTrigger(conn, ctxt, trig, null, true, newStateIfNotComplete, forceState, false);
/*      */       }
/*      */
/*  821 */       return true;
/*      */     } catch (Exception e) {
/*      */     }
/*  824 */     throw new JobPersistenceException("Couldn't update misfired trigger '" + groupName + "." + triggerName + "': " + e.getMessage(), e);
/*      */   }
/*      */
/*      */   protected void storeJob(Connection conn, SchedulingContext ctxt, JobDetail newJob, boolean replaceExisting)
/*      */     throws ObjectAlreadyExistsException, JobPersistenceException
/*      */   {
/*  838 */     if ((newJob.isVolatile()) && (isClustered())) {
/*  839 */       getLog().info("note: volatile jobs are effectively non-volatile in a clustered environment.");
/*      */     }
/*      */
/*  843 */     boolean existingJob = jobExists(conn, newJob.getName(), newJob.getGroup());
/*      */     try
/*      */     {
/*  846 */       if (existingJob) {
/*  847 */         if (!replaceExisting) throw new ObjectAlreadyExistsException(newJob);
/*      */
/*  849 */         getDelegate().updateJobDetail(conn, newJob);
/*      */       } else {
/*  851 */         getDelegate().insertJobDetail(conn, newJob);
/*      */       }
/*      */     } catch (IOException e) {
/*  854 */       throw new JobPersistenceException("Couldn't store job: " + e.getMessage(), e);
/*      */     }
/*      */     catch (SQLException e) {
/*  857 */       throw new JobPersistenceException("Couldn't store job: " + e.getMessage(), e);
/*      */     }
/*      */   }
/*      */
/*      */   protected boolean jobExists(Connection conn, String jobName, String groupName)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/*  870 */       return getDelegate().jobExists(conn, jobName, groupName); } catch (SQLException e) {
/*      */     }
/*  872 */     throw new JobPersistenceException("Couldn't determine job existence (" + groupName + "." + jobName + "): " + e.getMessage(), e);
/*      */   }
/*      */
/*      */   protected void storeTrigger(Connection conn, SchedulingContext ctxt, Trigger newTrigger, JobDetail job, boolean replaceExisting, String state, boolean forceState, boolean recovering)
/*      */     throws ObjectAlreadyExistsException, JobPersistenceException
/*      */   {
/*  887 */     if ((newTrigger.isVolatile()) && (isClustered())) {
/*  888 */       getLog().info("note: volatile triggers are effectively non-volatile in a clustered environment.");
/*      */     }
/*      */
/*  892 */     boolean existingTrigger = triggerExists(conn, newTrigger.getName(), newTrigger.getGroup());
/*      */     try
/*      */     {
/*  897 */       boolean shouldBepaused = false;
/*      */
/*  899 */       if (!forceState) {
/*  900 */         shouldBepaused = getDelegate().isTriggerGroupPaused(conn, newTrigger.getGroup());
/*      */
/*  903 */         if (!shouldBepaused) {
/*  904 */           shouldBepaused = getDelegate().isTriggerGroupPaused(conn, "_$_ALL_GROUPS_PAUSED_$_");
/*      */
/*  907 */           if (shouldBepaused) {
/*  908 */             getDelegate().insertPausedTriggerGroup(conn, newTrigger.getGroup());
/*      */           }
/*      */         }
/*      */
/*  912 */         if ((shouldBepaused) && ((state.equals("WAITING")) || (state.equals("ACQUIRED")))) {
/*  913 */           state = "PAUSED";
/*      */         }
/*      */       }
/*  916 */       if (job == null) {
/*  917 */         job = getDelegate().selectJobDetail(conn, newTrigger.getJobName(), newTrigger.getJobGroup(), getClassLoadHelper());
/*      */       }
/*      */
/*  921 */       if (job == null) {
/*  922 */         throw new JobPersistenceException("The job (" + newTrigger.getFullJobName() + ") referenced by the trigger does not exist.");
/*      */       }
/*      */
/*  925 */       if ((job.isVolatile()) && (!newTrigger.isVolatile())) {
/*  926 */         throw new JobPersistenceException("It does not make sense to associate a non-volatile Trigger with a volatile Job!");
/*      */       }
/*      */
/*  930 */       if ((job.isStateful()) && (!recovering)) {
/*  931 */         String bstate = getNewStatusForTrigger(conn, ctxt, job.getName(), job.getGroup());
/*      */
/*  933 */         if (("BLOCKED".equals(bstate)) && ("WAITING".equals(state)))
/*  934 */           state = "BLOCKED";
/*  935 */         if (("BLOCKED".equals(bstate)) && ("PAUSED".equals(state)))
/*  936 */           state = "PAUSED_BLOCKED";
/*      */       }
/*  938 */       if (existingTrigger) {
/*  939 */         if (!replaceExisting) throw new ObjectAlreadyExistsException(newTrigger);
/*      */
/*  941 */         if ((newTrigger instanceof SimpleTrigger)) {
/*  942 */           getDelegate().updateSimpleTrigger(conn, (SimpleTrigger)newTrigger);
/*      */         }
/*  944 */         else if ((newTrigger instanceof CronTrigger)) {
/*  945 */           getDelegate().updateCronTrigger(conn, (CronTrigger)newTrigger);
/*      */         }
/*      */         else {
/*  948 */           getDelegate().updateBlobTrigger(conn, newTrigger);
/*      */         }
/*  950 */         getDelegate().updateTrigger(conn, newTrigger, state, job);
/*      */       } else {
/*  952 */         getDelegate().insertTrigger(conn, newTrigger, state, job);
/*  953 */         if ((newTrigger instanceof SimpleTrigger)) {
/*  954 */           getDelegate().insertSimpleTrigger(conn, (SimpleTrigger)newTrigger);
/*      */         }
/*  956 */         else if ((newTrigger instanceof CronTrigger)) {
/*  957 */           getDelegate().insertCronTrigger(conn, (CronTrigger)newTrigger);
/*      */         }
/*      */         else
/*  960 */           getDelegate().insertBlobTrigger(conn, newTrigger);
/*      */       }
/*      */     }
/*      */     catch (Exception e) {
/*  964 */       throw new JobPersistenceException("Couldn't store trigger: " + e.getMessage(), e);
/*      */     }
/*      */   }
/*      */
/*      */   protected boolean triggerExists(Connection conn, String triggerName, String groupName)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/*  977 */       return getDelegate().triggerExists(conn, triggerName, groupName); } catch (SQLException e) {
/*      */     }
/*  979 */     throw new JobPersistenceException("Couldn't determine trigger existence (" + groupName + "." + triggerName + "): " + e.getMessage(), e);
/*      */   }
/*      */
/*      */   protected boolean removeJob(Connection conn, SchedulingContext ctxt, String jobName, String groupName, boolean activeDeleteSafe)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/*  990 */       Key[] jobTriggers = getDelegate().selectTriggerNamesForJob(conn, jobName, groupName);
/*      */
/*  992 */       for (int i = 0; i < jobTriggers.length; i++) {
/*  993 */         getDelegate().deleteSimpleTrigger(conn, jobTriggers[i].getName(), jobTriggers[i].getGroup());
/*      */
/*  995 */         getDelegate().deleteCronTrigger(conn, jobTriggers[i].getName(), jobTriggers[i].getGroup());
/*      */
/*  997 */         getDelegate().deleteBlobTrigger(conn, jobTriggers[i].getName(), jobTriggers[i].getGroup());
/*      */
/*  999 */         getDelegate().deleteTriggerListeners(conn, jobTriggers[i].getName(), jobTriggers[i].getGroup());
/*      */
/* 1001 */         getDelegate().deleteTrigger(conn, jobTriggers[i].getName(), jobTriggers[i].getGroup());
/*      */       }
/*      */
/* 1005 */       getDelegate().deleteJobListeners(conn, jobName, groupName);
/*      */
/* 1008 */       return getDelegate().deleteJobDetail(conn, jobName, groupName) > 0;
/*      */     }
/*      */     catch (SQLException e)
/*      */     {
/*      */     }
/*      */
/* 1013 */     throw new JobPersistenceException("Couldn't remove job: " + e.getMessage(), e);
/*      */   }
/*      */
/*      */   protected JobDetail retrieveJob(Connection conn, SchedulingContext ctxt, String jobName, String groupName)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1021 */       JobDetail job = getDelegate().selectJobDetail(conn, jobName, groupName, getClassLoadHelper());
/*      */
/* 1023 */       String[] listeners = getDelegate().selectJobListeners(conn, jobName, groupName);
/*      */
/* 1025 */       for (int i = 0; i < listeners.length; i++) {
/* 1026 */         job.addJobListener(listeners[i]);
/*      */       }
/*      */
/* 1029 */       return job;
/*      */     } catch (ClassNotFoundException e) {
/* 1031 */       throw new JobPersistenceException("Couldn't retrieve job because a required class was not found: " + e.getMessage(), e, 410);
/*      */     }
/*      */     catch (IOException e)
/*      */     {
/* 1036 */       throw new JobPersistenceException("Couldn't retrieve job because the BLOB couldn't be deserialized: " + e.getMessage(), e, 410);
/*      */     }
/*      */     catch (SQLException e)
/*      */     {
/*      */     }
/* 1041 */     throw new JobPersistenceException("Couldn't retrieve job: " + e.getMessage(), e);
/*      */   }
/*      */
/*      */   protected boolean removeTrigger(Connection conn, SchedulingContext ctxt, String triggerName, String groupName)
/*      */     throws JobPersistenceException
/*      */   {
/* 1049 */     boolean removedTrigger = false;
/*      */     try
/*      */     {
/* 1052 */       JobDetail job = getDelegate().selectJobForTrigger(conn, triggerName, groupName, getClassLoadHelper());
/*      */
/* 1055 */       getDelegate().deleteSimpleTrigger(conn, triggerName, groupName);
/* 1056 */       getDelegate().deleteCronTrigger(conn, triggerName, groupName);
/* 1057 */       getDelegate().deleteBlobTrigger(conn, triggerName, groupName);
/* 1058 */       getDelegate().deleteTriggerListeners(conn, triggerName, groupName);
/* 1059 */       removedTrigger = getDelegate().deleteTrigger(conn, triggerName, groupName) > 0;
/*      */
/* 1062 */       if ((null != job) && (!job.isDurable())) {
/* 1063 */         int numTriggers = getDelegate().selectNumTriggersForJob(conn, job.getName(), job.getGroup());
/*      */
/* 1065 */         if (numTriggers == 0)
/* 1066 */           removeJob(conn, ctxt, job.getName(), job.getGroup(), true);
/*      */       }
/*      */     }
/*      */     catch (ClassNotFoundException e) {
/* 1070 */       throw new JobPersistenceException("Couldn't remove trigger: " + e.getMessage(), e);
/*      */     }
/*      */     catch (SQLException e) {
/* 1073 */       throw new JobPersistenceException("Couldn't remove trigger: " + e.getMessage(), e);
/*      */     }
/*      */
/* 1077 */     return removedTrigger;
/*      */   }
/*      */
/*      */   protected boolean replaceTrigger(Connection conn, SchedulingContext ctxt, String triggerName, String groupName, Trigger newTrigger)
/*      */     throws JobPersistenceException
/*      */   {
/* 1083 */     boolean removedTrigger = false;
/*      */     try
/*      */     {
/* 1086 */       JobDetail job = getDelegate().selectJobForTrigger(conn, triggerName, groupName, getClassLoadHelper());
/*      */
/* 1089 */       if (job == null) {
/* 1090 */         return false;
/*      */       }
/* 1092 */       if ((!newTrigger.getJobName().equals(job.getName())) || (!newTrigger.getJobGroup().equals(job.getGroup())))
/*      */       {
/* 1094 */         throw new JobPersistenceException("New trigger is not related to the same job as the old trigger.");
/*      */       }
/* 1096 */       getDelegate().deleteSimpleTrigger(conn, triggerName, groupName);
/* 1097 */       getDelegate().deleteCronTrigger(conn, triggerName, groupName);
/* 1098 */       getDelegate().deleteBlobTrigger(conn, triggerName, groupName);
/* 1099 */       getDelegate().deleteTriggerListeners(conn, triggerName, groupName);
/* 1100 */       removedTrigger = getDelegate().deleteTrigger(conn, triggerName, groupName) > 0;
/*      */
/* 1103 */       storeTrigger(conn, ctxt, newTrigger, job, false, "WAITING", false, false);
/*      */     }
/*      */     catch (ClassNotFoundException e) {
/* 1106 */       throw new JobPersistenceException("Couldn't remove trigger: " + e.getMessage(), e);
/*      */     }
/*      */     catch (SQLException e) {
/* 1109 */       throw new JobPersistenceException("Couldn't remove trigger: " + e.getMessage(), e);
/*      */     }
/*      */
/* 1113 */     return removedTrigger;
/*      */   }
/*      */
/*      */   protected Trigger retrieveTrigger(Connection conn, SchedulingContext ctxt, String triggerName, String groupName) throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1120 */       Trigger trigger = getDelegate().selectTrigger(conn, triggerName, groupName);
/*      */
/* 1122 */       if (trigger == null) return null;
/* 1123 */       String[] listeners = getDelegate().selectTriggerListeners(conn, triggerName, groupName);
/*      */
/* 1125 */       for (int i = 0; i < listeners.length; i++) {
/* 1126 */         trigger.addTriggerListener(listeners[i]);
/*      */       }
/*      */
/* 1129 */       return trigger; } catch (Exception e) {
/*      */     }
/* 1131 */     throw new JobPersistenceException("Couldn't retrieve trigger: " + e.getMessage(), e);
/*      */   }
/*      */
/*      */   public int getTriggerState(Connection conn, SchedulingContext ctxt, String triggerName, String groupName)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1140 */       String ts = getDelegate().selectTriggerState(conn, triggerName, groupName);
/*      */
/* 1143 */       if (ts == null) return -1;
/*      */
/* 1145 */       if (ts.equals("DELETED")) return -1;
/*      */
/* 1147 */       if (ts.equals("COMPLETE")) return 2;
/*      */
/* 1149 */       if (ts.equals("PAUSED")) return 1;
/*      */
/* 1151 */       if (ts.equals("PAUSED_BLOCKED")) return 1;
/*      */
/* 1153 */       if (ts.equals("ERROR")) return 3;
/*      */
/* 1155 */       if (ts.equals("BLOCKED")) return 4;
/*      */
/* 1157 */       return 0;
/*      */     } catch (SQLException e) {
/*      */     }
/* 1160 */     throw new JobPersistenceException("Couldn't determine state of trigger (" + groupName + "." + triggerName + "): " + e.getMessage(), e);
/*      */   }
/*      */
/*      */   protected void storeCalendar(Connection conn, SchedulingContext ctxt, String calName, Calendar calendar, boolean replaceExisting, boolean updateTriggers)
/*      */     throws ObjectAlreadyExistsException, JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1170 */       boolean existingCal = calendarExists(conn, calName);
/* 1171 */       if ((existingCal) && (!replaceExisting)) throw new ObjectAlreadyExistsException("Calendar with name '" + calName + "' already exists.");
/*      */
/* 1174 */       if (existingCal) {
/* 1175 */         if (getDelegate().updateCalendar(conn, calName, calendar) < 1) throw new JobPersistenceException("Couldn't store calendar.  Update failed.");
/*      */
/* 1178 */         if (updateTriggers) {
/* 1179 */           Trigger[] trigs = getDelegate().selectTriggersForCalendar(conn, calName);
/*      */
/* 1181 */           for (int i = 0; i < trigs.length; i++) {
/* 1182 */             trigs[i].updateWithNewCalendar(calendar, getMisfireThreshold());
/* 1183 */             storeTrigger(conn, ctxt, trigs[i], null, true, "WAITING", false, false);
/*      */           }
/*      */         }
/*      */       }
/* 1187 */       else if (getDelegate().insertCalendar(conn, calName, calendar) < 1) { throw new JobPersistenceException("Couldn't store calendar.  Insert failed.");
/*      */       }
/*      */
/* 1191 */       this.calendarCache.put(calName, calendar);
/*      */     }
/*      */     catch (IOException e) {
/* 1194 */       throw new JobPersistenceException("Couldn't store calendar because the BLOB couldn't be serialized: " + e.getMessage(), e);
/*      */     }
/*      */     catch (ClassNotFoundException e)
/*      */     {
/* 1198 */       throw new JobPersistenceException("Couldn't store calendar: " + e.getMessage(), e);
/*      */     }
/*      */     catch (SQLException e) {
/* 1201 */       throw new JobPersistenceException("Couldn't store calendar: " + e.getMessage(), e);
/*      */     }
/*      */   }
/*      */
/*      */   protected boolean calendarExists(Connection conn, String calName) throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1209 */       return getDelegate().calendarExists(conn, calName); } catch (SQLException e) {
/*      */     }
/* 1211 */     throw new JobPersistenceException("Couldn't determine calendar existence (" + calName + "): " + e.getMessage(), e);
/*      */   }
/*      */
/*      */   protected boolean removeCalendar(Connection conn, SchedulingContext ctxt, String calName)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1220 */       if (getDelegate().calendarIsReferenced(conn, calName)) throw new JobPersistenceException("Calender cannot be removed if it referenced by a trigger!");
/*      */
/* 1223 */       this.calendarCache.remove(calName);
/*      */
/* 1225 */       return getDelegate().deleteCalendar(conn, calName) > 0; } catch (SQLException e) {
/*      */     }
/* 1227 */     throw new JobPersistenceException("Couldn't remove calendar: " + e.getMessage(), e);
/*      */   }
/*      */
/*      */   protected Calendar retrieveCalendar(Connection conn, SchedulingContext ctxt, String calName)
/*      */     throws JobPersistenceException
/*      */   {
/* 1237 */     Calendar cal = (Calendar)this.calendarCache.get(calName);
/* 1238 */     if (cal != null) return cal;
/*      */     try
/*      */     {
/* 1241 */       cal = getDelegate().selectCalendar(conn, calName);
/* 1242 */       this.calendarCache.put(calName, cal);
/* 1243 */       return cal;
/*      */     } catch (ClassNotFoundException e) {
/* 1245 */       throw new JobPersistenceException("Couldn't retrieve calendar because a required class was not found: " + e.getMessage(), e);
/*      */     }
/*      */     catch (IOException e)
/*      */     {
/* 1249 */       throw new JobPersistenceException("Couldn't retrieve calendar because the BLOB couldn't be deserialized: " + e.getMessage(), e);
/*      */     }
/*      */     catch (SQLException e) {
/*      */     }
/* 1253 */     throw new JobPersistenceException("Couldn't retrieve calendar: " + e.getMessage(), e);
/*      */   }
/*      */
/*      */   protected int getNumberOfJobs(Connection conn, SchedulingContext ctxt)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1261 */       return getDelegate().selectNumJobs(conn); } catch (SQLException e) {
/*      */     }
/* 1263 */     throw new JobPersistenceException("Couldn't obtain number of jobs: " + e.getMessage(), e);
/*      */   }
/*      */
/*      */   protected int getNumberOfTriggers(Connection conn, SchedulingContext ctxt)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1271 */       return getDelegate().selectNumTriggers(conn); } catch (SQLException e) {
/*      */     }
/* 1273 */     throw new JobPersistenceException("Couldn't obtain number of triggers: " + e.getMessage(), e);
/*      */   }
/*      */
/*      */   protected int getNumberOfCalendars(Connection conn, SchedulingContext ctxt)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1281 */       return getDelegate().selectNumCalendars(conn); } catch (SQLException e) {
/*      */     }
/* 1283 */     throw new JobPersistenceException("Couldn't obtain number of calendars: " + e.getMessage(), e);
/*      */   }
/*      */
/*      */   protected String[] getJobNames(Connection conn, SchedulingContext ctxt, String groupName)
/*      */     throws JobPersistenceException
/*      */   {
/* 1290 */     String[] jobNames = null;
/*      */     try
/*      */     {
/* 1293 */       jobNames = getDelegate().selectJobsInGroup(conn, groupName);
/*      */     } catch (SQLException e) {
/* 1295 */       throw new JobPersistenceException("Couldn't obtain job names: " + e.getMessage(), e);
/*      */     }
/*      */
/* 1299 */     return jobNames;
/*      */   }
/*      */
/*      */   protected String[] getTriggerNames(Connection conn, SchedulingContext ctxt, String groupName)
/*      */     throws JobPersistenceException
/*      */   {
/* 1305 */     String[] trigNames = null;
/*      */     try
/*      */     {
/* 1308 */       trigNames = getDelegate().selectTriggersInGroup(conn, groupName);
/*      */     } catch (SQLException e) {
/* 1310 */       throw new JobPersistenceException("Couldn't obtain trigger names: " + e.getMessage(), e);
/*      */     }
/*      */
/* 1314 */     return trigNames;
/*      */   }
/*      */
/*      */   protected String[] getJobGroupNames(Connection conn, SchedulingContext ctxt)
/*      */     throws JobPersistenceException
/*      */   {
/* 1320 */     String[] groupNames = null;
/*      */     try
/*      */     {
/* 1323 */       groupNames = getDelegate().selectJobGroups(conn);
/*      */     } catch (SQLException e) {
/* 1325 */       throw new JobPersistenceException("Couldn't obtain job groups: " + e.getMessage(), e);
/*      */     }
/*      */
/* 1329 */     return groupNames;
/*      */   }
/*      */
/*      */   protected String[] getTriggerGroupNames(Connection conn, SchedulingContext ctxt)
/*      */     throws JobPersistenceException
/*      */   {
/* 1335 */     String[] groupNames = null;
/*      */     try
/*      */     {
/* 1338 */       groupNames = getDelegate().selectTriggerGroups(conn);
/*      */     } catch (SQLException e) {
/* 1340 */       throw new JobPersistenceException("Couldn't obtain trigger groups: " + e.getMessage(), e);
/*      */     }
/*      */
/* 1344 */     return groupNames;
/*      */   }
/*      */
/*      */   protected String[] getCalendarNames(Connection conn, SchedulingContext ctxt) throws JobPersistenceException
/*      */   {
/*      */     try {
/* 1350 */       return getDelegate().selectCalendars(conn); } catch (SQLException e) {
/*      */     }
/* 1352 */     throw new JobPersistenceException("Couldn't obtain trigger groups: " + e.getMessage(), e);
/*      */   }
/*      */
/*      */   protected Trigger[] getTriggersForJob(Connection conn, SchedulingContext ctxt, String jobName, String groupName)
/*      */     throws JobPersistenceException
/*      */   {
/* 1360 */     Trigger[] array = null;
/*      */     try
/*      */     {
/* 1363 */       array = getDelegate().selectTriggersForJob(conn, jobName, groupName);
/*      */     }
/*      */     catch (Exception e) {
/* 1366 */       throw new JobPersistenceException("Couldn't obtain triggers for job: " + e.getMessage(), e);
/*      */     }
/*      */
/* 1370 */     return array;
/*      */   }
/*      */
/*      */   public void pauseTrigger(Connection conn, SchedulingContext ctxt, String triggerName, String groupName)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1385 */       String oldState = getDelegate().selectTriggerState(conn, triggerName, groupName);
/*      */
/* 1388 */       if ((oldState.equals("WAITING")) || (oldState.equals("ACQUIRED")))
/*      */       {
/* 1391 */         getDelegate().updateTriggerState(conn, triggerName, groupName, "PAUSED");
/*      */       }
/* 1394 */       else if (oldState.equals("BLOCKED"))
/* 1395 */         getDelegate().updateTriggerState(conn, triggerName, groupName, "PAUSED_BLOCKED");
/*      */     }
/*      */     catch (SQLException e)
/*      */     {
/* 1399 */       throw new JobPersistenceException("Couldn't pause trigger '" + groupName + "." + triggerName + "': " + e.getMessage(), e);
/*      */     }
/*      */   }
/*      */
/*      */   protected String getStatusForResumedTrigger(Connection conn, SchedulingContext ctxt, TriggerStatus status)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1409 */       String newState = "WAITING";
/*      */
/* 1411 */       List lst = getDelegate().selectFiredTriggerRecordsByJob(conn, status.getJobKey().getName(), status.getJobKey().getGroup());
/*      */
/* 1416 */       if (lst.size() > 0) {
/* 1417 */         FiredTriggerRecord rec = (FiredTriggerRecord)lst.get(0);
/* 1418 */         if (rec.isJobIsStateful())
/*      */         {
/* 1421 */           newState = "BLOCKED";
/*      */         }
/*      */       }
/* 1424 */       return newState;
/*      */     } catch (SQLException e) {
/*      */     }
/* 1427 */     throw new JobPersistenceException("Couldn't determine new state in order to resume trigger '" + status.getKey().getGroup() + "." + status.getKey().getName() + "': " + e.getMessage(), e);
/*      */   }
/*      */
/*      */   protected String getNewStatusForTrigger(Connection conn, SchedulingContext ctxt, String jobName, String groupName)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1441 */       String newState = "WAITING";
/*      */
/* 1443 */       List lst = getDelegate().selectFiredTriggerRecordsByJob(conn, jobName, groupName);
/*      */
/* 1446 */       if (lst.size() > 0) {
/* 1447 */         FiredTriggerRecord rec = (FiredTriggerRecord)lst.get(0);
/* 1448 */         if (rec.isJobIsStateful())
/*      */         {
/* 1451 */           newState = "BLOCKED";
/*      */         }
/*      */       }
/* 1454 */       return newState;
/*      */     } catch (SQLException e) {
/*      */     }
/* 1457 */     throw new JobPersistenceException("Couldn't determine state for new trigger: " + e.getMessage(), e);
/*      */   }
/*      */
/*      */   public void resumeTrigger(Connection conn, SchedulingContext ctxt, String triggerName, String groupName)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1510 */       TriggerStatus status = getDelegate().selectTriggerStatus(conn, triggerName, groupName);
/*      */
/* 1513 */       if ((status == null) || (status.getNextFireTime() == null)) return;
/*      */
/* 1515 */       boolean blocked = false;
/* 1516 */       if ("PAUSED_BLOCKED".equals(status.getStatus())) {
/* 1517 */         blocked = true;
/*      */       }
/* 1519 */       String newState = getStatusForResumedTrigger(conn, ctxt, status);
/*      */
/* 1521 */       boolean misfired = false;
/*      */
/* 1523 */       if (status.getNextFireTime().before(new Date())) {
/* 1524 */         misfired = updateMisfiredTrigger(conn, ctxt, triggerName, groupName, newState, true);
/*      */       }
/*      */
/* 1528 */       if (!misfired) {
/* 1529 */         if (blocked) {
/* 1530 */           getDelegate().updateTriggerStateFromOtherState(conn, triggerName, groupName, newState, "PAUSED_BLOCKED");
/*      */         }
/*      */         else
/* 1533 */           getDelegate().updateTriggerStateFromOtherState(conn, triggerName, groupName, newState, "PAUSED");
/*      */       }
/*      */     }
/*      */     catch (SQLException e)
/*      */     {
/* 1538 */       throw new JobPersistenceException("Couldn't resume trigger '" + groupName + "." + triggerName + "': " + e.getMessage(), e);
/*      */     }
/*      */   }
/*      */
/*      */   public void pauseTriggerGroup(Connection conn, SchedulingContext ctxt, String groupName)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1556 */       getDelegate().updateTriggerGroupStateFromOtherStates(conn, groupName, "PAUSED", "ACQUIRED", "WAITING", "WAITING");
/*      */
/* 1560 */       getDelegate().updateTriggerGroupStateFromOtherState(conn, groupName, "PAUSED_BLOCKED", "BLOCKED");
/*      */
/* 1563 */       if (!getDelegate().isTriggerGroupPaused(conn, groupName))
/* 1564 */         getDelegate().insertPausedTriggerGroup(conn, groupName);
/*      */     }
/*      */     catch (SQLException e)
/*      */     {
/* 1568 */       throw new JobPersistenceException("Couldn't pause trigger group '" + groupName + "': " + e.getMessage(), e);
/*      */     }
/*      */   }
/*      */
/*      */   public Set getPausedTriggerGroups(Connection conn, SchedulingContext ctxt)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1585 */       return getDelegate().selectPausedTriggerGroups(conn); } catch (SQLException e) {
/*      */     }
/* 1587 */     throw new JobPersistenceException("Couldn't determine paused trigger groups: " + e.getMessage(), e);
/*      */   }
/*      */
/*      */   public void resumeTriggerGroup(Connection conn, SchedulingContext ctxt, String groupName)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1610 */       getDelegate().deletePausedTriggerGroup(conn, groupName);
/*      */
/* 1612 */       String[] trigNames = getDelegate().selectTriggersInGroup(conn, groupName);
/*      */
/* 1615 */       for (int i = 0; i < trigNames.length; i++) {
/* 1616 */         resumeTrigger(conn, ctxt, trigNames[i], groupName);
/*      */       }
/*      */
/*      */     }
/*      */     catch (SQLException e)
/*      */     {
/* 1653 */       throw new JobPersistenceException("Couldn't pause trigger group '" + groupName + "': " + e.getMessage(), e);
/*      */     }
/*      */   }
/*      */
/*      */   public void pauseAll(Connection conn, SchedulingContext ctxt)
/*      */     throws JobPersistenceException
/*      */   {
/* 1675 */     String[] names = getTriggerGroupNames(conn, ctxt);
/*      */
/* 1677 */     for (int i = 0; i < names.length; i++) {
/* 1678 */       pauseTriggerGroup(conn, ctxt, names[i]);
/*      */     }
/*      */     try
/*      */     {
/* 1682 */       if (!getDelegate().isTriggerGroupPaused(conn, "_$_ALL_GROUPS_PAUSED_$_"))
/* 1683 */         getDelegate().insertPausedTriggerGroup(conn, "_$_ALL_GROUPS_PAUSED_$_");
/*      */     }
/*      */     catch (SQLException e)
/*      */     {
/* 1687 */       throw new JobPersistenceException("Couldn't pause all trigger groups: " + e.getMessage(), e);
/*      */     }
/*      */   }
/*      */
/*      */   public void resumeAll(Connection conn, SchedulingContext ctxt)
/*      */     throws JobPersistenceException
/*      */   {
/* 1710 */     String[] names = getTriggerGroupNames(conn, ctxt);
/*      */
/* 1712 */     for (int i = 0; i < names.length; i++) {
/* 1713 */       resumeTriggerGroup(conn, ctxt, names[i]);
/*      */     }
/*      */     try
/*      */     {
/* 1717 */       getDelegate().deletePausedTriggerGroup(conn, "_$_ALL_GROUPS_PAUSED_$_");
/*      */     } catch (SQLException e) {
/* 1719 */       throw new JobPersistenceException("Couldn't resume all trigger groups: " + e.getMessage(), e);
/*      */     }
/*      */   }
/*      */
/*      */   protected synchronized String getFiredTriggerRecordId()
/*      */   {
/* 1728 */     return getInstanceId() + ftrCtr++;
/*      */   }
/*      */
/*      */   protected Trigger acquireNextTrigger(Connection conn, SchedulingContext ctxt, long noLaterThan)
/*      */     throws JobPersistenceException
/*      */   {
/* 1735 */     Trigger nextTrigger = null;
/*      */
/* 1737 */     boolean acquiredOne = false;
/*      */     do {
/*      */       try
/*      */       {
/* 1741 */         getDelegate().updateTriggerStateFromOtherStatesBeforeTime(conn, "MISFIRED", "WAITING", "WAITING", getMisfireTime());
/*      */
/* 1745 */         long nextFireTime = getDelegate().selectNextFireTime(conn);
/*      */
/* 1747 */         if ((nextFireTime == 0L) || (nextFireTime > noLaterThan)) {
/* 1748 */           return null;
/*      */         }
/* 1750 */         Key triggerKey = null;
/*      */         do {
/* 1752 */           triggerKey = getDelegate().selectTriggerForFireTime(conn, nextFireTime);
/*      */
/* 1754 */           if (null != triggerKey)
/*      */           {
/* 1756 */             int res = getDelegate().updateTriggerStateFromOtherState(conn, triggerKey.getName(), triggerKey.getGroup(), "ACQUIRED", "WAITING");
/*      */
/* 1762 */             if (res > 0)
/*      */             {
/* 1764 */               nextTrigger = retrieveTrigger(conn, ctxt, triggerKey.getName(), triggerKey.getGroup());
/*      */
/* 1767 */               if (nextTrigger != null)
/*      */               {
/* 1769 */                 nextTrigger.setFireInstanceId(getFiredTriggerRecordId());
/*      */
/* 1771 */                 getDelegate().insertFiredTrigger(conn, nextTrigger, "ACQUIRED", null);
/*      */
/* 1774 */                 acquiredOne = true;
/*      */               }
/*      */             }
/*      */           }
/* 1776 */           if (triggerKey == null) break;
/* 1776 */         }while (!acquiredOne);
/*      */       } catch (Exception e) {
/* 1778 */         throw new JobPersistenceException("Couldn't acquire next trigger: " + e.getMessage(), e);
/*      */       }
/*      */     }
/*      */
/* 1782 */     while (!acquiredOne);
/*      */
/* 1784 */     return nextTrigger;
/*      */   }
/*      */
/*      */   protected void releaseAcquiredTrigger(Connection conn, SchedulingContext ctxt, Trigger trigger) throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1791 */       getDelegate().updateTriggerStateFromOtherState(conn, trigger.getName(), trigger.getGroup(), "WAITING", "ACQUIRED");
/*      */
/* 1794 */       getDelegate().deleteFiredTrigger(conn, trigger.getFireInstanceId());
/*      */     } catch (SQLException e) {
/* 1796 */       throw new JobPersistenceException("Couldn't release acquired trigger: " + e.getMessage(), e);
/*      */     }
/*      */   }
/*      */
/*      */   protected TriggerFiredBundle triggerFired(Connection conn, SchedulingContext ctxt, Trigger trigger)
/*      */     throws JobPersistenceException
/*      */   {
/* 1804 */     JobDetail job = null;
/* 1805 */     Calendar cal = null;
/*      */     try
/*      */     {
/* 1809 */       String state = getDelegate().selectTriggerState(conn, trigger.getName(), trigger.getGroup());
/*      */
/* 1811 */       if (!state.equals("ACQUIRED")) return null;
/*      */     }
/*      */     catch (SQLException e) {
/* 1813 */       throw new JobPersistenceException("Couldn't select trigger state: " + e.getMessage(), e);
/*      */     }
/*      */
/*      */     try
/*      */     {
/* 1818 */       job = retrieveJob(conn, ctxt, trigger.getJobName(), trigger.getJobGroup());
/*      */
/* 1820 */       if (job == null) return null;
/*      */     }
/*      */     catch (JobPersistenceException jpe) {
/*      */       try {
/* 1823 */         getLog().error("Error retrieving job, setting trigger state to ERROR.", jpe);
/* 1824 */         getDelegate().updateTriggerState(conn, trigger.getName(), trigger.getGroup(), "ERROR");
/*      */       }
/*      */       catch (SQLException sqle) {
/* 1827 */         getLog().error("Unable to set trigger state to ERROR.", sqle);
/*      */       }
/* 1829 */       throw jpe;
/*      */     }
/*      */
/* 1832 */     if (trigger.getCalendarName() != null) {
/* 1833 */       cal = retrieveCalendar(conn, ctxt, trigger.getCalendarName());
/* 1834 */       if (cal == null) return null;
/*      */     }
/*      */     try
/*      */     {
/* 1838 */       getDelegate().deleteFiredTrigger(conn, trigger.getFireInstanceId());
/* 1839 */       getDelegate().insertFiredTrigger(conn, trigger, "EXECUTING", job);
/*      */     }
/*      */     catch (SQLException e) {
/* 1842 */       throw new JobPersistenceException("Couldn't insert fired trigger: " + e.getMessage(), e);
/*      */     }
/*      */
/* 1846 */     Date prevFireTime = trigger.getPreviousFireTime();
/*      */
/* 1849 */     trigger.triggered(cal);
/*      */
/* 1851 */     String state = "WAITING";
/* 1852 */     boolean force = true;
/*      */
/* 1854 */     if (job.isStateful()) {
/* 1855 */       state = "BLOCKED";
/* 1856 */       force = false;
/*      */       try {
/* 1858 */         getDelegate().updateTriggerStatesForJobFromOtherState(conn, job.getName(), job.getGroup(), "BLOCKED", "WAITING");
/*      */
/* 1860 */         getDelegate().updateTriggerStatesForJobFromOtherState(conn, job.getName(), job.getGroup(), "BLOCKED", "ACQUIRED");
/*      */
/* 1862 */         getDelegate().updateTriggerStatesForJobFromOtherState(conn, job.getName(), job.getGroup(), "PAUSED_BLOCKED", "PAUSED");
/*      */       }
/*      */       catch (SQLException e) {
/* 1865 */         throw new JobPersistenceException("Couldn't update states of blocked triggers: " + e.getMessage(), e);
/*      */       }
/*      */
/*      */     }
/*      */
/* 1871 */     if (trigger.getNextFireTime() == null) {
/* 1872 */       state = "COMPLETE";
/* 1873 */       force = true;
/*      */     }
/*      */
/* 1876 */     storeTrigger(conn, ctxt, trigger, job, true, state, force, false);
/*      */
/* 1878 */     job.getJobDataMap().clearDirtyFlag();
/*      */
/* 1880 */     return new TriggerFiredBundle(job, trigger, cal, trigger.getGroup().equals("RECOVERING_JOBS"), new Date(), trigger.getPreviousFireTime(), prevFireTime, trigger.getNextFireTime());
/*      */   }
/*      */
/*      */   protected void triggeredJobComplete(Connection conn, SchedulingContext ctxt, Trigger trigger, JobDetail jobDetail, int triggerInstCode)
/*      */     throws JobPersistenceException
/*      */   {
/*      */     try
/*      */     {
/* 1889 */       if (triggerInstCode == 3) {
/* 1890 */         if (trigger.getNextFireTime() == null)
/*      */         {
/* 1893 */           TriggerStatus stat = getDelegate().selectTriggerStatus(conn, trigger.getName(), trigger.getGroup());
/*      */
/* 1895 */           if ((stat != null) && (stat.getNextFireTime() == null))
/* 1896 */             removeTrigger(conn, ctxt, trigger.getName(), trigger.getGroup());
/*      */         }
/*      */         else
/*      */         {
/* 1900 */           removeTrigger(conn, ctxt, trigger.getName(), trigger.getGroup());
/*      */         }
/* 1902 */       } else if (triggerInstCode == 2) {
/* 1903 */         getDelegate().updateTriggerState(conn, trigger.getName(), trigger.getGroup(), "COMPLETE");
/*      */       }
/* 1905 */       else if (triggerInstCode == 5) {
/* 1906 */         getLog().info("Trigger " + trigger.getFullName() + " set to ERROR state.");
/* 1907 */         getDelegate().updateTriggerState(conn, trigger.getName(), trigger.getGroup(), "ERROR");
/*      */       }
/* 1909 */       else if (triggerInstCode == 4) {
/* 1910 */         getDelegate().updateTriggerStatesForJob(conn, trigger.getJobName(), trigger.getJobGroup(), "COMPLETE");
/*      */       }
/* 1913 */       else if (triggerInstCode == 6) {
/* 1914 */         getLog().info("All triggers of Job " + trigger.getFullJobName() + " set to ERROR state.");
/*      */
/* 1916 */         getDelegate().updateTriggerStatesForJob(conn, trigger.getJobName(), trigger.getJobGroup(), "ERROR");
/*      */       }
/*      */
/* 1921 */       if (jobDetail.isStateful()) {
/* 1922 */         getDelegate().updateTriggerStatesForJobFromOtherState(conn, jobDetail.getName(), jobDetail.getGroup(), "WAITING", "BLOCKED");
/*      */
/* 1926 */         getDelegate().updateTriggerStatesForJobFromOtherState(conn, jobDetail.getName(), jobDetail.getGroup(), "PAUSED", "PAUSED_BLOCKED");
/*      */         try
/*      */         {
/* 1931 */           if (jobDetail.getJobDataMap().isDirty())
/* 1932 */             getDelegate().updateJobData(conn, jobDetail);
/*      */         }
/*      */         catch (IOException e) {
/* 1935 */           throw new JobPersistenceException("Couldn't serialize job data: " + e.getMessage(), e);
/*      */         }
/*      */         catch (SQLException e) {
/* 1938 */           throw new JobPersistenceException("Couldn't update job data: " + e.getMessage(), e);
/*      */         }
/*      */       }
/*      */     }
/*      */     catch (SQLException e) {
/* 1943 */       throw new JobPersistenceException("Couldn't update trigger state(s): " + e.getMessage(), e);
/*      */     }
/*      */
/*      */     try
/*      */     {
/* 1948 */       getDelegate().deleteFiredTrigger(conn, trigger.getFireInstanceId());
/*      */     } catch (SQLException e) {
/* 1950 */       throw new JobPersistenceException("Couldn't delete fired trigger: " + e.getMessage(), e);
/*      */     }
/*      */   }
/*      */
/*      */   protected DriverDelegate getDelegate()
/*      */     throws NoSuchDelegateException
/*      */   {
/* 1961 */     if (null == this.delegate) {
/*      */       try {
/* 1963 */         if (this.delegateClassName != null) {
/* 1964 */           this.delegateClass = getClassLoadHelper().loadClass(this.delegateClassName);
/*      */         }
/*      */
/* 1967 */         Constructor ctor = null;
/* 1968 */         Object[] ctorParams = null;
/* 1969 */         if (canUseProperties()) {
/* 1970 */           Class[] ctorParamTypes = { Log.class, String.class, String.class, Boolean.class };
/*      */
/* 1972 */           ctor = this.delegateClass.getConstructor(ctorParamTypes);
/* 1973 */           ctorParams = new Object[] { getLog(), this.tablePrefix, this.instanceId, new Boolean(canUseProperties()) };
/*      */         }
/*      */         else {
/* 1976 */           Class[] ctorParamTypes = { Log.class, String.class, String.class };
/*      */
/* 1978 */           ctor = this.delegateClass.getConstructor(ctorParamTypes);
/* 1979 */           ctorParams = new Object[] { getLog(), this.tablePrefix, this.instanceId };
/*      */         }
/*      */
/* 1982 */         this.delegate = ((DriverDelegate)ctor.newInstance(ctorParams));
/*      */       } catch (NoSuchMethodException e) {
/* 1984 */         throw new NoSuchDelegateException("Couldn't find delegate constructor: " + e.getMessage());
/*      */       }
/*      */       catch (InstantiationException e) {
/* 1987 */         throw new NoSuchDelegateException("Couldn't create delegate: " + e.getMessage());
/*      */       }
/*      */       catch (IllegalAccessException e) {
/* 1990 */         throw new NoSuchDelegateException("Couldn't create delegate: " + e.getMessage());
/*      */       }
/*      */       catch (InvocationTargetException e) {
/* 1993 */         throw new NoSuchDelegateException("Couldn't create delegate: " + e.getMessage());
/*      */       }
/*      */       catch (ClassNotFoundException e) {
/* 1996 */         throw new NoSuchDelegateException("Couldn't load delegate class: " + e.getMessage());
/*      */       }
/*      */
/*      */     }
/*      */
/* 2001 */     return this.delegate;
/*      */   }
/*      */
/*      */   protected Semaphore getLockHandler() {
/* 2005 */     return this.lockHandler;
/*      */   }
/*      */
/*      */   protected abstract boolean doRecoverMisfires()
/*      */     throws JobPersistenceException;
/*      */
/*      */   protected void signalSchedulingChange()
/*      */   {
/* 2016 */     this.signaler.signalSchedulingChange();
/*      */   }
/*      */
/*      */   protected abstract boolean doCheckin()
/*      */     throws JobPersistenceException;
/*      */
/*      */   protected List findFailedInstances(Connection conn)
/*      */     throws JobPersistenceException
/*      */   {
/* 2037 */     List failedInstances = new LinkedList();
/* 2038 */     boolean selfFailed = false;
/*      */
/* 2040 */     long timeNow = System.currentTimeMillis();
/*      */     try
/*      */     {
/* 2043 */       List states = getDelegate().selectSchedulerStateRecords(conn, null);
/*      */
/* 2045 */       HashMap statesById = new HashMap();
/* 2046 */       Iterator itr = states.iterator();
/* 2047 */       while (itr.hasNext()) {
/* 2048 */         SchedulerStateRecord rec = (SchedulerStateRecord)itr.next();
/* 2049 */         statesById.put(rec.getSchedulerInstanceId(), rec);
/*      */       }
/*      */
/* 2052 */       itr = states.iterator();
/* 2053 */       while (itr.hasNext()) {
/* 2054 */         SchedulerStateRecord rec = (SchedulerStateRecord)itr.next();
/*      */
/* 2057 */         if (rec.getSchedulerInstanceId().equals(getInstanceId())) {
/* 2058 */           if (this.firstCheckIn) {
/* 2059 */             if (rec.getRecoverer() == null) {
/* 2060 */               failedInstances.add(rec);
/*      */             }
/*      */             else {
/* 2063 */               SchedulerStateRecord recOrec = (SchedulerStateRecord)statesById.get(rec.getRecoverer());
/*      */
/* 2065 */               long failedIfAfter = recOrec == null ? timeNow : calcFailedIfAfter(recOrec);
/*      */
/* 2068 */               if ((failedIfAfter < timeNow) || (recOrec == null)) {
/* 2069 */                 failedInstances.add(rec);
/*      */               }
/*      */
/*      */             }
/*      */
/*      */           }
/*      */
/*      */         }
/*      */         else
/*      */         {
/* 2079 */           long failedIfAfter = calcFailedIfAfter(rec);
/*      */
/* 2081 */           if (rec.getRecoverer() == null) {
/* 2082 */             if (failedIfAfter < timeNow)
/* 2083 */               failedInstances.add(rec);
/*      */           }
/*      */           else
/*      */           {
/* 2087 */             SchedulerStateRecord recOrec = (SchedulerStateRecord)statesById.get(rec.getRecoverer());
/*      */
/* 2089 */             failedIfAfter = recOrec == null ? timeNow : calcFailedIfAfter(recOrec);
/*      */
/* 2092 */             if ((failedIfAfter < timeNow) || (recOrec == null))
/* 2093 */               failedInstances.add(rec);
/*      */           }
/*      */         }
/*      */       }
/*      */     }
/*      */     catch (Exception e) {
/* 2099 */       this.lastCheckin = System.currentTimeMillis();
/* 2100 */       throw new JobPersistenceException("Failure identifying failed instances when checking-in: " + e.getMessage(), e);
/*      */     }
/*      */
/* 2104 */     return failedInstances;
/*      */   }
/*      */
/*      */   protected long calcFailedIfAfter(SchedulerStateRecord rec) {
/* 2108 */     return rec.getCheckinTimestamp() + Math.max(rec.getCheckinInterval(), System.currentTimeMillis() - this.lastCheckin) + 7500L;
/*      */   }
/*      */
/*      */   protected List clusterCheckIn(Connection conn)
/*      */     throws JobPersistenceException
/*      */   {
/* 2117 */     List failedInstances = findFailedInstances(conn);
/*      */     try
/*      */     {
/* 2123 */       this.lastCheckin = System.currentTimeMillis();
/* 2124 */       if (getDelegate().updateSchedulerState(conn, getInstanceId(), this.lastCheckin, null) == 0) {
/* 2125 */         getDelegate().insertSchedulerState(conn, getInstanceId(), this.lastCheckin, getClusterCheckinInterval(), null);
/*      */       }
/*      */     }
/*      */     catch (Exception e)
/*      */     {
/* 2130 */       throw new JobPersistenceException("Failure updating scheduler state when checking-in: " + e.getMessage(), e);
/*      */     }
/*      */
/* 2134 */     return failedInstances;
/*      */   }
/*      */
/*      */   protected void clusterRecover(Connection conn, List failedInstances)
/*      */     throws JobPersistenceException
/*      */   {
/* 2140 */     if (failedInstances.size() > 0)
/*      */     {
/* 2142 */       long recoverIds = System.currentTimeMillis();
/*      */
/* 2144 */       logWarnIfNonZero(failedInstances.size(), "ClusterManager: detected " + failedInstances.size() + " failed or restarted instances.");
/*      */       try
/*      */       {
/* 2148 */         Iterator itr = failedInstances.iterator();
/* 2149 */         while (itr.hasNext()) {
/* 2150 */           SchedulerStateRecord rec = (SchedulerStateRecord)itr.next();
/*      */
/* 2153 */           getLog().info("ClusterManager: Scanning for instance \"" + rec.getSchedulerInstanceId() + "\"'s failed in-progress jobs.");
/*      */
/* 2158 */           List firedTriggerRecs = getDelegate().selectInstancesFiredTriggerRecords(conn, rec.getSchedulerInstanceId());
/*      */
/* 2162 */           int acquiredCount = 0;
/* 2163 */           int recoveredCount = 0;
/* 2164 */           int otherCount = 0;
/*      */
/* 2166 */           Iterator ftItr = firedTriggerRecs.iterator();
/* 2167 */           while (ftItr.hasNext()) {
/* 2168 */             FiredTriggerRecord ftRec = (FiredTriggerRecord)ftItr.next();
/*      */
/* 2171 */             Key tKey = ftRec.getTriggerKey();
/* 2172 */             Key jKey = ftRec.getJobKey();
/*      */
/* 2175 */             if (ftRec.getFireInstanceState().equals("BLOCKED")) {
/* 2176 */               getDelegate().updateTriggerStatesForJobFromOtherState(conn, jKey.getName(), jKey.getGroup(), "WAITING", "BLOCKED");
/*      */             }
/*      */
/* 2182 */             if (ftRec.getFireInstanceState().equals("PAUSED_BLOCKED")) {
/* 2183 */               getDelegate().updateTriggerStatesForJobFromOtherState(conn, jKey.getName(), jKey.getGroup(), "PAUSED", "PAUSED_BLOCKED");
/*      */             }
/*      */
/* 2191 */             if (ftRec.getFireInstanceState().equals("ACQUIRED")) {
/* 2192 */               getDelegate().updateTriggerStateFromOtherState(conn, tKey.getName(), tKey.getGroup(), "WAITING", "ACQUIRED");
/*      */
/* 2195 */               acquiredCount++;
/*      */             }
/* 2198 */             else if (ftRec.isJobRequestsRecovery()) {
/* 2199 */               if (jobExists(conn, jKey.getName(), jKey.getGroup())) {
/* 2200 */                 SimpleTrigger rcvryTrig = new SimpleTrigger("recover_" + rec.getSchedulerInstanceId() + "_" + String.valueOf(recoverIds++), "RECOVERING_JOBS", new Date(ftRec.getFireTimestamp()));
/*      */
/* 2207 */                 rcvryTrig.setJobName(jKey.getName());
/* 2208 */                 rcvryTrig.setJobGroup(jKey.getGroup());
/* 2209 */                 rcvryTrig.setMisfireInstruction(1);
/*      */
/* 2211 */                 JobDataMap jd = getDelegate().selectTriggerJobDataMap(conn, tKey.getName(), tKey.getGroup());
/* 2212 */                 jd.put("QRTZ_FAILED_JOB_ORIG_TRIGGER_NAME", tKey.getName());
/* 2213 */                 jd.put("QRTZ_FAILED_JOB_ORIG_TRIGGER_GROUP", tKey.getGroup());
/* 2214 */                 jd.put("QRTZ_FAILED_JOB_ORIG_TRIGGER_FIRETIME_IN_MILLISECONDS_AS_STRING", String.valueOf(ftRec.getFireTimestamp()));
/* 2215 */                 rcvryTrig.setJobDataMap(jd);
/*      */
/* 2217 */                 rcvryTrig.computeFirstFireTime(null);
/* 2218 */                 storeTrigger(conn, null, rcvryTrig, null, false, "WAITING", false, true);
/*      */
/* 2220 */                 recoveredCount++;
/*      */               } else {
/* 2222 */                 getLog().warn("ClusterManager: failed job '" + jKey + "' no longer exists, cannot schedule recovery.");
/*      */
/* 2227 */                 otherCount++;
/*      */               }
/*      */             } else {
/* 2230 */               otherCount++;
/*      */             }
/*      */
/* 2234 */             if (ftRec.isJobIsStateful()) {
/* 2235 */               getDelegate().updateTriggerStatesForJobFromOtherState(conn, jKey.getName(), jKey.getGroup(), "WAITING", "BLOCKED");
/*      */
/* 2240 */               getDelegate().updateTriggerStatesForJobFromOtherState(conn, jKey.getName(), jKey.getGroup(), "PAUSED", "PAUSED_BLOCKED");
/*      */             }
/*      */
/*      */           }
/*      */
/* 2248 */           getDelegate().deleteFiredTriggers(conn, rec.getSchedulerInstanceId());
/*      */
/* 2251 */           logWarnIfNonZero(acquiredCount, "ClusterManager: ......Freed " + acquiredCount + " acquired trigger(s).");
/*      */
/* 2254 */           logWarnIfNonZero(recoveredCount, "ClusterManager: ......Scheduled " + recoveredCount + " recoverable job(s) for recovery.");
/*      */
/* 2257 */           logWarnIfNonZero(otherCount, "ClusterManager: ......Cleaned-up " + otherCount + " other failed job(s).");
/*      */
/* 2261 */           getDelegate().deleteSchedulerState(conn, rec.getSchedulerInstanceId());
/*      */
/* 2265 */           if (rec.getSchedulerInstanceId().equals(getInstanceId())) {
/* 2266 */             getDelegate().insertSchedulerState(conn, rec.getSchedulerInstanceId(), System.currentTimeMillis(), rec.getCheckinInterval(), null);
/*      */           }
/*      */         }
/*      */
/*      */       }
/*      */       catch (Exception e)
/*      */       {
/* 2273 */         throw new JobPersistenceException("Failure recovering jobs: " + e.getMessage(), e);
/*      */       }
/*      */     }
/*      */   }
/*      */
/*      */   protected void logWarnIfNonZero(int val, String warning)
/*      */   {
/* 2280 */     if (val > 0) getLog().info(warning);
/*      */     else
/* 2282 */       getLog().debug(warning);
/*      */   }
/*      */
/*      */   protected void closeConnection(Connection conn)
/*      */     throws JobPersistenceException
/*      */   {
/* 2295 */     if (conn != null)
/*      */       try {
/* 2297 */         conn.close();
/*      */       } catch (SQLException e) {
/* 2299 */         throw new JobPersistenceException("Couldn't close jdbc connection. " + e.getMessage(), e);
/*      */       }
/*      */   }
/*      */
/*      */   protected void rollbackConnection(Connection conn)
/*      */     throws JobPersistenceException
/*      */   {
/* 2315 */     if (conn != null)
/*      */       try {
/* 2317 */         conn.rollback();
/*      */       } catch (SQLException e) {
/* 2319 */         throw new JobPersistenceException("Couldn't rollback jdbc connection. " + e.getMessage(), e);
/*      */       }
/*      */   }
/*      */
/*      */   protected void commitConnection(Connection conn)
/*      */     throws JobPersistenceException
/*      */   {
/* 2334 */     if (conn != null)
/*      */       try {
/* 2336 */         conn.commit();
/*      */       } catch (SQLException e) {
/* 2338 */         throw new JobPersistenceException("Couldn't commit jdbc connection. " + e.getMessage(), e);
/*      */       }
/*      */   }
/*      */
/*      */   class MisfireHandler extends Thread
/*      */   {
/* 2423 */     private boolean shutdown = false;
/*      */     private JobStoreSupport js;
/* 2427 */     private int numFails = 0;
/*      */
/*      */     MisfireHandler(JobStoreSupport js)
/*      */     {
/* 2431 */       this.js = js;
/* 2432 */       setName("QuartzScheduler_" + JobStoreSupport.this.instanceName + "-" + JobStoreSupport.this.instanceId + "_MisfireHandler");
/*      */     }
/*      */
/*      */     public void initialize()
/*      */     {
/* 2437 */       start();
/*      */     }
/*      */
/*      */     public void shutdown() {
/* 2441 */       this.shutdown = true;
/* 2442 */       interrupt();
/*      */     }
/*      */
/*      */     private boolean manage() {
/*      */       try {
/* 2447 */         JobStoreSupport.this.getLog().debug("MisfireHandler: scanning for misfires...");
/*      */
/* 2449 */         boolean res = this.js.doRecoverMisfires();
/* 2450 */         this.numFails = 0;
/* 2451 */         return res;
/*      */       } catch (Exception e) {
/* 2453 */         if (this.numFails % 4 == 0) {
/* 2454 */           JobStoreSupport.this.getLog().error("MisfireHandler: Error handling misfires: " + e.getMessage(), e);
/*      */         }
/*      */
/* 2457 */         this.numFails += 1;
/*      */       }
/* 2459 */       return false;
/*      */     }
/*      */
/*      */     public void run()
/*      */     {
/* 2464 */       while (!this.shutdown)
/*      */       {
/* 2466 */         long sTime = System.currentTimeMillis();
/*      */
/* 2468 */         boolean moreToDo = manage();
/*      */
/* 2470 */         if (JobStoreSupport.this.lastRecoverCount > 0) JobStoreSupport.this.signalSchedulingChange();
/*      */
/* 2472 */         long spanTime = System.currentTimeMillis() - sTime;
/*      */
/* 2474 */         if ((!this.shutdown) && (!moreToDo)) {
/* 2475 */           long timeToSleep = JobStoreSupport.this.getMisfireThreshold() - spanTime;
/* 2476 */           if (timeToSleep <= 0L) timeToSleep = 50L;
/*      */
/* 2478 */           if (this.numFails > 0) timeToSleep = Math.max(JobStoreSupport.this.getDbRetryInterval(), timeToSleep);
/*      */
/* 2480 */           if (timeToSleep > 0L) try {
/* 2481 */               Thread.sleep(timeToSleep);
/*      */             }
/*      */             catch (Exception ignore) {
/*      */             }
/*      */         }
/* 2485 */         else if (moreToDo) {
/*      */           try {
/* 2487 */             Thread.sleep(50L);
/*      */           }
/*      */           catch (Exception ignore)
/*      */           {
/*      */           }
/*      */         }
/*      */       }
/*      */     }
/*      */   }
/*      */
/*      */   class ClusterManager extends Thread
/*      */   {
/* 2352 */     private boolean shutdown = false;
/*      */     private JobStoreSupport js;
/* 2356 */     private int numFails = 0;
/*      */
/*      */     ClusterManager(JobStoreSupport js) {
/* 2359 */       this.js = js;
/* 2360 */       setPriority(7);
/* 2361 */       setName("QuartzScheduler_" + JobStoreSupport.this.instanceName + "-" + JobStoreSupport.this.instanceId + "_ClusterManager");
/*      */     }
/*      */
/*      */     public void initialize() {
/* 2365 */       manage();
/* 2366 */       start();
/*      */     }
/*      */
/*      */     public void shutdown() {
/* 2370 */       this.shutdown = true;
/* 2371 */       interrupt();
/*      */     }
/*      */
/*      */     private boolean manage() {
/* 2375 */       boolean res = false;
/*      */       try
/*      */       {
/* 2378 */         res = this.js.doCheckin();
/*      */
/* 2380 */         this.numFails = 0;
/* 2381 */         JobStoreSupport.this.getLog().debug("ClusterManager: Check-in complete.");
/*      */       } catch (Exception e) {
/* 2383 */         if (this.numFails % 4 == 0) {
/* 2384 */           JobStoreSupport.this.getLog().error("ClusterManager: Error managing cluster: " + e.getMessage(), e);
/*      */         }
/*      */
/* 2387 */         this.numFails += 1;
/*      */       }
/* 2389 */       return res;
/*      */     }
/*      */
/*      */     public void run() {
/* 2393 */       while (!this.shutdown)
/*      */       {
/* 2395 */         if (!this.shutdown) {
/* 2396 */           long timeToSleep = JobStoreSupport.this.getClusterCheckinInterval();
/* 2397 */           long transpiredTime = System.currentTimeMillis() - JobStoreSupport.this.lastCheckin;
/* 2398 */           timeToSleep -= transpiredTime;
/* 2399 */           if (timeToSleep <= 0L) timeToSleep = 100L;
/*      */
/* 2401 */           if (this.numFails > 0) timeToSleep = Math.max(JobStoreSupport.this.getDbRetryInterval(), timeToSleep);
/*      */           try
/*      */           {
/* 2404 */             Thread.sleep(timeToSleep);
/*      */           }
/*      */           catch (Exception ignore) {
/*      */           }
/*      */         }
/* 2409 */         if ((this.shutdown) || (!manage())) continue; JobStoreSupport.this.signalSchedulingChange();
/*      */       }
/*      */     }
/*      */   }
/*      */ }

/* Location:           /home/mnovotny/projects/EMBEDDED_JBOSS_BETA3_COMMUNITY/embedded/output/lib/embedded-jboss/lib/thirdparty-all.jar
* Qualified Name:     org.quartz.impl.jdbcjobstore.JobStoreSupport
* JD-Core Version:    0.6.0
*/
TOP

Related Classes of org.quartz.impl.jdbcjobstore.JobStoreSupport$ClusterManager

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.