帆软使用的第三方框架。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

255 lines
8.4 KiB

/*
* Copyright 2004-2005 OpenSymphony
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
/*
* Previously Copyright (c) 2001-2004 James House
*/
package com.fr.third.org.quartz.impl.jdbcjobstore;
import java.sql.Connection;
import java.sql.SQLException;
import com.fr.third.org.quartz.JobPersistenceException;
import com.fr.third.org.quartz.SchedulerConfigException;
import com.fr.third.org.quartz.spi.ClassLoadHelper;
import com.fr.third.org.quartz.spi.SchedulerSignaler;
import com.fr.third.org.quartz.utils.DBConnectionManager;
/**
* <p>
* <code>JobStoreCMT</code> is meant to be used in an application-server
* environment that provides container-managed-transactions. No commit /
* rollback will be1 handled by this class.
* </p>
*
* <p>
* If you need commit / rollback, use <code>{@link
* com.fr.third.org.quartz.impl.jdbcjobstore.JobStoreTX}</code>
* instead.
* </p>
*
* @author <a href="mailto:jeff@binaryfeed.org">Jeffrey Wescott</a>
* @author James House
* @author Srinivas Venkatarangaiah
*
*/
public class JobStoreCMT extends JobStoreSupport {
/*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Data members.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
protected String nonManagedTxDsName;
// Great name huh?
protected boolean dontSetNonManagedTXConnectionAutoCommitFalse = false;
protected boolean setTxIsolationLevelReadCommitted = false;
/*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Interface.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
/**
* <p>
* Set the name of the <code>DataSource</code> that should be used for
* performing database functions.
* </p>
*/
public void setNonManagedTXDataSource(String nonManagedTxDsName) {
this.nonManagedTxDsName = nonManagedTxDsName;
}
/**
* <p>
* Get the name of the <code>DataSource</code> that should be used for
* performing database functions.
* </p>
*/
public String getNonManagedTXDataSource() {
return nonManagedTxDsName;
}
public boolean isDontSetNonManagedTXConnectionAutoCommitFalse() {
return dontSetNonManagedTXConnectionAutoCommitFalse;
}
/**
* 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 setDontSetNonManagedTXConnectionAutoCommitFalse(boolean b) {
dontSetNonManagedTXConnectionAutoCommitFalse = b;
}
public boolean isTxIsolationLevelReadCommitted() {
return setTxIsolationLevelReadCommitted;
}
/**
* Set the transaction isolation level of DB connections to sequential.
*
* @param b
*/
public void setTxIsolationLevelReadCommitted(boolean b) {
setTxIsolationLevelReadCommitted = b;
}
public void initialize(ClassLoadHelper loadHelper,
SchedulerSignaler signaler) throws SchedulerConfigException {
if (nonManagedTxDsName == null) {
throw new SchedulerConfigException(
"Non-ManagedTX DataSource name not set! " +
"If your 'com.fr.third.org.quartz.jobStore.dataSource' is XA, then set " +
"'com.fr.third.org.quartz.jobStore.nonManagedTXDataSource' to a non-XA "+
"datasource (for the same DB). " +
"Otherwise, you can set them to be the same.");
}
if (getLockHandler() == null) {
// If the user hasn't specified an explicit lock handler,
// then we *must* use DB locks with CMT...
setUseDBLocks(true);
}
super.initialize(loadHelper, signaler);
getLog().info("JobStoreCMT initialized.");
}
public void shutdown() {
super.shutdown();
try {
DBConnectionManager.getInstance().shutdown(getNonManagedTXDataSource());
} catch (SQLException sqle) {
getLog().warn("Database connection shutdown unsuccessful.", sqle);
}
}
protected Connection getNonManagedTXConnection()
throws JobPersistenceException {
Connection conn = null;
try {
conn = DBConnectionManager.getInstance().getConnection(
getNonManagedTXDataSource());
} catch (SQLException sqle) {
throw new JobPersistenceException(
"Failed to obtain DB connection from data source '"
+ getNonManagedTXDataSource() + "': "
+ sqle.toString(), sqle);
} catch (Throwable e) {
throw new JobPersistenceException(
"Failed to obtain DB connection from data source '"
+ getNonManagedTXDataSource() + "': "
+ e.toString(), e,
JobPersistenceException.ERR_PERSISTENCE_CRITICAL_FAILURE);
}
if (conn == null) {
throw new JobPersistenceException(
"Could not get connection from DataSource '"
+ getNonManagedTXDataSource() + "'");
}
// Protect connection attributes we might change.
conn = getAttributeRestoringConnection(conn);
// Set any connection connection attributes we are to override.
try {
if (!isDontSetNonManagedTXConnectionAutoCommitFalse()) {
conn.setAutoCommit(false);
}
if (isTxIsolationLevelReadCommitted()) {
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
}
} 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;
}
/**
* Execute the given callback having optionally aquired the given lock.
* Because CMT assumes that the connection is already part of a managed
* transaction, it does not attempt to commit or rollback the
* enclosing transaction.
*
* @param lockName The name of the lock to aquire, for example
* "TRIGGER_ACCESS". If null, then no lock is aquired, but the
* txCallback is still executed in a transaction.
*
* @see JobStoreSupport#executeInNonManagedTXLock(String, TransactionCallback)
* @see JobStoreTX#executeInLock(String, TransactionCallback)
* @see JobStoreSupport#getNonManagedTXConnection()
* @see JobStoreSupport#getConnection()
*/
protected Object executeInLock(
String lockName,
TransactionCallback txCallback) throws JobPersistenceException {
boolean transOwner = false;
Connection conn = null;
try {
if (lockName != null) {
// If we aren't using db locks, then delay getting DB connection
// until after aquiring the lock since it isn't needed.
if (getLockHandler().requiresConnection()) {
conn = getConnection();
}
transOwner = getLockHandler().obtainLock(conn, lockName);
}
if (conn == null) {
conn = getConnection();
}
return txCallback.execute(conn);
} finally {
try {
releaseLock(conn, LOCK_TRIGGER_ACCESS, transOwner);
} finally {
cleanupConnection(conn);
}
}
}
}
// EOF