Search in sources :

Example 31 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 32 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 33 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)

Example 34 with TransactionList

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

the class RedeliverHandler method redeliver.

public void redeliver(ConsumerUID[] ids, SysMessageID[] sysids, IMQConnection con, TransactionUID tid, boolean redeliver) throws BrokerException, IOException {
    SysMessageID sysid = null;
    // really should only have one
    Set sessions = new HashSet();
    // but client to broker protocol doesnt specify
    HashMap cToM = new HashMap();
    HashMap noConsumerMap = new HashMap();
    HashMap storedIDToConsumerUIDMap = new HashMap();
    for (int i = 0; i < ids.length; i++) {
        ConsumerUID id = ids[i];
        id.setConnectionUID(con.getConnectionUID());
        sysid = sysids[i];
        PacketReference ref = DL.get(null, sysid, false);
        if (ref == null || ref.isInvalid()) {
            continue;
        }
        Session s = Session.getSession(id);
        Consumer c = null;
        if (s != null) {
            if (!sessions.contains(s)) {
                s.pause("redeliver");
                sessions.add(s);
            }
            c = (Consumer) s.getConsumerOnSession(id);
        }
        if (c == null) {
            // ok, make sure the consumer has really gone away
            // if not, something is really wrong
            // otherwise ...
            // consumer has gone away but session is still
            // valid ->
            c = Consumer.getConsumer(id);
            if (c != null) {
                logger.log(Logger.WARNING, "Internal Error " + " consumer with id of " + id + " is unavailable " + " on session " + s + "[conuid,sess conuid] =" + "[" + con.getConnectionUID().longValue() + "," + (s == null ? 0 : s.getConnectionUID().longValue()) + "] consumer session is : " + c.getSessionUID());
                continue;
            } else {
                if (s != null && s.isClientAck(id) && !s.isTransacted() && redeliver && tid == null) {
                    ConsumerUID storedID = s.getStoredIDForDetatchedConsumer(id);
                    if (storedID != null && !storedID.equals(id)) {
                        storedIDToConsumerUIDMap.put(id, storedID);
                        SortedSet refset = (SortedSet) noConsumerMap.get(id);
                        if (refset == null) {
                            refset = new TreeSet(new RefCompare());
                            noConsumerMap.put(id, refset);
                        }
                        ref.removeInDelivery(storedID);
                        refset.add(ref);
                    }
                }
                // the consumer for this message has been
                // closed before the redeliver was requested
                // (this means the message has not been acked and
                // the session is open)
                // we dont need to deliver this message, ignore it
                logger.log(Logger.DEBUG, " consumer with id of " + id + " is unavailable " + " on session " + s + "[conuid,sess conuid] =" + "[" + con.getConnectionUID().longValue() + "," + (s == null ? 0 : s.getConnectionUID().longValue()) + "] it has been closed");
                continue;
            }
        }
        // for client < 4.1, need check 'redeliver' as well
        if (redeliver && (tid != null || s.isTransacted())) {
            if (tid == null) {
                tid = s.getCurrentTransactionID();
            }
            TransactionList[] tls = Globals.getDestinationList().getTransactionList(con.getPartitionedStore());
            TransactionList translist = tls[0];
            if (translist != null) {
                if (checkRemovedConsumedMessage(ref, id, tid, translist, true)) {
                    if (DEBUG_CLUSTER_TXN) {
                        logger.log(logger.INFO, "Ignore redeliver request for [" + sysid + ":" + id + "], removed with transaction (rerouted)" + tid);
                    }
                    continue;
                }
                if (checkRemovedConsumedMessage(ref, id, tid, translist, false)) {
                    if (DEBUG_CLUSTER_TXN) {
                        logger.log(logger.INFO, "Ignore redeliver request for [" + sysid + ":" + id + "], removed with transaction " + tid);
                    }
                    continue;
                }
            }
        }
        Set set = (Set) cToM.get(c);
        if (set == null) {
            set = new LinkedHashSet();
            cToM.put(c, set);
        }
        if (!set.contains(ref)) {
            ref.removeInDelivery((c.getStoredConsumerUID() == null ? c.getConsumerUID() : c.getStoredConsumerUID()));
            set.add(ref);
        } else if (DEBUG_CLUSTER_TXN) {
            logger.log(logger.INFO, "Ignore duplicated redeliver request [" + sysid + ":" + id + "]");
        }
        if (redeliver) {
            ref.consumed(c.getStoredConsumerUID(), s.isDupsOK(c.getConsumerUID()), false);
        } else {
            ref.removeDelivered(c.getStoredConsumerUID(), false);
        }
    }
    Iterator itr = cToM.entrySet().iterator();
    while (itr.hasNext()) {
        Map.Entry entry = (Map.Entry) itr.next();
        Consumer c = (Consumer) entry.getKey();
        Set msgs = (Set) entry.getValue();
        c.pause("start redeliver");
        c.routeMessages(msgs, true);
        c.resume("end redeliver");
    }
    // help gc
    cToM.clear();
    if (noConsumerMap.size() > 0) {
        try {
            logger.log(logger.DEBUG, "REDELIVER unacked for closed consumers: " + noConsumerMap);
            TransactionHandler.redeliverUnackedNoConsumer(noConsumerMap, storedIDToConsumerUIDMap, redeliver, null, null);
        } catch (Exception e) {
            logger.logStack(logger.WARNING, "Exception in redelivering unacked messages for closed consumers", e);
        }
    }
    itr = sessions.iterator();
    while (itr.hasNext()) {
        Session s = (Session) itr.next();
        s.resume("redeliver");
    }
}
Also used : ConsumerUID(com.sun.messaging.jmq.jmsserver.core.ConsumerUID) TransactionList(com.sun.messaging.jmq.jmsserver.data.TransactionList) BrokerException(com.sun.messaging.jmq.jmsserver.util.BrokerException) Consumer(com.sun.messaging.jmq.jmsserver.core.Consumer) PacketReference(com.sun.messaging.jmq.jmsserver.core.PacketReference) Session(com.sun.messaging.jmq.jmsserver.core.Session)

Example 35 with TransactionList

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

the class RedeliverHandler method checkRemovedConsumedMessage.

private boolean checkRemovedConsumedMessage(PacketReference ref, ConsumerUID id, TransactionUID tid, TransactionList translist, boolean rerouted) throws BrokerException {
    SysMessageID sysid = ref.getSysMessageID();
    HashMap cmap = translist.retrieveRemovedConsumedMessages(tid, rerouted);
    if (cmap != null && cmap.size() > 0) {
        List interests = (List) cmap.get(sysid);
        if (interests == null || interests.size() == 0) {
            return false;
        }
        for (int j = 0; j < interests.size(); j++) {
            ConsumerUID intid = (ConsumerUID) interests.get(j);
            if (intid.equals(id)) {
                TransactionState ts = translist.retrieveState(tid);
                if (ts != null && ts.getState() == TransactionState.FAILED) {
                    if (!rerouted) {
                        TransactionHandler.releaseRemoteForActiveConsumer(ref, id, tid, translist);
                    }
                    return true;
                }
            }
        }
    }
    return false;
}
Also used : TransactionState(com.sun.messaging.jmq.jmsserver.data.TransactionState) ConsumerUID(com.sun.messaging.jmq.jmsserver.core.ConsumerUID) DestinationList(com.sun.messaging.jmq.jmsserver.core.DestinationList) 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