📄 jobstoresupport.java
字号:
/**
* Whether or not to obtain locks when inserting new jobs/triggers.
* Defaults to <code>true</code>, which is safest - some db's (such as
* MS SQLServer) seem to require this to avoid deadlocks under high load,
* while others seem to do fine without.
*
* <p>Setting this property to <code>false</code> will provide a
* significant performance increase during the addition of new jobs
* and triggers.</p>
*
* @param lockOnInsert
*/
public void setLockOnInsert(boolean lockOnInsert) {
this.lockOnInsert = lockOnInsert;
}
public long getMisfireThreshold() {
return misfireThreshold;
}
/**
* The the number of milliseconds by which a trigger must have missed its
* next-fire-time, in order for it to be considered "misfired" and thus
* have its misfire instruction applied.
*
* @param misfireThreshold
*/
public void setMisfireThreshold(long misfireThreshold) {
if (misfireThreshold < 1) {
throw new IllegalArgumentException(
"Misfirethreshold must be larger than 0");
}
this.misfireThreshold = misfireThreshold;
}
public boolean isDontSetAutoCommitFalse() {
return dontSetAutoCommitFalse;
}
/**
* Don't call set autocommit(false) on connections obtained from the
* DataSource. This can be helpfull in a few situations, such as if you
* have a driver that complains if it is called when it is already off.
*
* @param b
*/
public void setDontSetAutoCommitFalse(boolean b) {
dontSetAutoCommitFalse = b;
}
public boolean isTxIsolationLevelSerializable() {
return setTxIsolationLevelSequential;
}
/**
* Set the transaction isolation level of DB connections to sequential.
*
* @param b
*/
public void setTxIsolationLevelSerializable(boolean b) {
setTxIsolationLevelSequential = b;
}
/**
* <p>
* Set the JDBC driver delegate class.
* </p>
*
* @param delegateClassName
* the delegate class name
*/
public void setDriverDelegateClass(String delegateClassName)
throws InvalidConfigurationException {
this.delegateClassName = delegateClassName;
}
/**
* <p>
* Get the JDBC driver delegate class name.
* </p>
*
* @return the delegate class name
*/
public String getDriverDelegateClass() {
return delegateClassName;
}
public String getSelectWithLockSQL() {
return selectWithLockSQL;
}
/**
* <p>
* set the SQL statement to use to select and lock a row in the "locks"
* table.
* </p>
*
* @see StdRowLockSemaphore
*/
public void setSelectWithLockSQL(String string) {
selectWithLockSQL = string;
}
protected ClassLoadHelper getClassLoadHelper() {
return classLoadHelper;
}
/**
* Get whether the threads spawned by this JobStore should be
* marked as daemon. Possible threads include the <code>MisfireHandler</code>
* and the <code>ClusterManager</code>.
*
* @see Thread#setDaemon(boolean)
*/
public boolean getMakeThreadsDaemons() {
return makeThreadsDaemons;
}
/**
* Set whether the threads spawned by this JobStore should be
* marked as daemon. Possible threads include the <code>MisfireHandler</code>
* and the <code>ClusterManager</code>.
*
* @see Thread#setDaemon(boolean)
*/
public void setMakeThreadsDaemons(boolean makeThreadsDaemons) {
this.makeThreadsDaemons = makeThreadsDaemons;
}
/**
* Get whether to check to see if there are Triggers that have misfired
* before actually acquiring the lock to recover them. This should be
* set to false if the majority of the time, there are are misfired
* Triggers.
*/
public boolean getDoubleCheckLockMisfireHandler() {
return doubleCheckLockMisfireHandler;
}
/**
* Set whether to check to see if there are Triggers that have misfired
* before actually acquiring the lock to recover them. This should be
* set to false if the majority of the time, there are are misfired
* Triggers.
*/
public void setDoubleCheckLockMisfireHandler(
boolean doubleCheckLockMisfireHandler) {
this.doubleCheckLockMisfireHandler = doubleCheckLockMisfireHandler;
}
//---------------------------------------------------------------------------
// interface methods
//---------------------------------------------------------------------------
protected Log getLog() {
return log;
}
/**
* <p>
* Called by the QuartzScheduler before the <code>JobStore</code> is
* used, in order to give it a chance to initialize.
* </p>
*/
public void initialize(ClassLoadHelper loadHelper,
SchedulerSignaler signaler) throws SchedulerConfigException {
if (dsName == null) {
throw new SchedulerConfigException("DataSource name not set.");
}
classLoadHelper = loadHelper;
this.signaler = signaler;
// If the user hasn't specified an explicit lock handler, then
// choose one based on CMT/Clustered/UseDBLocks.
if (getLockHandler() == null) {
// If the user hasn't specified an explicit lock handler,
// then we *must* use DB locks with clustering
if (isClustered()) {
setUseDBLocks(true);
}
if (getUseDBLocks()) {
getLog().info(
"Using db table-based data access locking (synchronization).");
setLockHandler(
new StdRowLockSemaphore(getTablePrefix(), getSelectWithLockSQL()));
} else {
getLog().info(
"Using thread monitor-based data access locking (synchronization).");
setLockHandler(new SimpleSemaphore());
}
}
if (!isClustered()) {
try {
cleanVolatileTriggerAndJobs();
} catch (SchedulerException se) {
throw new SchedulerConfigException(
"Failure occured during job recovery.", se);
}
}
}
/**
* @see org.quartz.spi.JobStore#schedulerStarted()
*/
public void schedulerStarted() throws SchedulerException {
if (isClustered()) {
clusterManagementThread = new ClusterManager();
clusterManagementThread.initialize();
} else {
try {
recoverJobs();
} catch (SchedulerException se) {
throw new SchedulerConfigException(
"Failure occured during job recovery.", se);
}
}
misfireHandler = new MisfireHandler();
misfireHandler.initialize();
}
/**
* <p>
* Called by the QuartzScheduler to inform the <code>JobStore</code> that
* it should free up all of it's resources because the scheduler is
* shutting down.
* </p>
*/
public void shutdown() {
if (clusterManagementThread != null) {
clusterManagementThread.shutdown();
}
if (misfireHandler != null) {
misfireHandler.shutdown();
}
try {
DBConnectionManager.getInstance().shutdown(getDataSource());
} catch (SQLException sqle) {
getLog().warn("Database connection shutdown unsuccessful.", sqle);
}
}
public boolean supportsPersistence() {
return true;
}
//---------------------------------------------------------------------------
// helper methods for subclasses
//---------------------------------------------------------------------------
protected abstract Connection getNonManagedTXConnection()
throws JobPersistenceException;
/**
* Wrap the given <code>Connection</code> in a Proxy such that attributes
* that might be set will be restored before the connection is closed
* (and potentially restored to a pool).
*/
protected Connection getAttributeRestoringConnection(Connection conn) {
return (Connection)Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class[] { Connection.class },
new AttributeRestoringConnectionInvocationHandler(conn));
}
protected Connection getConnection() throws JobPersistenceException {
Connection conn = null;
try {
conn = DBConnectionManager.getInstance().getConnection(
getDataSource());
} catch (SQLException sqle) {
throw new JobPersistenceException(
"Failed to obtain DB connection from data source '"
+ getDataSource() + "': " + sqle.toString(), sqle);
} catch (Throwable e) {
throw new JobPersistenceException(
"Failed to obtain DB connection from data source '"
+ getDataSource() + "': " + e.toString(), e,
JobPersistenceException.ERR_PERSISTENCE_CRITICAL_FAILURE);
}
if (conn == null) {
throw new JobPersistenceException(
"Could not get connection from DataSource '"
+ getDataSource() + "'");
}
// Protect connection attributes we might change.
conn = getAttributeRestoringConnection(conn);
// Set any connection connection attributes we are to override.
try {
if (!isDontSetAutoCommitFalse()) {
conn.setAutoCommit(false);
}
if(isTxIsolationLevelSerializable()) {
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
}
} catch (SQLException sqle) {
getLog().warn("Failed to override connection auto commit/transaction isolation.", sqle);
} catch (Throwable e) {
try { conn.close(); } catch(Throwable tt) {}
throw new JobPersistenceException(
"Failure setting up connection.", e);
}
return conn;
}
protected void releaseLock(Connection conn, String lockName, boolean doIt) {
if (doIt && conn != null) {
try {
getLockHandler().releaseLock(conn, lockName);
} catch (LockException le) {
getLog().error("Error returning lock: " + le.getMessage(), le);
}
}
}
/**
* Removes all volatile data.
*
* @throws JobPersistenceException If jobs could not be recovered.
*/
protected void cleanVolatileTriggerAndJobs()
throws JobPersistenceException {
executeInNonManagedTXLock(
LOCK_TRIGGER_ACCESS,
new VoidTransactionCallback() {
public void execute(Connection conn) throws JobPersistenceException {
cleanVolatileTriggerAndJobs(conn);
}
});
}
/**
* <p>
* Removes all volatile data.
* </p>
*
* @throws JobPersistenceException
* if jobs could not be recovered
*/
protected void cleanVolatileTriggerAndJobs(Connection conn)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -