Search in sources :

Example 1 with MessageDeliveryTimeInfo

use of com.sun.messaging.jmq.jmsserver.core.MessageDeliveryTimeInfo in project openmq by eclipse-ee4j.

the class ProtocolImpl method processMessage.

/**
 * route, store and forward a message
 */
@Override
public void processMessage(IMQConnection con, Packet msg) throws BrokerException, SelectorFormatException, IOException {
    DataHandler handler = (DataHandler) pr.getHandler(PacketType.MESSAGE);
    Destination d = null;
    PacketReference ref = null;
    Set s = null;
    boolean route = false;
    boolean isadmin = con.isAdminConnection();
    List<MessageDeliveryTimeInfo> deliveryDelayReadyList = new ArrayList<>();
    try {
        Destination[] ds = DL.getDestination(con.getPartitionedStore(), msg.getDestination(), msg.getIsQueue());
        d = ds[0];
        if (d == null) {
            throw new BrokerException("Unknown Destination:" + msg.getDestination());
        }
        Producer pausedProducer = handler.checkFlow(msg, con);
        boolean transacted = (msg.getTransactionID() != 0);
        if (DEBUG) {
            logger.log(Logger.INFO, "ProtocolImpl.PROCESS MESSAGE[" + msg + "]TID=" + msg.getTransactionID() + " to destination " + d + ", on conn=@" + con.hashCode() + "[" + con.getConnectionUID() + ", " + con + "]");
        }
        // OK generate a ref. This checks message size and
        // will be needed for later operations
        ref = handler.createReference(msg, d.getDestinationUID(), con, isadmin);
        // dont bother calling route if there are no messages
        // 
        // to improve performance, we route and later forward
        route = handler.queueMessage(d, ref, transacted);
        s = handler.routeMessage(con.getPartitionedStore(), transacted, ref, route, d, deliveryDelayReadyList);
        // handle producer flow control
        handler.pauseProducer(d, pausedProducer, con);
    } catch (BrokerException ex) {
        int status = ex.getStatusCode();
        if (status == Status.ERROR && ref != null && d != null) {
            handler.cleanupOnError(d, ref);
        }
        // rethrow
        throw ex;
    }
    if (route && s != null) {
        try {
            handler.forwardMessage(d, ref, s);
        } catch (Exception e) {
            Object[] emsg = { ref, d.getDestinationUID(), s };
            logger.logStack(Logger.WARNING, Globals.getBrokerResources().getKString(BrokerResources.X_ROUTE_PRODUCED_MSG_FAIL, emsg), e);
        }
    }
    if (deliveryDelayReadyList.size() > 0) {
        MessageDeliveryTimeInfo di = null;
        Iterator<MessageDeliveryTimeInfo> itr = deliveryDelayReadyList.iterator();
        while (itr.hasNext()) {
            di = itr.next();
            di.setDeliveryReady();
        }
    }
}
Also used : Destination(com.sun.messaging.jmq.jmsserver.core.Destination) Set(java.util.Set) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) ArrayList(java.util.ArrayList) DataHandler(com.sun.messaging.jmq.jmsserver.data.handlers.DataHandler) AccessControlException(java.security.AccessControlException) SelectorFormatException(com.sun.messaging.jmq.util.selector.SelectorFormatException) IOException(java.io.IOException) MaxConsecutiveRollbackException(com.sun.messaging.jmq.jmsserver.util.MaxConsecutiveRollbackException) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) Producer(com.sun.messaging.jmq.jmsserver.core.Producer) PacketReference(com.sun.messaging.jmq.jmsserver.core.PacketReference) MessageDeliveryTimeInfo(com.sun.messaging.jmq.jmsserver.core.MessageDeliveryTimeInfo)

Example 2 with MessageDeliveryTimeInfo

use of com.sun.messaging.jmq.jmsserver.core.MessageDeliveryTimeInfo in project openmq by eclipse-ee4j.

the class DataHandler method handle.

/**
 * Method to handle normal/admin data messages
 */
protected boolean handle(IMQConnection con, Packet msg, boolean isadmin) throws BrokerException {
    // used for fault injection
    Hashtable props = null;
    if (!isadmin && fi.FAULT_INJECTION) {
        // for fault injection
        msgProcessCnt++;
        try {
            props = msg.getProperties();
        } catch (Exception ex) {
            props = new Properties();
        }
    } else {
        msgProcessCnt = 0;
    }
    boolean ack = msg.getSendAcknowledge();
    long cid = msg.getConsumerID();
    String refid = (((IMQBasicConnection) con).getDumpPacket() || ((IMQBasicConnection) con).getDumpOutPacket()) ? msg.getSysMessageID().toString() : "";
    boolean isIndemp = msg.getIndempotent();
    String reason = null;
    List failedrefs = null;
    int status = Status.OK;
    HashMap routedSet = null;
    List<MessageDeliveryTimeInfo> deliveryDelayReadyList = new ArrayList<>();
    boolean route = false;
    Producer pausedProducer = null;
    boolean transacted = false;
    try {
        pausedProducer = checkFlow(msg, con);
        transacted = (msg.getTransactionID() != 0);
        // OK .. handle Fault Injection
        if (!isadmin && fi.FAULT_INJECTION) {
            Map m = new HashMap();
            if (props != null) {
                m.putAll(props);
            }
            m.put("mqMsgCount", Integer.valueOf(msgProcessCnt));
            m.put("mqIsTransacted", Boolean.valueOf(transacted));
            fi.checkFaultAndExit(FaultInjection.FAULT_SEND_MSG_1, m, 2, false);
            if (fi.checkFault(FaultInjection.FAULT_SEND_MSG_1_EXCEPTION, m)) {
                fi.unsetFault(FaultInjection.FAULT_SEND_MSG_1_EXCEPTION);
                throw new BrokerException("FAULT INJECTION: " + FaultInjection.FAULT_SEND_MSG_1_EXCEPTION);
            }
            if (fi.checkFaultAndSleep(FaultInjection.FAULT_SEND_MSG_1_SLEEP, m, true)) {
                fi.unsetFault(FaultInjection.FAULT_SEND_MSG_1_SLEEP);
            }
            if (fi.checkFaultAndSleep(FaultInjection.FAULT_SEND_MSG_1_SLEEP_EXCEPTION, m, true)) {
                fi.unsetFault(FaultInjection.FAULT_SEND_MSG_1_SLEEP_EXCEPTION);
                throw new BrokerException("FAULT INJECTION: " + FaultInjection.FAULT_SEND_MSG_1_SLEEP_EXCEPTION);
            }
        }
        DestinationUID realduid = DestinationUID.getUID(msg.getDestination(), msg.getIsQueue());
        if (DEBUG) {
            logger.log(Logger.INFO, "DataHandler:Received JMS Message[" + msg.toString() + " : " + realduid + "]TID=" + msg.getTransactionID() + " on connection " + con + ", isadmin=" + isadmin);
        }
        // get the list of "real" destination UIDs (this will be one if the
        // destination if not a wildcard and 0 or more if it is
        List[] dds = DL.findMatchingIDs(con.getPartitionedStore(), realduid);
        List duids = dds[0];
        boolean packetUsed = false;
        if (duids.size() == 0) {
            // nothing to do
            route = false;
        } else {
            Iterator itr = duids.iterator();
            while (itr.hasNext()) {
                PacketReference ref = null;
                Exception lastthr = null;
                boolean isLast = false;
                DestinationUID duid = (DestinationUID) itr.next();
                isLast = !itr.hasNext();
                Destination[] ds = DL.getDestination(con.getPartitionedStore(), duid);
                Destination d = ds[0];
                try {
                    if (d == null) {
                        throw new BrokerException("Unknown Destination:" + msg.getDestination());
                    }
                    if (realduid.isWildcard() && d.isTemporary()) {
                        logger.log(Logger.DEBUG, "L10N-XXX: Wildcard production with destination name of " + realduid + " to temporary destination " + d.getUniqueName() + " is not supported, ignoring");
                        continue;
                    }
                    if (realduid.isWildcard() && d.isInternal()) {
                        logger.log(Logger.DEBUG, "L10N-XXX: Wildcard production with destination name of " + realduid + " to internal destination " + d.getUniqueName() + " is not supported, ignoring");
                        continue;
                    }
                    if (realduid.isWildcard() && d.isDMQ()) {
                        logger.log(Logger.DEBUG, "L10N-XXX: Wildcard production with destination name of " + realduid + " to the DeadMessageQueue" + d.getUniqueName() + " is not supported, ignoring");
                        continue;
                    }
                    if (pausedProducer != null) {
                        pauseProducer(d, duid, pausedProducer, con);
                        pausedProducer = null;
                    }
                    if (packetUsed) {
                        // create a new Packet for the message
                        // we need a new sysmsgid with it
                        Packet newp = new Packet();
                        newp.fill(msg);
                        newp.generateSequenceNumber(true);
                        newp.generateTimestamp(true);
                        newp.prepareToSend();
                        newp.generateSequenceNumber(false);
                        newp.generateTimestamp(false);
                        msg = newp;
                    }
                    packetUsed = true;
                    // OK generate a ref. This checks message size and
                    // will be needed for later operations
                    ref = createReference(msg, duid, con, isadmin);
                    // dont bother calling route if there are no messages
                    // 
                    // to improve performance, we route and later forward
                    route |= queueMessage(d, ref, transacted);
                    // ok ...
                    if (isLast && route && ack && !ref.isPersistent()) {
                        sendAcknowledge(refid, cid, status, con, reason, props, transacted);
                        ack = false;
                    }
                    Set s = routeMessage(con.getPartitionedStore(), transacted, ref, route, d, deliveryDelayReadyList);
                    if (s != null && !s.isEmpty()) {
                        if (routedSet == null) {
                            routedSet = new HashMap();
                        }
                        routedSet.put(ref, s);
                    }
                    // handle producer flow control
                    pauseProducer(d, duid, pausedProducer, con);
                } catch (Exception ex) {
                    if (ref != null) {
                        if (failedrefs == null) {
                            failedrefs = new ArrayList();
                        }
                        failedrefs.add(ref);
                    }
                    lastthr = ex;
                    logger.log(Logger.DEBUG, BrokerResources.W_MESSAGE_STORE_FAILED, con.toString(), ex);
                } finally {
                    if (pausedProducer != null) {
                        pauseProducer(d, duid, pausedProducer, con);
                        pausedProducer = null;
                    }
                    if (isLast && lastthr != null) {
                        throw lastthr;
                    }
                }
            }
        // while
        }
    } catch (BrokerException ex) {
        // dont log on dups if indemponent
        int loglevel = (isIndemp && ex.getStatusCode() == Status.NOT_MODIFIED) ? Logger.DEBUG : Logger.WARNING;
        logger.log(loglevel, BrokerResources.W_MESSAGE_STORE_FAILED, con.toString(), ex);
        reason = ex.getMessage();
        // LKS - we may want an improved error message in the wildcard case
        status = ex.getStatusCode();
    } catch (IOException ex) {
        logger.log(Logger.WARNING, BrokerResources.W_MESSAGE_STORE_FAILED, con.toString(), ex);
        reason = ex.getMessage();
        status = Status.ERROR;
    } catch (SecurityException ex) {
        logger.log(Logger.WARNING, BrokerResources.W_MESSAGE_STORE_FAILED, con.toString(), ex);
        reason = ex.getMessage();
        status = Status.FORBIDDEN;
    } catch (OutOfMemoryError err) {
        logger.logStack(Logger.WARNING, BrokerResources.W_MESSAGE_STORE_FAILED, con.toString() + ":" + msg.getPacketSize(), err);
        reason = err.getMessage();
        status = Status.ERROR;
    } catch (Exception ex) {
        logger.logStack(Logger.WARNING, BrokerResources.W_MESSAGE_STORE_FAILED, con.toString(), ex);
        reason = ex.getMessage();
        status = Status.ERROR;
    }
    if (status == Status.ERROR && failedrefs != null) {
        // make sure we remove the message
        // 
        // NOTE: we only want to remove the last failure (its too late
        // for the rest). In the non-wildcard case, this will be the
        // only entry. In the wildcard cause, it will be the one that had an issue
        Iterator itr = failedrefs.iterator();
        while (itr.hasNext()) {
            PacketReference ref = (PacketReference) itr.next();
            Destination[] ds = DL.getDestination(con.getPartitionedStore(), ref.getDestinationUID());
            Destination d = ds[0];
            if (d != null) {
                cleanupOnError(d, ref);
            }
        }
    }
    if (ack) {
        sendAcknowledge(refid, cid, status, con, reason, props, transacted);
    }
    if (route && routedSet != null) {
        Iterator<Map.Entry> itr = routedSet.entrySet().iterator();
        Map.Entry pair = null;
        while (itr.hasNext()) {
            pair = itr.next();
            PacketReference pktref = (PacketReference) pair.getKey();
            DestinationUID duid = pktref.getDestinationUID();
            Set s = (Set) pair.getValue();
            Destination[] ds = DL.getDestination(con.getPartitionedStore(), duid);
            Destination dest = ds[0];
            if (dest == null) {
                Object[] emsg = { pktref, s, duid };
                logger.log(logger.WARNING, br.getKString(br.W_ROUTE_PRODUCED_MSG_DEST_NOT_FOUND, emsg));
                continue;
            }
            try {
                forwardMessage(dest, pktref, s);
            } catch (Exception e) {
                Object[] emsg = { pktref, duid, s };
                logger.logStack(logger.WARNING, br.getKString(br.X_ROUTE_PRODUCED_MSG_FAIL, emsg), e);
            }
        }
    }
    if (deliveryDelayReadyList.size() > 0) {
        MessageDeliveryTimeInfo di = null;
        Iterator<MessageDeliveryTimeInfo> itr = deliveryDelayReadyList.iterator();
        while (itr.hasNext()) {
            di = itr.next();
            di.setDeliveryReady();
        }
    }
    // someone else will free
    return isadmin;
}
Also used : Destination(com.sun.messaging.jmq.jmsserver.core.Destination) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) PacketReference(com.sun.messaging.jmq.jmsserver.core.PacketReference) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList) MessageDeliveryTimeInfo(com.sun.messaging.jmq.jmsserver.core.MessageDeliveryTimeInfo) SelectorFormatException(com.sun.messaging.jmq.util.selector.SelectorFormatException) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) DestinationUID(com.sun.messaging.jmq.jmsserver.core.DestinationUID) Producer(com.sun.messaging.jmq.jmsserver.core.Producer)

Example 3 with MessageDeliveryTimeInfo

use of com.sun.messaging.jmq.jmsserver.core.MessageDeliveryTimeInfo in project openmq by eclipse-ee4j.

the class DataHandler method routeMessage.

public Set routeMessage(PartitionedStore storep, boolean transacted, PacketReference ref, boolean route, Destination d, List<MessageDeliveryTimeInfo> readylist) throws BrokerException, SelectorFormatException {
    String reason = null;
    int status = Status.OK;
    Set s = null;
    MessageDeliveryTimeInfo di = ref.getDeliveryTimeInfo();
    // if transacted, just store, dont route
    if (transacted) {
        try {
            TransactionList[] tls = DL.getTransactionList(storep);
            TransactionList tl = tls[0];
            tl.addMessage(ref);
        } catch (Exception ex) {
            String emsg = br.getKString(br.X_PROCESS_PRODUCED_MESSAGE_FAIL, ref + "[TID=" + ref.getTransactionID() + ", " + di + "]", ex.getMessage());
            ref.destroy();
            logger.logStack((BrokerStateHandler.isShuttingDown() ? Logger.DEBUG : Logger.WARNING), emsg, ex);
            reason = emsg;
            status = Status.ERROR;
            throw new BrokerException(reason, status);
        }
    } else {
        if (route) {
            if (di != null && di.getOnTimerState() != null) {
                d.routeNewMessageWithDeliveryDelay(ref);
                readylist.add(di);
            } else {
                s = d.routeNewMessage(ref);
            }
        }
    }
    return s;
}
Also used : BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList) MessageDeliveryTimeInfo(com.sun.messaging.jmq.jmsserver.core.MessageDeliveryTimeInfo) SelectorFormatException(com.sun.messaging.jmq.util.selector.SelectorFormatException) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException)

Example 4 with MessageDeliveryTimeInfo

use of com.sun.messaging.jmq.jmsserver.core.MessageDeliveryTimeInfo in project openmq by eclipse-ee4j.

the class TransactionHandler method doCommit.

/**
 * Commit a transaction. This method is invoked from two places: 1) From TransactionHandler.handle() when handling a
 * client COMMIT packet. This is the common case. 2) From the admin handler when an admin commit request has been issued
 * on a PREPARED XA transaction.
 *
 * @param id The TransactionUID to commit
 * @param xid The Xid of the transaction to commit. Required if transaction is an XA transaction. Must be null if it is
 * not an XA transaction.
 * @param xaFlags xaFlags passed on COMMIT operation. Used only if an XA transaction.
 * @param ts Current TransactionState of this transaction.
 * @param conlist List of transactions on this connection. Will be null if commit is trigger by an admin request.
 * @param sendReply True to have method send a Status.OK reply while processing transaction. This should be "true" for
 * client initiated commits, "false" for admin initiated commits.
 * @param con Connection client commit packet came in on or, for admin, the connection the admin request came in on.
 * @param msg Client commit packet. Should be "null" for admin initiated commits.
 *
 * @throws BrokerException on an error. The method will have logged a message to the broker log.
 */
public void doCommit(TransactionList translist, TransactionUID id, JMQXid xid, Integer xaFlags, TransactionState ts, List conlist, boolean sendReply, IMQConnection con, Packet msg, boolean startNextTransaction) throws BrokerException {
    int status = Status.OK;
    HashMap cmap = null;
    HashMap sToCmap = null;
    List plist = null;
    PartitionedStore pstore = translist.getPartitionedStore();
    // local, or cluster
    int transactionType = BaseTransaction.UNDEFINED_TRANSACTION_TYPE;
    if (fi.checkFault(FaultInjection.FAULT_TXN_COMMIT_1_EXCEPTION, null)) {
        fi.unsetFault(FaultInjection.FAULT_TXN_COMMIT_1_EXCEPTION);
        throw new BrokerException(FaultInjection.FAULT_TXN_COMMIT_1_EXCEPTION);
    }
    // let acks get handled at a lower level since the
    // lower level methods assumes only 1 ack per message
    plist = translist.retrieveSentMessages(id);
    cmap = translist.retrieveConsumedMessages(id);
    sToCmap = translist.retrieveStoredConsumerUIDs(id);
    cacheSetState(id, ts, con);
    // remove from our active connection list
    if (conlist != null) {
        conlist.remove(id);
    }
    try {
        Globals.getStore().txnLogSharedLock.lock();
        TransactionWork txnWork = null;
        if (Globals.isNewTxnLogEnabled()) {
            txnWork = getTransactionWork2(translist.getPartitionedStore(), plist, cmap, sToCmap);
        }
        // Update transaction state
        try {
            int s;
            if (xid == null) {
                // Plain JMS transaction.
                s = TransactionState.COMMITTED;
            } else {
                // XA Transaction.
                s = ts.nextState(PacketType.COMMIT_TRANSACTION, xaFlags);
            }
            // After this call, returned base transaction will either be:
            // a) null (for single phase LOCAL transaction)
            // b) a prepared XA LOCAL transaction
            // c) a prepared (XA or not) CLUSTER transaction
            // currently, all cluster transactions are 2 phase
            BaseTransaction baseTransaction = doRemoteCommit(translist, id, xaFlags, ts, s, msg, txnWork, con);
            if (Globals.isNewTxnLogEnabled()) {
                if (ts.getState() == TransactionState.PREPARED) {
                    // commit called (from client) on 2-phase transaction
                    transactionType = BaseTransaction.LOCAL_TRANSACTION_TYPE;
                    if (translist.isClusterTransaction(id)) {
                        transactionType = BaseTransaction.CLUSTER_TRANSACTION_TYPE;
                    }
                    logTxnCompletion(translist.getPartitionedStore(), id, TransactionState.COMMITTED, transactionType);
                } else if ((baseTransaction != null && baseTransaction.getState() == TransactionState.PREPARED)) {
                    transactionType = baseTransaction.getType();
                    logTxnCompletion(translist.getPartitionedStore(), id, TransactionState.COMMITTED, transactionType);
                } else {
                    // one phase commit, log all work here
                    transactionType = BaseTransaction.LOCAL_TRANSACTION_TYPE;
                    LocalTransaction localTxn = new LocalTransaction(id, TransactionState.COMMITTED, xid, txnWork);
                    logTxn(translist.getPartitionedStore(), localTxn);
                }
            } else {
            // System.out.println("isFastLogTransactions=false ");
            }
            if (fi.FAULT_INJECTION) {
                fi.checkFaultAndThrowBrokerException(FaultInjection.FAULT_TXN_COMMIT_1_1, null);
            }
            if (ts.getState() == TransactionState.PREPARED || (baseTransaction != null && baseTransaction.getState() == TransactionState.PREPARED)) {
                translist.updateState(id, s, true);
            } else {
                // 1-phase commit
                if (ts.getType() != AutoRollbackType.NEVER && Globals.isMinimumPersistLevel2()) {
                    translist.updateStateCommitWithWork(id, s, true);
                } else {
                    translist.updateState(id, s, true);
                }
            }
            if (fi.FAULT_INJECTION) {
                checkFIAfterDB(PacketType.COMMIT_TRANSACTION);
                fi.checkFaultAndExit(FaultInjection.FAULT_TXN_COMMIT_1_5, null, 2, false);
            }
            startTxnAndSendReply(translist, con, msg, status, startNextTransaction, conlist, xid, id, xaFlags, sendReply);
        } catch (BrokerException ex) {
            logger.logStack(((ex instanceof AckEntryNotFoundException) ? Logger.WARNING : Logger.ERROR), ex.toString() + ": TUID=" + id + " Xid=" + xid, ex);
            throw ex;
        }
        try {
            /*
                 * Can't really call the JMX notification code at the end of doCommit() because the call to
                 * translist.removeTransactionID(id) removes the MBean.
                 */
            Agent agent = Globals.getAgent();
            if (agent != null) {
                agent.notifyTransactionCommit(id);
            }
        } catch (Exception e) {
            logger.log(Logger.WARNING, "JMX agent notify transaction committed failed:" + e.getMessage());
        }
        // OK .. handle producer transaction
        int pLogRecordByteCount = 0;
        ArrayList pLogMsgList = null;
        for (int i = 0; plist != null && i < plist.size(); i++) {
            SysMessageID sysid = (SysMessageID) plist.get(i);
            PacketReference ref = DL.get(pstore, sysid);
            if (ref == null) {
                logger.log(Logger.WARNING, Globals.getBrokerResources().getKString(BrokerResources.W_MSG_REMOVED_BEFORE_SENDER_COMMIT, sysid));
                continue;
            }
            // handle forwarding the message
            try {
                if (Globals.txnLogEnabled()) {
                    if (pLogMsgList == null) {
                        pLogMsgList = new ArrayList();
                    }
                    // keep track for producer txn log
                    pLogRecordByteCount += ref.getSize();
                    pLogMsgList.add(ref.getPacket().getBytes());
                }
                Destination[] ds = DL.getDestination(pstore, ref.getDestinationUID());
                Destination d = ds[0];
                if (fi.FAULT_INJECTION) {
                    fi.checkFaultAndExit(FaultInjection.FAULT_TXN_COMMIT_1_6, null, 2, false);
                }
                MessageDeliveryTimeInfo di = ref.getDeliveryTimeInfo();
                if (di != null) {
                    d.routeCommittedMessageWithDeliveryTime(ref);
                } else {
                    Set s = d.routeNewMessage(ref);
                    d.forwardMessage(s, ref);
                }
            } catch (Exception ex) {
                logger.logStack((BrokerStateHandler.isShuttingDown() ? Logger.DEBUG : Logger.ERROR), ex.getMessage() + "[" + sysid + "]TUID=" + id, ex);
            }
        }
        boolean processDone = true;
        // handle consumer transaction
        int cLogRecordCount = 0;
        ArrayList cLogDstList = null;
        ArrayList cLogMsgList = null;
        ArrayList cLogIntList = null;
        HashMap<TransactionBroker, Object> remoteNotified = new HashMap<>();
        if (cmap != null && cmap.size() > 0) {
            Iterator itr = cmap.entrySet().iterator();
            while (itr.hasNext()) {
                Map.Entry entry = (Map.Entry) itr.next();
                SysMessageID sysid = (SysMessageID) entry.getKey();
                // CANT just pull from connection
                if (sysid == null) {
                    continue;
                }
                PacketReference ref = DL.get(null, sysid);
                if (ref == null || ref.isDestroyed() || ref.isInvalid()) {
                    // already been deleted .. ignore
                    continue;
                }
                PartitionedStore refpstore = ref.getPartitionedStore();
                Destination[] ds = DL.getDestination(refpstore, ref.getDestinationUID());
                Destination dst = ds[0];
                if (dst == null) {
                    if (ref.isDestroyed() || ref.isInvalid()) {
                        continue;
                    }
                }
                List interests = (List) entry.getValue();
                for (int i = 0; i < interests.size(); i++) {
                    ConsumerUID intid = (ConsumerUID) interests.get(i);
                    ConsumerUID sid = (ConsumerUID) sToCmap.get(intid);
                    if (sid == null) {
                        sid = intid;
                    }
                    try {
                        Session s = Session.getSession(intid);
                        if (s != null) {
                            Consumer c = Consumer.getConsumer(intid);
                            if (c != null) {
                                c.messageCommitted(sysid);
                            }
                            PacketReference r1 = null;
                            if (fi.FAULT_INJECTION && fi.checkFault(FaultInjection.FAULT_TXN_COMMIT_1_7_1, null)) {
                                Globals.getConnectionManager().getConnection(s.getConnectionUID()).destroyConnection(true, GoodbyeReason.OTHER, "Fault injection of closing connection");
                            }
                            r1 = (PacketReference) s.ackMessage(intid, sysid, id, translist, remoteNotified, true);
                            try {
                                s.postAckMessage(intid, sysid, true);
                                if (r1 != null) {
                                    if (fi.FAULT_INJECTION) {
                                        fi.checkFaultAndExit(FaultInjection.FAULT_TXN_COMMIT_1_7, null, 2, false);
                                    }
                                    if (dst != null) {
                                        dst.removeMessage(ref.getSysMessageID(), RemoveReason.ACKNOWLEDGED);
                                    }
                                } else {
                                    s = Session.getSession(intid);
                                }
                            } finally {
                                if (r1 != null) {
                                    r1.postAcknowledgedRemoval();
                                }
                            }
                        }
                        if (s == null) {
                            // with the stored UID
                            try {
                                if (ref.acknowledged(intid, sid, true, true, id, translist, remoteNotified, true)) {
                                    try {
                                        if (dst != null) {
                                            dst.removeMessage(ref.getSysMessageID(), RemoveReason.ACKNOWLEDGED);
                                        }
                                    } finally {
                                        ref.postAcknowledgedRemoval();
                                    }
                                }
                            } catch (BrokerException ex) {
                                // XXX improve internal error
                                logger.log(Logger.WARNING, "Internal error", ex);
                            }
                        }
                        if (Globals.txnLogEnabled()) {
                            if (cLogDstList == null) {
                                cLogDstList = new ArrayList();
                                cLogMsgList = new ArrayList();
                                cLogIntList = new ArrayList();
                            }
                            // ignore non-durable subscriber
                            if (dst == null || (!dst.isQueue() && !sid.shouldStore())) {
                                continue;
                            }
                            cLogRecordCount++;
                            cLogDstList.add(dst.getUniqueName());
                            cLogMsgList.add(sysid);
                            cLogIntList.add(sid);
                        }
                    } catch (Exception ex) {
                        processDone = false;
                        String[] args = { "[" + sysid + ":" + intid + ", " + dst + "]ref=" + ref.getSysMessageID(), id.toString(), con.getConnectionUID().toString() };
                        String emsg = Globals.getBrokerResources().getKString(BrokerResources.W_PROCCESS_COMMITTED_ACK, args);
                        logger.logStack(Logger.WARNING, emsg + "\n" + com.sun.messaging.jmq.io.PacketUtil.dumpPacket(msg) + "--------------------------------------------", ex);
                    }
                }
            }
        }
        if (Globals.isNewTxnLogEnabled()) {
            // notify that transaction work has been written to message store
            loggedCommitWrittenToMessageStore(translist.getPartitionedStore(), id, transactionType);
        }
        if (fi.FAULT_INJECTION) {
            checkFIAfterDB(PacketType.COMMIT_TRANSACTION);
            fi.checkFaultAndExit(FaultInjection.FAULT_TXN_COMMIT_2_1, null, 2, false);
        }
        // OK .. now remove the acks .. and free up the id for ues
        // XXX Fixed 6383878, memory leaks because txn ack can never be removed
        // from the store if the txn is removed before the ack; this is due
        // to the fack that in 4.0 when removing the ack, the method check
        // to see if the txn still exits in the cache. This temporary fix
        // will probably break some HA functionality and need to be revisited.
        translist.removeTransaction(id, (!processDone || (cmap.size() > 0 && BrokerStateHandler.isShuttingDown())));
        if (conlist == null) {
            // from admin
            logger.log(logger.WARNING, BrokerResources.W_ADMIN_COMMITTED_TXN, id, ((xid == null) ? "null" : xid.toString()));
        }
        // log to txn log if enabled
        try {
            if (pLogRecordByteCount > 0 && cLogRecordCount > 0) {
                // Log all msgs and acks for producing and consuming txn
                ByteArrayOutputStream bos = new ByteArrayOutputStream((pLogRecordByteCount) + (cLogRecordCount * (32 + SysMessageID.ID_SIZE + 8)) + 16);
                DataOutputStream dos = new DataOutputStream(bos);
                // Transaction ID (8 bytes)
                dos.writeLong(id.longValue());
                // Msgs produce section
                // Number of msgs (4 bytes)
                dos.writeInt(pLogMsgList.size());
                Iterator itr = pLogMsgList.iterator();
                while (itr.hasNext()) {
                    // Message
                    dos.write((byte[]) itr.next());
                }
                // Msgs consume section
                // Number of acks (4 bytes)
                dos.writeInt(cLogRecordCount);
                for (int i = 0; i < cLogRecordCount; i++) {
                    String dst = (String) cLogDstList.get(i);
                    // Destination
                    dos.writeUTF(dst);
                    SysMessageID sysid = (SysMessageID) cLogMsgList.get(i);
                    // SysMessageID
                    sysid.writeID(dos);
                    ConsumerUID intid = (ConsumerUID) cLogIntList.get(i);
                    // ConsumerUID
                    dos.writeLong(intid.longValue());
                }
                dos.close();
                bos.close();
                ((TxnLoggingStore) pstore).logTxn(TransactionLogType.PRODUCE_AND_CONSUME_TRANSACTION, bos.toByteArray());
            } else if (pLogRecordByteCount > 0) {
                // Log all msgs for producing txn
                ByteBuffer bbuf = ByteBuffer.allocate(pLogRecordByteCount + 12);
                // Transaction ID (8 bytes)
                bbuf.putLong(id.longValue());
                // Number of msgs (4 bytes)
                bbuf.putInt(pLogMsgList.size());
                Iterator itr = pLogMsgList.iterator();
                while (itr.hasNext()) {
                    // Message
                    bbuf.put((byte[]) itr.next());
                }
                ((TxnLoggingStore) pstore).logTxn(TransactionLogType.PRODUCE_TRANSACTION, bbuf.array());
            } else if (cLogRecordCount > 0) {
                // Log all acks for consuming txn
                ByteArrayOutputStream bos = new ByteArrayOutputStream((cLogRecordCount * (32 + SysMessageID.ID_SIZE + 8)) + 12);
                DataOutputStream dos = new DataOutputStream(bos);
                // Transaction ID (8 bytes)
                dos.writeLong(id.longValue());
                // Number of acks (4 bytes)
                dos.writeInt(cLogRecordCount);
                for (int i = 0; i < cLogRecordCount; i++) {
                    String dst = (String) cLogDstList.get(i);
                    // Destination
                    dos.writeUTF(dst);
                    SysMessageID sysid = (SysMessageID) cLogMsgList.get(i);
                    // SysMessageID
                    sysid.writeID(dos);
                    ConsumerUID intid = (ConsumerUID) cLogIntList.get(i);
                    // ConsumerUID
                    dos.writeLong(intid.longValue());
                }
                dos.close();
                bos.close();
                ((TxnLoggingStore) pstore).logTxn(TransactionLogType.CONSUME_TRANSACTION, bos.toByteArray());
            }
        } catch (IOException ex) {
            logger.logStack(Logger.ERROR, BrokerResources.E_INTERNAL_BROKER_ERROR, "Got exception while writing to transaction log", ex);
            throw new BrokerException("Got exception while writing to transaction log", ex);
        }
    } finally {
        // release lock
        Globals.getStore().txnLogSharedLock.unlock();
    }
}
Also used : Destination(com.sun.messaging.jmq.jmsserver.core.Destination) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) SortedSet(java.util.SortedSet) Set(java.util.Set) TreeSet(java.util.TreeSet) LocalTransaction(com.sun.messaging.jmq.jmsserver.data.LocalTransaction) HashMap(java.util.HashMap) CacheHashMap(com.sun.messaging.jmq.util.CacheHashMap) DataOutputStream(java.io.DataOutputStream) ArrayList(java.util.ArrayList) Consumer(com.sun.messaging.jmq.jmsserver.core.Consumer) PacketReference(com.sun.messaging.jmq.jmsserver.core.PacketReference) AckEntryNotFoundException(com.sun.messaging.jmq.jmsserver.util.AckEntryNotFoundException) Iterator(java.util.Iterator) DestinationList(com.sun.messaging.jmq.jmsserver.core.DestinationList) List(java.util.List) ArrayList(java.util.ArrayList) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList) MessageDeliveryTimeInfo(com.sun.messaging.jmq.jmsserver.core.MessageDeliveryTimeInfo) PartitionedStore(com.sun.messaging.jmq.jmsserver.persist.api.PartitionedStore) Agent(com.sun.messaging.jmq.jmsserver.management.agent.Agent) ConsumerUID(com.sun.messaging.jmq.jmsserver.core.ConsumerUID) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) 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) TransactionWork(com.sun.messaging.jmq.jmsserver.data.TransactionWork) TransactionBroker(com.sun.messaging.jmq.jmsserver.data.TransactionBroker) SysMessageID(com.sun.messaging.jmq.io.SysMessageID) BaseTransaction(com.sun.messaging.jmq.jmsserver.data.BaseTransaction) Map(java.util.Map) HashMap(java.util.HashMap) CacheHashMap(com.sun.messaging.jmq.util.CacheHashMap) TxnLoggingStore(com.sun.messaging.jmq.jmsserver.persist.api.TxnLoggingStore) Session(com.sun.messaging.jmq.jmsserver.core.Session)

Example 5 with MessageDeliveryTimeInfo

use of com.sun.messaging.jmq.jmsserver.core.MessageDeliveryTimeInfo in project openmq by eclipse-ee4j.

the class TransactionLogReplayer method rerouteMessage.

private void rerouteMessage(Packet pkt, SysMessageID mid, Destination dst) throws BrokerException {
    // TO DO
    // This should use existing routing
    logger.log(Logger.FORCE, BrokerResources.I_RECONSTRUCT_MSG_TXNLOG, mid, dst + " [reroute]");
    PacketReference pr = PacketReference.createReferenceWithDestination(msgStore.parent, pkt, dst, null);
    if (pr.isExpired()) {
        String msg = "not routing expired message on transaction log replay " + mid;
        logger.log(Logger.INFO, msg);
        return;
    }
    try {
        dst.queueMessage(pr, false);
        MessageDeliveryTimeInfo di = pr.getDeliveryTimeInfo();
        if (di == null || di.getOnTimerState() == null) {
            dst.routeNewMessage(pr);
        } else {
            di.setDeliveryReady();
        }
    } catch (SelectorFormatException e) {
        // shouldn't happens
        throw new BrokerException(Globals.getBrokerResources().getString(BrokerResources.E_ROUTE_RECONSTRUCTED_MSG_FAILED, mid), e);
    }
}
Also used : SelectorFormatException(com.sun.messaging.jmq.util.selector.SelectorFormatException) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) PacketReference(com.sun.messaging.jmq.jmsserver.core.PacketReference) MessageDeliveryTimeInfo(com.sun.messaging.jmq.jmsserver.core.MessageDeliveryTimeInfo)

Aggregations

MessageDeliveryTimeInfo (com.sun.messaging.jmq.jmsserver.core.MessageDeliveryTimeInfo)5 BrokerException (com.sun.messaging.jmq.jmsserver.util.BrokerException)5 SelectorFormatException (com.sun.messaging.jmq.util.selector.SelectorFormatException)5 PacketReference (com.sun.messaging.jmq.jmsserver.core.PacketReference)4 Destination (com.sun.messaging.jmq.jmsserver.core.Destination)3 TransactionList (com.sun.messaging.jmq.jmsserver.data.TransactionList)3 Producer (com.sun.messaging.jmq.jmsserver.core.Producer)2 MaxConsecutiveRollbackException (com.sun.messaging.jmq.jmsserver.util.MaxConsecutiveRollbackException)2 IOException (java.io.IOException)2 ArrayList (java.util.ArrayList)2 Set (java.util.Set)2 SysMessageID (com.sun.messaging.jmq.io.SysMessageID)1 Consumer (com.sun.messaging.jmq.jmsserver.core.Consumer)1 ConsumerUID (com.sun.messaging.jmq.jmsserver.core.ConsumerUID)1 DestinationList (com.sun.messaging.jmq.jmsserver.core.DestinationList)1 DestinationUID (com.sun.messaging.jmq.jmsserver.core.DestinationUID)1 Session (com.sun.messaging.jmq.jmsserver.core.Session)1 BaseTransaction (com.sun.messaging.jmq.jmsserver.data.BaseTransaction)1 LocalTransaction (com.sun.messaging.jmq.jmsserver.data.LocalTransaction)1 TransactionBroker (com.sun.messaging.jmq.jmsserver.data.TransactionBroker)1