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;
}
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;
}
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;
}
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");
}
}
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;
}
Aggregations