Search in sources :

Example 1 with JMQXid

use of com.sun.messaging.jmq.util.JMQXid 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 2 with JMQXid

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

the class TransactionList method addTransactionID.

private TransactionInformation addTransactionID(TransactionUID id, TransactionState ts, boolean takeover, int type, boolean persist) throws BrokerException {
    JMQXid xid = ts.getXid();
    shareLock.lock();
    try {
        if (inuse_translist.contains(id)) {
            if (!takeover || type != TransactionInfo.TXN_CLUSTER || translist.containsKey(id) || !remoteTranslist.containsKey(id)) {
                throw new BrokerException(Globals.getBrokerResources().getKString(BrokerResources.X_TRANSACTIONID_INUSE, id.toString()), BrokerResources.X_TRANSACTIONID_INUSE, (Throwable) null, Status.CONFLICT);
            }
        }
        // If transaction is an XA (has an xid) save it for reverse mapping
        if (xid != null && xidTable.containsKey(xid)) {
            // Xid already in use
            throw new BrokerException(Globals.getBrokerResources().getKString(BrokerResources.X_TRANSACTIONID_INUSE, id.toString() + "[Xid=" + xid.toString() + "]"), BrokerResources.X_TRANSACTIONID_INUSE, (Throwable) null, Status.CONFLICT);
        }
    } finally {
        shareLock.unlock();
    }
    try {
        if (persist) {
            pstore.storeTransaction(id, ts, Destination.PERSIST_SYNC);
        }
    } catch (Exception ex) {
        throw new BrokerException(Globals.getBrokerResources().getKString(BrokerResources.X_TRANSACTION_STORE_ERROR, id.toString()), BrokerResources.X_TRANSACTION_STORE_ERROR, ex, Status.ERROR);
    }
    TransactionInformation ti = new TransactionInformation(id, ts);
    if (takeover) {
        ti.getTakeoverLock();
    }
    exclusiveLock.lock();
    try {
        inuse_translist.add(id);
        translist.put(id, ti);
        if (xid != null) {
            xidTable.put(xid, id);
        }
    } finally {
        exclusiveLock.unlock();
    }
    return ti;
}
Also used : BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) JMQXid(com.sun.messaging.jmq.util.JMQXid) IOException(java.io.IOException) LoadException(com.sun.messaging.jmq.jmsserver.persist.api.LoadException) UnknownTransactionException(com.sun.messaging.jmq.jmsserver.util.UnknownTransactionException) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException)

Example 3 with JMQXid

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

the class PacketUtil method dumpBody.

/**
 * Dump the body of the packet.
 *
 * Note: This method is being refactored from the Packet class so that it can also be used by the old packet code, i.e.
 * the client. By doing this, the client doesn't have any dependency on the broker's Packet class.
 */
public static // Stream to dump contents to
void dumpBody(// Stream to dump contents to
PrintStream os, // Type of packet
int pType, // Input stream to body
InputStream is, // Number of bytes in body
int bodySize, // Packet properties
Hashtable props) {
    os.print("   Message Body: " + bodySize + " bytes ");
    if (is == null) {
        os.println();
        os.flush();
        return;
    }
    int n;
    switch(pType) {
        case PacketType.ACKNOWLEDGE:
        case PacketType.REDELIVER:
            SysMessageID id = new SysMessageID();
            n = bodySize / (SysMessageID.ID_SIZE + 8);
            // Read acknowledgement blocks out of body of packet
            try {
                Integer idType = null;
                if (props != null) {
                    idType = (Integer) props.get("JMQBodyType");
                }
                DataInputStream dis = new DataInputStream(is);
                while (n > 0) {
                    if (idType == null || idType.intValue() == PacketType.CONSUMERID_L_SYSMESSAGEID) {
                        os.print("[" + dis.readLong() + ":");
                    } else {
                        os.print("[" + dis.readInt() + ":");
                    }
                    id.readID(dis);
                    os.print(id + "]");
                    n--;
                }
                dis.close();
            } catch (Exception e) {
                os.println("Exception when reading packet body: " + e);
            }
            break;
        case PacketType.TEXT_MESSAGE:
            n = bodySize;
            if (n > 40) {
                n = 40;
            }
            byte[] buf = new byte[40];
            try {
                is.read(buf);
                os.print("[" + new String(buf));
                if (n < bodySize) {
                    os.print(". . .");
                }
                os.print("]");
            } catch (IOException e) {
                os.println("Exception when reading packet body: " + e);
            }
            break;
        case PacketType.MAP_MESSAGE:
        case PacketType.OBJECT_MESSAGE:
            try {
                ObjectInputStream ois = new FilteringObjectInputStream(is);
                Object o = ois.readObject();
                String s = o.toString();
                if (s.length() > 512) {
                    os.println(s.substring(0, 512) + ". . .");
                } else {
                    os.println(s);
                }
                ois.close();
            } catch (Exception e) {
                os.println("Exception when deserializing packet body: " + e);
            }
            break;
        case PacketType.AUTHENTICATE:
            try {
                String type = (String) props.get("JMQAuthType");
                os.print(type + ": ");
                DataInputStream dis = new DataInputStream(is);
                if (type.equals("basic")) {
                    String username = dis.readUTF();
                    String password = dis.readUTF();
                    os.print("username=" + username + ", password=" + password);
                } else if (type.equals("digest")) {
                    String username = dis.readUTF();
                    String password = dis.readUTF();
                    os.print("username=" + username + ", password=" + password);
                } else {
                    os.print("Unknown authentication type");
                }
            } catch (Exception e) {
                os.println("Exception when reading packet body: " + e);
            }
            break;
        case PacketType.RECOVER_TRANSACTION_REPLY:
            try {
                JMQXid xid;
                Integer quantity = (Integer) props.get("JMQQuantity");
                n = 0;
                if (quantity != null) {
                    n = quantity.intValue();
                }
                DataInputStream dis = new DataInputStream(is);
                while (n > 0) {
                    xid = JMQXid.read(dis);
                    os.println("[XID=" + xid + "], ");
                    n--;
                }
            } catch (IOException e) {
                os.println("Could not decode XIDs: " + e);
            }
            break;
        case PacketType.INFO:
            try {
                ObjectInputStream dis = new FilteringObjectInputStream(is);
                Hashtable ht = (Hashtable) dis.readObject();
                Iterator itr = ht.entrySet().iterator();
                while (itr.hasNext()) {
                    Map.Entry mEntry = (Map.Entry) itr.next();
                    Object key = mEntry.getKey();
                    Object value = mEntry.getValue();
                    if (value instanceof Hashtable) {
                        os.println("\tTable: " + key);
                        Iterator itr1 = ((Hashtable) value).entrySet().iterator();
                        while (itr1.hasNext()) {
                            Map.Entry mEntry1 = (Map.Entry) itr1.next();
                            Object key1 = mEntry1.getKey();
                            Object value1 = mEntry1.getValue();
                            os.println("\t\t" + key1 + "=" + value1);
                        }
                    } else {
                        os.println("\t" + key + "=" + value);
                    }
                }
            } catch (Exception e) {
                os.println("Could not decode INFO packet: " + e);
            }
            break;
        case PacketType.START_TRANSACTION:
        case PacketType.COMMIT_TRANSACTION:
        case PacketType.ROLLBACK_TRANSACTION:
        case PacketType.END_TRANSACTION:
        case PacketType.PREPARE_TRANSACTION:
        case PacketType.RECOVER_TRANSACTION:
            try {
                JMQXid xid;
                xid = JMQXid.read(new DataInputStream(is));
                os.println("[XID=" + xid + "]");
            } catch (IOException e) {
                os.println("Could not decode XID: " + e);
            }
            break;
        case PacketType.VERIFY_TRANSACTION_REPLY:
            try {
                ObjectInputStream oos = new FilteringObjectInputStream(is);
                Object newo = oos.readObject();
                os.println(newo);
            } catch (Exception e) {
                os.println("Could not decode verify body: " + e);
            }
            break;
    }
    os.println();
    os.flush();
}
Also used : Hashtable(java.util.Hashtable) JMQXid(com.sun.messaging.jmq.util.JMQXid) Iterator(java.util.Iterator) FilteringObjectInputStream(com.sun.messaging.jmq.util.io.FilteringObjectInputStream) Map(java.util.Map) FilteringObjectInputStream(com.sun.messaging.jmq.util.io.FilteringObjectInputStream)

Example 4 with JMQXid

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

the class JMSServiceImpl method prepareTransaction.

/**
 * Pepare a transaction.
 *
 * @param connectionId The Id of the connection
 * @param transactionId If non-zero, the transaction being prepared is identified by this broker-generated id
 * @param xid If transactionId is zero, then xid contains the Xid of the XA transaction being prepared
 *
 * @return The JMSServiceReply of the request to prepare a transaction
 *
 * @throws JMSServiceException if the Status returned for the prepareTransaction method is not
 * {@link JMSServiceReply.Status#OK}
 *
 * @see JMSServiceReply.Status#getJMQTransactionID
 *
 * @see JMSServiceReply.Status#BAD_REQUEST
 * @see JMSServiceReply.Status#NOT_FOUND
 * @see JMSServiceReply.Status#PRECONDITION_FAILED
 * @see JMSServiceReply.Status#TIMEOUT
 * @see JMSServiceReply.Status#ERROR
 */
@Override
public JMSServiceReply prepareTransaction(long connectionId, long transactionId, Xid xid) throws JMSServiceException {
    JMSServiceReply reply;
    HashMap props = new HashMap();
    IMQConnection cxn;
    TransactionUID txnUID = null;
    JMQXid jmqXid = null;
    cxn = checkConnectionId(connectionId, "prepareTransaction");
    /*
         * If transactionId is 0, extract it from XID
         */
    if (transactionId == 0) {
        jmqXid = new JMQXid(xid);
        Object[] oo = TransactionList.mapXidToTid(jmqXid, cxn);
        if (oo == null) {
            String errStr = "prepareTransaction(" + connectionId + "): Unknown XID " + jmqXid;
            BrokerException be = new BrokerException(errStr, Status.NOT_FOUND);
            props.put("JMQStatus", getErrorReplyStatus(be));
            throw new JMSServiceException(errStr, be, props);
        }
        txnUID = (TransactionUID) oo[1];
    } else {
        txnUID = new TransactionUID(transactionId);
    }
    try {
        protocol.prepareTransaction(txnUID, cxn);
    } catch (BrokerException be) {
        String errStr = "prepareTransaction: prepare transaction failed. Connection ID: " + connectionId + ", Transaction ID: " + transactionId + ", XID: " + xid;
        logger.logStack(Logger.ERROR, errStr, be);
        props.put("JMQStatus", getErrorReplyStatus(be));
        throw new JMSServiceException(errStr, be, props);
    }
    props.put("JMQStatus", JMSServiceReply.Status.OK);
    props.put("JMQTransactionID", txnUID.longValue());
    reply = new JMSServiceReply(props);
    return (reply);
}
Also used : TransactionUID(com.sun.messaging.jmq.jmsserver.data.TransactionUID) JMQXid(com.sun.messaging.jmq.util.JMQXid)

Example 5 with JMQXid

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

the class JMSServiceImpl method endTransaction.

/**
 * End a transaction.
 *
 * @param connectionId The Id of the connection
 * @param transactionId If non-zero, the transaction being ended is identified by this broker-generated id
 * @param xid If transactionId is zero, then xid contains the Xid of the XA transaction being ended
 * @param flags If this is an XA transaction, then flags is one of:
 * <UL>
 * <LI>XAResource.TMSUSPEND: If suspending a transaction</LI>
 * <LI>XAResource.TMFAIL: If failing a transaction</LI>
 * <LI>XAResource.TMSUCCESS: If ending a transaction</LI>
 * </UL>
 *
 * @return The JMSServiceReply of the request to end a transaction
 *
 * @throws JMSServiceException if the Status returned for the endTransaction method is not
 * {@link JMSServiceReply.Status#OK}
 *
 * @see JMSServiceReply.Status#getJMQTransactionID
 *
 * @see JMSServiceReply.Status#BAD_REQUEST
 * @see JMSServiceReply.Status#NOT_FOUND
 * @see JMSServiceReply.Status#PRECONDITION_FAILED
 * @see JMSServiceReply.Status#TIMEOUT
 * @see JMSServiceReply.Status#ERROR
 */
@Override
public JMSServiceReply endTransaction(long connectionId, long transactionId, Xid xid, int flags) throws JMSServiceException {
    JMSServiceReply reply;
    HashMap props = new HashMap();
    IMQConnection cxn;
    TransactionUID txnUID = null;
    JMQXid jmqXid = null;
    Integer xaFlags = null;
    cxn = checkConnectionId(connectionId, "endTransaction");
    txnUID = new TransactionUID(transactionId);
    if (xid != null) {
        jmqXid = new JMQXid(xid);
        xaFlags = Integer.valueOf(flags);
    }
    try {
        protocol.endTransaction(txnUID, jmqXid, xaFlags, cxn);
    } catch (BrokerException be) {
        String errStr = "endTransaction: end transaction failed. Connection ID: " + connectionId + ", Transaction ID: " + transactionId + ", XID: " + xid;
        logger.logStack(Logger.ERROR, errStr, be);
        props.put("JMQStatus", getErrorReplyStatus(be));
        throw new JMSServiceException(errStr, be, props);
    }
    props.put("JMQStatus", JMSServiceReply.Status.OK);
    props.put("JMQTransactionID", txnUID.longValue());
    reply = new JMSServiceReply(props);
    return (reply);
}
Also used : TransactionUID(com.sun.messaging.jmq.jmsserver.data.TransactionUID) JMQXid(com.sun.messaging.jmq.util.JMQXid)

Aggregations

JMQXid (com.sun.messaging.jmq.util.JMQXid)39 TransactionUID (com.sun.messaging.jmq.jmsserver.data.TransactionUID)13 TransactionState (com.sun.messaging.jmq.jmsserver.data.TransactionState)9 TransactionList (com.sun.messaging.jmq.jmsserver.data.TransactionList)6 BrokerException (com.sun.messaging.jmq.jmsserver.util.BrokerException)6 XidImpl (com.sun.messaging.jmq.util.XidImpl)4 JMSException (jakarta.jms.JMSException)4 Hashtable (java.util.Hashtable)4 XAException (javax.transaction.xa.XAException)4 JMSRASessionAdapter (com.sun.messaging.jms.ra.api.JMSRASessionAdapter)3 IOException (java.io.IOException)3 HashMap (java.util.HashMap)3 Iterator (java.util.Iterator)3 Map (java.util.Map)3 BrokerAddress (com.sun.messaging.jmq.jmsserver.core.BrokerAddress)2 TransactionBroker (com.sun.messaging.jmq.jmsserver.data.TransactionBroker)2 TransactionHandler (com.sun.messaging.jmq.jmsserver.data.handlers.TransactionHandler)2 PartitionedStore (com.sun.messaging.jmq.jmsserver.persist.api.PartitionedStore)2 UnknownTransactionException (com.sun.messaging.jmq.jmsserver.util.UnknownTransactionException)2 SelectorFormatException (com.sun.messaging.jmq.util.selector.SelectorFormatException)2