mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-04 20:29:27 +01:00
Make all connections READ COMMITTED isolation level instead of setting it everytime we get the db connection causing useless round trips
This commit is contained in:
parent
868373c280
commit
69d928b3d1
@ -78,7 +78,7 @@ public class Transaction {
|
|||||||
public static final short CLOUD_DB = 0;
|
public static final short CLOUD_DB = 0;
|
||||||
public static final short USAGE_DB = 1;
|
public static final short USAGE_DB = 1;
|
||||||
public static final short CONNECTED_DB = -1;
|
public static final short CONNECTED_DB = -1;
|
||||||
|
|
||||||
private static AtomicLong s_id = new AtomicLong();
|
private static AtomicLong s_id = new AtomicLong();
|
||||||
private static final TransactionMBeanImpl s_mbean = new TransactionMBeanImpl();
|
private static final TransactionMBeanImpl s_mbean = new TransactionMBeanImpl();
|
||||||
static {
|
static {
|
||||||
@ -91,7 +91,7 @@ public class Transaction {
|
|||||||
|
|
||||||
private final LinkedList<StackElement> _stack;
|
private final LinkedList<StackElement> _stack;
|
||||||
private long _id;
|
private long _id;
|
||||||
|
|
||||||
private final LinkedList<Pair<String, Long>> _lockTimes = new LinkedList<Pair<String, Long>>();
|
private final LinkedList<Pair<String, Long>> _lockTimes = new LinkedList<Pair<String, Long>>();
|
||||||
|
|
||||||
private String _name;
|
private String _name;
|
||||||
@ -101,17 +101,17 @@ public class Transaction {
|
|||||||
private long _txnTime;
|
private long _txnTime;
|
||||||
private Statement _stmt;
|
private Statement _stmt;
|
||||||
private String _creator;
|
private String _creator;
|
||||||
|
|
||||||
private Transaction _prev = null;
|
private Transaction _prev = null;
|
||||||
|
|
||||||
public static Transaction currentTxn() {
|
public static Transaction currentTxn() {
|
||||||
Transaction txn = tls.get();
|
Transaction txn = tls.get();
|
||||||
assert txn != null : "No Transaction on stack. Did you mark the method with @DB?";
|
assert txn != null : "No Transaction on stack. Did you mark the method with @DB?";
|
||||||
|
|
||||||
assert checkAnnotation(3, txn) : "Did you even read the guide to use Transaction...IOW...other people's code? Try method can't be private. What about @DB? hmmm... could that be it? " + txn;
|
assert checkAnnotation(3, txn) : "Did you even read the guide to use Transaction...IOW...other people's code? Try method can't be private. What about @DB? hmmm... could that be it? " + txn;
|
||||||
return txn;
|
return txn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Transaction open(final short databaseId) {
|
public static Transaction open(final short databaseId) {
|
||||||
String name = buildName();
|
String name = buildName();
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
@ -130,17 +130,17 @@ public class Transaction {
|
|||||||
_conn = conn;
|
_conn = conn;
|
||||||
_dbId = CONNECTED_DB;
|
_dbId = CONNECTED_DB;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void transitToAutoManagedConnection(short dbId) {
|
public void transitToAutoManagedConnection(short dbId) {
|
||||||
// assert(_stack.size() <= 1) : "Can't change to auto managed connection unless your stack is empty";
|
// assert(_stack.size() <= 1) : "Can't change to auto managed connection unless your stack is empty";
|
||||||
_dbId = dbId;
|
_dbId = dbId;
|
||||||
_conn = null;
|
_conn = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Transaction open(final String name) {
|
public static Transaction open(final String name) {
|
||||||
return open(name, CLOUD_DB, false);
|
return open(name, CLOUD_DB, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Transaction open(final String name, final short databaseId, final boolean forceDbChange) {
|
public static Transaction open(final String name, final short databaseId, final boolean forceDbChange) {
|
||||||
Transaction txn = tls.get();
|
Transaction txn = tls.get();
|
||||||
boolean isNew = false;
|
boolean isNew = false;
|
||||||
@ -169,46 +169,46 @@ public class Transaction {
|
|||||||
}
|
}
|
||||||
return txn;
|
return txn;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected StackElement peekInStack(Object obj) {
|
protected StackElement peekInStack(Object obj) {
|
||||||
final Iterator<StackElement> it = _stack.iterator();
|
final Iterator<StackElement> it = _stack.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
StackElement next = it.next();
|
StackElement next = it.next();
|
||||||
if (next.type == obj) {
|
if (next.type == obj) {
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerLock(String sql) {
|
public void registerLock(String sql) {
|
||||||
if (_txn && s_lockLogger.isDebugEnabled()) {
|
if (_txn && s_lockLogger.isDebugEnabled()) {
|
||||||
Pair<String, Long> time = new Pair<String, Long>(sql, System.currentTimeMillis());
|
Pair<String, Long> time = new Pair<String, Long>(sql, System.currentTimeMillis());
|
||||||
_lockTimes.add(time);
|
_lockTimes.add(time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean dbTxnStarted() {
|
public boolean dbTxnStarted() {
|
||||||
return _txn;
|
return _txn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Connection getStandaloneConnectionWithException() throws SQLException {
|
public static Connection getStandaloneConnectionWithException() throws SQLException {
|
||||||
Connection conn = s_ds.getConnection();
|
Connection conn = s_ds.getConnection();
|
||||||
if (s_connLogger.isTraceEnabled()) {
|
if (s_connLogger.isTraceEnabled()) {
|
||||||
s_connLogger.trace("Retrieving a standalone connection: dbconn" + System.identityHashCode(conn));
|
s_connLogger.trace("Retrieving a standalone connection: dbconn" + System.identityHashCode(conn));
|
||||||
}
|
}
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Connection getStandaloneConnection() {
|
public static Connection getStandaloneConnection() {
|
||||||
try {
|
try {
|
||||||
return getStandaloneConnectionWithException();
|
return getStandaloneConnectionWithException();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
s_logger.error("Unexpected exception: ", e);
|
s_logger.error("Unexpected exception: ", e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Connection getStandaloneUsageConnection() {
|
public static Connection getStandaloneUsageConnection() {
|
||||||
try {
|
try {
|
||||||
Connection conn = s_usageDS.getConnection();
|
Connection conn = s_usageDS.getConnection();
|
||||||
@ -221,11 +221,11 @@ public class Transaction {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void attach(TransactionAttachment value) {
|
protected void attach(TransactionAttachment value) {
|
||||||
_stack.push(new StackElement(ATTACHMENT, value));
|
_stack.push(new StackElement(ATTACHMENT, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TransactionAttachment detach(String name) {
|
protected TransactionAttachment detach(String name) {
|
||||||
Iterator<StackElement> it = _stack.descendingIterator();
|
Iterator<StackElement> it = _stack.descendingIterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
@ -241,20 +241,20 @@ public class Transaction {
|
|||||||
assert false : "Are you sure you attached this: " + name;
|
assert false : "Are you sure you attached this: " + name;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void attachToTxn(TransactionAttachment value) {
|
public static void attachToTxn(TransactionAttachment value) {
|
||||||
Transaction txn = tls.get();
|
Transaction txn = tls.get();
|
||||||
assert txn != null && txn.peekInStack(CURRENT_TXN) != null: "Come on....how can we attach something to the transaction if you haven't started it?";
|
assert txn != null && txn.peekInStack(CURRENT_TXN) != null: "Come on....how can we attach something to the transaction if you haven't started it?";
|
||||||
|
|
||||||
txn.attach(value);
|
txn.attach(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TransactionAttachment detachFromTxn(String name) {
|
public static TransactionAttachment detachFromTxn(String name) {
|
||||||
Transaction txn = tls.get();
|
Transaction txn = tls.get();
|
||||||
assert txn != null : "No Transaction in TLS";
|
assert txn != null : "No Transaction in TLS";
|
||||||
return txn.detach(name);
|
return txn.detach(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static boolean checkAnnotation(int stack, Transaction txn) {
|
protected static boolean checkAnnotation(int stack, Transaction txn) {
|
||||||
final StackTraceElement[] stacks = Thread.currentThread().getStackTrace();
|
final StackTraceElement[] stacks = Thread.currentThread().getStackTrace();
|
||||||
StackElement se = txn.peekInStack(CURRENT_TXN);
|
StackElement se = txn.peekInStack(CURRENT_TXN);
|
||||||
@ -283,7 +283,7 @@ public class Transaction {
|
|||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
str.append("-").append(stacks[i].getClassName().substring(stacks[i].getClassName().lastIndexOf(".") + 1)).append(".").append(stacks[i].getMethodName()).append(":").append(stacks[i].getLineNumber());
|
str.append("-").append(stacks[i].getClassName().substring(stacks[i].getClassName().lastIndexOf(".") + 1)).append(".").append(stacks[i].getMethodName()).append(":").append(stacks[i].getLineNumber());
|
||||||
j++;
|
j++;
|
||||||
i++;
|
i++;
|
||||||
@ -303,11 +303,11 @@ public class Transaction {
|
|||||||
_id = s_id.incrementAndGet();
|
_id = s_id.incrementAndGet();
|
||||||
_creator = Thread.currentThread().getName();
|
_creator = Thread.currentThread().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCreator() {
|
public String getCreator() {
|
||||||
return _creator;
|
return _creator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getId() {
|
public long getId() {
|
||||||
return _id;
|
return _id;
|
||||||
}
|
}
|
||||||
@ -342,7 +342,7 @@ public class Transaction {
|
|||||||
if (lockMaster == null) {
|
if (lockMaster == null) {
|
||||||
throw new CloudRuntimeException("There's no support for locking yet");
|
throw new CloudRuntimeException("There's no support for locking yet");
|
||||||
}
|
}
|
||||||
return lockMaster.acquire(name, timeoutSeconds);
|
return lockMaster.acquire(name, timeoutSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean release(final String name) {
|
public boolean release(final String name) {
|
||||||
@ -350,7 +350,7 @@ public class Transaction {
|
|||||||
if (lockMaster == null) {
|
if (lockMaster == null) {
|
||||||
throw new CloudRuntimeException("There's no support for locking yet");
|
throw new CloudRuntimeException("There's no support for locking yet");
|
||||||
}
|
}
|
||||||
return lockMaster.release(name);
|
return lockMaster.release(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
@ -364,7 +364,7 @@ public class Transaction {
|
|||||||
s_logger.trace("txn: has already been started.");
|
s_logger.trace("txn: has already been started.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_txn = true;
|
_txn = true;
|
||||||
|
|
||||||
_txnTime = System.currentTimeMillis();
|
_txnTime = System.currentTimeMillis();
|
||||||
@ -378,28 +378,28 @@ public class Transaction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void closePreviousStatement() {
|
protected void closePreviousStatement() {
|
||||||
if (_stmt != null) {
|
if (_stmt != null) {
|
||||||
try {
|
try {
|
||||||
if (s_stmtLogger.isTraceEnabled()) {
|
if (s_stmtLogger.isTraceEnabled()) {
|
||||||
s_stmtLogger.trace("Closing: " + _stmt);
|
s_stmtLogger.trace("Closing: " + _stmt);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ResultSet rs = _stmt.getResultSet();
|
ResultSet rs = _stmt.getResultSet();
|
||||||
if (rs != null && _stmt.getResultSetHoldability() != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
|
if (rs != null && _stmt.getResultSetHoldability() != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
|
||||||
rs.close();
|
rs.close();
|
||||||
}
|
}
|
||||||
} catch(SQLException e) {
|
} catch(SQLException e) {
|
||||||
s_stmtLogger.trace("Unable to close resultset");
|
s_stmtLogger.trace("Unable to close resultset");
|
||||||
}
|
}
|
||||||
_stmt.close();
|
_stmt.close();
|
||||||
} catch (final SQLException e) {
|
} catch (final SQLException e) {
|
||||||
s_stmtLogger.trace("Unable to close statement: " + _stmt);
|
s_stmtLogger.trace("Unable to close statement: " + _stmt);
|
||||||
} finally {
|
} finally {
|
||||||
_stmt = null;
|
_stmt = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -413,17 +413,17 @@ public class Transaction {
|
|||||||
* @see java.sql.Connection
|
* @see java.sql.Connection
|
||||||
*/
|
*/
|
||||||
public PreparedStatement prepareAutoCloseStatement(final String sql) throws SQLException {
|
public PreparedStatement prepareAutoCloseStatement(final String sql) throws SQLException {
|
||||||
PreparedStatement stmt = prepareStatement(sql);
|
PreparedStatement stmt = prepareStatement(sql);
|
||||||
closePreviousStatement();
|
closePreviousStatement();
|
||||||
_stmt = stmt;
|
_stmt = stmt;
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreparedStatement prepareStatement(final String sql) throws SQLException {
|
public PreparedStatement prepareStatement(final String sql) throws SQLException {
|
||||||
final Connection conn = getConnection();
|
final Connection conn = getConnection();
|
||||||
final PreparedStatement pstmt = conn.prepareStatement(sql);
|
final PreparedStatement pstmt = conn.prepareStatement(sql);
|
||||||
if (s_stmtLogger.isTraceEnabled()) {
|
if (s_stmtLogger.isTraceEnabled()) {
|
||||||
s_stmtLogger.trace("Preparing: " + sql);
|
s_stmtLogger.trace("Preparing: " + sql);
|
||||||
}
|
}
|
||||||
return pstmt;
|
return pstmt;
|
||||||
}
|
}
|
||||||
@ -443,7 +443,7 @@ public class Transaction {
|
|||||||
final Connection conn = getConnection();
|
final Connection conn = getConnection();
|
||||||
final PreparedStatement pstmt = conn.prepareStatement(sql, autoGeneratedKeys);
|
final PreparedStatement pstmt = conn.prepareStatement(sql, autoGeneratedKeys);
|
||||||
if (s_stmtLogger.isTraceEnabled()) {
|
if (s_stmtLogger.isTraceEnabled()) {
|
||||||
s_stmtLogger.trace("Preparing: " + sql);
|
s_stmtLogger.trace("Preparing: " + sql);
|
||||||
}
|
}
|
||||||
closePreviousStatement();
|
closePreviousStatement();
|
||||||
_stmt = pstmt;
|
_stmt = pstmt;
|
||||||
@ -465,13 +465,13 @@ public class Transaction {
|
|||||||
final Connection conn = getConnection();
|
final Connection conn = getConnection();
|
||||||
final PreparedStatement pstmt = conn.prepareStatement(sql, columnNames);
|
final PreparedStatement pstmt = conn.prepareStatement(sql, columnNames);
|
||||||
if (s_stmtLogger.isTraceEnabled()) {
|
if (s_stmtLogger.isTraceEnabled()) {
|
||||||
s_stmtLogger.trace("Preparing: " + sql);
|
s_stmtLogger.trace("Preparing: " + sql);
|
||||||
}
|
}
|
||||||
closePreviousStatement();
|
closePreviousStatement();
|
||||||
_stmt = pstmt;
|
_stmt = pstmt;
|
||||||
return pstmt;
|
return pstmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepares an auto close statement. The statement is closed automatically if it is
|
* Prepares an auto close statement. The statement is closed automatically if it is
|
||||||
* retrieved with this method.
|
* retrieved with this method.
|
||||||
@ -486,7 +486,7 @@ public class Transaction {
|
|||||||
final Connection conn = getConnection();
|
final Connection conn = getConnection();
|
||||||
final PreparedStatement pstmt = conn.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
|
final PreparedStatement pstmt = conn.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
|
||||||
if (s_stmtLogger.isTraceEnabled()) {
|
if (s_stmtLogger.isTraceEnabled()) {
|
||||||
s_stmtLogger.trace("Preparing: " + sql);
|
s_stmtLogger.trace("Preparing: " + sql);
|
||||||
}
|
}
|
||||||
closePreviousStatement();
|
closePreviousStatement();
|
||||||
_stmt = pstmt;
|
_stmt = pstmt;
|
||||||
@ -508,32 +508,31 @@ public class Transaction {
|
|||||||
if (_conn == null) {
|
if (_conn == null) {
|
||||||
switch (_dbId) {
|
switch (_dbId) {
|
||||||
case CLOUD_DB:
|
case CLOUD_DB:
|
||||||
if(s_ds != null) {
|
if(s_ds != null) {
|
||||||
_conn = s_ds.getConnection();
|
_conn = s_ds.getConnection();
|
||||||
} else {
|
} else {
|
||||||
s_logger.warn("A static-initialized variable becomes null, process is dying?");
|
s_logger.warn("A static-initialized variable becomes null, process is dying?");
|
||||||
throw new CloudRuntimeException("Database is not initialized, process is dying?");
|
throw new CloudRuntimeException("Database is not initialized, process is dying?");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case USAGE_DB:
|
case USAGE_DB:
|
||||||
if(s_usageDS != null) {
|
if(s_usageDS != null) {
|
||||||
_conn = s_usageDS.getConnection();
|
_conn = s_usageDS.getConnection();
|
||||||
} else {
|
} else {
|
||||||
s_logger.warn("A static-initialized variable becomes null, process is dying?");
|
s_logger.warn("A static-initialized variable becomes null, process is dying?");
|
||||||
throw new CloudRuntimeException("Database is not initialized, process is dying?");
|
throw new CloudRuntimeException("Database is not initialized, process is dying?");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new CloudRuntimeException("No database selected for the transaction");
|
throw new CloudRuntimeException("No database selected for the transaction");
|
||||||
}
|
}
|
||||||
_conn.setAutoCommit(!_txn);
|
_conn.setAutoCommit(!_txn);
|
||||||
|
|
||||||
//
|
//
|
||||||
// MySQL default transaction isolation level is REPEATABLE READ,
|
// MySQL default transaction isolation level is REPEATABLE READ,
|
||||||
// to reduce chances of DB deadlock, we will use READ COMMITED isolation level instead
|
// to reduce chances of DB deadlock, we will use READ COMMITED isolation level instead
|
||||||
// see http://dev.mysql.com/doc/refman/5.0/en/innodb-deadlocks.html
|
// see http://dev.mysql.com/doc/refman/5.0/en/innodb-deadlocks.html
|
||||||
//
|
//
|
||||||
_conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
|
|
||||||
_stack.push(new StackElement(CREATE_CONN, null));
|
_stack.push(new StackElement(CREATE_CONN, null));
|
||||||
if (s_connLogger.isTraceEnabled()) {
|
if (s_connLogger.isTraceEnabled()) {
|
||||||
s_connLogger.trace("Creating a DB connection with " + (_txn ? " txn: " : " no txn: ") + " for " + _dbId + ": dbconn" + System.identityHashCode(_conn) + ". Stack: " + buildName());
|
s_connLogger.trace("Creating a DB connection with " + (_txn ? " txn: " : " no txn: ") + " for " + _dbId + ": dbconn" + System.identityHashCode(_conn) + ". Stack: " + buildName());
|
||||||
@ -580,8 +579,8 @@ public class Transaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void cleanup() {
|
public void cleanup() {
|
||||||
closePreviousStatement();
|
closePreviousStatement();
|
||||||
|
|
||||||
removeUpTo(null, null);
|
removeUpTo(null, null);
|
||||||
if (_txn) {
|
if (_txn) {
|
||||||
rollbackTransaction();
|
rollbackTransaction();
|
||||||
@ -590,7 +589,7 @@ public class Transaction {
|
|||||||
_name = null;
|
_name = null;
|
||||||
|
|
||||||
closeConnection();
|
closeConnection();
|
||||||
|
|
||||||
_stack.clear();
|
_stack.clear();
|
||||||
Merovingian2 lockMaster = Merovingian2.getLockMaster();
|
Merovingian2 lockMaster = Merovingian2.getLockMaster();
|
||||||
if (lockMaster != null) {
|
if (lockMaster != null) {
|
||||||
@ -600,19 +599,19 @@ public class Transaction {
|
|||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
removeUpTo(CURRENT_TXN, null);
|
removeUpTo(CURRENT_TXN, null);
|
||||||
|
|
||||||
if (_stack.size() == 0) {
|
if (_stack.size() == 0) {
|
||||||
s_logger.trace("Transaction is done");
|
s_logger.trace("Transaction is done");
|
||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this._dbId == CONNECTED_DB) {
|
if(this._dbId == CONNECTED_DB) {
|
||||||
tls.set(_prev);
|
tls.set(_prev);
|
||||||
_prev = null;
|
_prev = null;
|
||||||
s_mbean.removeTransaction(this);
|
s_mbean.removeTransaction(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* close() is used by endTxn to close the connection. This method only
|
* close() is used by endTxn to close the connection. This method only
|
||||||
* closes the connection if the name is the same as what's stored.
|
* closes the connection if the name is the same as what's stored.
|
||||||
@ -644,16 +643,16 @@ public class Transaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected boolean hasTxnInStack() {
|
protected boolean hasTxnInStack() {
|
||||||
return peekInStack(START_TXN) != null;
|
return peekInStack(START_TXN) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void clearLockTimes() {
|
protected void clearLockTimes() {
|
||||||
if (s_lockLogger.isDebugEnabled()) {
|
if (s_lockLogger.isDebugEnabled()) {
|
||||||
for (Pair<String, Long> time : _lockTimes) {
|
for (Pair<String, Long> time : _lockTimes) {
|
||||||
s_lockLogger.trace("SQL " + time.first() + " took " + (System.currentTimeMillis() - time.second()));
|
s_lockLogger.trace("SQL " + time.first() + " took " + (System.currentTimeMillis() - time.second()));
|
||||||
}
|
}
|
||||||
_lockTimes.clear();
|
_lockTimes.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean commit() {
|
public boolean commit() {
|
||||||
@ -694,8 +693,8 @@ public class Transaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void closeConnection() {
|
protected void closeConnection() {
|
||||||
closePreviousStatement();
|
closePreviousStatement();
|
||||||
|
|
||||||
if (_conn == null) {
|
if (_conn == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -712,7 +711,7 @@ public class Transaction {
|
|||||||
if(this._dbId != CONNECTED_DB) {
|
if(this._dbId != CONNECTED_DB) {
|
||||||
_conn.close();
|
_conn.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
_conn = null;
|
_conn = null;
|
||||||
} catch (final SQLException e) {
|
} catch (final SQLException e) {
|
||||||
s_logger.warn("Unable to close connection", e);
|
s_logger.warn("Unable to close connection", e);
|
||||||
@ -726,12 +725,12 @@ public class Transaction {
|
|||||||
StackElement item = it.next();
|
StackElement item = it.next();
|
||||||
|
|
||||||
it.remove();
|
it.remove();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (item.type == type && (ref == null || item.ref == ref)) {
|
if (item.type == type && (ref == null || item.ref == ref)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.type == CURRENT_TXN) {
|
if (item.type == CURRENT_TXN) {
|
||||||
if (s_logger.isTraceEnabled()) {
|
if (s_logger.isTraceEnabled()) {
|
||||||
s_logger.trace("Releasing the current txn: " + (item.ref != null ? item.ref : ""));
|
s_logger.trace("Releasing the current txn: " + (item.ref != null ? item.ref : ""));
|
||||||
@ -755,37 +754,37 @@ public class Transaction {
|
|||||||
s_stmtLogger.trace("Closing: " + ref);
|
s_stmtLogger.trace("Closing: " + ref);
|
||||||
}
|
}
|
||||||
Statement stmt = (Statement)ref;
|
Statement stmt = (Statement)ref;
|
||||||
try {
|
try {
|
||||||
ResultSet rs = stmt.getResultSet();
|
ResultSet rs = stmt.getResultSet();
|
||||||
if (rs != null) {
|
if (rs != null) {
|
||||||
rs.close();
|
rs.close();
|
||||||
}
|
}
|
||||||
} catch(SQLException e) {
|
} catch(SQLException e) {
|
||||||
s_stmtLogger.trace("Unable to close resultset");
|
s_stmtLogger.trace("Unable to close resultset");
|
||||||
}
|
}
|
||||||
stmt.close();
|
stmt.close();
|
||||||
} catch (final SQLException e) {
|
} catch (final SQLException e) {
|
||||||
s_stmtLogger.trace("Unable to close statement: " + item);
|
s_stmtLogger.trace("Unable to close statement: " + item);
|
||||||
}
|
}
|
||||||
} else if (item.type == ATTACHMENT) {
|
} else if (item.type == ATTACHMENT) {
|
||||||
TransactionAttachment att = (TransactionAttachment)item.ref;
|
TransactionAttachment att = (TransactionAttachment)item.ref;
|
||||||
if (s_logger.isTraceEnabled()) {
|
if (s_logger.isTraceEnabled()) {
|
||||||
s_logger.trace("Cleaning up " + att.getName());
|
s_logger.trace("Cleaning up " + att.getName());
|
||||||
}
|
}
|
||||||
att.cleanup();
|
att.cleanup();
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
s_logger.error("Unable to clean up " + item, e);
|
s_logger.error("Unable to clean up " + item, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rollback) {
|
if (rollback) {
|
||||||
rollback();
|
rollback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void rollbackTransaction() {
|
protected void rollbackTransaction() {
|
||||||
closePreviousStatement();
|
closePreviousStatement();
|
||||||
if (!_txn) {
|
if (!_txn) {
|
||||||
if (s_logger.isTraceEnabled()) {
|
if (s_logger.isTraceEnabled()) {
|
||||||
s_logger.trace("Rollback called for " + _name + " when there's no transaction: " + buildName());
|
s_logger.trace("Rollback called for " + _name + " when there's no transaction: " + buildName());
|
||||||
@ -807,7 +806,7 @@ public class Transaction {
|
|||||||
s_logger.warn("Unable to rollback", e);
|
s_logger.warn("Unable to rollback", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void rollbackSavepoint(Savepoint sp) {
|
protected void rollbackSavepoint(Savepoint sp) {
|
||||||
try {
|
try {
|
||||||
if (_conn != null) {
|
if (_conn != null) {
|
||||||
@ -816,7 +815,7 @@ public class Transaction {
|
|||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
s_logger.warn("Unable to rollback to savepoint " + sp);
|
s_logger.warn("Unable to rollback to savepoint " + sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasTxnInStack()) {
|
if (!hasTxnInStack()) {
|
||||||
_txn = false;
|
_txn = false;
|
||||||
closeConnection();
|
closeConnection();
|
||||||
@ -836,7 +835,7 @@ public class Transaction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rollbackTransaction();
|
rollbackTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -867,13 +866,13 @@ public class Transaction {
|
|||||||
if (_conn != null) {
|
if (_conn != null) {
|
||||||
_conn.releaseSavepoint(sp);
|
_conn.releaseSavepoint(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasTxnInStack()) {
|
if (!hasTxnInStack()) {
|
||||||
_txn = false;
|
_txn = false;
|
||||||
closeConnection();
|
closeConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean hasSavepointInStack(Savepoint sp) {
|
protected boolean hasSavepointInStack(Savepoint sp) {
|
||||||
Iterator<StackElement> it = _stack.iterator();
|
Iterator<StackElement> it = _stack.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
@ -884,14 +883,14 @@ public class Transaction {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void removeTxn(Savepoint sp) {
|
protected void removeTxn(Savepoint sp) {
|
||||||
assert hasSavepointInStack(sp) : "Removing a save point that's not in the stack";
|
assert hasSavepointInStack(sp) : "Removing a save point that's not in the stack";
|
||||||
|
|
||||||
if (!hasSavepointInStack(sp)) {
|
if (!hasSavepointInStack(sp)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator<StackElement> it = _stack.iterator();
|
Iterator<StackElement> it = _stack.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
StackElement se = it.next();
|
StackElement se = it.next();
|
||||||
@ -906,26 +905,26 @@ public class Transaction {
|
|||||||
|
|
||||||
public void rollback(final Savepoint sp) {
|
public void rollback(final Savepoint sp) {
|
||||||
removeTxn(sp);
|
removeTxn(sp);
|
||||||
|
|
||||||
rollbackSavepoint(sp);
|
rollbackSavepoint(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Connection getCurrentConnection() {
|
public Connection getCurrentConnection() {
|
||||||
return _conn;
|
return _conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<StackElement> getStack() {
|
public List<StackElement> getStack() {
|
||||||
return _stack;
|
return _stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Transaction() {
|
protected Transaction() {
|
||||||
_name = null;
|
_name = null;
|
||||||
_conn = null;
|
_conn = null;
|
||||||
_stack = null;
|
_stack = null;
|
||||||
_txn = false;
|
_txn = false;
|
||||||
_dbId = -1;
|
_dbId = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
if (!(_conn == null && (_stack == null || _stack.size() == 0))) {
|
if (!(_conn == null && (_stack == null || _stack.size() == 0))) {
|
||||||
@ -934,22 +933,22 @@ public class Transaction {
|
|||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class StackElement {
|
protected class StackElement {
|
||||||
public String type;
|
public String type;
|
||||||
public Object ref;
|
public Object ref;
|
||||||
|
|
||||||
public StackElement (String type, Object ref) {
|
public StackElement (String type, Object ref) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.ref = ref;
|
this.ref = ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return type + "-" + ref;
|
return type + "-" + ref;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DataSource s_ds;
|
private static DataSource s_ds;
|
||||||
private static DataSource s_usageDS;
|
private static DataSource s_usageDS;
|
||||||
static {
|
static {
|
||||||
@ -969,6 +968,21 @@ public class Transaction {
|
|||||||
final String cloudDbName = dbProps.getProperty("db.cloud.name");
|
final String cloudDbName = dbProps.getProperty("db.cloud.name");
|
||||||
final boolean cloudAutoReconnect = Boolean.parseBoolean(dbProps.getProperty("db.cloud.autoReconnect"));
|
final boolean cloudAutoReconnect = Boolean.parseBoolean(dbProps.getProperty("db.cloud.autoReconnect"));
|
||||||
final String cloudValidationQuery = dbProps.getProperty("db.cloud.validationQuery");
|
final String cloudValidationQuery = dbProps.getProperty("db.cloud.validationQuery");
|
||||||
|
final String cloudIsolationLevel = dbProps.getProperty("db.cloud.isolation.level");
|
||||||
|
int isolationLevel = Connection.TRANSACTION_READ_COMMITTED;
|
||||||
|
if (cloudIsolationLevel == null) {
|
||||||
|
isolationLevel = Connection.TRANSACTION_READ_COMMITTED;
|
||||||
|
} else if (cloudIsolationLevel.equalsIgnoreCase("readcommitted")) {
|
||||||
|
isolationLevel = Connection.TRANSACTION_READ_COMMITTED;
|
||||||
|
} else if (cloudIsolationLevel.equalsIgnoreCase("repeatableread")) {
|
||||||
|
isolationLevel = Connection.TRANSACTION_REPEATABLE_READ;
|
||||||
|
} else if (cloudIsolationLevel.equalsIgnoreCase("serializable")) {
|
||||||
|
isolationLevel = Connection.TRANSACTION_SERIALIZABLE;
|
||||||
|
} else if (cloudIsolationLevel.equalsIgnoreCase("readuncommitted")) {
|
||||||
|
isolationLevel = Connection.TRANSACTION_READ_UNCOMMITTED;
|
||||||
|
} else {
|
||||||
|
s_logger.warn("Unknown isolation level " + cloudIsolationLevel + ". Using read uncommitted");
|
||||||
|
}
|
||||||
final boolean cloudTestOnBorrow = Boolean.parseBoolean(dbProps.getProperty("db.cloud.testOnBorrow"));
|
final boolean cloudTestOnBorrow = Boolean.parseBoolean(dbProps.getProperty("db.cloud.testOnBorrow"));
|
||||||
final boolean cloudTestWhileIdle = Boolean.parseBoolean(dbProps.getProperty("db.cloud.testWhileIdle"));
|
final boolean cloudTestWhileIdle = Boolean.parseBoolean(dbProps.getProperty("db.cloud.testWhileIdle"));
|
||||||
final long cloudTimeBtwEvictionRunsMillis = Long.parseLong(dbProps.getProperty("db.cloud.timeBetweenEvictionRunsMillis"));
|
final long cloudTimeBtwEvictionRunsMillis = Long.parseLong(dbProps.getProperty("db.cloud.timeBetweenEvictionRunsMillis"));
|
||||||
@ -985,7 +999,7 @@ public class Transaction {
|
|||||||
"?autoReconnect="+cloudAutoReconnect + (url != null ? "&" + url : ""), cloudUsername, cloudPassword);
|
"?autoReconnect="+cloudAutoReconnect + (url != null ? "&" + url : ""), cloudUsername, cloudPassword);
|
||||||
final KeyedObjectPoolFactory poolableObjFactory = (cloudPoolPreparedStatements ? new StackKeyedObjectPoolFactory() : null);
|
final KeyedObjectPoolFactory poolableObjFactory = (cloudPoolPreparedStatements ? new StackKeyedObjectPoolFactory() : null);
|
||||||
final PoolableConnectionFactory cloudPoolableConnectionFactory = new PoolableConnectionFactory(cloudConnectionFactory, cloudConnectionPool, poolableObjFactory,
|
final PoolableConnectionFactory cloudPoolableConnectionFactory = new PoolableConnectionFactory(cloudConnectionFactory, cloudConnectionPool, poolableObjFactory,
|
||||||
cloudValidationQuery, false, false);
|
cloudValidationQuery, false, false, isolationLevel);
|
||||||
s_ds = new PoolingDataSource(cloudPoolableConnectionFactory.getPool());
|
s_ds = new PoolingDataSource(cloudPoolableConnectionFactory.getPool());
|
||||||
|
|
||||||
// configure the usage db
|
// configure the usage db
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user