use of com.arjuna.ats.internal.jta.xa.XID in project narayana by jbosstm.
the class XATxConverter method getXid.
private static XID getXid(Uid uid, Uid branch, int formatId, Integer eisName) throws IllegalStateException {
if (uid == null) {
throw new IllegalStateException();
}
XID xid = new XID();
xid.formatID = formatId;
// gtrid is uid byte form followed by as many chars of the node name as will fit.
byte[] gtridUid = uid.getBytes();
if (gtridUid.length > XID.MAXGTRIDSIZE) {
// Uid is too long!!!!
throw new IllegalStateException();
}
String nodeName = TxControl.getXANodeName();
if (nodeName == null) {
throw new IllegalStateException(jtaLogger.i18NLogger.get_nodename_null());
}
int nodeNameLengthToUse = nodeName.getBytes(StandardCharsets.UTF_8).length;
xid.gtrid_length = gtridUid.length + nodeNameLengthToUse;
// src, srcPos, dest, destPos, length
System.arraycopy(gtridUid, 0, xid.data, 0, gtridUid.length);
System.arraycopy(nodeName.getBytes(StandardCharsets.UTF_8), 0, xid.data, gtridUid.length, nodeNameLengthToUse);
if (branch.notEquals(Uid.nullUid())) {
// bqual is uid byte form plus EIS name.
byte[] bqualUid = branch.getBytes();
if (bqualUid.length > XID.MAXBQUALSIZE) {
// Uid is too long!!!!
throw new IllegalStateException();
}
int spareBqualBytes = XID.MAXBQUALSIZE - (bqualUid.length + 4);
xid.bqual_length = bqualUid.length + 4 + 4;
// src, srcPos, dest, destPos, length
int offset = xid.gtrid_length;
System.arraycopy(bqualUid, 0, xid.data, offset, bqualUid.length);
setEisName(xid, eisName);
} else {
/*
* Note: for some dbs we seem to be able to get
* away with setting the size field to the size
* of the actual branch. However, for Oracle,
* it appears as though it must always be 64.
* (At least for zero branches.)
*/
xid.data[xid.gtrid_length] = (byte) 0;
xid.bqual_length = 64;
}
return xid;
}
use of com.arjuna.ats.internal.jta.xa.XID in project narayana by jbosstm.
the class XidImple method copy.
public final void copy(Xid xid) {
_theXid = new XID();
if (xid != null) {
if (xid instanceof XidImple)
_theXid.copy(((XidImple) xid)._theXid);
else {
_theXid.formatID = xid.getFormatId();
byte[] gtx = xid.getGlobalTransactionId();
byte[] bql = xid.getBranchQualifier();
final int bqlength = (bql == null ? 0 : bql.length);
_theXid.gtrid_length = gtx.length;
_theXid.bqual_length = bqlength;
System.arraycopy(gtx, 0, _theXid.data, 0, gtx.length);
if (bqlength > 0) {
System.arraycopy(bql, 0, _theXid.data, gtx.length, bql.length);
}
}
}
}
use of com.arjuna.ats.internal.jta.xa.XID in project narayana by jbosstm.
the class CommitMarkableResourceRecordRecoveryModule method delete.
private void delete(String jndiName, List<Xid> completedXids) {
int batchSize = jtaEnvironmentBean.getCommitMarkableResourceRecordDeleteBatchSize();
Integer integer = jtaEnvironmentBean.getCommitMarkableResourceRecordDeleteBatchSizeMap().get(jndiName);
if (integer != null) {
batchSize = integer;
}
try {
while (completedXids.size() > 0) {
int sendingSize = batchSize < 0 ? completedXids.size() : completedXids.size() < batchSize ? completedXids.size() : batchSize;
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < sendingSize; i++) {
buffer.append("?,");
}
if (buffer.length() > 0) {
Connection connection = null;
DataSource dataSource = (DataSource) context.lookup(jndiName);
try {
connection = dataSource.getConnection();
connection.setAutoCommit(false);
String tableName = commitMarkableResourceTableNameMap.get(jndiName);
if (tableName == null) {
tableName = defaultTableName;
}
String sql = "DELETE from " + tableName + " where xid in (" + buffer.substring(0, buffer.length() - 1) + ")";
if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("Attempting to delete number of entries: " + buffer.length());
}
PreparedStatement prepareStatement = connection.prepareStatement(sql);
List<Xid> deleted = new ArrayList<Xid>();
try {
for (int i = 0; i < sendingSize; i++) {
XidImple xid = (XidImple) completedXids.remove(0);
deleted.add(xid);
XID toSave = xid.getXID();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeInt(toSave.formatID);
dos.writeInt(toSave.gtrid_length);
dos.writeInt(toSave.bqual_length);
dos.writeInt(toSave.data.length);
dos.write(toSave.data);
dos.flush();
prepareStatement.setBytes(i + 1, baos.toByteArray());
}
int executeUpdate = prepareStatement.executeUpdate();
if (executeUpdate != sendingSize) {
tsLogger.logger.error("Update was not successful, expected: " + sendingSize + " actual:" + executeUpdate);
connection.rollback();
} else {
connection.commit();
committedXidsToJndiNames.keySet().removeAll(deleted);
}
} catch (IOException e) {
tsLogger.logger.warn("Could not generate prepareStatement paramaters", e);
} finally {
try {
prepareStatement.close();
} catch (SQLException e) {
tsLogger.logger.warn("Could not close the prepared statement", e);
}
}
} catch (SQLException e) {
tsLogger.logger.warn("Could not handle the connection", e);
// the connection is unavailable so try again later
break;
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
tsLogger.logger.warn("Could not close the connection", e);
}
}
}
}
}
} catch (NamingException e) {
tsLogger.logger.warn("Could not lookup commitMarkable: " + jndiName);
tsLogger.logger.debug("Could not lookup commitMarkable: " + jndiName, e);
} catch (IllegalStateException e) {
// Thrown when AS is shutting down and we attempt a lookup
tsLogger.logger.debug("Could not lookup datasource, AS is shutting down: " + e.getMessage(), e);
}
}
use of com.arjuna.ats.internal.jta.xa.XID in project narayana by jbosstm.
the class CommitMarkableResourceRecord method topLevelPrepare.
/**
* This will add the required recovery data about this resource into the
* resources preparedConnection. If the preparedConnection is in read only
* mode, we do not need to persist this information.
*/
public int topLevelPrepare() {
if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("CommitMarkableResourceRecord.topLevelPrepare for " + this + ", record id=" + order());
}
try {
PreparedStatement prepareStatement = null;
preparedConnection = (Connection) connectableResource.getConnection();
try {
prepareStatement = preparedConnection.prepareStatement("insert into " + tableName + " (xid, transactionManagerID, actionuid) values (?,?,?)");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
XID toSave = ((XidImple) xid).getXID();
dos.writeInt(toSave.formatID);
dos.writeInt(toSave.gtrid_length);
dos.writeInt(toSave.bqual_length);
dos.writeInt(toSave.data.length);
dos.write(toSave.data);
dos.flush();
prepareStatement.setBytes(1, baos.toByteArray());
prepareStatement.setString(2, TxControl.getXANodeName());
prepareStatement.setBytes(3, basicAction.get_uid().getBytes());
if (prepareStatement.executeUpdate() != 1) {
tsLogger.logger.warn("Update was not successful");
removeConnection();
return TwoPhaseOutcome.PREPARE_NOTOK;
}
} finally {
if (prepareStatement != null)
prepareStatement.close();
}
return TwoPhaseOutcome.PREPARE_OK;
} catch (Throwable t) {
tsLogger.logger.error("Could not add recovery data to the 1PC resource", t);
return TwoPhaseOutcome.PREPARE_NOTOK;
}
}
use of com.arjuna.ats.internal.jta.xa.XID in project narayana by jbosstm.
the class CommitMarkableResourceRecordRecoveryModule method periodicWorkFirstPass.
@Override
public synchronized void periodicWorkFirstPass() {
if (inFirstPass) {
return;
}
inFirstPass = true;
// TODO - this is one shot only due to a
// remove in the function, if this delete fails only normal
// recovery is possible
Map<String, List<Xid>> completedBranches2 = new HashMap<String, List<Xid>>();
synchronized (completedBranches) {
completedBranches2.putAll(completedBranches);
completedBranches.clear();
}
for (Map.Entry<String, List<Xid>> e : completedBranches2.entrySet()) delete(e.getKey(), e.getValue());
if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("CommitMarkableResourceRecordRecoveryModule::periodicWorkFirstPass");
}
this.committedXidsToJndiNames.clear();
this.queriedResourceManagers.clear();
this.jndiNamesToPossibleXidsForGC.clear();
// committed
try {
Iterator<String> iterator = jndiNamesToContact.iterator();
while (iterator.hasNext()) {
String jndiName = iterator.next();
try {
if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("CommitMarkableResourceRecordRecoveryModule::connecting to: " + jndiName);
}
DataSource dataSource = (DataSource) context.lookup(jndiName);
Connection connection = dataSource.getConnection();
try {
Statement createStatement = connection.createStatement();
try {
String tableName = commitMarkableResourceTableNameMap.get(jndiName);
if (tableName == null) {
tableName = defaultTableName;
}
ResultSet rs = createStatement.executeQuery("SELECT xid,actionuid from " + tableName + whereFilter);
try {
int i = 0;
while (rs.next()) {
i++;
byte[] xidAsBytes = rs.getBytes(1);
ByteArrayInputStream bais = new ByteArrayInputStream(xidAsBytes);
DataInputStream dis = new DataInputStream(bais);
XID _theXid = new XID();
_theXid.formatID = dis.readInt();
_theXid.gtrid_length = dis.readInt();
_theXid.bqual_length = dis.readInt();
int dataLength = dis.readInt();
_theXid.data = new byte[dataLength];
dis.read(_theXid.data, 0, dataLength);
XidImple xid = new XidImple(_theXid);
byte[] actionuidAsBytes = new byte[Uid.UID_SIZE];
byte[] bytes = rs.getBytes(2);
System.arraycopy(bytes, 0, actionuidAsBytes, 0, bytes.length);
committedXidsToJndiNames.put(xid, jndiName);
if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("committedXidsToJndiNames.put" + xid + " " + jndiName);
}
// Populate the map of possible GCable Xids
Uid actionuid = new Uid(actionuidAsBytes);
Map<Xid, Uid> map = jndiNamesToPossibleXidsForGC.get(jndiName);
if (map == null) {
map = new HashMap<Xid, Uid>();
jndiNamesToPossibleXidsForGC.put(jndiName, map);
}
map.put(xid, actionuid);
}
} finally {
try {
rs.close();
} catch (SQLException e) {
tsLogger.logger.warn("Could not close resultset", e);
}
}
} finally {
try {
createStatement.close();
} catch (SQLException e) {
tsLogger.logger.warn("Could not close statement", e);
}
}
queriedResourceManagers.add(jndiName);
} finally {
try {
connection.close();
} catch (SQLException e) {
tsLogger.logger.warn("Could not close connection", e);
}
}
} catch (NamingException e) {
tsLogger.logger.debug("Could not lookup CommitMarkableResource: " + jndiName, e);
} catch (SQLException e) {
tsLogger.logger.warn("Could not handle connection", e);
} catch (IOException e) {
tsLogger.logger.warn("Could not lookup write data to select", e);
}
}
// reference
try {
InputObjectState uidList = new InputObjectState();
recoveryStore.allObjUids(CONNECTABLE_ATOMIC_ACTION_TYPE, uidList);
Uid currentUid = UidHelper.unpackFrom(uidList);
while (Uid.nullUid().notEquals(currentUid)) {
// Make sure it isn't garbage from a failure to move before:
InputObjectState state = recoveryStore.read_committed(currentUid, ATOMIC_ACTION_TYPE);
if (state != null) {
if (!recoveryStore.remove_committed(currentUid, CONNECTABLE_ATOMIC_ACTION_TYPE)) {
tsLogger.logger.debug("Could not remove a: " + CONNECTABLE_ATOMIC_ACTION_TYPE + " uid: " + currentUid);
}
} else {
state = recoveryStore.read_committed(currentUid, CONNECTABLE_ATOMIC_ACTION_TYPE);
// TX may have been in progress and cleaned up by now
if (state != null) {
RecoverConnectableAtomicAction rcaa = new RecoverConnectableAtomicAction(CONNECTABLE_ATOMIC_ACTION_TYPE, currentUid, state);
if (rcaa.containsIncompleteCommitMarkableResourceRecord()) {
String commitMarkableResourceJndiName = rcaa.getCommitMarkableResourceJndiName();
// Check if the resource manager is online yet
if (queriedResourceManagers.contains(commitMarkableResourceJndiName)) {
// If it is remove the CRR and move it back and
// let
// the
// next stage update it
moveRecord(currentUid, CONNECTABLE_ATOMIC_ACTION_TYPE, ATOMIC_ACTION_TYPE);
}
} else {
if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("Moving " + currentUid + " back to being an AA");
}
// It is now safe to move it back to being an AA so that it can call getNewXAResourceRecord
moveRecord(currentUid, CONNECTABLE_ATOMIC_ACTION_TYPE, ATOMIC_ACTION_TYPE);
}
}
}
currentUid = UidHelper.unpackFrom(uidList);
}
} catch (ObjectStoreException | IOException ex) {
tsLogger.logger.warn("Could not query objectstore: ", ex);
}
// moved in stage 2
if (tsLogger.logger.isDebugEnabled()) {
tsLogger.logger.debug("processing " + ATOMIC_ACTION_TYPE + " transactions");
}
try {
InputObjectState uidList = new InputObjectState();
recoveryStore.allObjUids(ATOMIC_ACTION_TYPE, uidList);
Uid currentUid = UidHelper.unpackFrom(uidList);
while (Uid.nullUid().notEquals(currentUid)) {
// process.
if (!isTransactionInMidFlight(transactionStatusConnectionMgr.getTransactionStatus(ATOMIC_ACTION_TYPE, currentUid))) {
InputObjectState state = recoveryStore.read_committed(currentUid, ATOMIC_ACTION_TYPE);
if (state != null) {
// Try to load it is a BasicAction that has a
// ConnectedResourceRecord
RecoverConnectableAtomicAction rcaa = new RecoverConnectableAtomicAction(ATOMIC_ACTION_TYPE, currentUid, state);
// Check if it did have a ConnectedResourceRecord
if (rcaa.containsIncompleteCommitMarkableResourceRecord()) {
String commitMarkableResourceJndiName = rcaa.getCommitMarkableResourceJndiName();
// online
if (!queriedResourceManagers.contains(commitMarkableResourceJndiName)) {
// If the resource manager wasn't online, move
// it
moveRecord(currentUid, ATOMIC_ACTION_TYPE, CONNECTABLE_ATOMIC_ACTION_TYPE);
} else {
// Update the completed outcome for the 1PC
// resource
rcaa.updateCommitMarkableResourceRecord(committedXidsToJndiNames.get(rcaa.getXid()) != null);
// Swap the type to avoid the rest of recovery round processing this TX as it already called getNewXAResourceRecord
moveRecord(currentUid, ATOMIC_ACTION_TYPE, CONNECTABLE_ATOMIC_ACTION_TYPE);
}
}
}
}
currentUid = UidHelper.unpackFrom(uidList);
}
} catch (ObjectStoreException | IOException ex) {
tsLogger.logger.warn("Could not query objectstore: ", ex);
}
} catch (IllegalStateException e) {
// Thrown when AS is shutting down and we attempt a lookup
tsLogger.logger.debug("Could not lookup datasource, AS is shutting down: " + e.getMessage(), e);
}
inFirstPass = false;
}
Aggregations