int doTransaction(Xid xid, int mode, int command) throws XAException { int returnVal = -1; try { try { T4CTTIOtxen otxen = physicalConn.otxen; byte xidxid[] = null; byte gtrid[] = xid.getGlobalTransactionId(); byte bqual[] = xid.getBranchQualifier(); int gtrid_l = 0; int bqual_l = 0; if (gtrid != null && bqual != null) { gtrid_l = Math.min(gtrid.length, 64); bqual_l = Math.min(bqual.length, 64); xidxid = new byte[128]; System.arraycopy(gtrid, 0, xidxid, 0, gtrid_l); System.arraycopy(bqual, 0, xidxid, gtrid_l, bqual_l); } byte txctx[] = context; physicalConn.sendPiggyBackedMessages(); otxen.marshal(mode, txctx, xidxid, xid.getFormatId(), gtrid_l, bqual_l, timeout, command); returnVal = otxen.receive(errorNumber); } catch (IOException ioe) { DatabaseError.throwSqlException(ioe); } } catch (SQLException s) { errorNumber[0] = s.getErrorCode(); } if (errorNumber[0] == 0) { throw new XAException(-6); } if (returnVal == -1) { returnVal = errorNumber[0]; } return returnVal; }
private Xid randomXid(Boolean trueForPositive) { while (true) { Xid xid = new XidImpl(randomBytes(), randomBytes()); if (trueForPositive == null || xid.hashCode() > 0 == trueForPositive.booleanValue()) return xid; } }
/** Construct an XID as a clone of another XID. */ public JtdsXid(Xid xid) { fmtId = xid.getFormatId(); gtran = new byte[xid.getGlobalTransactionId().length]; System.arraycopy(xid.getGlobalTransactionId(), 0, gtran, 0, gtran.length); bqual = new byte[xid.getBranchQualifier().length]; System.arraycopy(xid.getBranchQualifier(), 0, bqual, 0, bqual.length); calculateHash(); }
@Override public byte[] serialize(Xid xid) { return ByteBuffer.allocate(this.size()) .putInt(xid.getFormatId()) .put(xid.getGlobalTransactionId()) .put(xid.getBranchQualifier()) .array(); }
public boolean equals(Object object) { if (object instanceof Xid) { Xid xid = (Xid) object; return xid.getFormatId() == 1 && Arrays.equals(xid.getGlobalTransactionId(), gid) && xid.getBranchQualifier() == null; } else { return false; } }
private void clearRemoteTransactions(Xid xid) { NodeEngine nodeEngine = getNodeEngine(); InternalPartitionService partitionService = nodeEngine.getPartitionService(); OperationService operationService = nodeEngine.getOperationService(); SerializableXID serializableXID = new SerializableXID( xid.getFormatId(), xid.getGlobalTransactionId(), xid.getBranchQualifier()); Data xidData = nodeEngine.toData(serializableXID); int partitionId = partitionService.getPartitionId(xidData); ClearRemoteTransactionOperation operation = new ClearRemoteTransactionOperation(xidData); operationService.invokeOnPartition(SERVICE_NAME, operation, partitionId); }
@Override public boolean equals(Object other) { if (other instanceof Xid) { Xid xid = (Xid) other; if (xid.getFormatId() == formatId) { if (Arrays.equals(branchQualifier, xid.getBranchQualifier())) { if (Arrays.equals(globalTransactionId, xid.getGlobalTransactionId())) { return true; } } } } return false; }
private boolean isOnePhase() { if (resourceList.size() == 0) { log.severe("Detected zero resources in resourceList"); return true; } // check for more than one unique xid Iterator<ResourceElement> itr = resourceList.iterator(); Xid xid = itr.next().getXid(); while (itr.hasNext()) { if (!xid.equals(itr.next().getXid())) { return false; } } return true; }
public synchronized void xaStart(final Xid xid) throws Exception { if (tx != null) { HornetQServerLogger.LOGGER.xidReplacedOnXStart(tx.getXid().toString(), xid.toString()); try { if (tx.getState() != Transaction.State.PREPARED) { // we don't want to rollback anything prepared here if (tx.getXid() != null) { resourceManager.removeTransaction(tx.getXid()); } tx.rollback(); } } catch (Exception e) { HornetQServerLogger.LOGGER.debug( "An exception happened while we tried to debug the previous tx, we can ignore this exception", e); } } tx = newTransaction(xid); if (isTrace) { HornetQServerLogger.LOGGER.trace("xastart into tx= " + tx); } boolean added = resourceManager.putTransaction(xid, tx); if (!added) { final String msg = "Cannot start, there is already a xid " + tx.getXid(); throw new HornetQXAException(XAException.XAER_DUPID, msg); } }
/** * Preconditions: 1. Flags is one of TMSUCCESS, TMFAIL, TMSUSPEND 2. xid != null 3. Connection is * associated with transaction xid * * <p>Implementation deficiency preconditions: 1. Flags is not TMSUSPEND * * <p>Postconditions: 1. connection is disassociated from the transaction. */ public void end(Xid xid, int flags) throws XAException { if (logger.logDebug()) debug("ending transaction xid = " + xid); // Check preconditions if (flags != XAResource.TMSUSPEND && flags != XAResource.TMFAIL && flags != XAResource.TMSUCCESS) throw new PGXAException(GT.tr("Invalid flags"), XAException.XAER_INVAL); if (xid == null) throw new PGXAException(GT.tr("xid must not be null"), XAException.XAER_INVAL); if (state != STATE_ACTIVE || !currentXid.equals(xid)) throw new PGXAException( GT.tr("tried to call end without corresponding start call"), XAException.XAER_PROTO); // Check implementation deficiency preconditions if (flags == XAResource.TMSUSPEND) throw new PGXAException(GT.tr("suspend/resume not implemented"), XAException.XAER_RMERR); // We ignore TMFAIL. It's just a hint to the RM. We could roll back immediately // if TMFAIL was given. // All clear. We don't have any real work to do. state = STATE_ENDED; }
/** * Preconditions: 1. xid is known to the RM or it's in prepared state * * <p>Implementation deficiency preconditions: 1. xid must be associated with this connection if * it's not in prepared state. * * <p>Postconditions: 1. Transaction is rolled back and disassociated from connection */ public void rollback(Xid xid) throws XAException { if (logger.logDebug()) debug("rolling back xid = " + xid); // We don't explicitly check precondition 1. try { if (currentXid != null && xid.equals(currentXid)) { state = STATE_IDLE; currentXid = null; conn.rollback(); conn.setAutoCommit(localAutoCommitMode); } else { String s = RecoveredXid.xidToString(xid); conn.setAutoCommit(true); Statement stmt = conn.createStatement(); try { stmt.executeUpdate("ROLLBACK PREPARED '" + s + "'"); } finally { stmt.close(); } } } catch (SQLException ex) { throw new PGXAException( GT.tr("Error rolling back prepared transaction"), ex, XAException.XAER_RMERR); } }
/** * Constructor * * @param xid The Xid */ public GlobalXID(Xid xid) { gid = xid.getGlobalTransactionId(); for (int i = 0; i < gid.length; ++i) hashCode += 37 * gid[i]; toString = Arrays.toString(gid); }
/** * Preconditions: 1. xid must in ended state. * * <p>Implementation deficiency preconditions: 1. this connection must have been used to run the * transaction * * <p>Postconditions: 1. Transaction is committed */ private void commitOnePhase(Xid xid) throws XAException { try { // Check preconditions if (currentXid == null || !currentXid.equals(xid)) { // In fact, we don't know if xid is bogus, or if it just wasn't associated with this // connection. // Assume it's our fault. throw new PGXAException( GT.tr( "Not implemented: one-phase commit must be issued using the same connection that was used to start it"), XAException.XAER_RMERR); } if (state != STATE_ENDED) throw new PGXAException(GT.tr("commit called before end"), XAException.XAER_PROTO); // Preconditions are met. Commit state = STATE_IDLE; currentXid = null; conn.commit(); conn.setAutoCommit(localAutoCommitMode); } catch (SQLException ex) { throw new PGXAException(GT.tr("Error during one-phase commit"), ex, XAException.XAER_RMERR); } }
@Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((xid == null) ? 0 : xid.hashCode()); return result; }
public final void connect() { while (running) { try { disconnect(); session = sf.createXASession(); if (activeXid != null) { synchronized (ClientAbstract.class) { Xid[] xids = session.recover(XAResource.TMSTARTRSCAN); boolean found = false; for (Xid recXid : xids) { if (recXid.equals(activeXid)) { // System.out.println("Calling commit after a prepare on " + this); found = true; callCommit(); } } if (!found) { if (pendingCommit) { onCommit(); } else { onRollback(); } activeXid = null; pendingCommit = false; } } } connectClients(); break; } catch (Exception e) { ClientAbstract.log.warn("Can't connect to server, retrying"); disconnect(); try { Thread.sleep(1000); } catch (InterruptedException ignored) { // if an interruption was sent, we will respect it and leave the loop break; } } } }
private void addResourceToList(Xid xid, XAResource xaRes) { ResourceElement element = new ResourceElement(xid, xaRes); if (Arrays.equals(NeoStoreXaDataSource.BRANCH_ID, xid.getBranchQualifier())) { resourceList.addFirst(element); } else { resourceList.add(element); } }
private static byte[] toByteArray(final Xid xid) { byte[] branchQualifier = xid.getBranchQualifier(); byte[] globalTransactionId = xid.getGlobalTransactionId(); int formatId = xid.getFormatId(); byte[] hashBytes = new byte[branchQualifier.length + globalTransactionId.length + 4]; System.arraycopy(branchQualifier, 0, hashBytes, 0, branchQualifier.length); System.arraycopy( globalTransactionId, 0, hashBytes, branchQualifier.length, globalTransactionId.length); byte[] intBytes = new byte[4]; for (int i = 0; i < 4; i++) { intBytes[i] = (byte) ((formatId >> i * 8) % 0xFF); } System.arraycopy( intBytes, 0, hashBytes, branchQualifier.length + globalTransactionId.length, 4); return hashBytes; }
protected int doEnd(Xid xid, int flag) throws XAException { int returnVal = -1; synchronized (physicalConn) { synchronized (this) { try { try { T4CTTIOtxse otxse = physicalConn.otxse; byte xidxid[] = null; byte gtrid[] = xid.getGlobalTransactionId(); byte bqual[] = xid.getBranchQualifier(); int gtrid_l = 0; int bqual_l = 0; if (gtrid != null && bqual != null) { gtrid_l = Math.min(gtrid.length, 64); bqual_l = Math.min(bqual.length, 64); xidxid = new byte[128]; System.arraycopy(gtrid, 0, xidxid, 0, gtrid_l); System.arraycopy(bqual, 0, xidxid, gtrid_l, bqual_l); } byte txctx[] = context; int t4cflag = 0; if (((flag & 2) == 2 || (flag & 0x100000) != 0x100000) && (flag & 0x2000000) == 0x2000000) { t4cflag = 0x100000; } physicalConn.sendPiggyBackedMessages(); otxse.marshal(2, txctx, xidxid, xid.getFormatId(), gtrid_l, bqual_l, timeout, t4cflag); byte ctx[] = otxse.receive(applicationValueArr); if (ctx != null) { context = ctx; } returnVal = 0; } catch (IOException ioe) { DatabaseError.throwSqlException(ioe); } } catch (SQLException s) { returnVal = s.getErrorCode(); if (returnVal == 0) { throw new XAException(-6); } } } } return returnVal; }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (!(obj instanceof SessionXAJoinMessage)) return false; SessionXAJoinMessage other = (SessionXAJoinMessage) obj; if (xid == null) { if (other.xid != null) return false; } else if (!xid.equals(other.xid)) return false; return true; }
public boolean equals(Object another) { if (another instanceof Xid) { Xid anotherAsXid = (Xid) another; if (this.myFormatId != anotherAsXid.getFormatId()) { return false; } byte[] otherBqual = anotherAsXid.getBranchQualifier(); byte[] otherGtrid = anotherAsXid.getGlobalTransactionId(); if (otherGtrid != null && otherGtrid.length == this.myGtrid.length) { int length = otherGtrid.length; for (int i = 0; i < length; i++) { if (otherGtrid[i] != this.myGtrid[i]) { return false; } } if (otherBqual != null && otherBqual.length == myBqual.length) { length = otherBqual.length; for (int i = 0; i < length; i++) { if (otherBqual[i] != this.myBqual[i]) { return false; } } } else { return false; } return true; } else { return false; } } else { return false; } }
private Xid createXid(Xid xidToBranch) throws IOException { ByteArrayOutputStream bqualOut = new ByteArrayOutputStream(); DataOutputStream dataOut = new DataOutputStream(bqualOut); new UID().write(dataOut); final byte[] bqual = bqualOut.toByteArray(); Xid xid = new MysqlXid(xidToBranch.getGlobalTransactionId(), bqual, 3306); return xid; }
@Override public boolean equals(final Object other) { if (this == other) { return true; } if (!(other instanceof Xid)) { return false; } Xid xother = (Xid) other; if (xother.getFormatId() != formatId) { return false; } if (xother.getBranchQualifier().length != branchQualifier.length) { return false; } if (xother.getGlobalTransactionId().length != globalTransactionId.length) { return false; } for (int i = 0; i < branchQualifier.length; i++) { byte[] otherBQ = xother.getBranchQualifier(); if (branchQualifier[i] != otherBQ[i]) { return false; } } for (int i = 0; i < globalTransactionId.length; i++) { byte[] otherGtx = xother.getGlobalTransactionId(); if (globalTransactionId[i] != otherGtx[i]) { return false; } } return true; }
public static void assertSameXids(final List<Xid> expected, final List<Xid> actual) { Assert.assertNotNull(expected); Assert.assertNotNull(actual); Assert.assertEquals(expected.size(), actual.size()); for (int i = 0; i < expected.size(); i++) { Xid expectedXid = expected.get(i); Xid actualXid = actual.get(i); UnitTestCase.assertEqualsByteArrays( expectedXid.getBranchQualifier(), actualXid.getBranchQualifier()); Assert.assertEquals(expectedXid.getFormatId(), actualXid.getFormatId()); UnitTestCase.assertEqualsByteArrays( expectedXid.getGlobalTransactionId(), actualXid.getGlobalTransactionId()); } }
private void finalizeTransactionRemotely(Xid xid, boolean isCommit) throws XAException { NodeEngine nodeEngine = getNodeEngine(); InternalPartitionService partitionService = nodeEngine.getPartitionService(); OperationService operationService = nodeEngine.getOperationService(); SerializableXID serializableXID = new SerializableXID( xid.getFormatId(), xid.getGlobalTransactionId(), xid.getBranchQualifier()); Data xidData = nodeEngine.toData(serializableXID); int partitionId = partitionService.getPartitionId(xidData); FinalizeRemoteTransactionOperation operation = new FinalizeRemoteTransactionOperation(xidData, isCommit); InternalCompletableFuture<Integer> future = operationService.invokeOnPartition(SERVICE_NAME, operation, partitionId); Integer errorCode; try { errorCode = future.get(); } catch (Exception e) { throw ExceptionUtil.rethrow(e); } if (errorCode != null) { throw new XAException(errorCode); } }
@Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof Xid)) { return false; } Xid that = (Xid) o; if (formatId != that.getFormatId()) { return false; } if (!Arrays.equals(branchQualifier, that.getBranchQualifier())) { return false; } if (!Arrays.equals(globalTransactionId, that.getGlobalTransactionId())) { return false; } return true; }
/** * @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"); } }
private boolean equals(Xid xid1, Xid xid2) { if (xid1 == xid2) { return true; } if (xid1 == null ^ xid2 == null) { return false; } return xid1.getFormatId() == xid2.getFormatId() && Arrays.equals(xid1.getBranchQualifier(), xid2.getBranchQualifier()) && Arrays.equals(xid1.getGlobalTransactionId(), xid2.getGlobalTransactionId()); }
public RemoteTransaction removeRemoteTransaction(Xid xid) { if (clustered) { Iterator<RemoteTransaction> it = getRemoteTransactions().iterator(); while (it.hasNext()) { RemoteTransaction next = it.next(); RecoverableTransactionIdentifier gtx = (RecoverableTransactionIdentifier) next.getGlobalTransaction(); if (xid.equals(gtx.getXid())) { it.remove(); recalculateMinTopologyIdIfNeeded(next); next.notifyOnTransactionFinished(); return next; } } } return null; }
/** * Preconditions: 1. flags must be one of TMNOFLAGS, TMRESUME or TMJOIN 2. xid != null 3. * connection must not be associated with a transaction 4. the TM hasn't seen the xid before * * <p>Implementation deficiency preconditions: 1. TMRESUME not supported. 2. if flags is TMJOIN, * we must be in ended state, and xid must be the current transaction 3. unless flags is TMJOIN, * previous transaction using the connection must be committed or prepared or rolled back * * <p>Postconditions: 1. Connection is associated with the transaction */ public void start(Xid xid, int flags) throws XAException { if (logger.logDebug()) debug("starting transaction xid = " + xid); // Check preconditions if (flags != XAResource.TMNOFLAGS && flags != XAResource.TMRESUME && flags != XAResource.TMJOIN) throw new PGXAException(GT.tr("Invalid flags"), XAException.XAER_INVAL); if (xid == null) throw new PGXAException(GT.tr("xid must not be null"), XAException.XAER_INVAL); if (state == STATE_ACTIVE) throw new PGXAException( GT.tr("Connection is busy with another transaction"), XAException.XAER_PROTO); // We can't check precondition 4 easily, so we don't. Duplicate xid will be catched in prepare // phase. // Check implementation deficiency preconditions if (flags == TMRESUME) throw new PGXAException(GT.tr("suspend/resume not implemented"), XAException.XAER_RMERR); // It's ok to join an ended transaction. WebLogic does that. if (flags == TMJOIN) { if (state != STATE_ENDED) throw new PGXAException( GT.tr("Transaction interleaving not implemented"), XAException.XAER_RMERR); if (!xid.equals(currentXid)) throw new PGXAException( GT.tr("Transaction interleaving not implemented"), XAException.XAER_RMERR); } else if (state == STATE_ENDED) throw new PGXAException( GT.tr("Transaction interleaving not implemented"), XAException.XAER_RMERR); try { localAutoCommitMode = conn.getAutoCommit(); conn.setAutoCommit(false); } catch (SQLException ex) { throw new PGXAException(GT.tr("Error disabling autocommit"), ex, XAException.XAER_RMERR); } // Preconditions are met, Associate connection with the transaction state = STATE_ACTIVE; currentXid = xid; }
/** * Preconditions: 1. xid != null 2. xid is in ended state * * <p>Implementation deficiency preconditions: 1. xid was associated with this connection * * <p>Postconditions: 1. Transaction is prepared */ public int prepare(Xid xid) throws XAException { if (logger.logDebug()) debug("preparing transaction xid = " + xid); // Check preconditions if (!currentXid.equals(xid)) { throw new PGXAException( GT.tr( "Not implemented: Prepare must be issued using the same connection that started the transaction"), XAException.XAER_RMERR); } if (state != STATE_ENDED) throw new PGXAException(GT.tr("Prepare called before end"), XAException.XAER_INVAL); state = STATE_IDLE; currentXid = null; if (!conn.haveMinimumServerVersion("8.1")) throw new PGXAException( GT.tr("Server versions prior to 8.1 do not support two-phase commit."), XAException.XAER_RMERR); try { String s = RecoveredXid.xidToString(xid); Statement stmt = conn.createStatement(); try { stmt.executeUpdate("PREPARE TRANSACTION '" + s + "'"); } finally { stmt.close(); } conn.setAutoCommit(localAutoCommitMode); return XA_OK; } catch (SQLException ex) { throw new PGXAException(GT.tr("Error preparing transaction"), ex, XAException.XAER_RMERR); } }