Search in sources :

Example 21 with TransactionList

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

the class RaptorProtocol method sendClusterTransactionInfo.

// Caller must ensure this is the transaction home broker
private void sendClusterTransactionInfo(TransactionUID tid, BrokerAddress to, Long xid) {
    TransactionList tl = null;
    TransactionState ts = null;
    Object[] oo = TransactionList.getTransListAndState(tid, null, true, false);
    if (oo != null) {
        tl = (TransactionList) oo[0];
        ts = (TransactionState) oo[1];
    }
    BrokerAddress[] parties = null;
    BrokerAddress[] waitfor = null;
    TransactionBroker[] brokers = null;
    if (ts != null) {
        try {
            brokers = tl.getClusterTransactionBrokers(tid);
        } catch (Exception e) {
            logger.log(logger.WARNING, "Can't retrieve cluster transaction brokers:" + e.getMessage());
        }
        if (brokers == null) {
            logger.log(logger.WARNING, "No cluster transaction brokers information for TID=" + tid);
        } else {
            parties = new BrokerAddress[brokers.length];
            ArrayList waits = new ArrayList();
            for (int i = 0; i < brokers.length; i++) {
                parties[i] = brokers[i].getBrokerAddress();
                if (!brokers[i].isCompleted()) {
                    waits.add(brokers[i].getBrokerAddress());
                }
            }
            if (waits.size() > 0) {
                waitfor = (BrokerAddress[]) waits.toArray(new BrokerAddress[waits.size()]);
            }
        }
    }
    UID tranpid = null;
    if (tl != null && Globals.getDestinationList().isPartitionMode()) {
        tranpid = tl.getPartitionedStore().getPartitionID();
    }
    ClusterTxnInfoInfo ii = ClusterTxnInfoInfo.newInstance(Long.valueOf(tid.longValue()), (ts == null ? TransactionState.NULL : ts.getState()), parties, waitfor, Globals.getMyAddress(), true, tranpid, c, xid);
    if (DEBUG_CLUSTER_TXN) {
        logger.log(logger.INFO, Globals.getBrokerResources().getKString(BrokerResources.I_SEND_CLUSTER_TXN_INFO, to.toString(), ii.toString()));
    }
    try {
        c.unicast(to, ii.getGPacket());
    } catch (Exception e) {
        String[] args = { ii.toString(), to.toString(), e.getMessage() };
        logger.log(Logger.WARNING, Globals.getBrokerResources().getKString(BrokerResources.W_SEND_CLUSTER_TXN_INFO_FAIL, args));
    }
}
Also used : TransactionState(com.sun.messaging.jmq.jmsserver.data.TransactionState) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList) HandshakeInProgressException(com.sun.messaging.jmq.jmsserver.multibroker.HandshakeInProgressException) ConnectionUID(com.sun.messaging.jmq.jmsserver.service.ConnectionUID) TransactionUID(com.sun.messaging.jmq.jmsserver.data.TransactionUID) TransactionBroker(com.sun.messaging.jmq.jmsserver.data.TransactionBroker)

Example 22 with TransactionList

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

the class BrokerConsumers method acknowledgeMessageFromRemote2P.

public void acknowledgeMessageFromRemote2P(int ackType, SysMessageID[] sysids, com.sun.messaging.jmq.jmsserver.core.ConsumerUID[] cuids, Map optionalProps, Long txnID, com.sun.messaging.jmq.jmsserver.core.BrokerAddress txnHomeBroker) throws BrokerException {
    if (txnID == null) {
        throw new BrokerException("Internal Error: call with null txnID");
    }
    // handle 2-phase remote ack
    TransactionUID tid = new TransactionUID(txnID.longValue());
    if (ackType == ClusterBroadcast.MSG_PREPARE) {
        PartitionedStore refpstore = null;
        TransactionAcknowledgement ta = null;
        ArrayList<TransactionAcknowledgement> tltas = null;
        TransactionAcknowledgement[] tas = null;
        HashMap<TransactionList, ArrayList<TransactionAcknowledgement>> tltasmap = new HashMap<>();
        TransactionList tl = null;
        AckEntry entry = null, value = null;
        StringBuilder dbuf = new StringBuilder();
        AckEntryNotFoundException ae = null;
        synchronized (deliveredMessages) {
            for (int i = 0; i < sysids.length; i++) {
                entry = new AckEntry(sysids[i], cuids[i], null);
                value = (AckEntry) deliveredMessages.get(entry);
                if (value == null) {
                    // XXX
                    String emsg = "[" + sysids[i] + ":" + cuids[i] + "]TID=" + tid + " not found, maybe rerouted";
                    if (ae == null) {
                        ae = new AckEntryNotFoundException(emsg);
                    }
                    ae.addAckEntry(sysids[i], cuids[i]);
                    logger.log(logger.WARNING, "[" + sysids[i] + ":" + cuids[i] + "] not found for preparing remote transaction " + tid + ", maybe rerouted");
                    continue;
                }
                if (value.getTUID() != null) {
                    String emsg = "[" + sysids[i] + ":" + cuids[i] + "]TID=" + tid + "  has been rerouted";
                    if (ae == null) {
                        ae = new AckEntryNotFoundException(emsg);
                    }
                    ae.addAckEntry(sysids[i], cuids[i]);
                    logger.log(logger.WARNING, "[" + sysids[i] + ":" + cuids[i] + "] for preparing remote transaction " + tid + " conflict with transaction " + value.getTUID());
                    continue;
                }
                PacketReference ref = value.getReference();
                if (ref == null) {
                    deliveredMessages.remove(entry);
                    String emsg = "Unable to prepare [" + sysids[i] + ":" + cuids[i] + "]TID=" + tid + " because the message has been removed";
                    if (ae == null) {
                        ae = new AckEntryNotFoundException(emsg);
                    }
                    ae.addAckEntry(sysids[i], cuids[i]);
                    logger.log(logger.WARNING, emsg);
                    continue;
                }
                com.sun.messaging.jmq.jmsserver.core.ConsumerUID scuid = value.getStoredConsumerUID();
                ta = new TransactionAcknowledgement(sysids[i], cuids[i], scuid);
                if (!scuid.shouldStore() || !ref.isPersistent()) {
                    ta.setShouldStore(false);
                }
                if (!Globals.getDestinationList().isPartitionMode()) {
                    TransactionList[] tls = DL.getTransactionList(Globals.getStore().getPrimaryPartition());
                    tl = tls[0];
                } else {
                    refpstore = ref.getPartitionedStore();
                    TransactionList[] tls = Globals.getDestinationList().getTransactionList(refpstore);
                    tl = tls[0];
                    if (tl == null) {
                        deliveredMessages.remove(entry);
                        String emsg = "Unable to prepare [" + sysids[i] + ":" + cuids[i] + "]TID=" + tid + " because transaction list for partition " + refpstore + " not found";
                        if (ae == null) {
                            ae = new AckEntryNotFoundException(emsg);
                        }
                        ae.addAckEntry(sysids[i], cuids[i]);
                        logger.log(logger.WARNING, emsg);
                        continue;
                    }
                }
                tltas = tltasmap.get(tl);
                if (tltas == null) {
                    tltas = new ArrayList<>();
                    tltasmap.put(tl, tltas);
                }
                tltas.add(ta);
                if (getDEBUG()) {
                    dbuf.append("\n\t[" + ta + "]" + tl);
                }
            }
            if (ae != null) {
                throw ae;
            }
            Iterator<Map.Entry<TransactionList, ArrayList<TransactionAcknowledgement>>> itr = tltasmap.entrySet().iterator();
            Map.Entry<TransactionList, ArrayList<TransactionAcknowledgement>> pair = null;
            while (itr.hasNext()) {
                pair = itr.next();
                tl = pair.getKey();
                tltas = pair.getValue();
                tas = tltas.toArray(new TransactionAcknowledgement[tltas.size()]);
                TransactionState ts = new TransactionState(AutoRollbackType.NOT_PREPARED, 0L, true);
                ts.setState(TransactionState.PREPARED);
                if (getDEBUG()) {
                    logger.log(logger.INFO, "Preparing remote transaction " + tid + " for [" + tltas + "]" + tl + " from " + txnHomeBroker);
                }
                tl.logRemoteTransaction(tid, ts, tas, txnHomeBroker, false, true, true);
            }
            for (int i = 0; i < sysids.length; i++) {
                entry = new AckEntry(sysids[i], cuids[i], null);
                value = (AckEntry) deliveredMessages.get(entry);
                value.setTUID(tid);
            }
        }
        Iterator<TransactionList> itr = tltasmap.keySet().iterator();
        while (itr.hasNext()) {
            tl = itr.next();
            tl.pendingStartedForRemotePreparedTransaction(tid);
        }
        notifyPendingCheckTimer();
        if (getDEBUG()) {
            logger.log(logger.INFO, "Prepared remote transaction " + tid + " from " + txnHomeBroker + dbuf.toString());
        }
        return;
    }
    if (ackType == ClusterBroadcast.MSG_ROLLEDBACK) {
        if (getDEBUG()) {
            logger.log(logger.INFO, "Rolling back remote transaction " + tid + " from " + txnHomeBroker);
        }
        List<Object[]> list = TransactionList.getTransListsAndRemoteTranStates(tid);
        if (list == null) {
            if (getDEBUG()) {
                logger.log(logger.INFO, "Rolling back non-prepared remote transaction " + tid + " from " + txnHomeBroker);
            }
            List<AckEntry> entries = null;
            synchronized (deliveredMessages) {
                entries = getPendingConsumerUID(tid);
                Iterator<AckEntry> itr = entries.iterator();
                AckEntry e = null;
                while (itr.hasNext()) {
                    e = itr.next();
                    if (deliveredMessages.get(e) == null) {
                        itr.remove();
                        continue;
                    }
                    if (consumers.get(e.getConsumerUID()) != null) {
                        itr.remove();
                        continue;
                    }
                }
                if (e != null) {
                    deliveredMessages.remove(e);
                    cleanupPendingConsumerUID(e.getConsumerUID(), e.getSysMessageID());
                }
            }
            if (entries.size() == 0) {
                logger.log(logger.INFO, br.getKString(br.I_ROLLBACK_REMOTE_TXN_NOT_FOUND, tid, txnHomeBroker));
                return;
            }
            Iterator<AckEntry> itr = entries.iterator();
            while (itr.hasNext()) {
                AckEntry e = itr.next();
                SysMessageID sysid = e.getSysMessageID();
                com.sun.messaging.jmq.jmsserver.core.ConsumerUID cuid = e.getConsumerUID();
                com.sun.messaging.jmq.jmsserver.core.ConsumerUID suid = e.getStoredConsumerUID();
                if (suid == null) {
                    suid = cuid;
                }
                // PART
                PacketReference ref = DL.get(null, sysid);
                if (ref == null) {
                    if (getDEBUG()) {
                        logger.log(logger.INFO, "[" + sysid + ":" + cuid + "] reference not found in rolling back remote non-prepared transaction " + tid);
                    }
                    continue;
                }
                ref.removeInDelivery(suid);
                ref.getDestination().forwardOrphanMessage(ref, suid);
            }
            return;
        }
        // if list == null
        TransactionList tl = null;
        Object[] oo = null;
        for (int li = 0; li < list.size(); li++) {
            oo = list.get(li);
            tl = (TransactionList) oo[0];
            if (!tl.updateRemoteTransactionState(tid, TransactionState.ROLLEDBACK, false, false, true)) {
                return;
            }
            if (tl.getRecoveryRemoteTransactionAcks(tid) != null) {
                rollbackRecoveryRemoteTransaction(tl, tid, txnHomeBroker);
            }
            RemoteTransactionAckEntry tae = tl.getRemoteTransactionAcks(tid);
            if (tae == null) {
                logger.log(logger.INFO, Globals.getBrokerResources().getKString(BrokerResources.I_NO_NONRECOVERY_TXNACK_TO_ROLLBACK, tid));
            } else if (tae.processed()) {
                logger.log(logger.INFO, Globals.getBrokerResources().getKString(BrokerResources.I_NO_MORE_TXNACK_TO_ROLLBACK, tid));
            } else if (!tae.isLocalRemote()) {
                TransactionAcknowledgement[] tas = tae.getAcks();
                Set s = new LinkedHashSet();
                AckEntry entry = null, value = null;
                for (int i = 0; i < tas.length; i++) {
                    SysMessageID sysid = tas[i].getSysMessageID();
                    com.sun.messaging.jmq.jmsserver.core.ConsumerUID uid = tas[i].getConsumerUID();
                    com.sun.messaging.jmq.jmsserver.core.ConsumerUID suid = tas[i].getStoredConsumerUID();
                    if (suid == null) {
                        suid = uid;
                    }
                    synchronized (deliveredMessages) {
                        entry = new AckEntry(sysid, uid, null);
                        value = (AckEntry) deliveredMessages.get(entry);
                        if (value == null) {
                            if (getDEBUG()) {
                                logger.log(logger.INFO, "[" + sysid + ":" + uid + "] not found in rolling back remote transaction " + tid);
                            }
                            continue;
                        }
                        if (value.getTUID() == null || !value.getTUID().equals(tid)) {
                            if (getDEBUG()) {
                                logger.log(logger.INFO, "[" + sysid + ":" + uid + "] with TUID=" + value.getTUID() + ", in confict for rolling back remote transaction " + tid);
                            }
                            continue;
                        }
                        if (consumers.get(uid) == null) {
                            deliveredMessages.remove(entry);
                            cleanupPendingConsumerUID(uid, sysid);
                            s.add(tas[i]);
                        } else {
                            value.setTUID(null);
                        }
                    }
                }
                Iterator itr = s.iterator();
                while (itr.hasNext()) {
                    TransactionAcknowledgement ta = (TransactionAcknowledgement) itr.next();
                    SysMessageID sysid = ta.getSysMessageID();
                    com.sun.messaging.jmq.jmsserver.core.ConsumerUID cuid = ta.getConsumerUID();
                    com.sun.messaging.jmq.jmsserver.core.ConsumerUID suid = ta.getStoredConsumerUID();
                    if (suid == null) {
                        suid = cuid;
                    }
                    // PART
                    PacketReference ref = DL.get(null, sysid);
                    if (ref == null) {
                        if (getDEBUG()) {
                            logger.log(logger.INFO, "[" + sysid + ":" + cuid + "] reference not found in rolling back remote transaction " + tid);
                        }
                        continue;
                    }
                    ref.removeInDelivery(suid);
                    ref.getDestination().forwardOrphanMessage(ref, suid);
                }
            }
            try {
                tl.removeRemoteTransactionAck(tid);
            } catch (Exception e) {
                logger.log(logger.WARNING, "Unable to remove transaction ack for rolledback transaction " + tid + ": " + e.getMessage());
            }
            try {
                tl.removeRemoteTransactionID(tid, true);
            } catch (Exception e) {
                logger.log(logger.WARNING, "Unable to remove rolledback remote transaction " + tid + ": " + e.getMessage());
            }
        }
        // for
        return;
    }
    int cLogRecordCount = 0;
    ArrayList cLogDstList = null;
    ArrayList cLogMsgList = null;
    ArrayList cLogIntList = null;
    if (ackType == ClusterBroadcast.MSG_ACKNOWLEDGED) {
        if (getDEBUG()) {
            logger.log(logger.INFO, "Committing remote transaction " + tid + " from " + txnHomeBroker);
        }
        List<Object[]> list = TransactionList.getTransListsAndRemoteTranStates(tid);
        if (list == null) {
            throw new BrokerException("Committing remote transaction " + tid + " not found", Status.NOT_FOUND);
        }
        TransactionList tl = null;
        Object[] oo = null;
        for (int li = 0; li < list.size(); li++) {
            oo = list.get(li);
            tl = (TransactionList) oo[0];
            if (!tl.updateRemoteTransactionState(tid, TransactionState.COMMITTED, (sysids == null), true, true)) {
                if (getDEBUG()) {
                    logger.log(logger.INFO, "Remote transaction " + tid + " already committed, from " + txnHomeBroker);
                }
                continue;
            }
            boolean done = true;
            if (tl.getRecoveryRemoteTransactionAcks(tid) != null) {
                done = commitRecoveryRemoteTransaction(tl, tid, txnHomeBroker);
            }
            RemoteTransactionAckEntry tae = tl.getRemoteTransactionAcks(tid);
            if (tae == null) {
                logger.log(logger.INFO, "No non-recovery transaction acks to process for committing remote transaction " + tid);
            } else if (tae.processed()) {
                logger.log(logger.INFO, "No more transaction acks to process for committing remote transaction " + tid);
            } else if (!tae.isLocalRemote()) {
                boolean found = false;
                TransactionAcknowledgement[] tas = tae.getAcks();
                for (int i = 0; i < tas.length; i++) {
                    SysMessageID sysid = tas[i].getSysMessageID();
                    com.sun.messaging.jmq.jmsserver.core.ConsumerUID cuid = tas[i].getConsumerUID();
                    if (sysids != null && !found) {
                        if (sysid.equals(sysids[0]) && cuid.equals(cuids[0])) {
                            found = true;
                        }
                    }
                    String dstName = null;
                    if (Globals.txnLogEnabled()) {
                        if (cLogDstList == null) {
                            cLogDstList = new ArrayList();
                            cLogMsgList = new ArrayList();
                            cLogIntList = new ArrayList();
                        }
                        PacketReference ref = DL.get(null, sysid);
                        if (ref != null && !ref.isDestroyed() && !ref.isInvalid()) {
                            Destination[] ds = DL.getDestination(ref.getPartitionedStore(), ref.getDestinationUID());
                            Destination dst = ds[0];
                            dstName = dst.getUniqueName();
                        }
                    }
                    if (acknowledgeMessageFromRemote(ackType, sysid, cuid, optionalProps)) {
                        if (dstName != null) {
                            // keep track for consumer txn log
                            com.sun.messaging.jmq.jmsserver.core.ConsumerUID suid = tas[i].getStoredConsumerUID();
                            if (suid == null) {
                                suid = cuid;
                            }
                            cLogRecordCount++;
                            cLogDstList.add(dstName);
                            cLogMsgList.add(sysid);
                            cLogIntList.add(suid);
                        }
                    } else {
                        done = false;
                    }
                }
                // notify that message acks have been written to store
                if (Globals.isNewTxnLogEnabled()) {
                    if (DL.isPartitionMode()) {
                        throw new BrokerException("Partition mode not supported if newTxnLog enabled");
                    }
                    ((TxnLoggingStore) Globals.getStore().getPrimaryPartition()).loggedCommitWrittenToMessageStore(tid, BaseTransaction.REMOTE_TRANSACTION_TYPE);
                }
                if (sysids != null && !found) {
                    logger.log(logger.ERROR, "Internal Error: [" + sysids[0] + ":" + cuids[0] + "] not found in remote transaction " + tid);
                    done = false;
                }
            }
            // tae != null
            if (done) {
                try {
                    tl.removeRemoteTransactionAck(tid);
                } catch (Exception e) {
                    logger.logStack(logger.WARNING, "Unable to remove transaction ack for committed remote transaction " + tid, e);
                }
                try {
                    tl.removeRemoteTransactionID(tid, true);
                } catch (Exception e) {
                    logger.logStack(logger.WARNING, "Unable to remove committed remote transaction " + tid, e);
                }
            } else if (Globals.getHAEnabled()) {
                throw new BrokerException("Remote transaction processing incomplete, TUID=" + tid);
            }
        }
        // log to txn log if enabled
        try {
            if (Globals.txnLogEnabled() && (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(tid.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);
                    long intid = ((com.sun.messaging.jmq.jmsserver.core.ConsumerUID) cLogIntList.get(i)).longValue();
                    // ConsumerUID
                    dos.writeLong(intid);
                }
                dos.close();
                bos.close();
                // PART
                ((TxnLoggingStore) Globals.getStore().getPrimaryPartition()).logTxn(TransactionLogType.CONSUME_TRANSACTION, bos.toByteArray());
            }
        } catch (IOException ex) {
            logger.logStack(Logger.ERROR, Globals.getBrokerResources().E_INTERNAL_BROKER_ERROR, "Got exception while writing to transaction log", ex);
            throw new BrokerException("Internal Error: Got exception while writing to transaction log", ex);
        }
        return;
    }
    throw new BrokerException("acknowledgeMessageFromRemotePriv:Unexpected ack type:" + ackType);
}
Also used : LinkedHashSet(java.util.LinkedHashSet) TransactionState(com.sun.messaging.jmq.jmsserver.data.TransactionState) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ConsumerUID(com.sun.messaging.jmq.jmsserver.core.ConsumerUID) ArrayList(java.util.ArrayList) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList) TransactionUID(com.sun.messaging.jmq.jmsserver.data.TransactionUID) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) TxnLoggingStore(com.sun.messaging.jmq.jmsserver.persist.api.TxnLoggingStore) Destination(com.sun.messaging.jmq.jmsserver.core.Destination) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) Set(java.util.Set) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) DataOutputStream(java.io.DataOutputStream) PacketReference(com.sun.messaging.jmq.jmsserver.core.PacketReference) AckEntryNotFoundException(com.sun.messaging.jmq.jmsserver.util.AckEntryNotFoundException) Iterator(java.util.Iterator) PartitionedStore(com.sun.messaging.jmq.jmsserver.persist.api.PartitionedStore) TransactionAcknowledgement(com.sun.messaging.jmq.jmsserver.data.TransactionAcknowledgement) ConsumerUID(com.sun.messaging.jmq.jmsserver.core.ConsumerUID) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) ConsumerAlreadyAddedException(com.sun.messaging.jmq.jmsserver.util.ConsumerAlreadyAddedException) SelectorFormatException(com.sun.messaging.jmq.util.selector.SelectorFormatException) IOException(java.io.IOException) AckEntryNotFoundException(com.sun.messaging.jmq.jmsserver.util.AckEntryNotFoundException) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) SysMessageID(com.sun.messaging.jmq.io.SysMessageID)

Example 23 with TransactionList

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

the class AckHandler method handle.

/**
 * Method to handle Acknowledgement messages
 */
@Override
public boolean handle(IMQConnection con, Packet msg) throws BrokerException {
    int size = msg.getMessageBodySize();
    int ackcount = size / ACK_BLOCK_SIZE;
    int mod = size % ACK_BLOCK_SIZE;
    int status = Status.OK;
    String reason = null;
    if (DEBUG) {
        logger.log(Logger.INFO, "AckHandler: processing packet " + msg.toString() + ", on connection " + con);
    }
    PartitionedStore pstore = con.getPartitionedStore();
    TransactionList[] tls = DL.getTransactionList(pstore);
    TransactionList translist = tls[0];
    if (!con.isAdminConnection() && fi.FAULT_INJECTION) {
        // for fault injection
        ackProcessCnt++;
    } else {
        ackProcessCnt = 0;
    }
    if (ackcount == 0) {
        logger.log(Logger.ERROR, BrokerResources.E_INTERNAL_BROKER_ERROR, "Internal Error: Empty Ack Message " + msg.getSysMessageID().toString());
        reason = "Empty ack message";
        status = Status.ERROR;
    }
    if (mod != 0) {
        logger.log(Logger.ERROR, BrokerResources.E_INTERNAL_BROKER_ERROR, "Internal Error: Invalid Ack Message Size " + size + " for message " + msg.getSysMessageID().toString());
        reason = "corrupted ack message";
        status = Status.ERROR;
    }
    TransactionUID tid = null;
    if (msg.getTransactionID() != 0) {
        // HANDLE TRANSACTION
        try {
            tid = new TransactionUID(msg.getTransactionID());
        } catch (Exception ex) {
            logger.logStack(Logger.ERROR, BrokerResources.E_INTERNAL_BROKER_ERROR, "Internal Error: can not create transactionID for " + msg, ex);
            status = Status.ERROR;
        }
    }
    ArrayList<PacketReference> cleanList = new ArrayList<>();
    try {
        // cleanList
        Hashtable props = null;
        Throwable deadthr = null;
        String deadcmt = null;
        int deadrs = DEAD_REASON_UNDELIVERABLE;
        int deliverCnt = 0;
        boolean deliverCntUpdateOnly = false;
        int ackType = ACKNOWLEDGE_REQUEST;
        boolean JMQValidate = false;
        try {
            props = msg.getProperties();
            Integer iackType = (props == null ? null : (Integer) props.get("JMQAckType"));
            ackType = (iackType == null ? ACKNOWLEDGE_REQUEST : iackType.intValue());
            Boolean validateFlag = (props == null ? null : (Boolean) props.get("JMQValidate"));
            JMQValidate = validateFlag != null && validateFlag.booleanValue();
            checkRequestType(ackType);
            if (ackType == DEAD_REQUEST) {
                deadthr = (Throwable) props.get("JMQException");
                deadcmt = (String) props.get("JMQComment");
                Integer val = (Integer) props.get("JMQDeadReason");
                if (val != null) {
                    deadrs = val.intValue();
                }
            }
            if (props != null) {
                if (ackType == DEAD_REQUEST || ackType == UNDELIVERABLE_REQUEST || tid != null) {
                    // Client runtime retry count
                    Integer val = (Integer) props.get("JMSXDeliveryCount");
                    deliverCnt = (val == null ? -1 : val.intValue());
                    if (tid == null) {
                        if (deliverCnt >= 0) {
                            deliverCnt += 1;
                        }
                    }
                }
                if (ackType == UNDELIVERABLE_REQUEST) {
                    Boolean val = (Boolean) props.get("JMSXDeliveryCountUpdateOnly");
                    deliverCntUpdateOnly = val != null && val.booleanValue();
                }
            }
        } catch (Exception ex) {
            // assume not dead
            logger.logStack(Logger.INFO, "Internal Error: bad protocol", ex);
            ackType = ACKNOWLEDGE_REQUEST;
        }
        // OK .. handle Fault Injection
        if (!con.isAdminConnection() && fi.FAULT_INJECTION) {
            Map m = new HashMap();
            if (props != null) {
                m.putAll(props);
            }
            m.put("mqAckCount", Integer.valueOf(ackProcessCnt));
            m.put("mqIsTransacted", Boolean.valueOf(tid != null));
            fi.checkFaultAndExit(FaultInjection.FAULT_ACK_MSG_1, m, 2, false);
        }
        boolean remoteStatus = false;
        StringBuilder remoteConsumerUIDs = null;
        SysMessageID[] ids = null;
        ConsumerUID[] cids = null;
        try {
            if (status == Status.OK) {
                DataInputStream is = new DataInputStream(msg.getMessageBodyStream());
                // pull out the messages into two lists
                ids = new SysMessageID[ackcount];
                cids = new ConsumerUID[ackcount];
                for (int i = 0; i < ackcount; i++) {
                    long newid = is.readLong();
                    cids[i] = new ConsumerUID(newid);
                    cids[i].setConnectionUID(con.getConnectionUID());
                    ids[i] = new SysMessageID();
                    ids[i].readID(is);
                }
                if (JMQValidate) {
                    if (ackType == DEAD_REQUEST || ackType == UNDELIVERABLE_REQUEST) {
                        status = Status.BAD_REQUEST;
                        reason = "Can not use JMQValidate with ackType of " + ackType;
                    } else if (tid == null) {
                        status = Status.BAD_REQUEST;
                        reason = "Can not use JMQValidate with no tid ";
                    } else if (!validateMessages(translist, tid, ids, cids)) {
                        status = Status.NOT_FOUND;
                        reason = "Acknowledgement not processed";
                    }
                } else if (ackType == DEAD_REQUEST) {
                    handleDeadMsgs(con, ids, cids, deadrs, deadthr, deadcmt, deliverCnt, cleanList);
                } else if (ackType == UNDELIVERABLE_REQUEST) {
                    handleUndeliverableMsgs(con, ids, cids, cleanList, deliverCnt, deliverCntUpdateOnly);
                } else {
                    if (tid != null) {
                        handleTransaction(translist, con, tid, ids, cids, deliverCnt);
                    } else {
                        handleAcks(con, ids, cids, msg.getSendAcknowledge(), cleanList);
                    }
                }
            }
        } catch (Throwable thr) {
            status = Status.ERROR;
            if (thr instanceof BrokerException) {
                status = ((BrokerException) thr).getStatusCode();
                remoteStatus = ((BrokerException) thr).isRemote();
                if (remoteStatus && ids != null && cids != null) {
                    remoteConsumerUIDs = new StringBuilder();
                    remoteConsumerUIDs.append(((BrokerException) thr).getRemoteConsumerUIDs());
                    remoteConsumerUIDs.append(' ');
                    String cidstr = null;
                    ArrayList remoteConsumerUIDa = new ArrayList();
                    for (int i = 0; i < ids.length; i++) {
                        PacketReference ref = DL.get(pstore, ids[i]);
                        Consumer c = Consumer.getConsumer(cids[i]);
                        if (c == null) {
                            continue;
                        }
                        ConsumerUID sid = c.getStoredConsumerUID();
                        if (sid == null || sid.equals(cids[i])) {
                            continue;
                        }
                        BrokerAddress ba = (ref == null ? null : ref.getBrokerAddress());
                        BrokerAddress rba = (BrokerAddress) ((BrokerException) thr).getRemoteBrokerAddress();
                        if (ref != null && ba != null && rba != null && ba.equals(rba)) {
                            cidstr = String.valueOf(c.getConsumerUID().longValue());
                            if (!remoteConsumerUIDa.contains(cidstr)) {
                                remoteConsumerUIDa.add(cidstr);
                                remoteConsumerUIDs.append(cidstr);
                                remoteConsumerUIDs.append(' ');
                            }
                        }
                    }
                }
            }
            reason = thr.getMessage();
            if (status == Status.ERROR) {
                // something went wrong
                logger.logStack(Logger.ERROR, BrokerResources.E_INTERNAL_BROKER_ERROR, "-------------------------------------------" + "Internal Error: Invalid Acknowledge Packet processing\n" + " " + (msg.getSendAcknowledge() ? " notifying client\n" : " can not notify the client") + com.sun.messaging.jmq.io.PacketUtil.dumpPacket(msg) + "--------------------------------------------", thr);
            }
        }
        // OK .. handle Fault Injection
        if (!con.isAdminConnection() && fi.FAULT_INJECTION) {
            Map m = new HashMap();
            if (props != null) {
                m.putAll(props);
            }
            m.put("mqAckCount", Integer.valueOf(ackProcessCnt));
            m.put("mqIsTransacted", Boolean.valueOf(tid != null));
            fi.checkFaultAndExit(FaultInjection.FAULT_ACK_MSG_2, m, 2, false);
        }
        // send the reply (if necessary)
        if (msg.getSendAcknowledge()) {
            Packet pkt = new Packet(con.useDirectBuffers());
            pkt.setPacketType(PacketType.ACKNOWLEDGE_REPLY);
            pkt.setConsumerID(msg.getConsumerID());
            Hashtable hash = new Hashtable();
            hash.put("JMQStatus", Integer.valueOf(status));
            if (reason != null) {
                hash.put("JMQReason", reason);
            }
            if (remoteStatus) {
                hash.put("JMQRemote", Boolean.TRUE);
                if (remoteConsumerUIDs != null) {
                    hash.put("JMQRemoteConsumerIDs", remoteConsumerUIDs.toString());
                }
            }
            if (((IMQBasicConnection) con).getDumpPacket() || ((IMQBasicConnection) con).getDumpOutPacket()) {
                hash.put("JMQReqID", msg.getSysMessageID().toString());
            }
            pkt.setProperties(hash);
            con.sendControlMessage(pkt);
        }
        // OK .. handle Fault Injection
        if (!con.isAdminConnection() && fi.FAULT_INJECTION) {
            Map m = new HashMap();
            if (props != null) {
                m.putAll(props);
            }
            m.put("mqAckCount", Integer.valueOf(ackProcessCnt));
            m.put("mqIsTransacted", Boolean.valueOf(tid != null));
            fi.checkFaultAndExit(FaultInjection.FAULT_ACK_MSG_3, m, 2, false);
        }
    } finally {
        // we dont need to clear the memory up until after we reply
        cleanUp(cleanList);
    }
    return true;
}
Also used : BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) Consumer(com.sun.messaging.jmq.jmsserver.core.Consumer) PacketReference(com.sun.messaging.jmq.jmsserver.core.PacketReference) PartitionedStore(com.sun.messaging.jmq.jmsserver.persist.api.PartitionedStore) ConsumerUID(com.sun.messaging.jmq.jmsserver.core.ConsumerUID) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList) TransactionAckExistException(com.sun.messaging.jmq.jmsserver.util.TransactionAckExistException) UnknownTransactionException(com.sun.messaging.jmq.jmsserver.util.UnknownTransactionException) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) BrokerAddress(com.sun.messaging.jmq.jmsserver.core.BrokerAddress) TransactionUID(com.sun.messaging.jmq.jmsserver.data.TransactionUID)

Example 24 with TransactionList

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

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

the class QBrowseHandler method getQBrowseList.

public ArrayList getQBrowseList(Destination d, String selectorstr) throws BrokerException, SelectorFormatException {
    Collection msgs = null;
    if (selectorstr == null) {
        msgs = d.getAll((Filter) null).values();
    } else {
        SelectorFilter f = new SelectorFilter(selectorstr);
        Map m = d.getAll(f);
        msgs = m.values();
    }
    // sort the messages
    ArrayList sorted = new ArrayList(msgs);
    Collections.sort(sorted, new RefCompare());
    TransactionList[] tls = DL.getTransactionList(d.getPartitionedStore());
    TransactionList tlist = tls[0];
    // remove any expired messages or messages in open txn
    Iterator itr = sorted.iterator();
    while (itr.hasNext()) {
        PacketReference p = (PacketReference) itr.next();
        if (p.isExpired()) {
            itr.remove();
        }
        if (!p.isDeliveryDue()) {
            itr.remove();
        }
        if (p.getTransactionID() != null) {
            // look up txn
            TransactionState ts = tlist.retrieveState(p.getTransactionID());
            if (ts != null && ts.getState() != TransactionState.COMMITTED) {
                // open txn, remove
                itr.remove();
            }
        }
        // check in takeover processing
        if (p.checkLock(false) == null) {
            itr.remove();
        }
    }
    ArrayList returnmsgs = new ArrayList();
    itr = sorted.iterator();
    while (itr.hasNext()) {
        PacketReference p = (PacketReference) itr.next();
        if (p == null) {
            continue;
        }
        returnmsgs.add(p.getSysMessageID());
    }
    return returnmsgs;
}
Also used : TransactionState(com.sun.messaging.jmq.jmsserver.data.TransactionState) SelectorFilter(com.sun.messaging.jmq.jmsserver.core.SelectorFilter) PacketReference(com.sun.messaging.jmq.jmsserver.core.PacketReference) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList)

Aggregations

TransactionList (com.sun.messaging.jmq.jmsserver.data.TransactionList)48 TransactionState (com.sun.messaging.jmq.jmsserver.data.TransactionState)25 TransactionUID (com.sun.messaging.jmq.jmsserver.data.TransactionUID)23 BrokerException (com.sun.messaging.jmq.jmsserver.util.BrokerException)23 ArrayList (java.util.ArrayList)12 HashMap (java.util.HashMap)10 ConsumerUID (com.sun.messaging.jmq.jmsserver.core.ConsumerUID)9 DestinationList (com.sun.messaging.jmq.jmsserver.core.DestinationList)9 PacketReference (com.sun.messaging.jmq.jmsserver.core.PacketReference)8 TransactionHandler (com.sun.messaging.jmq.jmsserver.data.handlers.TransactionHandler)8 List (java.util.List)8 PartitionedStore (com.sun.messaging.jmq.jmsserver.persist.api.PartitionedStore)7 IOException (java.io.IOException)7 TransactionBroker (com.sun.messaging.jmq.jmsserver.data.TransactionBroker)6 CacheHashMap (com.sun.messaging.jmq.util.CacheHashMap)6 JMQXid (com.sun.messaging.jmq.util.JMQXid)6 SelectorFormatException (com.sun.messaging.jmq.util.selector.SelectorFormatException)6 Iterator (java.util.Iterator)6 Map (java.util.Map)6 SysMessageID (com.sun.messaging.jmq.io.SysMessageID)5