Search in sources :

Example 1 with XID

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;
}
Also used : XID(com.arjuna.ats.internal.jta.xa.XID)

Example 2 with 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);
            }
        }
    }
}
Also used : XID(com.arjuna.ats.internal.jta.xa.XID)

Example 3 with XID

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);
    }
}
Also used : XidImple(com.arjuna.ats.jta.xa.XidImple) SQLException(java.sql.SQLException) DataOutputStream(java.io.DataOutputStream) Connection(java.sql.Connection) ArrayList(java.util.ArrayList) PreparedStatement(java.sql.PreparedStatement) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) DataSource(javax.sql.DataSource) Xid(javax.transaction.xa.Xid) XID(com.arjuna.ats.internal.jta.xa.XID) NamingException(javax.naming.NamingException)

Example 4 with XID

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;
    }
}
Also used : XidImple(com.arjuna.ats.jta.xa.XidImple) XID(com.arjuna.ats.internal.jta.xa.XID) DataOutputStream(java.io.DataOutputStream) PreparedStatement(java.sql.PreparedStatement) ByteArrayOutputStream(java.io.ByteArrayOutputStream)

Example 5 with XID

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;
}
Also used : HashMap(java.util.HashMap) SQLException(java.sql.SQLException) ResultSet(java.sql.ResultSet) ArrayList(java.util.ArrayList) List(java.util.List) NamingException(javax.naming.NamingException) XidImple(com.arjuna.ats.jta.xa.XidImple) InputObjectState(com.arjuna.ats.arjuna.state.InputObjectState) ObjectStoreException(com.arjuna.ats.arjuna.exceptions.ObjectStoreException) PreparedStatement(java.sql.PreparedStatement) Statement(java.sql.Statement) Connection(java.sql.Connection) IOException(java.io.IOException) DataInputStream(java.io.DataInputStream) DataSource(javax.sql.DataSource) Uid(com.arjuna.ats.arjuna.common.Uid) Xid(javax.transaction.xa.Xid) XID(com.arjuna.ats.internal.jta.xa.XID) ByteArrayInputStream(java.io.ByteArrayInputStream) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

XID (com.arjuna.ats.internal.jta.xa.XID)8 XidImple (com.arjuna.ats.jta.xa.XidImple)6 Uid (com.arjuna.ats.arjuna.common.Uid)3 PreparedStatement (java.sql.PreparedStatement)3 ByteArrayOutputStream (java.io.ByteArrayOutputStream)2 DataOutputStream (java.io.DataOutputStream)2 IOException (java.io.IOException)2 Connection (java.sql.Connection)2 SQLException (java.sql.SQLException)2 ArrayList (java.util.ArrayList)2 NamingException (javax.naming.NamingException)2 DataSource (javax.sql.DataSource)2 Xid (javax.transaction.xa.Xid)2 Test (org.junit.Test)2 AtomicAction (com.arjuna.ats.arjuna.AtomicAction)1 ObjectStoreException (com.arjuna.ats.arjuna.exceptions.ObjectStoreException)1 InputObjectState (com.arjuna.ats.arjuna.state.InputObjectState)1 ByteArrayInputStream (java.io.ByteArrayInputStream)1 DataInputStream (java.io.DataInputStream)1 ResultSet (java.sql.ResultSet)1