Search in sources :

Example 1 with ClusterTransaction

use of com.sun.messaging.jmq.jmsserver.data.ClusterTransaction in project openmq by eclipse-ee4j.

the class TransactionHandler method doRemotePrepare.

private ClusterTransaction doRemotePrepare(TransactionList translist, TransactionUID id, TransactionState nextState, TransactionWork txnWork) throws BrokerException {
    if (nextState.getState() != TransactionState.PREPARED) {
        throw new BrokerException("Unexpected state " + nextState + " for transactionID:" + id);
    }
    HashMap[] rets = retrieveConsumedRemoteMessages(translist, id, false);
    if (DEBUG_CLUSTER_TXN) {
        logger.log(logger.INFO, "doRemotePrepare(" + translist + ", " + id + "): retrievedConsumedRemoteMsgs:" + (rets == null ? "null" : rets[0] + ", " + rets[1]));
    }
    if (fi.FAULT_INJECTION) {
        if (fi.checkFault(fi.FAULT_MSG_REMOTE_ACK_C_TXNPREPARE_0_5, null)) {
            fi.unsetFault(fi.FAULT_MSG_REMOTE_ACK_C_TXNPREPARE_0_5);
            throw new BrokerException(fi.FAULT_MSG_REMOTE_ACK_C_TXNPREPARE_0_5);
        }
    }
    if (rets == null) {
        return null;
    }
    if (Globals.getClusterBroadcast().getClusterVersion() < ClusterBroadcast.VERSION_410) {
        return null;
    }
    HashMap<BrokerAddress, ArrayList[]> bmmap = rets[0];
    TransactionBroker[] tranbas = (TransactionBroker[]) rets[1].keySet().toArray(new TransactionBroker[rets[1].size()]);
    BrokerAddress[] bas = bmmap.keySet().toArray(new BrokerAddress[bmmap.size()]);
    boolean persist = true;
    ClusterTransaction clusterTransaction = null;
    if (Globals.isNewTxnLogEnabled()) {
        // create a cluster transaction which will be logged
        clusterTransaction = new ClusterTransaction(id, nextState, txnWork, tranbas);
        translist.logClusterTransaction(id, nextState, tranbas, true, persist, clusterTransaction);
    } else {
        translist.logClusterTransaction(id, nextState, tranbas, true, persist);
    }
    if (DEBUG_CLUSTER_TXN) {
        StringBuilder buf = new StringBuilder();
        buf.append("Preparing transaction ").append(id).append(", brokers");
        for (TransactionBroker tranba : tranbas) {
            buf.append("\n\t").append(tranba);
        }
        logger.log(logger.INFO, buf.toString());
    }
    UID tranpid = null;
    if (Globals.getDestinationList().isPartitionMode()) {
        tranpid = translist.getPartitionedStore().getPartitionID();
        ArrayList<TransactionAcknowledgement> mcl = null;
        TransactionBroker tba = null;
        UID tbapid = null;
        TransactionAcknowledgement[] tas = null;
        TransactionList tl = null;
        for (int i = 0; i < tranbas.length; i++) {
            tba = tranbas[i];
            if (!tba.getBrokerAddress().equals(Globals.getMyAddress())) {
                continue;
            }
            tbapid = tba.getBrokerAddress().getStoreSessionUID();
            if (tbapid.equals(tranpid)) {
                continue;
            }
            mcl = (ArrayList<TransactionAcknowledgement>) rets[1].get(tba);
            tas = mcl.toArray(new TransactionAcknowledgement[mcl.size()]);
            tl = TransactionList.getTransListByPartitionID(tbapid);
            if (tl == null) {
                throw new BrokerException("Can't prepare transaction " + id + " because " + "transaction list for partition " + tbapid + " not found");
            }
            BrokerAddress home = (BrokerAddress) Globals.getMyAddress().clone();
            home.setStoreSessionUID(tranpid);
            tl.logLocalRemoteTransaction(id, nextState, tas, home, false, true, persist);
        }
    }
    // handle remote brokers
    ArrayList[] mcll = null;
    BrokerAddress ba = null;
    for (int i = 0; i < bas.length; i++) {
        ba = bas[i];
        if (ba == Globals.getMyAddress() || ba.equals(Globals.getMyAddress())) {
            continue;
        }
        mcll = bmmap.get(ba);
        try {
            Globals.getClusterBroadcast().acknowledgeMessage2P(ba, (SysMessageID[]) mcll[0].toArray(new SysMessageID[mcll[0].size()]), (ConsumerUID[]) mcll[1].toArray(new ConsumerUID[mcll[1].size()]), ClusterBroadcast.MSG_PREPARE, null, Long.valueOf(id.longValue()), tranpid, true, false);
        } catch (BrokerException e) {
            if (!(e instanceof BrokerDownException) && !(e instanceof AckEntryNotFoundException)) {
                throw e;
            }
            HashMap sToCmap = translist.retrieveStoredConsumerUIDs(id);
            ArrayList remoteConsumerUIDa = new ArrayList();
            StringBuilder remoteConsumerUIDs = new StringBuilder();
            String uidstr = null;
            StringBuilder debugbuf = new StringBuilder();
            for (int j = 0; j < mcll[0].size(); j++) {
                SysMessageID sysid = (SysMessageID) mcll[0].get(j);
                ConsumerUID uid = (ConsumerUID) mcll[1].get(j);
                ConsumerUID suid = (ConsumerUID) sToCmap.get(uid);
                if (suid == null || suid.equals(uid)) {
                    continue;
                }
                if (e.isRemote()) {
                    uidstr = String.valueOf(uid.longValue());
                    if (!remoteConsumerUIDa.contains(uidstr)) {
                        remoteConsumerUIDa.add(uidstr);
                        remoteConsumerUIDs.append(uidstr);
                        remoteConsumerUIDs.append(' ');
                        Consumer c = Consumer.getConsumer(uid);
                        if (c != null) {
                            c.recreationRequested();
                        } else {
                            logger.log(logger.WARNING, "Consumer " + uid + " not found in processing remote exception on preparing transaction " + id);
                        }
                    }
                }
                debugbuf.append("\n\t[").append(sysid).append(':').append(uid).append(']');
            }
            if (e.isRemote()) {
                e.setRemoteConsumerUIDs(remoteConsumerUIDs.toString());
                if (DEBUG_CLUSTER_TXN) {
                    logger.log(logger.INFO, "doRemotePrepare: JMQRemote Exception:remoteConsumerUIDs=" + remoteConsumerUIDs + ", remote broker " + ba);
                }
            }
            try {
                translist.updateState(id, TransactionState.FAILED, false, TransactionState.PREPARED, true);
            } catch (Exception ex) {
                logger.logStack(logger.WARNING, "Unable to update transaction " + id + " state to FAILED on PREPARE failure from " + ba + ": " + ex.getMessage() + debugbuf.toString(), ex);
                throw e;
            }
            if (e instanceof AckEntryNotFoundException) {
                mcll = ((AckEntryNotFoundException) e).getAckEntries();
            }
            for (int j = 0; j < mcll[0].size(); j++) {
                SysMessageID sysid = (SysMessageID) mcll[0].get(j);
                ConsumerUID uid = (ConsumerUID) mcll[1].get(j);
                boolean remove = true;
                if (e instanceof BrokerDownException) {
                    ConsumerUID suid = (ConsumerUID) sToCmap.get(uid);
                    if (suid == null || suid.equals(uid)) {
                        if (DEBUG_CLUSTER_TXN) {
                            logger.log(logger.INFO, "doRemotePrepare: no remove txnack " + sysid + ", " + uid + " for BrokerDownException from " + ba);
                        }
                        remove = false;
                    }
                }
                if (remove) {
                    try {
                        translist.removeAcknowledgement(id, sysid, uid, (e instanceof AckEntryNotFoundException));
                        if (DEBUG_CLUSTER_TXN) {
                            logger.log(logger.INFO, "doRemotePrepare: removed txnack " + sysid + ", " + uid + " for BrokerDownException from " + ba);
                        }
                    } catch (Exception ex) {
                        logger.logStack(logger.WARNING, "Unable to remove transaction " + id + " ack [" + sysid + ":" + uid + "] on PREPARE failure from " + ba + ": " + ex.getMessage(), ex);
                    }
                }
            }
            logger.log(logger.WARNING, "Preparing transaction " + id + " failed from " + ba + ": " + e.getMessage() + debugbuf.toString());
            throw e;
        }
    }
    return clusterTransaction;
}
Also used : BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) HashMap(java.util.HashMap) CacheHashMap(com.sun.messaging.jmq.util.CacheHashMap) ArrayList(java.util.ArrayList) ClusterTransaction(com.sun.messaging.jmq.jmsserver.data.ClusterTransaction) Consumer(com.sun.messaging.jmq.jmsserver.core.Consumer) AckEntryNotFoundException(com.sun.messaging.jmq.jmsserver.util.AckEntryNotFoundException) BrokerDownException(com.sun.messaging.jmq.jmsserver.util.BrokerDownException) TransactionAcknowledgement(com.sun.messaging.jmq.jmsserver.data.TransactionAcknowledgement) ConsumerUID(com.sun.messaging.jmq.jmsserver.core.ConsumerUID) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList) BrokerAddress(com.sun.messaging.jmq.jmsserver.core.BrokerAddress) BrokerDownException(com.sun.messaging.jmq.jmsserver.util.BrokerDownException) SelectorFormatException(com.sun.messaging.jmq.util.selector.SelectorFormatException) IOException(java.io.IOException) AckEntryNotFoundException(com.sun.messaging.jmq.jmsserver.util.AckEntryNotFoundException) MaxConsecutiveRollbackException(com.sun.messaging.jmq.jmsserver.util.MaxConsecutiveRollbackException) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) ConsumerUID(com.sun.messaging.jmq.jmsserver.core.ConsumerUID) DestinationUID(com.sun.messaging.jmq.jmsserver.core.DestinationUID) UID(com.sun.messaging.jmq.util.UID) TransactionUID(com.sun.messaging.jmq.jmsserver.data.TransactionUID) TransactionBroker(com.sun.messaging.jmq.jmsserver.data.TransactionBroker) SysMessageID(com.sun.messaging.jmq.io.SysMessageID)

Example 2 with ClusterTransaction

use of com.sun.messaging.jmq.jmsserver.data.ClusterTransaction in project openmq by eclipse-ee4j.

the class ClusterTransaction2PCompleteEvent method readFromBytes.

@Override
void readFromBytes(byte[] data) throws IOException, BrokerException {
    ByteArrayInputStream bais = new ByteArrayInputStream(data);
    DataInputStream dis = new DataInputStream(bais);
    clusterTransaction = new ClusterTransaction();
    dis.skip(2);
    clusterTransaction.getTransactionDetails().readContent(dis);
    dis.close();
    bais.close();
}
Also used : ByteArrayInputStream(java.io.ByteArrayInputStream) DataInputStream(java.io.DataInputStream) ClusterTransaction(com.sun.messaging.jmq.jmsserver.data.ClusterTransaction)

Example 3 with ClusterTransaction

use of com.sun.messaging.jmq.jmsserver.data.ClusterTransaction in project openmq by eclipse-ee4j.

the class ClusterTransaction2PPrepareEvent method readFromBytes.

@Override
public void readFromBytes(byte[] data) throws IOException, BrokerException {
    if (Store.getDEBUG()) {
        Globals.getLogger().log(Logger.DEBUG, getPrefix() + "readFromBytes");
    }
    ByteArrayInputStream bais = new ByteArrayInputStream(data);
    DataInputStream dis = new DataInputStream(bais);
    clusterTransaction = new ClusterTransaction();
    dis.skip(2);
    clusterTransaction.getTransactionDetails().readContent(dis);
    if (Store.getDEBUG()) {
        Globals.getLogger().log(Logger.DEBUG, getPrefix() + "read details " + clusterTransaction.getTransactionDetails());
    }
    TransactionWork work = new TransactionWork();
    work.readWork(dis);
    clusterTransaction.setTransactionWork(work);
    int objectBodySize = dis.readInt();
    byte[] objectBody = new byte[objectBodySize];
    dis.read(objectBody);
    ByteArrayInputStream bais2 = new ByteArrayInputStream(objectBody);
    ObjectInputStream ois = new FilteringObjectInputStream(bais2);
    try {
        clusterTransaction.setTransactionState((TransactionState) ois.readObject());
        clusterTransaction.setTransactionBrokers((TransactionBroker[]) ois.readObject());
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    ois.close();
    bais2.close();
    dis.close();
    bais.close();
}
Also used : TransactionWork(com.sun.messaging.jmq.jmsserver.data.TransactionWork) ByteArrayInputStream(java.io.ByteArrayInputStream) TransactionBroker(com.sun.messaging.jmq.jmsserver.data.TransactionBroker) FilteringObjectInputStream(com.sun.messaging.jmq.util.io.FilteringObjectInputStream) DataInputStream(java.io.DataInputStream) ClusterTransaction(com.sun.messaging.jmq.jmsserver.data.ClusterTransaction) FilteringObjectInputStream(com.sun.messaging.jmq.util.io.FilteringObjectInputStream) ObjectInputStream(java.io.ObjectInputStream)

Example 4 with ClusterTransaction

use of com.sun.messaging.jmq.jmsserver.data.ClusterTransaction in project openmq by eclipse-ee4j.

the class ClusterTransactionManager method replayTransactionEvent.

@Override
void replayTransactionEvent(TransactionEvent txnEvent, HashSet dstLoadedSet) throws BrokerException, IOException {
    if (Store.getDEBUG()) {
        Globals.getLogger().log(Logger.DEBUG, getPrefix() + " replayTransactionEvent");
    }
    ClusterTransactionEvent clusterTxnEvent = (ClusterTransactionEvent) txnEvent;
    // replay to store on commit
    ClusterTransaction clusterTxn = clusterTxnEvent.clusterTransaction;
    int state = clusterTxn.getState();
    TransactionUID tid = clusterTxn.getTid();
    if (clusterTxnEvent.getSubType() == ClusterTransactionEvent.Type2PPrepareEvent) {
        // in prepared txn store and resetting the transaction log
        if (incompleteStored.containsKey(tid)) {
            if (Store.getDEBUG()) {
                String msg = getPrefix() + " found matching txn in prepared store on replay " + clusterTxn;
                Globals.getLogger().log(Logger.DEBUG, msg);
            }
        } else {
            addToIncompleteUnstored(clusterTxn);
        }
    } else if (clusterTxnEvent.getSubType() == ClusterTransactionEvent.Type2PCompleteEvent) {
        // we are completing a transaction
        // the transaction could be
        // a) unstored (prepare replayed earlier)
        // b) stored incomplete (prepare occurred before last checkpoint,
        // completion not written to prepared store yet)
        // This should therefore be the last entry in log.
        // c) stored complete (prepare occurred before last checkpoint,
        // and failure occurred after completion stored in prepared store
        BaseTransaction existingWork = null;
        if (incompleteUnstored.containsKey(tid)) {
            // a) unstored (prepare replayed earlier)
            if (state == TransactionState.ROLLEDBACK) {
                existingWork = removeFromIncompleteUnstored(tid);
            } else if (state == TransactionState.COMMITTED) {
                existingWork = incompleteUnstored.get(tid);
                existingWork.getTransactionDetails().setState(state);
                existingWork.getTransactionState().setState(state);
            }
        } else if (incompleteStored.containsKey(tid)) {
            // b) stored incomplete (prepare occurred before last checkpoint,
            // completion not written to prepared store yet)
            existingWork = removeFromIncompleteStored(tid);
            updateStoredState(tid, state);
            addToCompleteStored(existingWork);
        } else if (completeStored.containsKey(tid)) {
            // c) stored complete (prepare occurred before last checkpoint,
            // and failure occurred after completion stored in prepared store
            existingWork = completeStored.get(tid);
        }
        if (existingWork != null) {
            if (state == TransactionState.COMMITTED) {
                transactionLogManager.transactionLogReplayer.replayTransactionWork(existingWork.getTransactionWork(), tid, dstLoadedSet);
            }
        } else {
            logger.log(Logger.ERROR, "Could not find prepared work for completing two-phase transaction " + clusterTxn.getTid());
        }
    }
}
Also used : TransactionUID(com.sun.messaging.jmq.jmsserver.data.TransactionUID) BaseTransaction(com.sun.messaging.jmq.jmsserver.data.BaseTransaction) ClusterTransaction(com.sun.messaging.jmq.jmsserver.data.ClusterTransaction)

Example 5 with ClusterTransaction

use of com.sun.messaging.jmq.jmsserver.data.ClusterTransaction in project openmq by eclipse-ee4j.

the class ClusterTransactionManager method updateTransactionBrokerState.

void updateTransactionBrokerState(TransactionUID tid, int expectedTxnState, TransactionBroker txnBkr, boolean sync) throws BrokerException {
    if (Store.getDEBUG()) {
        String msg = getPrefix() + " updateTransactionBrokerState: tx = " + tid + " txnBkr=" + txnBkr;
        Globals.getLogger().log(Logger.DEBUG, msg);
    }
    // store txnBroker state update in txn log
    // if txn is complete then mark this also
    // clustered txnUpdate record
    // TO DO
    // first look in unstored
    ClusterTransaction clusterTxn = null;
    boolean stored = false;
    clusterTxn = (ClusterTransaction) incompleteUnstored.get(tid);
    if (clusterTxn == null) {
        clusterTxn = (ClusterTransaction) incompleteStored.get(tid);
        if (clusterTxn != null) {
            stored = true;
        }
    }
    if (clusterTxn != null) {
        boolean allComplete = updateTransactionBrokerState(txnBkr, clusterTxn);
        if (Store.getDEBUG()) {
            Globals.getLogger().log(Logger.DEBUG, getPrefix() + " allComplete:  = " + allComplete);
        }
        if (allComplete) {
            clusterTxn.getTransactionDetails().setComplete(true);
            if (!stored) {
                removeFromIncompleteUnstored(tid);
            } else {
                removeFromIncompleteStored(tid);
                addToCompleteStored(clusterTxn);
                try {
                    this.updateStoredCompletion(tid, true);
                } catch (IOException ioe) {
                    throw new BrokerException("Could not update completion state of stored cluster transaction " + tid, ioe);
                }
            }
        }
    } else {
        logger.log(Logger.ERROR, "Could not find matching cluster transaction for " + tid);
    }
}
Also used : BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) IOException(java.io.IOException) ClusterTransaction(com.sun.messaging.jmq.jmsserver.data.ClusterTransaction)

Aggregations

ClusterTransaction (com.sun.messaging.jmq.jmsserver.data.ClusterTransaction)5 TransactionBroker (com.sun.messaging.jmq.jmsserver.data.TransactionBroker)2 TransactionUID (com.sun.messaging.jmq.jmsserver.data.TransactionUID)2 BrokerException (com.sun.messaging.jmq.jmsserver.util.BrokerException)2 ByteArrayInputStream (java.io.ByteArrayInputStream)2 DataInputStream (java.io.DataInputStream)2 IOException (java.io.IOException)2 SysMessageID (com.sun.messaging.jmq.io.SysMessageID)1 BrokerAddress (com.sun.messaging.jmq.jmsserver.core.BrokerAddress)1 Consumer (com.sun.messaging.jmq.jmsserver.core.Consumer)1 ConsumerUID (com.sun.messaging.jmq.jmsserver.core.ConsumerUID)1 DestinationUID (com.sun.messaging.jmq.jmsserver.core.DestinationUID)1 BaseTransaction (com.sun.messaging.jmq.jmsserver.data.BaseTransaction)1 TransactionAcknowledgement (com.sun.messaging.jmq.jmsserver.data.TransactionAcknowledgement)1 TransactionList (com.sun.messaging.jmq.jmsserver.data.TransactionList)1 TransactionWork (com.sun.messaging.jmq.jmsserver.data.TransactionWork)1 AckEntryNotFoundException (com.sun.messaging.jmq.jmsserver.util.AckEntryNotFoundException)1 BrokerDownException (com.sun.messaging.jmq.jmsserver.util.BrokerDownException)1 MaxConsecutiveRollbackException (com.sun.messaging.jmq.jmsserver.util.MaxConsecutiveRollbackException)1 CacheHashMap (com.sun.messaging.jmq.util.CacheHashMap)1