/** * @throws XAException if the given Xid is the not the Xid of the * current transaction for this XAResource object. */ private void validateXid(Xid xid) throws XAException { if (xid == null) { throw new XAException("Null Xid"); } if (this.xid == null) { throw new XAException( "There is no live transaction for this XAResource"); } if (!xid.equals(this.xid)) { throw new XAException( "Given Xid is not that associated with this XAResource object"); } }
@Override public void commit(Xid xid, boolean onePhase) throws XAException { if (logger.logDebug()) { debug("committing xid = " + xid + (onePhase ? " (one phase) " : " (two phase)")); } if (xid == null) { throw new CloudSpannerXAException("xid must not be null", Code.INVALID_ARGUMENT, XAException.XAER_INVAL); } if (onePhase) { commitOnePhase(xid); } else { commitPrepared(xid); } }
/** * Tests fix for BUG#69506 - XAER_DUPID error code is not returned when a duplicate XID is offered in Java. * * @throws Exception * if the test fails. */ public void testBug69506() throws Exception { MysqlXADataSource dataSource = new MysqlXADataSource(); dataSource.setUrl(dbUrl); XAConnection testXAConn1 = dataSource.getXAConnection(); XAConnection testXAConn2 = dataSource.getXAConnection(); Xid duplicateXID = new MysqlXid("1".getBytes(), "1".getBytes(), 1); testXAConn1.getXAResource().start(duplicateXID, 0); try { testXAConn2.getXAResource().start(duplicateXID, 0); fail("XAException was expected."); } catch (XAException e) { assertEquals("Wrong error code retured for duplicated XID.", XAException.XAER_DUPID, e.errorCode); } }
public void end(Xid xid, int flags) throws XAException { validateXid(xid); if (state != XA_STATE_STARTED) { throw new XAException("Invalid XAResource state"); } try { connection.setAutoCommit(originalAutoCommitMode); // real/phys. } catch (SQLException se) { throw new XAException(se.getMessage()); } state = XA_STATE_ENDED; }
/** * The XAResource API spec indicates implies that this is only for * 2-phase transactions. * I guess that one-phase transactions need to call rollback() to abort. * * I think we want this JDBCXAResource instance to be garbage-collectable * after (a) this method is called, and (b) the tx manager releases its * handle to it. * * @see javax.transaction.xa.XAResource#forget(Xid) */ public void forget(Xid xid) throws XAException { /** * Should this method not attempt to clean up the aborted * transaction by rolling back or something? Maybe the * tx manager will already have called rollback() if * it were necessasry? */ validateXid(xid); if (state != XA_STATE_PREPARED) { throw new XAException( "Attempted to forget a XAResource that " + "is not in a heuristically completed state"); } dispose(); state = XA_STATE_INITIAL; }
/** * This rolls back the connection associated with <i>this</i> XAResource. * * @throws javax.transaction.xa.XAException generically, since the more * specific exceptions require a JTA API to compile. */ /* @throws javax.transaction.HeuristicCommitException * if work was committed. * @throws javax.transaction.HeuristicMixedException * if some work was committed and some work was rolled back */ public void rollbackThis() throws XAException { if (state != XA_STATE_PREPARED && state != XA_STATE_ENDED) { throw new XAException("Invalid XAResource state"); } try { /** * @todo: Determine if work was committed, rolled back, or both, * and return appropriate Heuristic Exception. */ connection.rollback(); // real/phys. } catch (SQLException se) { throw new XAException(se.toString()); } dispose(); }
/** * * @throws XAException if the given Xid is the not the Xid of the current * transaction for this XAResource object. * @param xid Xid */ private void validateXid(Xid xid) throws XAException { if (xid == null) { throw new XAException("Null Xid"); } if (this.xid == null) { throw new XAException( "There is no live transaction for this XAResource"); } if (!xid.equals(this.xid)) { throw new XAException( "Given Xid is not that associated with this XAResource object"); } }
public void start(Xid xid, int flag) throws XAException { if (flag == XAResource.TMNOFLAGS) { // first time in this transaction if (this.xid != null) { throw new XAException("already enlisted"); } this.xid = xid; try { localTransaction.begin(); } catch (ResourceException e) { throw (XAException) new XAException("could not start local tx").initCause(e); } } else if (flag == XAResource.TMRESUME) { if (xid != this.xid) { throw new XAException("attempting to resume in different transaction"); } } else { throw new XAException("unknown state"); } }
/** * Starts work on behalf of a transaction branch specified in xid. * * If TMJOIN is specified, the start applies to joining a transaction * previously seen by the resource manager. * * If TMRESUME is specified, the start applies to resuming a suspended * transaction specified in the parameter xid. * * If neither TMJOIN nor TMRESUME is specified and the transaction specified * by xid has previously been seen by the resource manager, the resource * manager throws the XAException exception with XAER_DUPID error code. * * @parameter xid A global transaction identifier to be associated with the * resource. * * @parameter flags One of TMNOFLAGS, TMJOIN, or TMRESUME. * * @throws XAException * An error has occurred. Possible exceptions are XA_RB*, * XAER_RMERR, XAER_RMFAIL, XAER_DUPID, XAER_OUTSIDE, XAER_NOTA, * XAER_INVAL, or XAER_PROTO. */ public void start(Xid xid, int flags) throws XAException { StringBuilder commandBuf = new StringBuilder(MAX_COMMAND_LENGTH); commandBuf.append("XA START "); appendXid(commandBuf, xid); switch (flags) { case TMJOIN: commandBuf.append(" JOIN"); break; case TMRESUME: commandBuf.append(" RESUME"); break; case TMNOFLAGS: // no-op break; default: throw new XAException(XAException.XAER_INVAL); } dispatchCommand(commandBuf.toString()); this.underlyingConnection.setInGlobalTx(true); }
private synchronized void switchToXid(Xid xid) throws XAException { if (xid == null) { throw new XAException(); } try { if (!xid.equals(this.currentXid)) { XAConnection toSwitchTo = findConnectionForXid(this.underlyingConnection, xid); this.currentXAConnection = toSwitchTo; this.currentXid = xid; this.currentXAResource = toSwitchTo.getXAResource(); } } catch (SQLException sqlEx) { throw new XAException(); } }
private int rollbackXaTranInner(List<Map> xaList){ boolean flag=true; for(Map xaInfo:xaList){ XAResource xaResource=(XAResource) xaInfo.get("xaResource"); MyXid myXid=(MyXid) xaInfo.get("myXid"); try { xaResource.rollback(myXid); } catch (XAException e) { flag=false; e.printStackTrace(); } } if(flag==false){ return 1; } return 0; }
/** * Per the JDBC 3.0 spec, this commits the transaction for the specified * Xid, not necessarily for the transaction associated with this XAResource * object. * * @param xid Xid * @param onePhase boolean * @throws XAException */ public void commit(Xid xid, boolean onePhase) throws XAException { // Comment out following debug statement before public release: /* System.err.println("Performing a " + (onePhase ? "1-phase" : "2-phase") + " commit on " + xid); */ JDBCXAResource resource = xaDataSource.getResource(xid); if (resource == null) { throw new XAException("The XADataSource has no such Xid: " + xid); } resource.commitThis(onePhase); }
@Test public void testEnd() throws SQLException, XAException { CloudSpannerXAConnection subject = createSubject(); Xid xid = createXid(); subject.start(xid, XAResource.TMNOFLAGS); subject.end(xid, XAResource.TMSUCCESS); }
/** * Stub. See implementation comment in the method for why this is not * implemented yet. * * @return false. * @param xares XAResource * @throws XAException */ public boolean isSameRM(XAResource xares) throws XAException { if (!(xares instanceof JDBCXAResource)) { return false; } return xaDataSource == ((JDBCXAResource) xares).getXADataSource(); }
@Test public void testCommitTwoPhase() throws SQLException, XAException { CloudSpannerXAConnection subject = createSubject(); Xid xid = createXid(); subject.start(xid, XAResource.TMNOFLAGS); subject.end(xid, XAResource.TMSUCCESS); subject.prepare(xid); subject.commit(xid, false); }
private Xid prepareDeleteRow(CloudSpannerXAConnection xaConnection) throws SQLException, XAException { Random rnd = new Random(); Connection connection = xaConnection.getConnection(); int id = rnd.nextInt(); Xid xid = RecoveredXid.stringToXid(String.valueOf(id) + "_Z3RyaWQ=_YnF1YWw="); xaConnection.start(xid, XAResource.TMNOFLAGS); String sql = "delete from test where id=1000000"; PreparedStatement statement = connection.prepareStatement(sql); statement.executeUpdate(); xaConnection.end(xid, XAResource.TMSUCCESS); xaConnection.prepare(xid); return xid; }
public int prepareThis() throws XAException { /** * @todo: This is where the real 2-phase work should be done to * determine if a commit done here would succeed or not. */ /** * @todo: May improve performance to return XA_RDONLY whenever * possible, but I don't know. * Could determine this by checking if DB instance is in RO mode, * or perhaps (with much difficulty) to determine if there have * been any modifications performed. */ if (state != XA_STATE_ENDED) { throw new XAException("Invalid XAResource state"); } try { connection.getSession().prepareCommit(); } catch (HsqlException e) { state = XA_STATE_PREPARED; // ??? didn't prepare throw new XAException(e.getMessage()); } state = XA_STATE_PREPARED; return XA_OK; // As noted above, should check non-committed work. }
/** * Vote on whether to commit the global transaction. We assume Xid may be * different from this, as in commit() method. * * @throws XAException to vote negative. * @return commitType of XA_RDONLY or XA_OK. (Actually only XA_OK now). * @param xid Xid */ public int prepare(Xid xid) throws XAException { JDBCXAResource resource = xaDataSource.getResource(xid); if (resource == null) { throw new XAException("The XADataSource has no such Xid: " + xid); } return resource.prepareThis(); }
/** * This commits the connection associated with <i>this</i> XAResource. * * @throws XAException generically, since the more specific exceptions * require a JTA API to compile. * @param onePhase boolean */ public void commitThis(boolean onePhase) throws XAException { if (onePhase && state == XA_STATE_PREPARED) { throw new XAException( "Transaction is in a 2-phase state when 1-phase is requested"); } if ((!onePhase) && state != XA_STATE_PREPARED) { throw new XAException("Attempt to do a 2-phase commit when " + "transaction is not prepared"); } //if (!onePhase) { // throw new XAException( // "Sorry. HSQLDB has not implemented 2-phase commits yet"); //} try { /** * @todo: Determine if work was committed, rolled back, or both, * and return appropriate Heuristic*Exception. * connection.commit(); * Commits the real, physical conn. */ connection.commit(); } catch (SQLException se) { throw new XAException(se.toString()); } dispose(); }
/** * This commits the connection associated with <i>this</i> XAResource. * * @throws javax.transaction.xa.XAException generically, since the more * specific exceptions require a JTA API to compile. */ /* * @throws javax.transaction.HeuristicRollbackException * if work was rolled back. * since these specific exceptions require a JTA API. * @throws javax.transaction.HeuristicMixedException * if some work was committed and some work was rolled back */ public void commitThis(boolean onePhase) throws XAException { if (onePhase && state == XA_STATE_PREPARED) { throw new XAException( "Transaction is in a 2-phase state when 1-phase is requested"); } if ((!onePhase) && state != XA_STATE_PREPARED) { throw new XAException("Attempt to do a 2-phase commit when " + "transaction is not prepared"); } //if (!onePhase) { // throw new XAException( // "Sorry. HSQLDB has not implemented 2-phase commits yet"); //} try { /** * @todo: Determine if work was committed, rolled back, or both, * and return appropriate Heuristic*Exception. * connection.commit(); * Commits the real, physical conn. */ connection.commit(); } catch (SQLException se) { throw new XAException(se.getMessage()); } dispose(); }
/** * Create XAException with message */ @Test public void test2() { XAException ex = new XAException(reason); assertTrue(ex.getMessage().equals(reason) && ex.getCause() == null && ex.errorCode == 0); }
/** * Per the JDBC 3.0 spec, this rolls back the transaction for the * specified Xid, not necessarily for the transaction associated * with this XAResource object. */ public void rollback(Xid xid) throws XAException { JDBCXAResource resource = xaDataSource.getResource(xid); if (resource == null) { throw new XAException( "The XADataSource has no such Xid in prepared state: " + xid); } resource.rollbackThis(); }
public void start(Xid xid, int flags) throws XAException { // Comment out following debug statement before public release: System.err.println("STARTING NEW Xid: " + xid); if (state != XA_STATE_INITIAL && state != XA_STATE_DISPOSED) { throw new XAException("Invalid XAResource state"); } if (xaDataSource == null) { throw new XAException( "JDBCXAResource has not been associated with a XADataSource"); } if (xid == null) { // This block asserts that all JDBCXAResources with state // >= XA_STATE_STARTED have a non-null xid. throw new XAException("Null Xid"); } try { originalAutoCommitMode = connection.getAutoCommit(); // real/phys. connection.setAutoCommit(false); // real/phys. } catch (SQLException se) { throw new XAException(se.getMessage()); } this.xid = xid; state = XA_STATE_STARTED; xaDataSource.addResource(this.xid, this); // N.b. The DataSource does not have this XAResource in its list // until right here. We can't tell DataSource before our start() // method, because we don't know our Xid before now. }
public void start(Xid xid, int arg1) throws XAException { switchToXid(xid); if (arg1 != XAResource.TMJOIN) { this.currentXAResource.start(xid, arg1); return; } // // Emulate join, by using resume on the same physical connection // this.currentXAResource.start(xid, XAResource.TMRESUME); }
/** * Create TransactionRolledbackException specifying an error code */ @Test public void test4() { int error = 21; XAException ex = new XAException(error); assertTrue(ex.getMessage() == null && ex.getCause() == null && ex.errorCode == error); }
protected static XAException mapXAExceptionFromSQLException(SQLException sqlEx) { Integer xaCode = MYSQL_ERROR_CODES_TO_XA_ERROR_CODES.get(Integer.valueOf(sqlEx.getErrorCode())); if (xaCode != null) { return (XAException) new MysqlXAException(xaCode.intValue(), sqlEx.getMessage(), null).initCause(sqlEx); } return (XAException) new MysqlXAException(XAException.XAER_RMFAIL, Messages.getString("MysqlXAConnection.003"), null).initCause(sqlEx); }
/** * Create XAException with no-arg constructor */ @Test public void test1() { XAException ex = new XAException(); assertTrue(ex.getMessage() == null && ex.getCause() == null && ex.errorCode == 0); }
@Override public void end(Xid xid, int flags) throws XAException { try { getXAResource().end(xid, flags); } finally { setInXaTransaction(false); } }
protected static XAException mapXAExceptionFromSQLException(SQLException sqlEx) { Integer xaCode = MYSQL_ERROR_CODES_TO_XA_ERROR_CODES.get(sqlEx.getErrorCode()); if (xaCode != null) { return (XAException) new MysqlXAException(xaCode.intValue(), sqlEx.getMessage(), null).initCause(sqlEx); } return (XAException) new MysqlXAException(XAException.XAER_RMFAIL, Messages.getString("MysqlXAConnection.003"), null).initCause(sqlEx); }
public void end(Xid xid, int arg1) throws XAException { switchToXid(xid); this.currentXAResource.end(xid, arg1); }
@Override public void forget(Xid xid) throws XAException { throw new CloudSpannerXAException("Heuristic commit/rollback not supported", Code.UNIMPLEMENTED, XAException.XAER_NOTA); }
private void deleteTestRow(CloudSpannerXAConnection xaConnection) throws XAException, SQLException { Xid xid = prepareDeleteRow(xaConnection); xaConnection.commit(xid, false); }
/** * Ends the work performed on behalf of a transaction branch. * * The resource manager disassociates the XA resource from the transaction * branch specified and lets the transaction complete. * * If TMSUSPEND is specified in the flags, the transaction branch is * temporarily suspended in an incomplete state. The transaction context is * in a suspended state and must be resumed via the start method with * TMRESUME specified. * * If TMFAIL is specified, the portion of work has failed. The resource * manager may mark the transaction as rollback-only * * If TMSUCCESS is specified, the portion of work has completed * successfully. * * @parameter xid A global transaction identifier that is the same as the * identifier used previously in the start method. * * @parameter flags One of TMSUCCESS, TMFAIL, or TMSUSPEND. * * @throws XAException * - * An error has occurred. Possible XAException values are * XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, XAER_PROTO, * or XA_RB*. */ public void end(Xid xid, int flags) throws XAException { StringBuilder commandBuf = new StringBuilder(MAX_COMMAND_LENGTH); commandBuf.append("XA END "); appendXid(commandBuf, xid); switch (flags) { case TMSUCCESS: break; // no-op case TMSUSPEND: commandBuf.append(" SUSPEND"); break; case TMFAIL: break; // no-op default: throw new XAException(XAException.XAER_INVAL); } dispatchCommand(commandBuf.toString()); }