int flags) throws XAException {
checkXAActive();
// JDBC 3.0 section 12.3 - One transaction associated with a XAConnection
if (currentXid != null)
throw new XAException(XAException.XAER_PROTO);
// ensure immtable and correct equals method.
XAXactId xid_im = new XAXactId(xid);
XATransactionState tranState = getTransactionState(xid_im);
switch (flags) {
case XAResource.TMNOFLAGS:
if (tranState != null)
throw new XAException(XAException.XAER_DUPID);
try {
if (con.realConnection == null) {
con.openRealConnection();
if (con.currentConnectionHandle != null) {
// since this is a new connection, set its complete
// state according to the application's Connection
// handle view of the world.
con.currentConnectionHandle.setState(true);
con.realConnection.setApplicationConnection
(con.currentConnectionHandle);
}
} else {
// XAResource.start() auto commits in DB2 when in
// auto commit mode.
if (con.currentConnectionHandle != null) {
if (con.currentConnectionHandle.getAutoCommit())
con.currentConnectionHandle.rollback();
}
if (!con.realConnection.transactionIsIdle())
throw new XAException(XAException.XAER_OUTSIDE);
if (con.currentConnectionHandle != null) {
// It is possible that the isolation level state
// in connection handle has gotten out of sync
// with the real isolation level. This can happen
// if SLQ instead of JDBC api has been used to set
// the isolation level. The code below will check
// if isolation was set using JDBC or SQL and if
// yes, then it will update the isolation state
// in BrokeredConnection with EmbedConnection's
// isolation level.
con.currentConnectionHandle.getIsolationUptoDate();
// we have a current handle so we need to keep
// the connection state of the current connection.
con.currentConnectionHandle.setState(true);
// At the local to global transition we need
// to discard and close any open held result
// sets, a rollback will do this.
con.realConnection.rollback();
} else {
con.resetRealConnection();
}
}
// Global connections are always in auto commit false mode.
con.realConnection.setAutoCommit(false);
// and holdability false (cannot hold cursors across
// XA transactions.
con.realConnection.setHoldability(
JDBC30Translation.CLOSE_CURSORS_AT_COMMIT);
con.realConnection.getLanguageConnection().
getTransactionExecute().
createXATransactionFromLocalTransaction(
xid_im.getFormatId(),
xid_im.getGlobalTransactionId(),
xid_im.getBranchQualifier());
} catch (StandardException se) {
throw wrapInXAException(se);
} catch (SQLException sqle) {
throw wrapInXAException(sqle);
}
tranState = new XATransactionState(
con.realConnection.getContextManager(),
con.realConnection, this, xid_im);
if (!ra.addConnection(xid_im, tranState))
throw new XAException(XAException.XAER_DUPID);
currentXid = xid_im;
// If the the timeout specified is equal to Integer.MAX_VALUE
// it means that transaction timeout is disabled.
if (timeoutSeconds != Integer.MAX_VALUE) {
// Find out the value of the transaction timeout
long timeoutMillis;
if (timeoutSeconds > 0) {
timeoutMillis = 1000*timeoutSeconds;
} else {
timeoutMillis = getDefaultXATransactionTimeout();
}
// If we have non-zero transaction timeout schedule a timeout task.
// The only way how timeoutMillis might be equeal to 0 is that
// it was specified as a default transaction timeout
if (timeoutMillis > 0) {
tranState.scheduleTimeoutTask(timeoutMillis);
}
}
break;
case XAResource.TMRESUME:
case XAResource.TMJOIN:
if (tranState == null)
throw new XAException(XAException.XAER_NOTA);
tranState.start(this, flags);
if (tranState.conn != con.realConnection) {
if (con.realConnection != null) {
if (!con.realConnection.transactionIsIdle())
throw new XAException(XAException.XAER_OUTSIDE);
// We need to get the isolation level up to date same
// way as it is done at start of a transaction. Before
// joining the transaction, it is possible that the
// isolation level was updated using SQL. We need to
// get this state and store in the connection handle so
// that we can restore the isolation when we are in the
// local mode.
try {
if (con.currentConnectionHandle != null) {
con.currentConnectionHandle.getIsolationUptoDate();
}
} catch (SQLException sqle) {
throw wrapInXAException(sqle);
}
closeUnusedConnection(con.realConnection);
}
con.realConnection = tranState.conn;
if (con.currentConnectionHandle != null) {
try {
// only reset the non-transaction specific
// Connection state.
con.currentConnectionHandle.setState(false);
con.realConnection.setApplicationConnection(
con.currentConnectionHandle);
} catch (SQLException sqle) {
throw wrapInXAException(sqle);
}
}
}
break;
default:
throw new XAException(XAException.XAER_INVAL);
}
currentXid = xid_im;
}