Search in sources :

Example 1 with TransactionAcknowledgement

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

the class TransactionHandler method retrieveConsumedRemoteMessages.

private HashMap[] retrieveConsumedRemoteMessages(TransactionList translist, TransactionUID id, boolean checkOnly) throws BrokerException {
    HashMap mcmap = translist.retrieveConsumedMessages(id);
    HashMap sToCmap = translist.retrieveStoredConsumerUIDs(id);
    if (DEBUG_CLUSTER_TXN) {
        logger.log(logger.INFO, "retrieveConsumedRemoteMessages(" + translist + ",TID=" + id + ") retrieveConsumedMessages: " + mcmap);
    }
    if (mcmap == null || mcmap.size() == 0) {
        return null;
    }
    HashMap[] rets = new HashMap[2];
    HashMap<BrokerAddress, ArrayList[]> bmmap = new HashMap<>();
    HashMap<TransactionBroker, ArrayList<TransactionAcknowledgement>> tbmmap = new HashMap<>();
    ArrayList[] bmcll = null;
    ArrayList<TransactionAcknowledgement> tbmcl = null;
    boolean hasRemote = false;
    BrokerAddress myba = Globals.getMyAddress();
    UID tranpid = translist.getPartitionedStore().getPartitionID();
    UID refpid = null;
    ConsumerUID cuid = null, scuid = null;
    TransactionAcknowledgement ta = null;
    Iterator<Map.Entry> itr = mcmap.entrySet().iterator();
    Map.Entry pair = null;
    while (itr.hasNext()) {
        pair = itr.next();
        SysMessageID sysid = (SysMessageID) pair.getKey();
        if (sysid == null) {
            continue;
        }
        PacketReference ref = DL.get(null, sysid, false);
        if (checkRefRequeued(translist, id, ref, sysid)) {
            BrokerException bex = new BrokerException(Globals.getBrokerResources().getKString(BrokerResources.X_MESSAGE_MAYBE_REROUTED, sysid) + ", TUID=" + id, Status.GONE);
            bex.setRemote(true);
            StringBuilder buf = new StringBuilder();
            List interests = (List) pair.getValue();
            for (int i = 0; i < interests.size(); i++) {
                buf.append(String.valueOf(((ConsumerUID) interests.get(i)).longValue()));
                buf.append(' ');
            }
            bex.setRemoteConsumerUIDs(buf.toString());
            throw bex;
        }
        if (ref == null) {
            throw new BrokerException(Globals.getBrokerResources().getKString(BrokerResources.X_MESSAGE_REF_GONE, sysid) + ", TUID=" + id, Status.CONFLICT);
        }
        BrokerAddress ba = ref.getBrokerAddress();
        if (ba == null) {
            if (!DL.isPartitionMode()) {
                ba = myba;
            } else {
                refpid = ref.getPartitionedStore().getPartitionID();
                ba = (BrokerAddress) myba.clone();
                ba.setStoreSessionUID(refpid);
                if (!refpid.equals(tranpid)) {
                    hasRemote = true;
                }
            }
        } else if (!hasRemote) {
            hasRemote = true;
        }
        if (hasRemote && checkOnly) {
            return rets;
        }
        TransactionBroker tba = new TransactionBroker(ba);
        bmcll = bmmap.get(tba.getBrokerAddress());
        tbmcl = tbmmap.get(tba);
        if (bmcll == null) {
            bmcll = new ArrayList[2];
            bmcll[0] = new ArrayList();
            bmcll[1] = new ArrayList();
            bmmap.put(tba.getBrokerAddress(), bmcll);
        }
        if (tbmcl == null) {
            tbmcl = new ArrayList<>();
            tbmmap.put(tba, tbmcl);
        }
        List interests = (List) mcmap.get(sysid);
        for (int i = 0; i < interests.size(); i++) {
            cuid = (ConsumerUID) interests.get(i);
            bmcll[0].add(sysid);
            bmcll[1].add(cuid);
            scuid = (ConsumerUID) sToCmap.get(cuid);
            ta = new TransactionAcknowledgement(sysid, cuid, scuid);
            if (!scuid.shouldStore() || !ref.isPersistent()) {
                ta.setShouldStore(false);
            }
            tbmcl.add(ta);
        }
        if (DEBUG_CLUSTER_TXN) {
            logger.log(logger.INFO, "retrieveConsumedRemoteMessages() for broker " + tba + ": " + Arrays.toString(bmcll) + ", " + tbmcl);
        }
    }
    if (!hasRemote) {
        return null;
    }
    rets[0] = bmmap;
    rets[1] = tbmmap;
    return rets;
}
Also used : TransactionAcknowledgement(com.sun.messaging.jmq.jmsserver.data.TransactionAcknowledgement) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) HashMap(java.util.HashMap) CacheHashMap(com.sun.messaging.jmq.util.CacheHashMap) ConsumerUID(com.sun.messaging.jmq.jmsserver.core.ConsumerUID) ArrayList(java.util.ArrayList) BrokerAddress(com.sun.messaging.jmq.jmsserver.core.BrokerAddress) ConsumerUID(com.sun.messaging.jmq.jmsserver.core.ConsumerUID) DestinationUID(com.sun.messaging.jmq.jmsserver.core.DestinationUID) UID(com.sun.messaging.jmq.util.UID) TransactionUID(com.sun.messaging.jmq.jmsserver.data.TransactionUID) TransactionBroker(com.sun.messaging.jmq.jmsserver.data.TransactionBroker) PacketReference(com.sun.messaging.jmq.jmsserver.core.PacketReference) SysMessageID(com.sun.messaging.jmq.io.SysMessageID) DestinationList(com.sun.messaging.jmq.jmsserver.core.DestinationList) List(java.util.List) ArrayList(java.util.ArrayList) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList) Map(java.util.Map) HashMap(java.util.HashMap) CacheHashMap(com.sun.messaging.jmq.util.CacheHashMap)

Example 2 with TransactionAcknowledgement

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

the class TransactionHandler method doRemotePrepare.

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

Example 3 with TransactionAcknowledgement

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

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

the class JDBCStore method storeRemoteTransactionInternal.

public void storeRemoteTransactionInternal(TransactionUID tid, TransactionState ts, TransactionAcknowledgement[] txnAcks, BrokerAddress txnHomeBroker, boolean sync, long storeSession) throws BrokerException {
    if (tid == null) {
        throw new NullPointerException();
    }
    if (Globals.getHAEnabled()) {
        throw new UnsupportedOperationException("Operation not supported by the " + getStoreType() + " store in HA mode");
    }
    if (DEBUG) {
        logger.log(Logger.INFO, "JDBCStore.storeRemoteTransactionInternal(" + tid + ", " + ts + ", " + Arrays.toString(txnAcks) + ", " + txnHomeBroker + ", " + sync + ")");
    }
    Connection conn = null;
    Exception myex = null;
    try {
        conn = dbmgr.getConnection(false);
        Util.RetryStrategy retry = null;
        do {
            try {
                // First, store the txn
                daoFactory.getTransactionDAO().insert(conn, tid, ts, txnHomeBroker, null, TransactionInfo.TXN_REMOTE, storeSession);
                // Now, store the acks if any
                if (txnAcks != null && txnAcks.length > 0) {
                    for (int i = 0, len = txnAcks.length; i < len; i++) {
                        TransactionAcknowledgement ack = txnAcks[i];
                        if (ack.shouldStore()) {
                            daoFactory.getConsumerStateDAO().updateTransaction(conn, ack.getSysMessageID(), ack.getStoredConsumerUID(), tid);
                        }
                    }
                }
                conn.commit();
                return;
            } catch (Exception e) {
                // Exception will be log & re-throw if operation cannot be retry
                if (retry == null) {
                    retry = new Util.RetryStrategy();
                }
                retry.assertShouldRetry(e);
            }
        } while (true);
    } catch (BrokerException e) {
        myex = e;
        throw e;
    } finally {
        Util.close(null, null, conn, myex);
    }
}
Also used : TransactionAcknowledgement(com.sun.messaging.jmq.jmsserver.data.TransactionAcknowledgement) DupKeyException(com.sun.messaging.bridge.api.DupKeyException) KeyNotFoundException(com.sun.messaging.bridge.api.KeyNotFoundException)

Example 5 with TransactionAcknowledgement

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

the class JDBCStore method updateTransactionStateWithWorkInternal.

public void updateTransactionStateWithWorkInternal(TransactionUID tid, TransactionState ts, TransactionWork txnwork, long storeSessionID, boolean sync) throws BrokerException {
    if (tid == null || ts == null || txnwork == null) {
        throw new NullPointerException();
    }
    if (DEBUG) {
        logger.log(Logger.INFO, "JDBCStore.updateTransactionStateInternal(" + tid + ", " + ts + ", " + ", " + txnwork + ", " + sync + ")");
    }
    Connection conn = null;
    Exception myex = null;
    try {
        conn = dbmgr.getConnection(false);
        Util.RetryStrategy retry = null;
        do {
            boolean inside = false;
            try {
                Iterator<TransactionWorkMessage> itr1 = txnwork.getSentMessages().iterator();
                while (itr1.hasNext()) {
                    TransactionWorkMessage txnmsg = itr1.next();
                    Packet m = txnmsg.getMessage();
                    if (m == null) {
                        continue;
                    }
                    inside = true;
                    daoFactory.getMessageDAO().insert(conn, txnmsg.getDestUID(), m, null, null, storeSessionID, m.getTimestamp(), true, false);
                    inside = false;
                }
                if (FI.FAULT_INJECTION) {
                    try {
                        FI.checkFaultAndThrowBrokerException(FaultInjection.FAULT_TXN_PERSIST_WORK_1_5, null);
                    } catch (BrokerException e) {
                        FI.unsetFault(FI.FAULT_TXN_PERSIST_WORK_1_5);
                        throw e;
                    }
                }
                List<TransactionWorkMessageAck> txnacks = txnwork.getMessageAcknowledgments();
                if (txnacks != null) {
                    Iterator<TransactionWorkMessageAck> itr2 = txnacks.iterator();
                    while (itr2.hasNext()) {
                        TransactionWorkMessageAck txnack = itr2.next();
                        TransactionAcknowledgement ta = txnack.getTransactionAcknowledgement();
                        if (ta != null) {
                            inside = true;
                            daoFactory.getConsumerStateDAO().updateTransaction(conn, ta.getSysMessageID(), ta.getStoredConsumerUID(), tid);
                            inside = false;
                        }
                    }
                }
                inside = true;
                daoFactory.getTransactionDAO().updateTransactionState(conn, tid, ts, false);
                inside = false;
                conn.commit();
                return;
            } catch (Exception e) {
                if (!inside) {
                    try {
                        conn.rollback();
                    } catch (SQLException rbe) {
                        logger.logStack(Logger.WARNING, BrokerResources.X_DB_ROLLBACK_FAILED, rbe);
                    }
                }
                if (retry == null) {
                    retry = new Util.RetryStrategy();
                }
                try {
                    retry.assertShouldRetry(e, conn);
                } catch (RetrySQLRecoverableException ee) {
                    try {
                        Util.close(null, null, conn, ee);
                        conn = dbmgr.getConnection(false);
                    } catch (Exception eee) {
                        logger.logStack(Logger.WARNING, eee.getMessage(), eee);
                        conn = null;
                        if (e instanceof BrokerException) {
                            throw (BrokerException) e;
                        }
                        throw new BrokerException(e.getMessage(), e);
                    }
                }
            }
        } while (true);
    } catch (BrokerException e) {
        myex = e;
        throw e;
    } finally {
        Util.close(null, null, conn, myex);
    }
}
Also used : Packet(com.sun.messaging.jmq.io.Packet) TransactionWorkMessageAck(com.sun.messaging.jmq.jmsserver.data.TransactionWorkMessageAck) TransactionAcknowledgement(com.sun.messaging.jmq.jmsserver.data.TransactionAcknowledgement) DupKeyException(com.sun.messaging.bridge.api.DupKeyException) KeyNotFoundException(com.sun.messaging.bridge.api.KeyNotFoundException) TransactionWorkMessage(com.sun.messaging.jmq.jmsserver.data.TransactionWorkMessage)

Aggregations

TransactionAcknowledgement (com.sun.messaging.jmq.jmsserver.data.TransactionAcknowledgement)17 SysMessageID (com.sun.messaging.jmq.io.SysMessageID)10 ConsumerUID (com.sun.messaging.jmq.jmsserver.core.ConsumerUID)10 TransactionUID (com.sun.messaging.jmq.jmsserver.data.TransactionUID)8 DestinationUID (com.sun.messaging.jmq.jmsserver.core.DestinationUID)6 BrokerException (com.sun.messaging.jmq.jmsserver.util.BrokerException)6 PacketReference (com.sun.messaging.jmq.jmsserver.core.PacketReference)5 Packet (com.sun.messaging.jmq.io.Packet)4 BrokerAddress (com.sun.messaging.jmq.jmsserver.core.BrokerAddress)4 Destination (com.sun.messaging.jmq.jmsserver.core.Destination)4 TransactionBroker (com.sun.messaging.jmq.jmsserver.data.TransactionBroker)4 TransactionList (com.sun.messaging.jmq.jmsserver.data.TransactionList)4 DupKeyException (com.sun.messaging.bridge.api.DupKeyException)3 KeyNotFoundException (com.sun.messaging.bridge.api.KeyNotFoundException)3 Consumer (com.sun.messaging.jmq.jmsserver.core.Consumer)3 TransactionState (com.sun.messaging.jmq.jmsserver.data.TransactionState)3 AckEntryNotFoundException (com.sun.messaging.jmq.jmsserver.util.AckEntryNotFoundException)3 SelectorFormatException (com.sun.messaging.jmq.util.selector.SelectorFormatException)3 IOException (java.io.IOException)3 ArrayList (java.util.ArrayList)3