Search in sources :

Example 1 with MaxConsecutiveRollbackException

use of com.sun.messaging.jmq.jmsserver.util.MaxConsecutiveRollbackException in project openmq by eclipse-ee4j.

the class TransactionHandler method sortPreprocessRetrievedMessages.

private HashMap sortPreprocessRetrievedMessages(Map cmap, Map sToCmap, boolean processActiveConsumers, int maxRollbacks, boolean dmqOnMaxRollbacks, TransactionUID tid) throws BrokerException {
    HashMap sendMap = new HashMap();
    // loop through the transaction ack list
    if (cmap != null && cmap.size() > 0) {
        Iterator itr = cmap.entrySet().iterator();
        while (itr.hasNext()) {
            Map.Entry entry = (Map.Entry) itr.next();
            SysMessageID sysid = (SysMessageID) entry.getKey();
            // CANT just pull from connection
            if (sysid == null) {
                continue;
            }
            PacketReference ref = DL.get(null, sysid, false);
            if (ref == null || ref.isDestroyed() || ref.isInvalid()) {
                // already been deleted .. ignore
                if (DEBUG) {
                    logger.log(logger.INFO, "redeliverUnacked:tid=" + tid + ": ref=" + ref + " already deleted");
                }
                continue;
            }
            if (ref.isOverrided()) {
                continue;
            }
            // now get the interests and stick each message
            // in a list specific to the consumer
            // the list is automatically sorted
            List interests = (List) entry.getValue();
            for (int i = 0; i < interests.size(); i++) {
                ConsumerUID intid = (ConsumerUID) interests.get(i);
                ConsumerUID stored = (ConsumerUID) sToCmap.get(intid);
                if (stored == null) {
                    stored = intid;
                }
                if (processActiveConsumers && !dmqOnMaxRollbacks) {
                    Consumer cs = Consumer.getConsumer(intid);
                    if (cs != null) {
                        if (!cs.addRollbackCnt(ref.getSysMessageID(), maxRollbacks)) {
                            Object[] args = { ref, cs, tid };
                            String emsg = br.getKString(br.X_MAX_ROLLBACKS_MSG_NO_ROLLBACK, args);
                            logger.log(logger.ERROR, emsg);
                            throw new MaxConsecutiveRollbackException(emsg);
                        }
                    }
                }
                SortedSet ss = (SortedSet) sendMap.get(intid);
                if (ss == null) {
                    ss = new TreeSet(new RefCompare());
                    sendMap.put(intid, ss);
                }
                ref.removeInDelivery(stored);
                ss.add(ref);
            }
        }
    }
    return sendMap;
}
Also used : HashMap(java.util.HashMap) CacheHashMap(com.sun.messaging.jmq.util.CacheHashMap) ConsumerUID(com.sun.messaging.jmq.jmsserver.core.ConsumerUID) MaxConsecutiveRollbackException(com.sun.messaging.jmq.jmsserver.util.MaxConsecutiveRollbackException) SortedSet(java.util.SortedSet) Consumer(com.sun.messaging.jmq.jmsserver.core.Consumer) PacketReference(com.sun.messaging.jmq.jmsserver.core.PacketReference) TreeSet(java.util.TreeSet) Iterator(java.util.Iterator) SysMessageID(com.sun.messaging.jmq.io.SysMessageID) DestinationList(com.sun.messaging.jmq.jmsserver.core.DestinationList) List(java.util.List) ArrayList(java.util.ArrayList) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList) Map(java.util.Map) HashMap(java.util.HashMap) CacheHashMap(com.sun.messaging.jmq.util.CacheHashMap)

Example 2 with MaxConsecutiveRollbackException

use of com.sun.messaging.jmq.jmsserver.util.MaxConsecutiveRollbackException in project openmq by eclipse-ee4j.

the class TransactionHandler method handle.

/**
 * Method to handle Transaction Messages
 */
@Override
public boolean handle(IMQConnection con, Packet msg) throws BrokerException {
    long messagetid = 0;
    TransactionUID id = null;
    TransactionState ts = null;
    JMQXid xid = null;
    Integer xaFlags = null;
    boolean redeliverMsgs = false;
    boolean startNextTransaction = false;
    boolean setRedeliverFlag = true;
    boolean isIndemp = msg.getIndempotent();
    boolean replay = false;
    boolean jmqonephase = false;
    Boolean jmqonephaseFlag = null;
    Hashtable props = null;
    String reason = null;
    TransactionList[] tls = Globals.getDestinationList().getTransactionList(con.getPartitionedStore());
    TransactionList translist = tls[0];
    try {
        props = msg.getProperties();
        if (props == null) {
            props = new Hashtable();
        }
    } catch (Exception ex) {
        logger.logStack(Logger.WARNING, "Unable to retrieve " + " properties from transaction message " + msg, ex);
        props = new Hashtable();
    }
    // performance optimisation:
    // start a new transaction immediately after commit or rollback and return
    // transactionID in message ack.
    // The client then does not need to make a separate call to startTransaction.
    Boolean startNextTransactionBool = (Boolean) props.get("JMQStartNextTransaction");
    startNextTransaction = startNextTransactionBool != null && startNextTransactionBool.booleanValue();
    Boolean redeliverMsgBool = (Boolean) props.get("JMQRedeliver");
    redeliverMsgs = redeliverMsgBool != null && redeliverMsgBool.booleanValue();
    Boolean b = (Boolean) props.get("JMQUpdateConsumed");
    boolean updateConsumed = b != null && b.booleanValue();
    Boolean redeliverFlag = (Boolean) props.get("JMQSetRedelivered");
    setRedeliverFlag = redeliverFlag == null || redeliverFlag.booleanValue();
    Integer maxRollbackFlag = (Integer) props.get("JMQMaxRollbacks");
    int maxRollbacks = (maxRollbackFlag == null ? -1 : maxRollbackFlag.intValue());
    /**
     * if dmqOnMaxRollbacks false, and max rollbacks reached, return error to client without rollback and without redelivery
     * any consumed messages
     */
    Boolean dmqOnMaxRollbacksFlag = (Boolean) props.get("JMQDMQOnMaxRollbacks");
    boolean dmqOnMaxRollbacks = dmqOnMaxRollbacksFlag != null && dmqOnMaxRollbacksFlag.booleanValue();
    if (maxRollbacks <= 0) {
        dmqOnMaxRollbacks = !(Consumer.MSG_MAX_CONSECUTIVE_ROLLBACKS <= 0);
    }
    jmqonephaseFlag = (Boolean) props.get("JMQXAOnePhase");
    jmqonephase = jmqonephaseFlag != null && jmqonephaseFlag.booleanValue();
    if (DEBUG) {
        logger.log(Logger.DEBUG, PacketType.getString(msg.getPacketType()) + ": " + "TUID=" + id + ", JMQRedeliver=" + redeliverMsgBool + (jmqonephaseFlag == null ? "" : ", JMQXAOnePhase=" + jmqonephase));
    }
    List conlist = (List) con.getClientData(IMQConnection.TRANSACTION_LIST);
    if (conlist == null) {
        conlist = new ArrayList();
        con.addClientData(IMQConnection.TRANSACTION_LIST, conlist);
    }
    // If there is a message body, then it should contain an Xid.
    ByteBuffer body = msg.getMessageBodyByteBuffer();
    if (body != null) {
        JMQByteBufferInputStream bbis = new JMQByteBufferInputStream(body);
        try {
            xid = JMQXid.read(new DataInputStream(bbis));
            startNextTransaction = false;
        } catch (IOException e) {
            logger.log(Logger.ERROR, BrokerResources.E_INTERNAL_BROKER_ERROR, "Could not decode xid from packet: " + e + " Ignoring " + PacketType.getString(msg.getPacketType()));
            reason = e.getMessage();
            sendReply(con, msg, msg.getPacketType() + 1, Status.BAD_REQUEST, 0, reason);
            return true;
        }
    }
    // Get XAFlags. Note, not all packets will have this -- that's OK.
    xaFlags = (Integer) props.get("JMQXAFlags");
    // tidMap maps an old style transaction identifier to a TransactionUID.
    // In iMQ2.0 the transaction identifier in the packet was an int
    // generated by the client and only unique on the connection.
    // In Falcon it is a long that is unique accross the cluster.
    // So for 2.0 clients we allocate a TransactionUID and map the old
    // style identifier to it.
    // 
    // Get tidMap
    HashMap tidMap = null;
    synchronized (con) {
        tidMap = (HashMap) con.getClientData(IMQConnection.TRANSACTION_IDMAP);
        if (tidMap == null) {
            tidMap = new HashMap();
            con.addClientData(IMQConnection.TRANSACTION_IDMAP, tidMap);
        }
    }
    // Go ahead and get the value of "JMQTransactionID" from the packet.
    // may not be used in all cases.
    messagetid = getJMQTransactionID(props);
    if (fi.FAULT_INJECTION) {
        checkFIBeforeProcess(msg.getPacketType());
    }
    boolean translistResolved = false;
    // else wrap the one specified in the packet
    if (msg.getPacketType() == PacketType.START_TRANSACTION && (xaFlags == null || TransactionState.isFlagSet(XAResource.TMNOFLAGS, xaFlags))) {
        if (isIndemp) {
            // deal with indemp flag
            Object[] rets = TransactionList.getTransactionByCreator(msg.getSysMessageID().toString());
            if (rets == null) {
                id = new TransactionUID();
            } else {
                translist = (TransactionList) rets[0];
                id = (TransactionUID) rets[1];
                replay = true;
            }
        } else {
            id = new TransactionUID();
        }
        translistResolved = true;
    } else if (msg.getPacketType() == PacketType.RECOVER_TRANSACTION) {
        if (messagetid != 0) {
            // Recovering a specific transaction.
            id = new TransactionUID(messagetid);
        }
        xid = null;
    } else {
        // If only Xid was specified need to lookup TransactionUID
        if (messagetid == 0 && xid != null) {
            Object[] rets = TransactionList.mapXidToTid(xid, con);
            if (rets != null) {
                translist = (TransactionList) rets[0];
                id = (TransactionUID) rets[1];
                messagetid = id.longValue();
                translistResolved = true;
            } else {
                // Hmmm...haven't seen this Xid before.
                // XXX I18N
                logger.log(Logger.WARNING, PacketType.getString(msg.getPacketType()) + ": Ignoring unknown XID=" + xid + " broker will " + (msg.getSendAcknowledge() ? "notify the client" : " not notify the client"));
                if (msg.getSendAcknowledge()) {
                    reason = "Uknown XID " + xid;
                    sendReply(con, msg, msg.getPacketType() + 1, Status.NOT_FOUND, 0, reason);
                }
                return true;
            }
        } else if (messagetid != 0) {
            if (con.getClientProtocolVersion() == PacketType.VERSION1) {
                // Map old style to new
                synchronized (tidMap) {
                    id = (TransactionUID) tidMap.get(Long.valueOf(messagetid));
                }
            } else {
                // Wrap new style
                id = new TransactionUID(messagetid);
            }
        }
        // Get the state of the transaction
        if (id == null) {
            logger.log(Logger.INFO, "InternalError: " + "Transaction ID was not passed by " + "the jms api on a method that reqires an " + "existing transaction ");
            sendReply(con, msg, msg.getPacketType() + 1, Status.ERROR, 0, "Internal Error: bad MQ protocol," + " missing TransactionID");
            return true;
        }
        if (translistResolved) {
            if (translist == null) {
                String emsg = "XXXNo transaction list found to process " + PacketType.getString(msg.getPacketType()) + " for transaction " + id + "[" + xid + "]";
                logger.log(Logger.WARNING, emsg);
                if (msg.getSendAcknowledge()) {
                    reason = emsg;
                    sendReply(con, msg, msg.getPacketType() + 1, Status.GONE, 0, reason);
                }
                return true;
            }
            ts = translist.retrieveState(id);
        } else {
            Object[] oo = TransactionList.getTransListAndState(id, con, false, false);
            if (oo != null) {
                translist = (TransactionList) oo[0];
                ts = (TransactionState) oo[1];
            }
        }
        if (ts == null) {
            if (isIndemp && (msg.getPacketType() == PacketType.ROLLBACK_TRANSACTION || msg.getPacketType() == PacketType.COMMIT_TRANSACTION)) {
                if (msg.getSendAcknowledge()) {
                    sendReply(con, msg, msg.getPacketType() + 1, Status.OK, id.longValue(), reason);
                    return true;
                }
                if (fi.FAULT_INJECTION) {
                    checkFIAfterProcess(msg.getPacketType());
                    checkFIAfterReply(msg.getPacketType());
                }
            } else {
                ts = cacheGetState(id, con);
                if (ts != null) {
                    // XXX l10n
                    logger.log(Logger.ERROR, "Transaction ID " + id + " has already been resolved. Ignoring request: " + PacketType.getString(msg.getPacketType()) + ". Last state of this transaction: " + ts.toString() + " broker will " + (msg.getSendAcknowledge() ? "notify the client" : " not notify the client"));
                } else {
                    logger.log((BrokerStateHandler.isShuttingDown() ? Logger.DEBUG : Logger.WARNING), Globals.getBrokerResources().getKString((msg.getSendAcknowledge() ? BrokerResources.W_UNKNOWN_TRANSACTIONID_NOTIFY_CLIENT : BrokerResources.W_UNKNOWN_TRANSACTIONID_NONOTIFY_CLIENT), "" + id + "(" + messagetid + ")" + (xid == null ? "" : "XID=" + xid), PacketType.getString(msg.getPacketType())) + "\n" + com.sun.messaging.jmq.io.PacketUtil.dumpPacket(msg));
                }
                // Only send reply if A bit is set
                if (msg.getSendAcknowledge()) {
                    reason = "Unknown transaction " + id;
                    sendReply(con, msg, msg.getPacketType() + 1, Status.NOT_FOUND, id.longValue(), reason);
                }
                return true;
            }
        }
    }
    if (DEBUG) {
        logger.log(Logger.INFO, this.getClass().getName() + ": " + PacketType.getString(msg.getPacketType()) + ": " + "TUID=" + id + " XAFLAGS=" + TransactionState.xaFlagToString(xaFlags) + (jmqonephaseFlag == null ? "" : " JMQXAOnePhase=" + jmqonephase) + " State=" + ts + " Xid=" + xid);
    }
    // we have in the transaction table.
    if (xid != null && ts != null) {
        if (ts.getXid() == null || !xid.equals(ts.getXid())) {
            // This should never happen
            logger.log(Logger.ERROR, BrokerResources.E_INTERNAL_BROKER_ERROR, "Transaction Xid mismatch. " + PacketType.getString(msg.getPacketType()) + " Packet has tuid=" + id + " xid=" + xid + ", transaction table has tuid=" + id + " xid=" + ts.getXid() + ". Using values from table.");
            xid = ts.getXid();
        }
    }
    if (xid == null && ts != null && ts.getXid() != null && msg.getPacketType() != PacketType.RECOVER_TRANSACTION) {
        // Client forgot to put Xid in packet.
        xid = ts.getXid();
        logger.log(Logger.WARNING, BrokerResources.E_INTERNAL_BROKER_ERROR, "Transaction Xid " + xid + " not found in " + PacketType.getString(msg.getPacketType()) + " packet for tuid " + id + ". Will use " + xid);
    }
    int status = Status.OK;
    // retrieve new 4.0 properties
    AutoRollbackType type = null;
    long lifetime = 0;
    boolean sessionLess = false;
    Integer typeValue = (Integer) props.get("JMQAutoRollback");
    Long lifetimeValue = (Long) props.get("JMQLifetime");
    Boolean sessionLessValue = (Boolean) props.get("JMQSessionLess");
    if (typeValue != null) {
        type = AutoRollbackType.getType(typeValue.intValue());
    }
    if (lifetimeValue != null) {
        lifetime = lifetimeValue.longValue();
    }
    if (sessionLessValue != null) {
        sessionLess = sessionLessValue.booleanValue();
    } else {
        sessionLess = xid != null;
    }
    switch(msg.getPacketType()) {
        case PacketType.START_TRANSACTION:
            {
                try {
                    doStart(translist, id, conlist, con, type, xid, sessionLess, lifetime, messagetid, xaFlags, msg.getPacketType(), replay, msg.getSysMessageID().toString());
                } catch (Exception ex) {
                    status = Status.ERROR;
                    logger.logStack(Logger.ERROR, ex.toString() + ": TUID=" + id + " Xid=" + xid, ex);
                    reason = ex.getMessage();
                    if (ex instanceof BrokerException) {
                        status = ((BrokerException) ex).getStatusCode();
                    }
                }
                sendReply(con, msg, PacketType.START_TRANSACTION_REPLY, status, id.longValue(), reason);
                break;
            }
        case PacketType.END_TRANSACTION:
            try {
                // if the noop flag is set the we don't want to actually
                // process the XA_END. See bug 12364646 and XAResourceImpl.end()
                Boolean jmqnoop = (Boolean) props.get("JMQNoOp");
                if (jmqnoop == null || jmqnoop == false) {
                    doEnd(translist, msg.getPacketType(), xid, xaFlags, ts, id);
                }
            } catch (Exception ex) {
                status = Status.ERROR;
                reason = ex.getMessage();
                if (ex instanceof BrokerException) {
                    status = ((BrokerException) ex).getStatusCode();
                }
            }
            sendReply(con, msg, msg.getPacketType() + 1, status, id.longValue(), reason);
            break;
        case PacketType.PREPARE_TRANSACTION:
            BrokerException bex = null;
            HashMap tmpp = null;
            try {
                doPrepare(translist, id, xaFlags, ts, msg.getPacketType(), jmqonephase, null, con);
            } catch (Exception ex) {
                status = Status.ERROR;
                if ((!(ex instanceof BrokerDownException) && !(ex instanceof AckEntryNotFoundException)) || DEBUG_CLUSTER_TXN) {
                    logger.logStack(Logger.ERROR, ex.toString() + ": TUID=" + id + " Xid=" + xid, ex);
                } else {
                    logger.log(((ex instanceof AckEntryNotFoundException) ? Logger.WARNING : Logger.ERROR), ex.toString() + ": TUID=" + id + " Xid=" + xid);
                }
                reason = ex.getMessage();
                if (ex instanceof BrokerException) {
                    status = ((BrokerException) ex).getStatusCode();
                    bex = (BrokerException) ex;
                }
                if (ts.getState() == TransactionState.FAILED) {
                    tmpp = new HashMap();
                    tmpp.put("JMQPrepareStateFAILED", Boolean.TRUE);
                }
            }
            sendReply(con, msg, msg.getPacketType() + 1, status, id.longValue(), reason, bex, tmpp, 0L);
            break;
        case PacketType.RECOVER_TRANSACTION:
            Vector v = null;
            if (id != null) {
                // Check if specified transaction is in PREPARED state
                v = new Vector();
                ts = translist.retrieveState(id);
                if (ts.getState() == TransactionState.PREPARED) {
                    v.add(id);
                }
            } else {
                // and nothing on ENDRSCAN or NOFLAGS
                if (xaFlags == null || !TransactionState.isFlagSet(XAResource.TMSTARTRSCAN, xaFlags)) {
                    Hashtable hash = new Hashtable();
                    hash.put("JMQQuantity", Integer.valueOf(0));
                    sendReplyBody(con, msg, PacketType.RECOVER_TRANSACTION_REPLY, Status.OK, hash, null);
                    break;
                }
                // Get list of transactions in PENDING state and marshal
                // the Xid's to a byte array.
                v = translist.getTransactions(TransactionState.PREPARED);
            }
            int nIDs = v.size();
            int nWritten = 0;
            ByteArrayOutputStream bos = new ByteArrayOutputStream(nIDs * JMQXid.size());
            DataOutputStream dos = new DataOutputStream(bos);
            for (int n = 0; n < nIDs; n++) {
                TransactionUID tuid = (TransactionUID) v.get(n);
                TransactionState _ts = translist.retrieveState(tuid);
                if (_ts == null) {
                    // Should never happen
                    logger.log(Logger.ERROR, BrokerResources.E_INTERNAL_BROKER_ERROR, "Could not find state for TUID " + tuid);
                    continue;
                }
                JMQXid _xid = _ts.getXid();
                if (_xid != null) {
                    try {
                        _xid.write(dos);
                        nWritten++;
                    } catch (Exception e) {
                        logger.log(Logger.ERROR, BrokerResources.E_INTERNAL_BROKER_ERROR, "Could not write Xid " + _xid + " to message body: " + e.toString());
                    }
                }
            }
            Hashtable hash = new Hashtable();
            hash.put("JMQQuantity", Integer.valueOf(nWritten));
            if (id != null) {
                hash.put("JMQTransactionID", Long.valueOf(id.longValue()));
            }
            // Send reply with serialized Xids as the body
            sendReplyBody(con, msg, PacketType.RECOVER_TRANSACTION_REPLY, Status.OK, hash, bos.toByteArray());
            break;
        case PacketType.COMMIT_TRANSACTION:
            try {
                // doCommit will send reply if successful
                if (xaFlags != null && jmqonephase) {
                    Integer newxaFlags = Integer.valueOf(xaFlags.intValue() & ~XAResource.TMONEPHASE);
                    doCommit(translist, id, xid, newxaFlags, ts, conlist, true, con, msg);
                } else {
                    doCommit(translist, id, xid, xaFlags, ts, conlist, true, con, msg, startNextTransaction);
                }
            } catch (BrokerException ex) {
                // doCommit has already logged error
                status = ex.getStatusCode();
                reason = ex.getMessage();
                if (msg.getSendAcknowledge()) {
                    HashMap tmppp = null;
                    if (!jmqonephase && TransactionState.isFlagSet(XAResource.TMONEPHASE, xaFlags)) {
                        if (ts.getState() == TransactionState.FAILED) {
                            tmppp = new HashMap();
                            tmppp.put("JMQPrepareStateFAILED", Boolean.TRUE);
                        }
                    }
                    sendReply(con, msg, msg.getPacketType() + 1, status, id.longValue(), reason, ex, tmppp, 0L);
                } else {
                    if (fi.FAULT_INJECTION) {
                        checkFIAfterProcess(msg.getPacketType());
                        checkFIAfterReply(msg.getPacketType());
                    }
                }
            }
            break;
        case PacketType.ROLLBACK_TRANSACTION:
            {
                BrokerException maxrbex = null;
                try {
                    preRollback(translist, id, xid, xaFlags, ts);
                    try {
                        // if redeliverMsgs is true, we want to redeliver
                        // to both active and inactive consumers
                        boolean processActiveConsumers = redeliverMsgs;
                        redeliverUnacked(translist, id, processActiveConsumers, setRedeliverFlag, updateConsumed, maxRollbacks, dmqOnMaxRollbacks);
                    } catch (BrokerException ex) {
                        if (ex instanceof MaxConsecutiveRollbackException) {
                            maxrbex = ex;
                        } else {
                            logger.logStack(Logger.ERROR, "REDELIVER: " + ex.toString() + ": TUID=" + id + " Xid=" + xid, ex);
                        }
                        reason = ex.getMessage();
                        status = ex.getStatusCode();
                    }
                    if (!(maxrbex != null && !dmqOnMaxRollbacks)) {
                        try {
                            if (fi.checkFault(fi.FAULT_TXN_ROLLBACK_1_5_EXCEPTION, null)) {
                                // fi.unsetFault(fi.FAULT_TXN_ROLLBACK_1_5_EXCEPTION);
                                throw new BrokerException(fi.FAULT_TXN_ROLLBACK_1_5_EXCEPTION);
                            }
                            doRollback(translist, id, xid, xaFlags, ts, conlist, con, RollbackReason.APPLICATION);
                        } catch (BrokerException ex) {
                            if (!ex.isStackLogged()) {
                                logger.logStack(logger.WARNING, ex.getMessage(), ex);
                            } else {
                                logger.log(logger.WARNING, br.getKString(br.X_ROLLBACK_TXN, id, ex.getMessage()));
                            }
                            // doRollback has already logged error
                            if (maxrbex == null) {
                                reason = ex.getMessage();
                                status = ex.getStatusCode();
                            }
                        }
                    }
                } catch (BrokerException ex) {
                    reason = ex.getMessage();
                    status = ex.getStatusCode();
                }
                // performance optimisation
                // start next transaction and return transaction id
                long nextTxnID = 0;
                if (startNextTransaction) {
                    try {
                        TransactionUID nextid = new TransactionUID();
                        doStart(translist, nextid, conlist, con, type, xid, sessionLess, lifetime, 0, xaFlags, PacketType.START_TRANSACTION, replay, msg.getSysMessageID().toString());
                        nextTxnID = nextid.longValue();
                    } catch (Exception ex) {
                        logger.logStack(Logger.ERROR, ex.toString() + ": TUID=" + id + " Xid=" + xid, ex);
                        if (maxrbex == null) {
                            status = Status.ERROR;
                            reason = ex.getMessage();
                            if (ex instanceof BrokerException) {
                                status = ((BrokerException) ex).getStatusCode();
                            }
                        }
                    }
                }
                if (msg.getSendAcknowledge()) {
                    sendReply(con, msg, msg.getPacketType() + 1, status, id.longValue(), reason, null, null, nextTxnID);
                } else {
                    if (fi.FAULT_INJECTION) {
                        checkFIAfterProcess(msg.getPacketType());
                        checkFIAfterReply(msg.getPacketType());
                    }
                }
                break;
            }
    }
    return true;
}
Also used : TransactionState(com.sun.messaging.jmq.jmsserver.data.TransactionState) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) HashMap(java.util.HashMap) CacheHashMap(com.sun.messaging.jmq.util.CacheHashMap) DataOutputStream(java.io.DataOutputStream) ArrayList(java.util.ArrayList) MaxConsecutiveRollbackException(com.sun.messaging.jmq.jmsserver.util.MaxConsecutiveRollbackException) JMQByteBufferInputStream(com.sun.messaging.jmq.io.JMQByteBufferInputStream) AckEntryNotFoundException(com.sun.messaging.jmq.jmsserver.util.AckEntryNotFoundException) DestinationList(com.sun.messaging.jmq.jmsserver.core.DestinationList) List(java.util.List) ArrayList(java.util.ArrayList) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList) AutoRollbackType(com.sun.messaging.jmq.jmsserver.data.AutoRollbackType) Vector(java.util.Vector) BrokerDownException(com.sun.messaging.jmq.jmsserver.util.BrokerDownException) Hashtable(java.util.Hashtable) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList) IOException(java.io.IOException) ByteArrayOutputStream(java.io.ByteArrayOutputStream) JMQXid(com.sun.messaging.jmq.util.JMQXid) DataInputStream(java.io.DataInputStream) ByteBuffer(java.nio.ByteBuffer) 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) TransactionUID(com.sun.messaging.jmq.jmsserver.data.TransactionUID)

Example 3 with MaxConsecutiveRollbackException

use of com.sun.messaging.jmq.jmsserver.util.MaxConsecutiveRollbackException in project openmq by eclipse-ee4j.

the class TransactionHandler method redeliverUnacked.

/**
 * this method triggers a redeliver of all unacked messages in the transaction. Since there may be multiple connections
 * for the various consumers .. we guarentee that the messages for this transaction are resent in order but make no
 * guarentee about other messages arriving before these messages.
 */
public void redeliverUnacked(TransactionList translist, TransactionUID tid, boolean processActiveConsumers, boolean redeliver, boolean updateConsumed, int maxRollbacks, boolean dmqOnMaxRollbacks) throws BrokerException {
    HashMap cmap = null;
    HashMap sToCmap = null;
    cmap = translist.retrieveConsumedMessages(tid, true);
    sToCmap = translist.retrieveStoredConsumerUIDs(tid);
    if (DEBUG) {
        logger.log(logger.INFO, "redeliverUnacked:tid=" + tid + ", consumed#=" + cmap);
    }
    HashMap sendMap = sortPreprocessRetrievedMessages(cmap, sToCmap, processActiveConsumers, maxRollbacks, dmqOnMaxRollbacks, tid);
    if (DEBUG) {
        logger.log(logger.INFO, "redeliverUnacked:tid=" + tid + ", sendMap#=" + sendMap.size());
    }
    HashMap sendMapRemoved = null;
    if (processActiveConsumers) {
        HashMap cmapRemoved = translist.retrieveRemovedConsumedMessages(tid, false);
        sendMapRemoved = sortPreprocessRetrievedMessages(cmapRemoved, sToCmap, processActiveConsumers, maxRollbacks, dmqOnMaxRollbacks, tid);
    }
    String deadComment = null;
    // OK -> now we have a NEW hashmap id -> messages (sorted)
    // lets resend the ones we can to the consumer
    ArrayList updatedRefs = new ArrayList();
    Iterator sitr = sendMap.entrySet().iterator();
    while (sitr.hasNext()) {
        Map.Entry entry = (Map.Entry) sitr.next();
        ConsumerUID intid = (ConsumerUID) entry.getKey();
        ConsumerUID stored = (ConsumerUID) sToCmap.get(intid);
        if (stored == null) {
            stored = intid;
        }
        SortedSet ss = (SortedSet) entry.getValue();
        Consumer cs = Consumer.getConsumer(intid);
        if ((cs != null && processActiveConsumers) || updateConsumed) {
            updateRefsState(stored, ss, (redeliver | updateConsumed), updatedRefs, tid);
        }
        if (cs == null) {
            if (DEBUG) {
                logger.log(Logger.INFO, tid + ":Can not redeliver messages to " + intid + " consumer is gone");
            }
            continue;
        }
        if (DEBUG) {
            logger.log(Logger.INFO, tid + ":Redelivering " + ss.size() + " msgs to " + intid);
        }
        if (!processActiveConsumers) {
            // we dont want to process open consumers
            // if the boolen is false ->
            // remove them so that we only process inactive
            // consumers later
            sitr.remove();
        } else if (ss.size() > 0) {
            if (dmqOnMaxRollbacks) {
                PacketReference lastref = (PacketReference) ss.last();
                String emsg = makeDeadIfMaxRollbacked(lastref, cs, tid, maxRollbacks);
                if (emsg != null) {
                    if (deadComment == null) {
                        deadComment = emsg;
                    }
                    ss.remove(lastref);
                }
            }
            if (cs.routeMessages(ss, true)) {
                if (DEBUG) {
                    logger.log(Logger.INFO, "Sucessfully routed msgs to " + cs);
                }
                sitr.remove();
            } else {
                // couldnt route messages ..invalid consumer
                if (DEBUG) {
                    logger.log(Logger.INFO, "Could not route messages to " + cs);
                }
            }
        }
    }
    // ones that dont have consumers)
    if (DEBUG) {
        logger.log(Logger.INFO, tid + ":after redeliver, " + sendMap.size() + " inactive consumers remaining");
    }
    // loop through remaining messages
    redeliverUnackedNoConsumer(sendMap, sToCmap, redeliver, tid, translist);
    if (sendMapRemoved != null) {
        releaseRemovedConsumedForActiveConsumer(sendMapRemoved, sToCmap, updatedRefs, tid, translist, redeliver, updateConsumed, maxRollbacks, dmqOnMaxRollbacks);
    }
    if (deadComment != null) {
        throw new MaxConsecutiveRollbackException(deadComment);
    }
}
Also used : Consumer(com.sun.messaging.jmq.jmsserver.core.Consumer) HashMap(java.util.HashMap) CacheHashMap(com.sun.messaging.jmq.util.CacheHashMap) ConsumerUID(com.sun.messaging.jmq.jmsserver.core.ConsumerUID) PacketReference(com.sun.messaging.jmq.jmsserver.core.PacketReference) ArrayList(java.util.ArrayList) Iterator(java.util.Iterator) MaxConsecutiveRollbackException(com.sun.messaging.jmq.jmsserver.util.MaxConsecutiveRollbackException) Map(java.util.Map) HashMap(java.util.HashMap) CacheHashMap(com.sun.messaging.jmq.util.CacheHashMap) SortedSet(java.util.SortedSet)

Example 4 with MaxConsecutiveRollbackException

use of com.sun.messaging.jmq.jmsserver.util.MaxConsecutiveRollbackException in project openmq by eclipse-ee4j.

the class ProtocolImpl method rollbackTransaction.

/**
 * Rollback a transaction
 *
 * @param id The TransactionUID to rollback
 * @param xid The Xid of the transaction to rollback. Required if transaction is an XA transaction. Must be null if it
 * is not an XA transaction.
 * @param redeliver should messages be redelivered
 * @param setRedeliver if the messages are redelivered, should the redeliver flag be set on all messages or not
 * @param con Connection client rollback packet came in on (or null if internal)
 */
@Override
public void rollbackTransaction(TransactionUID id, JMQXid xid, IMQConnection con, boolean redeliver, boolean setRedeliver, int maxRollbacks, boolean dmqOnMaxRollbacks) throws BrokerException {
    if (maxRollbacks <= 0) {
        dmqOnMaxRollbacks = !(Consumer.MSG_MAX_CONSECUTIVE_ROLLBACKS <= 0);
    }
    if (DEBUG) {
        logger.log(Logger.INFO, "ProtocolImpl.ROLLBACK TRANSACTION:TID=" + id + ", XID=" + xid + ", conn=@" + con.hashCode() + "[" + con.getConnectionUID() + ", " + con + "], redeliver=" + redeliver + ", setRedeliver=" + setRedeliver);
    }
    List conlist = con.getTransactionListThreadSafe();
    TransactionHandler handler = (TransactionHandler) pr.getHandler(PacketType.START_TRANSACTION);
    TransactionList tl = null;
    if (0L == id.longValue()) {
        if (xid == null) {
            throw new BrokerException("Unexpected TransactionUID  " + id);
        }
        Object[] oo = TransactionList.mapXidToTid(xid, con);
        if (oo == null) {
            id = null;
        } else {
            tl = (TransactionList) oo[0];
            id = (TransactionUID) oo[1];
        }
        if (id == null) {
            throw new BrokerException("Unknown XID " + xid, Status.NOT_FOUND);
        }
    }
    TransactionState ts = null;
    if (tl == null) {
        Object[] oo = TransactionList.getTransListAndState(id, con, false, false);
        if (oo != null) {
            tl = (TransactionList) oo[0];
            ts = (TransactionState) oo[1];
        }
    }
    if (tl == null) {
        throw new BrokerException("Unknown transaction " + id + (xid == null ? "" : " XID=" + xid), Status.NOT_FOUND);
    }
    if (ts == null) {
        ts = tl.retrieveState(id);
        if (ts == null) {
            throw new BrokerException("Unknown transaction " + id + (xid == null ? "" : " XID=" + xid), Status.NOT_FOUND);
        }
    }
    if (xid != null) {
        if (ts.getXid() == null || !xid.equals(ts.getXid())) {
            throw new BrokerException("Transaction XID mismatch " + xid + ", expected " + ts.getXid() + " for transaction " + id);
        }
    }
    handler.preRollback(tl, id, xid, null, /* xaFlags */
    ts);
    BrokerException bex = null;
    if (redeliver) {
        try {
            handler.redeliverUnacked(tl, id, true, setRedeliver, false, maxRollbacks, dmqOnMaxRollbacks);
        } catch (MaxConsecutiveRollbackException e) {
            bex = e;
            if (!dmqOnMaxRollbacks) {
                throw bex;
            }
        }
    }
    try {
        handler.doRollback(tl, id, xid, null, /* xaFlags */
        ts, conlist, con, RollbackReason.APPLICATION);
    } catch (BrokerException e) {
        if (bex != null) {
            throw bex;
        }
        throw e;
    }
    if (bex != null) {
        throw bex;
    }
}
Also used : TransactionState(com.sun.messaging.jmq.jmsserver.data.TransactionState) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) TransactionHandler(com.sun.messaging.jmq.jmsserver.data.handlers.TransactionHandler) MaxConsecutiveRollbackException(com.sun.messaging.jmq.jmsserver.util.MaxConsecutiveRollbackException) DestinationList(com.sun.messaging.jmq.jmsserver.core.DestinationList) List(java.util.List) ArrayList(java.util.ArrayList) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList)

Aggregations

MaxConsecutiveRollbackException (com.sun.messaging.jmq.jmsserver.util.MaxConsecutiveRollbackException)4 ArrayList (java.util.ArrayList)4 DestinationList (com.sun.messaging.jmq.jmsserver.core.DestinationList)3 TransactionList (com.sun.messaging.jmq.jmsserver.data.TransactionList)3 CacheHashMap (com.sun.messaging.jmq.util.CacheHashMap)3 HashMap (java.util.HashMap)3 List (java.util.List)3 Consumer (com.sun.messaging.jmq.jmsserver.core.Consumer)2 ConsumerUID (com.sun.messaging.jmq.jmsserver.core.ConsumerUID)2 PacketReference (com.sun.messaging.jmq.jmsserver.core.PacketReference)2 TransactionState (com.sun.messaging.jmq.jmsserver.data.TransactionState)2 BrokerException (com.sun.messaging.jmq.jmsserver.util.BrokerException)2 Iterator (java.util.Iterator)2 Map (java.util.Map)2 SortedSet (java.util.SortedSet)2 JMQByteBufferInputStream (com.sun.messaging.jmq.io.JMQByteBufferInputStream)1 SysMessageID (com.sun.messaging.jmq.io.SysMessageID)1 AutoRollbackType (com.sun.messaging.jmq.jmsserver.data.AutoRollbackType)1 TransactionUID (com.sun.messaging.jmq.jmsserver.data.TransactionUID)1 TransactionHandler (com.sun.messaging.jmq.jmsserver.data.handlers.TransactionHandler)1