Search in sources :

Example 1 with TransactionState

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

the class TransactionHandler method doStart.

public void doStart(TransactionList translist, TransactionUID id, List conlist, IMQConnection con, AutoRollbackType type, JMQXid xid, boolean sessionLess, long lifetime, long messagetid, Integer xaFlags, int pktType, boolean replay, String creatorID) throws BrokerException {
    HashMap tidMap = (HashMap) con.getClientData(IMQConnection.TRANSACTION_IDMAP);
    int status = 0;
    String reason = null;
    TransactionState ts = null;
    ts = translist.retrieveState(id);
    if (type == AutoRollbackType.NEVER || lifetime > 0) {
        // not supported
        status = Status.NOT_IMPLEMENTED;
        reason = "AutoRollbackType of NEVER not supported";
        throw new BrokerException(reason, status);
    } else if (xid != null && !sessionLess) {
        // not supported yet
        status = Status.NOT_IMPLEMENTED;
        reason = "XA transactions only supported on sessionless " + "connections";
        throw new BrokerException(reason, status);
    } else if (xid == null && sessionLess) {
        // not supported yet
        status = Status.ERROR;
        reason = "non-XA transactions only supported on " + " non-sessionless connections";
        throw new BrokerException(reason, status);
    } else {
        if (replay) {
        // do nothing it already happened
        } else if (xaFlags != null && !TransactionState.isFlagSet(XAResource.TMNOFLAGS, xaFlags)) {
            // This is either a TMJOIN or TMRESUME. We just need to
            // update the transaction state
            int s = ts.nextState(pktType, xaFlags);
            translist.updateState(id, s, true);
        } else {
            // Brand new transaction
            try {
                if (con.getClientProtocolVersion() == PacketType.VERSION1) {
                    // If 2.0 client Map old style ID to new
                    tidMap.put(Long.valueOf(messagetid), id);
                }
                if (xid != null && type == null) {
                    type = translist.AUTO_ROLLBACK ? AutoRollbackType.ALL : AutoRollbackType.NOT_PREPARED;
                }
                ts = new TransactionState(type, lifetime, sessionLess);
                ts.setState(TransactionState.STARTED);
                ts.setUser(con.getUserName());
                ts.setCreator(creatorID);
                ts.setClientID((String) con.getClientData(IMQConnection.CLIENT_ID));
                ts.setXid(xid);
                ts.setConnectionString(con.userReadableString());
                ts.setConnectionUID(con.getConnectionUID());
                translist.addTransactionID(id, ts);
                conlist.add(id);
            } catch (BrokerException ex) {
                // XXX I18N
                logger.log(Logger.ERROR, "Exception starting new transaction: " + ex.toString(), ex);
                throw ex;
            }
        }
    }
}
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)

Example 2 with TransactionState

use of com.sun.messaging.jmq.jmsserver.data.TransactionState 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 TransactionState

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

the class RaptorProtocol method sendRemoteTransactionInfo.

private void sendRemoteTransactionInfo(TransactionUID tid, BrokerAddress to, Long xid, boolean ownerWaitingFor) {
    List<Object[]> list = TransactionList.getTransListsAndRemoteTranStates(tid);
    TransactionList tl = null;
    TransactionState ts = null;
    Object[] oo = null;
    if (list != null) {
        oo = list.get(0);
        tl = (TransactionList) oo[0];
        ts = (TransactionState) oo[1];
    }
    if (ts == null && !ownerWaitingFor) {
        if (DEBUG_CLUSTER_TXN) {
            logger.log(logger.INFO, "Remote transaction " + tid + " not found");
        }
        return;
    }
    UID tlss = null;
    boolean partitionmode = Globals.getDestinationList().isPartitionMode();
    int loop = (list == null ? 1 : list.size());
    for (int i = 0; i < loop; i++) {
        if (list != null) {
            oo = list.get(i);
            tl = (TransactionList) oo[0];
            ts = (TransactionState) oo[1];
        }
        if (ts != null && ts.getState() != TransactionState.ROLLEDBACK && ts.getState() != TransactionState.COMMITTED) {
            continue;
        }
        tlss = null;
        if (tl != null && partitionmode) {
            tlss = tl.getPartitionedStore().getPartitionID();
        }
        int s = (ts == null ? TransactionState.NULL : ts.getState());
        TransactionBroker txnhome = null;
        if (s == TransactionState.ROLLEDBACK || s == TransactionState.COMMITTED) {
            if (tl != null) {
                txnhome = tl.getRemoteTransactionHomeBroker(tid);
            }
        }
        ClusterTxnInfoInfo ii = ClusterTxnInfoInfo.newInstance(Long.valueOf(tid.longValue()), s, null, null, (txnhome == null ? null : txnhome.getBrokerAddress()), false, tlss, c, xid);
        if (DEBUG_CLUSTER_TXN) {
            logger.log(logger.INFO, Globals.getBrokerResources().getKString(BrokerResources.I_SEND_REMOTE_TXN_INFO, to, ii.toString()));
        }
        try {
            c.unicast(to, ii.getGPacket());
        } catch (Exception e) {
            String[] args = { ii.toString(), to.toString(), e.getMessage() };
            logger.log(Logger.WARNING, Globals.getBrokerResources().getString(BrokerResources.W_SEND_REMOTE_TXN_INFO_FAIL, args));
        }
    }
// for
}
Also used : TransactionState(com.sun.messaging.jmq.jmsserver.data.TransactionState) ConnectionUID(com.sun.messaging.jmq.jmsserver.service.ConnectionUID) TransactionUID(com.sun.messaging.jmq.jmsserver.data.TransactionUID) TransactionBroker(com.sun.messaging.jmq.jmsserver.data.TransactionBroker) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList) HandshakeInProgressException(com.sun.messaging.jmq.jmsserver.multibroker.HandshakeInProgressException)

Example 4 with TransactionState

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

the class DestinationList method loadTakeoverMsgs.

public static synchronized void loadTakeoverMsgs(PartitionedStore storep, Map<String, String> msgs, List txns, Map txacks) throws BrokerException {
    DestinationList dl = destinationListList.get(storep);
    Map m = new HashMap();
    Logger logger = Globals.getLogger();
    Map ackLookup = new HashMap();
    // ok create a hashtable for looking up txns
    if (txacks != null) {
        Iterator itr = txacks.entrySet().iterator();
        while (itr.hasNext()) {
            Map.Entry entry = (Map.Entry) itr.next();
            TransactionUID tuid = (TransactionUID) entry.getKey();
            List l = (List) entry.getValue();
            Iterator litr = l.iterator();
            while (litr.hasNext()) {
                TransactionAcknowledgement ta = (TransactionAcknowledgement) litr.next();
                String key = ta.getSysMessageID() + ":" + ta.getStoredConsumerUID();
                ackLookup.put(key, tuid);
            }
        }
    }
    // Alright ...
    // all acks fail once takeover begins
    // we expect all transactions to rollback
    // here is the logic:
    // - load all messages
    // - remove any messages in open transactions
    // - requeue all messages
    // - resort (w/ load comparator)
    // 
    // 
    // OK, first get msgs and sort by destination
    HashMap openMessages = new HashMap();
    Iterator itr = msgs.entrySet().iterator();
    while (itr.hasNext()) {
        Map.Entry me = (Map.Entry) itr.next();
        String msgID = (String) me.getKey();
        String dst = (String) me.getValue();
        DestinationUID dUID = new DestinationUID(dst);
        Packet p = null;
        try {
            p = storep.getMessage(dUID, msgID);
        } catch (BrokerException ex) {
            Throwable cause = ex.getCause();
            if (cause instanceof InvalidPacketException) {
                String[] args = { msgID, dst, cause.toString() };
                String emsg = Globals.getBrokerResources().getKString(BrokerResources.X_MSG_CORRUPTED_IN_STORE, args);
                logger.logStack(Logger.ERROR, emsg, ex);
                handleInvalidPacket(msgID, dst, emsg, (InvalidPacketException) cause, storep);
                itr.remove();
                continue;
            }
            // Check if dst even exists!
            if (ex.getStatusCode() == Status.NOT_FOUND) {
                Destination[] ds = getDestination(storep, dUID);
                Destination d = ds[0];
                if (d == null) {
                    String[] args = { msgID, dst, Globals.getBrokerResources().getString(BrokerResources.E_DESTINATION_NOT_FOUND_IN_STORE, dst) };
                    logger.log(Logger.ERROR, BrokerResources.W_CAN_NOT_LOAD_MSG, args, ex);
                }
            }
            throw ex;
        }
        dUID = DestinationUID.getUID(p.getDestination(), p.getIsQueue());
        PacketReference pr = PacketReference.createReference(storep, p, dUID, null);
        // mark already stored and make packet a SoftReference to
        // prevent running out of memory if dest has lots of msgs
        pr.setLoaded();
        logger.log(Logger.DEBUG, "Loading message " + pr.getSysMessageID() + " on " + pr.getDestinationUID());
        // check transactions
        TransactionUID tid = pr.getTransactionID();
        if (tid != null) {
            // see if in transaction list
            if (txns.contains(tid)) {
                // open transaction
                TransactionState ts = dl.getTransactionList().retrieveState(pr.getTransactionID());
                if (ts != null && ts.getState() != TransactionState.ROLLEDBACK && ts.getState() != TransactionState.COMMITTED) {
                    // in transaction ...
                    logger.log(Logger.DEBUG, "Processing open transacted message " + pr.getSysMessageID() + " on " + tid + "[" + TransactionState.toString(ts.getState()) + "]");
                    openMessages.put(pr.getSysMessageID(), tid);
                } else if (ts != null && ts.getState() == TransactionState.ROLLEDBACK) {
                    pr.destroy();
                    continue;
                } else {
                }
            }
        }
        dl.packetlistAdd(pr.getSysMessageID(), pr.getDestinationUID(), null);
        Set l = null;
        if ((l = (Set) m.get(dUID)) == null) {
            l = new TreeSet(new RefCompare());
            m.put(dUID, l);
        }
        l.add(pr);
    }
    // OK, handle determining how to queue the messages
    Map<PacketReference, MessageDeliveryTimeInfo> deliveryDelays = new HashMap<>();
    // first add all messages
    Iterator dsts = m.entrySet().iterator();
    while (dsts.hasNext()) {
        Map.Entry entry = (Map.Entry) dsts.next();
        DestinationUID dst = (DestinationUID) entry.getKey();
        Set l = (Set) entry.getValue();
        Destination[] ds = getDestination(storep, dst);
        Destination d = ds[0];
        if (d == null) {
            // create it
            String destinationName = dst.getName();
            try {
                ds = getDestination(storep, destinationName, (dst.isQueue() ? DestType.DEST_TYPE_QUEUE : DestType.DEST_TYPE_TOPIC), true, true);
                d = ds[0];
            } catch (IOException ex) {
                throw new BrokerException(Globals.getBrokerResources().getKString(BrokerResources.X_CANT_LOAD_DEST, destinationName));
            }
        } else {
            synchronized (d) {
                if (d.isLoaded()) {
                    // Destination has already been loaded so just called
                    // initialize() to update the size and bytes variables
                    d.initialize();
                }
                d.load(l);
            }
        }
        logger.log(Logger.INFO, BrokerResources.I_LOADING_DST, d.getName(), String.valueOf(l.size()));
        MessageDeliveryTimeTimer dt = d.deliveryTimeTimer;
        if (dt == null && !d.isDMQ()) {
            if (!d.isValid()) {
                String emsg = Globals.getBrokerResources().getKString(BrokerResources.W_UNABLE_LOAD_TAKEOVER_MSGS_TO_DESTROYED_DST, d.getDestinationUID());
                logger.log(Logger.WARNING, emsg);
                continue;
            }
            String emsg = Globals.getBrokerResources().getKString(BrokerResources.W_UNABLE_LOAD_TAKEOVER_MSGS_NO_DST_DELIVERY_TIMER, d.getDestinationUID() + "[" + d.isValid() + "]");
            logger.log(Logger.WARNING, emsg);
            continue;
        }
        // now we're sorted, process
        Iterator litr = l.iterator();
        try {
            MessageDeliveryTimeInfo di = null;
            while (litr.hasNext()) {
                PacketReference pr = (PacketReference) litr.next();
                di = pr.getDeliveryTimeInfo();
                if (di != null) {
                    dt.removeMessage(di);
                }
                try {
                    // ok allow overrun
                    boolean el = d.destMessages.getEnforceLimits();
                    d.destMessages.enforceLimits(false);
                    if (DEBUG) {
                        logger.log(logger.INFO, "Put message " + pr + "[" + di + "] to destination " + d);
                    }
                    pr.lock();
                    d.acquireQueueRemoteLock();
                    try {
                        d.putMessage(pr, AddReason.LOADED, true);
                    } finally {
                        d.clearQueueRemoteLock();
                    }
                    // turn off overrun
                    d.destMessages.enforceLimits(el);
                } catch (IllegalStateException | OutOfLimitsException ex) {
                    // thats ok, we already exists
                    String[] args = { pr.getSysMessageID().toString(), pr.getDestinationUID().toString(), ex.getMessage() };
                    logger.logStack(Logger.WARNING, BrokerResources.W_CAN_NOT_LOAD_MSG, args, ex);
                    continue;
                } finally {
                    if (di != null && !di.isDeliveryDue()) {
                        dt.addMessage(di);
                        deliveryDelays.put(pr, di);
                    }
                }
            }
            // then resort the destination
            d.sort(new RefCompare());
        } catch (Exception ex) {
        }
    }
    // now route
    dsts = m.entrySet().iterator();
    while (dsts.hasNext()) {
        Map.Entry entry = (Map.Entry) dsts.next();
        DestinationUID dst = (DestinationUID) entry.getKey();
        Set l = (Set) entry.getValue();
        Destination d = dl.getDestination(dst);
        // now we're sorted, process
        Iterator litr = l.iterator();
        try {
            while (litr.hasNext()) {
                PacketReference pr = (PacketReference) litr.next();
                if (DEBUG) {
                    logger.log(logger.INFO, "Process takeover message " + pr + "[" + pr.getDeliveryTimeInfo() + "] for destination " + d);
                }
                TransactionUID tuid = (TransactionUID) openMessages.get(pr.getSysMessageID());
                if (tuid != null) {
                    dl.getTransactionList().addMessage(tuid, pr.getSysMessageID(), true);
                    pr.unlock();
                    continue;
                }
                ConsumerUID[] consumers = storep.getConsumerUIDs(dst, pr.getSysMessageID());
                if (consumers == null) {
                    consumers = new ConsumerUID[0];
                }
                if (consumers.length == 0 && storep.hasMessageBeenAcked(dst, pr.getSysMessageID())) {
                    logger.log(Logger.INFO, Globals.getBrokerResources().getString(BrokerResources.W_TAKEOVER_MSG_ALREADY_ACKED, pr.getSysMessageID()));
                    d.unputMessage(pr, RemoveReason.ACKNOWLEDGED);
                    pr.destroy();
                    pr.unlock();
                    continue;
                }
                if (consumers.length > 0) {
                    pr.setStoredWithInterest(true);
                } else {
                    pr.setStoredWithInterest(false);
                }
                int[] states = null;
                if (consumers.length == 0 && deliveryDelays.get(pr) == null) {
                    // message
                    try {
                        consumers = d.routeLoadedTransactionMessage(pr);
                    } catch (Exception ex) {
                        logger.logStack(Logger.WARNING, Globals.getBrokerResources().getKString(BrokerResources.W_EXCEPTION_ROUTE_LOADED_MSG, pr.getSysMessageID(), ex.getMessage()), ex);
                    }
                    states = new int[consumers.length];
                    for (int i = 0; i < states.length; i++) {
                        states[i] = PartitionedStore.INTEREST_STATE_ROUTED;
                    }
                    try {
                        storep.storeInterestStates(d.getDestinationUID(), pr.getSysMessageID(), consumers, states, true, null);
                        pr.setStoredWithInterest(true);
                    } catch (Exception ex) {
                        // message already routed
                        StringBuilder debuf = new StringBuilder();
                        for (int i = 0; i < consumers.length; i++) {
                            if (i > 0) {
                                debuf.append(", ");
                            }
                            debuf.append(consumers[i]);
                        }
                        logger.log(logger.WARNING, BrokerResources.W_TAKEOVER_MSG_ALREADY_ROUTED, pr.getSysMessageID(), debuf.toString(), ex);
                    }
                } else if (consumers.length > 0) {
                    states = new int[consumers.length];
                    for (int i = 0; i < consumers.length; i++) {
                        states[i] = storep.getInterestState(dst, pr.getSysMessageID(), consumers[i]);
                    }
                }
                pr.update(consumers, states, false);
                // OK deal w/ transsactions
                // LKS - XXX
                ExpirationInfo ei = pr.getExpireInfo();
                if (ei != null && d.expireReaper != null) {
                    d.expireReaper.addExpiringMessage(ei);
                }
                List<ConsumerUID> consumerList = new ArrayList(Arrays.asList(consumers));
                // OK ... see if we are in txn
                Iterator citr = consumerList.iterator();
                while (citr.hasNext()) {
                    logger.log(Logger.DEBUG, " Message " + pr.getSysMessageID() + " has " + consumerList.size() + " consumers ");
                    ConsumerUID cuid = (ConsumerUID) citr.next();
                    String key = pr.getSysMessageID() + ":" + cuid;
                    TransactionList tl = dl.getTransactionList();
                    TransactionUID tid = (TransactionUID) ackLookup.get(key);
                    if (DEBUG) {
                        logger.log(logger.INFO, "loadTakeoverMsgs: lookup " + key + " found tid=" + tid);
                    }
                    if (tid != null) {
                        boolean remote = false;
                        TransactionState ts = tl.retrieveState(tid);
                        if (ts == null) {
                            ts = tl.getRemoteTransactionState(tid);
                            remote = true;
                        }
                        if (DEBUG) {
                            logger.log(logger.INFO, "tid=" + tid + " has state=" + TransactionState.toString(ts.getState()));
                        }
                        if (ts != null && ts.getState() != TransactionState.ROLLEDBACK && ts.getState() != TransactionState.COMMITTED) {
                            // in transaction ...
                            if (DEBUG) {
                                logger.log(Logger.INFO, "loadTakeoverMsgs: Open transaction ack [" + key + "]" + (remote ? "remote" : "") + ", TUID=" + tid);
                            }
                            if (!remote) {
                                try {
                                    tl.addAcknowledgement(tid, pr.getSysMessageID(), cuid, cuid, true, false);
                                } catch (TransactionAckExistException e) {
                                    // can happen if takeover tid's remote txn after restart
                                    // then txn ack would have already been loaded
                                    logger.log(Logger.INFO, Globals.getBrokerResources().getKString(BrokerResources.I_TAKINGOVER_TXN_ACK_ALREADY_EXIST, "[" + pr.getSysMessageID() + "]" + cuid + ":" + cuid, tid + "[" + TransactionState.toString(ts.getState()) + "]"));
                                }
                                tl.addOrphanAck(tid, pr.getSysMessageID(), cuid);
                            }
                            citr.remove();
                            logger.log(Logger.INFO, "Processing open ack " + pr.getSysMessageID() + ":" + cuid + " on " + tid);
                            continue;
                        } else if (ts != null && ts.getState() == TransactionState.COMMITTED) {
                            logger.log(Logger.INFO, "Processing committed ack " + pr.getSysMessageID() + ":" + cuid + " on " + tid);
                            if (pr.acknowledged(cuid, cuid, false, true)) {
                                d.unputMessage(pr, RemoveReason.ACKNOWLEDGED);
                                pr.destroy();
                                continue;
                            }
                            citr.remove();
                            continue;
                        }
                    }
                }
                // route msgs not in transaction
                if (DEBUG) {
                    StringBuilder buf = new StringBuilder();
                    ConsumerUID cid = null;
                    for (int j = 0; j < consumerList.size(); j++) {
                        cid = consumerList.get(j);
                        buf.append(cid);
                        buf.append(' ');
                    }
                    if (deliveryDelays.get(pr) == null) {
                        logger.log(Logger.INFO, "non-transacted: Routing Message " + pr.getSysMessageID() + " to " + consumerList.size() + " consumers:" + buf.toString());
                    } else {
                        logger.log(Logger.INFO, "non-transacted: deliver time not arrived for message " + pr.getSysMessageID());
                    }
                }
                pr.unlock();
                if (deliveryDelays.get(pr) == null) {
                    if (DEBUG) {
                        logger.log(logger.INFO, "Route takeover message " + pr + "[" + pr.getDeliveryTimeInfo() + "] for destination " + d + " to consumers " + consumerList);
                    }
                    if (pr.getDeliveryTimeInfo() != null) {
                        d.forwardDeliveryDelayedMessage(new HashSet<>(consumerList), pr);
                    } else {
                        d.routeLoadedMessage(pr, consumerList);
                    }
                } else {
                    MessageDeliveryTimeInfo di = pr.getDeliveryTimeInfo();
                    di.setDeliveryReady();
                }
                if (d.destReaper != null) {
                    d.destReaper.cancel();
                    d.destReaper = null;
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
Also used : TransactionState(com.sun.messaging.jmq.jmsserver.data.TransactionState) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) SizeString(com.sun.messaging.jmq.util.SizeString) Logger(com.sun.messaging.jmq.util.log.Logger) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList) Packet(com.sun.messaging.jmq.io.Packet) TransactionAcknowledgement(com.sun.messaging.jmq.jmsserver.data.TransactionAcknowledgement) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList) InvalidSysMessageIDException(com.sun.messaging.jmq.io.InvalidSysMessageIDException) PartitionNotFoundException(com.sun.messaging.jmq.jmsserver.util.PartitionNotFoundException) ConflictException(com.sun.messaging.jmq.jmsserver.util.ConflictException) LoadException(com.sun.messaging.jmq.jmsserver.persist.api.LoadException) TransactionAckExistException(com.sun.messaging.jmq.jmsserver.util.TransactionAckExistException) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) InvalidPacketException(com.sun.messaging.jmq.io.InvalidPacketException) InvalidPacketException(com.sun.messaging.jmq.io.InvalidPacketException) RefCompare(com.sun.messaging.jmq.jmsserver.data.handlers.RefCompare) TransactionUID(com.sun.messaging.jmq.jmsserver.data.TransactionUID) TransactionAckExistException(com.sun.messaging.jmq.jmsserver.util.TransactionAckExistException)

Example 5 with TransactionState

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

the class SessionOp method close.

@Override
public void close(Connection conn) {
    TransactionList[] tls = DL.getTransactionList(((IMQConnection) conn).getPartitionedStore());
    TransactionList translist = tls[0];
    // deal w/ old messages
    synchronized (deliveredMessages) {
        if (!deliveredMessages.isEmpty()) {
            // get the list by IDs
            HashMap openMsgs = new HashMap();
            Iterator itr = deliveredMessages.entrySet().iterator();
            while (itr.hasNext()) {
                Map.Entry entry = (Map.Entry) itr.next();
                ackEntry e = (ackEntry) entry.getValue();
                ConsumerUID cuid = e.getConsumerUID();
                ConsumerUID storeduid = (e.getStoredUID() == null ? cuid : e.getStoredUID());
                // deal w/ orphan messages
                TransactionUID tid = e.getTUID();
                if (tid != null) {
                    JMQXid jmqxid = translist.UIDToXid(tid);
                    if (jmqxid != null) {
                        translist.addOrphanAck(tid, e.getSysMessageID(), storeduid, cuid);
                        itr.remove();
                        continue;
                    }
                    TransactionState ts = translist.retrieveState(tid, true);
                    if (ts != null && ts.getState() == TransactionState.PREPARED) {
                        translist.addOrphanAck(tid, e.getSysMessageID(), storeduid, cuid);
                        itr.remove();
                        continue;
                    }
                    if (ts != null && ts.getState() == TransactionState.COMMITTED) {
                        itr.remove();
                        continue;
                    }
                    if (ts != null && ts.getState() == TransactionState.COMPLETE && conn.getConnectionState() >= Connection.STATE_CLOSED) {
                        String[] args = { "" + tid, TransactionState.toString(ts.getState()), session.getConnectionUID().toString() };
                        logger.log(Logger.INFO, Globals.getBrokerResources().getKString(BrokerResources.I_CONN_CLEANUP_KEEP_TXN, args));
                        translist.addOrphanAck(tid, e.getSysMessageID(), storeduid, cuid);
                        itr.remove();
                        continue;
                    }
                }
                PacketReference ref = e.getReference();
                if (ref == null) {
                    // PART
                    ref = DL.get(null, e.getSysMessageID());
                }
                if (ref != null && !ref.isLocal()) {
                    itr.remove();
                    try {
                        if ((ref = e.acknowledged(false)) != null) {
                            try {
                                Destination d = ref.getDestination();
                                d.removeRemoteMessage(ref.getSysMessageID(), RemoveReason.ACKNOWLEDGED, ref);
                            } finally {
                                ref.postAcknowledgedRemoval();
                            }
                        }
                    } catch (Exception ex) {
                        logger.logStack(session.DEBUG_CLUSTER_MSG ? Logger.WARNING : Logger.DEBUG, "Unable to clean up remote message " + e.getDebugMessage(false), ex);
                    }
                    continue;
                }
                // we arent in a transaction ID .. cool
                // add to redeliver list
                Set s = (Set) openMsgs.get(cuid);
                if (s == null) {
                    s = new LinkedHashSet();
                    openMsgs.put(cuid, s);
                }
                if (ref != null) {
                    ref.removeInDelivery(storeduid);
                }
                s.add(e);
            }
            // OK .. see if we ack or cleanup
            itr = openMsgs.entrySet().iterator();
            Map.Entry pair = null;
            while (itr.hasNext()) {
                pair = (Map.Entry) itr.next();
                ConsumerUID cuid = (ConsumerUID) pair.getKey();
                Map parentmp = (Map) cleanupList.get(cuid);
                ConsumerUID suid = (ConsumerUID) storeMap.get(cuid);
                if (parentmp == null || parentmp.size() == 0) {
                    Set s = (Set) pair.getValue();
                    Iterator sitr = s.iterator();
                    while (sitr.hasNext()) {
                        ackEntry e = (ackEntry) sitr.next();
                        try {
                            PacketReference ref = e.acknowledged(false);
                            if (ref != null) {
                                try {
                                    Destination d = ref.getDestination();
                                    try {
                                        if (ref.isLocal()) {
                                            d.removeMessage(ref.getSysMessageID(), RemoveReason.ACKNOWLEDGED);
                                        } else {
                                            d.removeRemoteMessage(ref.getSysMessageID(), RemoveReason.ACKNOWLEDGED, ref);
                                        }
                                    } catch (Exception ex) {
                                        Object[] args = { ref, this, ex.getMessage() };
                                        logger.logStack(Logger.WARNING, Globals.getBrokerResources().getKString(BrokerResources.X_CLEANUP_MSG_CLOSE_SESSION, args), ex);
                                    }
                                } finally {
                                    ref.postAcknowledgedRemoval();
                                }
                            }
                        } catch (Exception ex) {
                        // ignore
                        }
                    }
                } else {
                    Map mp = new LinkedHashMap();
                    Set msgs = null;
                    PartitionedStore ps = null;
                    Set s = (Set) openMsgs.get(cuid);
                    Iterator sitr = s.iterator();
                    while (sitr.hasNext()) {
                        ackEntry e = (ackEntry) sitr.next();
                        PacketReference ref = e.getReference();
                        if (ref != null) {
                            try {
                                if (!e.hasMarkConsumed()) {
                                    ref.consumed(suid, !session.isUnsafeAck(cuid), session.isAutoAck(cuid));
                                }
                            } catch (Exception ex) {
                                logger.logStack(Logger.WARNING, "Unable to consume " + suid + ":" + ref, ex);
                            }
                            ps = ref.getPartitionedStore();
                            if (!ref.getDestinationUID().isQueue()) {
                                ps = new NoPersistPartitionedStoreImpl(suid);
                            }
                            msgs = (Set) mp.get(ps);
                            if (msgs == null) {
                                msgs = new LinkedHashSet();
                                mp.put(ps, msgs);
                            }
                            msgs.add(ref);
                        } else {
                            sitr.remove();
                        }
                    }
                    SubSet pl = null;
                    itr = mp.entrySet().iterator();
                    pair = null;
                    while (itr.hasNext()) {
                        pair = (Map.Entry) itr.next();
                        ps = (PartitionedStore) pair.getKey();
                        pl = (SubSet) parentmp.get(ps);
                        if (pl != null) {
                            ((Prioritized) pl).addAllOrdered((Set) pair.getValue());
                        } else {
                            logger.log(logger.WARNING, "Message(s) " + mp.get(ps) + "[" + suid + ", " + cuid + "] parentlist not found on session closing");
                        }
                    }
                }
            }
            deliveredMessages.clear();
            cleanupList.clear();
            storeMap.clear();
        }
    }
    if (!session.isXATransacted()) {
        Iterator itr = null;
        synchronized (detachedRConsumerUIDs) {
            itr = (new LinkedHashSet(detachedRConsumerUIDs)).iterator();
        }
        while (itr.hasNext()) {
            Consumer c = Consumer.newInstance((ConsumerUID) itr.next());
            try {
                Globals.getClusterBroadcast().destroyConsumer(c, null, true);
            } catch (Exception e) {
                logger.log(Logger.WARNING, "Unable to send consumer [" + c + "] cleanup notification for closing of SessionOp[" + this + "].");
            }
        }
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) TransactionState(com.sun.messaging.jmq.jmsserver.data.TransactionState) LinkedHashSet(java.util.LinkedHashSet) Set(java.util.Set) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) LinkedHashMap(java.util.LinkedHashMap) Iterator(java.util.Iterator) PartitionedStore(com.sun.messaging.jmq.jmsserver.persist.api.PartitionedStore) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList) JMQXid(com.sun.messaging.jmq.util.JMQXid) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) TransactionUID(com.sun.messaging.jmq.jmsserver.data.TransactionUID) NoPersistPartitionedStoreImpl(com.sun.messaging.jmq.jmsserver.persist.api.NoPersistPartitionedStoreImpl) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Aggregations

TransactionState (com.sun.messaging.jmq.jmsserver.data.TransactionState)49 TransactionList (com.sun.messaging.jmq.jmsserver.data.TransactionList)25 TransactionUID (com.sun.messaging.jmq.jmsserver.data.TransactionUID)22 BrokerException (com.sun.messaging.jmq.jmsserver.util.BrokerException)14 JMQXid (com.sun.messaging.jmq.util.JMQXid)9 IOException (java.io.IOException)9 TransactionBroker (com.sun.messaging.jmq.jmsserver.data.TransactionBroker)8 TransactionInfo (com.sun.messaging.jmq.jmsserver.persist.api.TransactionInfo)8 TransactionHandler (com.sun.messaging.jmq.jmsserver.data.handlers.TransactionHandler)7 HashMap (java.util.HashMap)7 ArrayList (java.util.ArrayList)6 PHashMapLoadException (com.sun.messaging.jmq.io.disk.PHashMapLoadException)5 DestinationList (com.sun.messaging.jmq.jmsserver.core.DestinationList)5 LoadException (com.sun.messaging.jmq.jmsserver.persist.api.LoadException)5 BrokerAddress (com.sun.messaging.jmq.jmsserver.core.BrokerAddress)4 PartitionedStore (com.sun.messaging.jmq.jmsserver.persist.api.PartitionedStore)4 ConnectionUID (com.sun.messaging.jmq.jmsserver.service.ConnectionUID)4 SizeString (com.sun.messaging.jmq.util.SizeString)4 Iterator (java.util.Iterator)4 PHashMap (com.sun.messaging.jmq.io.disk.PHashMap)3