use of com.sun.messaging.jmq.jmsserver.core.DestinationUID in project openmq by eclipse-ee4j.
the class DataHandler method handle.
/**
* Method to handle normal/admin data messages
*/
protected boolean handle(IMQConnection con, Packet msg, boolean isadmin) throws BrokerException {
// used for fault injection
Hashtable props = null;
if (!isadmin && fi.FAULT_INJECTION) {
// for fault injection
msgProcessCnt++;
try {
props = msg.getProperties();
} catch (Exception ex) {
props = new Properties();
}
} else {
msgProcessCnt = 0;
}
boolean ack = msg.getSendAcknowledge();
long cid = msg.getConsumerID();
String refid = (((IMQBasicConnection) con).getDumpPacket() || ((IMQBasicConnection) con).getDumpOutPacket()) ? msg.getSysMessageID().toString() : "";
boolean isIndemp = msg.getIndempotent();
String reason = null;
List failedrefs = null;
int status = Status.OK;
HashMap routedSet = null;
List<MessageDeliveryTimeInfo> deliveryDelayReadyList = new ArrayList<>();
boolean route = false;
Producer pausedProducer = null;
boolean transacted = false;
try {
pausedProducer = checkFlow(msg, con);
transacted = (msg.getTransactionID() != 0);
// OK .. handle Fault Injection
if (!isadmin && fi.FAULT_INJECTION) {
Map m = new HashMap();
if (props != null) {
m.putAll(props);
}
m.put("mqMsgCount", Integer.valueOf(msgProcessCnt));
m.put("mqIsTransacted", Boolean.valueOf(transacted));
fi.checkFaultAndExit(FaultInjection.FAULT_SEND_MSG_1, m, 2, false);
if (fi.checkFault(FaultInjection.FAULT_SEND_MSG_1_EXCEPTION, m)) {
fi.unsetFault(FaultInjection.FAULT_SEND_MSG_1_EXCEPTION);
throw new BrokerException("FAULT INJECTION: " + FaultInjection.FAULT_SEND_MSG_1_EXCEPTION);
}
if (fi.checkFaultAndSleep(FaultInjection.FAULT_SEND_MSG_1_SLEEP, m, true)) {
fi.unsetFault(FaultInjection.FAULT_SEND_MSG_1_SLEEP);
}
if (fi.checkFaultAndSleep(FaultInjection.FAULT_SEND_MSG_1_SLEEP_EXCEPTION, m, true)) {
fi.unsetFault(FaultInjection.FAULT_SEND_MSG_1_SLEEP_EXCEPTION);
throw new BrokerException("FAULT INJECTION: " + FaultInjection.FAULT_SEND_MSG_1_SLEEP_EXCEPTION);
}
}
DestinationUID realduid = DestinationUID.getUID(msg.getDestination(), msg.getIsQueue());
if (DEBUG) {
logger.log(Logger.INFO, "DataHandler:Received JMS Message[" + msg.toString() + " : " + realduid + "]TID=" + msg.getTransactionID() + " on connection " + con + ", isadmin=" + isadmin);
}
// get the list of "real" destination UIDs (this will be one if the
// destination if not a wildcard and 0 or more if it is
List[] dds = DL.findMatchingIDs(con.getPartitionedStore(), realduid);
List duids = dds[0];
boolean packetUsed = false;
if (duids.size() == 0) {
// nothing to do
route = false;
} else {
Iterator itr = duids.iterator();
while (itr.hasNext()) {
PacketReference ref = null;
Exception lastthr = null;
boolean isLast = false;
DestinationUID duid = (DestinationUID) itr.next();
isLast = !itr.hasNext();
Destination[] ds = DL.getDestination(con.getPartitionedStore(), duid);
Destination d = ds[0];
try {
if (d == null) {
throw new BrokerException("Unknown Destination:" + msg.getDestination());
}
if (realduid.isWildcard() && d.isTemporary()) {
logger.log(Logger.DEBUG, "L10N-XXX: Wildcard production with destination name of " + realduid + " to temporary destination " + d.getUniqueName() + " is not supported, ignoring");
continue;
}
if (realduid.isWildcard() && d.isInternal()) {
logger.log(Logger.DEBUG, "L10N-XXX: Wildcard production with destination name of " + realduid + " to internal destination " + d.getUniqueName() + " is not supported, ignoring");
continue;
}
if (realduid.isWildcard() && d.isDMQ()) {
logger.log(Logger.DEBUG, "L10N-XXX: Wildcard production with destination name of " + realduid + " to the DeadMessageQueue" + d.getUniqueName() + " is not supported, ignoring");
continue;
}
if (pausedProducer != null) {
pauseProducer(d, duid, pausedProducer, con);
pausedProducer = null;
}
if (packetUsed) {
// create a new Packet for the message
// we need a new sysmsgid with it
Packet newp = new Packet();
newp.fill(msg);
newp.generateSequenceNumber(true);
newp.generateTimestamp(true);
newp.prepareToSend();
newp.generateSequenceNumber(false);
newp.generateTimestamp(false);
msg = newp;
}
packetUsed = true;
// OK generate a ref. This checks message size and
// will be needed for later operations
ref = createReference(msg, duid, con, isadmin);
// dont bother calling route if there are no messages
//
// to improve performance, we route and later forward
route |= queueMessage(d, ref, transacted);
// ok ...
if (isLast && route && ack && !ref.isPersistent()) {
sendAcknowledge(refid, cid, status, con, reason, props, transacted);
ack = false;
}
Set s = routeMessage(con.getPartitionedStore(), transacted, ref, route, d, deliveryDelayReadyList);
if (s != null && !s.isEmpty()) {
if (routedSet == null) {
routedSet = new HashMap();
}
routedSet.put(ref, s);
}
// handle producer flow control
pauseProducer(d, duid, pausedProducer, con);
} catch (Exception ex) {
if (ref != null) {
if (failedrefs == null) {
failedrefs = new ArrayList();
}
failedrefs.add(ref);
}
lastthr = ex;
logger.log(Logger.DEBUG, BrokerResources.W_MESSAGE_STORE_FAILED, con.toString(), ex);
} finally {
if (pausedProducer != null) {
pauseProducer(d, duid, pausedProducer, con);
pausedProducer = null;
}
if (isLast && lastthr != null) {
throw lastthr;
}
}
}
// while
}
} catch (BrokerException ex) {
// dont log on dups if indemponent
int loglevel = (isIndemp && ex.getStatusCode() == Status.NOT_MODIFIED) ? Logger.DEBUG : Logger.WARNING;
logger.log(loglevel, BrokerResources.W_MESSAGE_STORE_FAILED, con.toString(), ex);
reason = ex.getMessage();
// LKS - we may want an improved error message in the wildcard case
status = ex.getStatusCode();
} catch (IOException ex) {
logger.log(Logger.WARNING, BrokerResources.W_MESSAGE_STORE_FAILED, con.toString(), ex);
reason = ex.getMessage();
status = Status.ERROR;
} catch (SecurityException ex) {
logger.log(Logger.WARNING, BrokerResources.W_MESSAGE_STORE_FAILED, con.toString(), ex);
reason = ex.getMessage();
status = Status.FORBIDDEN;
} catch (OutOfMemoryError err) {
logger.logStack(Logger.WARNING, BrokerResources.W_MESSAGE_STORE_FAILED, con.toString() + ":" + msg.getPacketSize(), err);
reason = err.getMessage();
status = Status.ERROR;
} catch (Exception ex) {
logger.logStack(Logger.WARNING, BrokerResources.W_MESSAGE_STORE_FAILED, con.toString(), ex);
reason = ex.getMessage();
status = Status.ERROR;
}
if (status == Status.ERROR && failedrefs != null) {
// make sure we remove the message
//
// NOTE: we only want to remove the last failure (its too late
// for the rest). In the non-wildcard case, this will be the
// only entry. In the wildcard cause, it will be the one that had an issue
Iterator itr = failedrefs.iterator();
while (itr.hasNext()) {
PacketReference ref = (PacketReference) itr.next();
Destination[] ds = DL.getDestination(con.getPartitionedStore(), ref.getDestinationUID());
Destination d = ds[0];
if (d != null) {
cleanupOnError(d, ref);
}
}
}
if (ack) {
sendAcknowledge(refid, cid, status, con, reason, props, transacted);
}
if (route && routedSet != null) {
Iterator<Map.Entry> itr = routedSet.entrySet().iterator();
Map.Entry pair = null;
while (itr.hasNext()) {
pair = itr.next();
PacketReference pktref = (PacketReference) pair.getKey();
DestinationUID duid = pktref.getDestinationUID();
Set s = (Set) pair.getValue();
Destination[] ds = DL.getDestination(con.getPartitionedStore(), duid);
Destination dest = ds[0];
if (dest == null) {
Object[] emsg = { pktref, s, duid };
logger.log(logger.WARNING, br.getKString(br.W_ROUTE_PRODUCED_MSG_DEST_NOT_FOUND, emsg));
continue;
}
try {
forwardMessage(dest, pktref, s);
} catch (Exception e) {
Object[] emsg = { pktref, duid, s };
logger.logStack(logger.WARNING, br.getKString(br.X_ROUTE_PRODUCED_MSG_FAIL, emsg), e);
}
}
}
if (deliveryDelayReadyList.size() > 0) {
MessageDeliveryTimeInfo di = null;
Iterator<MessageDeliveryTimeInfo> itr = deliveryDelayReadyList.iterator();
while (itr.hasNext()) {
di = itr.next();
di.setDeliveryReady();
}
}
// someone else will free
return isadmin;
}
use of com.sun.messaging.jmq.jmsserver.core.DestinationUID in project openmq by eclipse-ee4j.
the class DestinationHandler method handle.
/**
* Method to handle Destination (create or delete) messages
*/
@Override
public boolean handle(IMQConnection con, Packet msg) throws BrokerException {
int status = Status.OK;
String reason = null;
// XXX - REVISIT 2/25/00 racer
// do we need to create a reply packet each time ?
Packet pkt = new Packet(con.useDirectBuffers());
pkt.setConsumerID(msg.getConsumerID());
Hashtable hash = new Hashtable();
Hashtable props = null;
try {
props = msg.getProperties();
} catch (Exception ex) {
assert false;
logger.logStack(Logger.ERROR, BrokerResources.E_INTERNAL_BROKER_ERROR, "Unable to create/destroy destination - no properties", ex);
throw new BrokerException(Globals.getBrokerResources().getString(BrokerResources.X_INTERNAL_EXCEPTION, "Can not handle create/destroy destination"));
}
String destination = (String) props.get("JMQDestination");
Integer inttype = (Integer) props.get("JMQDestType");
int type = (inttype == null) ? 0 : inttype.intValue();
pkt.setPacketType(msg.getPacketType() + 1);
if (msg.getPacketType() == PacketType.CREATE_DESTINATION) {
if (DEBUG) {
logger.log(Logger.DEBUGHIGH, "ConsumerHandler: handle() [ Received AddDestination message {0}]", msg.toString());
}
assert destination != null;
assert inttype != null;
if (con.isAdminConnection()) {
type |= DestType.DEST_ADMIN | DestType.DEST_LOCAL | DestType.DEST_AUTO;
}
assert pkt.getPacketType() == PacketType.CREATE_DESTINATION_REPLY;
try {
Destination d = null;
if (DestType.isTemporary(type)) {
// deal w/ versioning .. only store
// 3.5 or later
boolean storeTemps = con.getConnectionUID().getCanReconnect();
long reconnectTime = con.getReconnectInterval();
Destination[] ds = DL.createTempDestination(con.getPartitionedStore(), destination, type, con.getConnectionUID(), storeTemps, reconnectTime);
d = ds[0];
if (con.getConnectionUID().equals(d.getConnectionUID())) {
con.attachTempDestination(d.getDestinationUID());
}
} else if (destination.startsWith(Globals.INTERNAL_PREFIX)) {
// do nothing
} else if (DestinationUID.isWildcard(destination)) {
pkt.setWildcard(true);
// dont create a destination
} else {
Destination[] ds = DL.getDestination(con.getPartitionedStore(), destination, type, true, !con.isAdminConnection());
d = ds[0];
}
hash.put("JMQDestType", Integer.valueOf(type));
hash.put("JMQDestUID", destination);
/*
* Set XML Schema validation properties
*/
hash.put("JMQValidateXMLSchema", Boolean.valueOf(isXMLSchemaValidationOn(d)));
String uris = getXMLSchemaURIList(d);
if (uris != null) {
hash.put("JMQXMLSchemaURIList", uris);
}
hash.put("JMQReloadXMLSchemaOnFailure", Boolean.valueOf(getReloadXMLSchemaOnFailure(d)));
} catch (BrokerException ex) {
status = ex.getStatusCode();
reason = ex.getMessage();
if (status != Status.CONFLICT) {
logger.log(Logger.WARNING, BrokerResources.W_CREATE_DEST_FAILED, destination, ex);
} else if (DEBUG) {
logger.log(Logger.DEBUG, BrokerResources.W_CREATE_DEST_FAILED, destination, ex);
}
} catch (IOException ex) {
status = Status.ERROR;
reason = ex.getMessage();
logger.log(Logger.WARNING, BrokerResources.W_CREATE_DEST_FAILED, destination, ex);
}
} else {
// removing Interest
assert msg.getPacketType() == PacketType.DESTROY_DESTINATION;
assert pkt.getPacketType() == PacketType.DESTROY_DESTINATION_REPLY;
Destination d = null;
try {
DestinationUID rmuid = DestinationUID.getUID(destination, DestType.isQueue(type));
if (destination == null) {
throw new BrokerException(Globals.getBrokerResources().getString(BrokerResources.X_INTERNAL_EXCEPTION, "protocol error, destination is null"), Status.NOT_FOUND);
}
Destination[] ds = DL.getDestination(con.getPartitionedStore(), rmuid);
d = ds[0];
assert d != null;
DL.removeDestination(con.getPartitionedStore(), rmuid, true, Globals.getBrokerResources().getString(BrokerResources.M_CLIENT_REQUEST, con.getConnectionUID()));
con.detachTempDestination(rmuid);
} catch (BrokerException ex) {
status = ex.getStatusCode();
reason = ex.getMessage();
logger.log(Logger.WARNING, BrokerResources.W_DESTROY_DEST_FAILED, destination, ex);
} catch (IOException ex) {
status = Status.ERROR;
reason = ex.getMessage();
logger.log(Logger.WARNING, BrokerResources.W_DESTROY_DEST_FAILED, destination, ex);
}
}
hash.put("JMQStatus", Integer.valueOf(status));
if (reason != null) {
hash.put("JMQReason", reason);
}
if (((IMQBasicConnection) con).getDumpPacket() || ((IMQBasicConnection) con).getDumpOutPacket()) {
hash.put("JMQReqID", msg.getSysMessageID().toString());
}
pkt.setProperties(hash);
con.sendControlMessage(pkt);
return true;
}
use of com.sun.messaging.jmq.jmsserver.core.DestinationUID in project openmq by eclipse-ee4j.
the class ProducerHandler method handle.
/**
* Method to handle Producers
*/
@Override
public boolean handle(IMQConnection con, Packet msg) throws BrokerException {
Packet reply = new Packet(con.useDirectBuffers());
reply.setPacketType(msg.getPacketType() + 1);
reply.setConsumerID(msg.getConsumerID());
boolean isIndemp = msg.getIndempotent();
int status = Status.OK;
String reason = null;
Hashtable props = null;
try {
props = msg.getProperties();
} catch (Exception ex) {
throw new RuntimeException("Can not load props", ex);
}
Hashtable returnprop = new Hashtable();
Destination d = null;
try {
if (msg.getPacketType() == PacketType.ADD_PRODUCER) {
String dest = (String) props.get("JMQDestination");
Integer type = (Integer) props.get("JMQDestType");
if (!con.isAdminConnection() && MemoryGlobals.getMEM_DISALLOW_PRODUCERS()) {
status = Status.ERROR;
reason = "Low memory";
logger.log(Logger.WARNING, BrokerResources.W_LOW_MEM_REJECT_PRODUCER);
throw new BrokerException(reason, status);
}
Long lsessionid = (Long) props.get("JMQSessionID");
if (lsessionid != null) {
// 3.5 protocol
SessionUID sessionID = new SessionUID(lsessionid.longValue());
// single threaded .. we dont have to worry about
// someone else creating it
Session session = con.getSession(sessionID);
if (session == null) {
throw new BrokerException("Internal Error: client sent " + "invalid sessionUID w/ ADD_PRODUCER " + sessionID + " session does not exist");
}
}
Destination[] ds = null;
DestinationUID duid = null;
if (dest != null && !DestinationUID.isWildcard(dest) && type != null) {
while (true) {
ds = DL.getDestination(con.getPartitionedStore(), dest, type.intValue(), true, !con.isAdminConnection());
d = ds[0];
if (d != null) {
try {
d.incrementRefCount();
} catch (BrokerException ex) {
// try again
continue;
} catch (IllegalStateException ex) {
throw new BrokerException(Globals.getBrokerResources().getKString(BrokerResources.X_SHUTTING_DOWN_BROKER), BrokerResources.X_SHUTTING_DOWN_BROKER, ex, Status.ERROR);
}
}
// got a lock on the dest
break;
}
if (d == null) {
logger.log(Logger.DEBUG, "Unable to add " + "producer to " + dest + " :" + DestType.toString(type.intValue()) + " destination can not be autocreated ");
reason = "can not create destination";
status = Status.NOT_FOUND;
throw new BrokerException(reason, status);
}
duid = d.getDestinationUID();
} else if (dest == null || type == null) {
reason = "no destination passed [dest,type] = [" + dest + "," + type + "]";
status = Status.ERROR;
throw new BrokerException(reason, status);
} else {
duid = DestinationUID.getUID(dest, DestType.isQueue(type.intValue()));
}
String info = msg.getSysMessageID().toString();
Producer p = addProducer(duid, con, info, isIndemp);
ProducerUID pid = p.getProducerUID();
assert pid != null;
// LKS - XXX - REVISIT - WHAT ABOUT FLOW CONTROL
boolean active = d == null || d.isProducerActive(pid);
returnprop.put("JMQProducerID", Long.valueOf(pid.longValue()));
returnprop.put("JMQDestinationID", duid.toString());
if (d == null) {
returnprop.put("JMQBytes", Long.valueOf(-1));
returnprop.put("JMQSize", Integer.valueOf(-1));
} else if (active) {
returnprop.put("JMQBytes", Long.valueOf(d.getBytesProducerFlow()));
returnprop.put("JMQSize", Integer.valueOf(d.getSizeProducerFlow()));
} else {
returnprop.put("JMQBytes", Long.valueOf(0));
returnprop.put("JMQSize", Integer.valueOf(0));
}
} else {
assert msg.getPacketType() == PacketType.DELETE_PRODUCER;
Long pid_l = (Long) props.get("JMQProducerID");
ProducerUID pid = new ProducerUID(pid_l == null ? 0 : pid_l.longValue());
removeProducer(pid, isIndemp, con, "Producer closed requested:\n\tconnection: " + con.getConnectionUID() + "\n\tproducerID: " + pid + "\n\trequest sysmsgid message: " + msg.getSysMessageID());
}
} catch (BrokerException ex) {
status = ex.getStatusCode();
reason = ex.getMessage();
logger.log(Logger.INFO, reason);
} catch (Exception ex) {
logger.logStack(Logger.INFO, BrokerResources.E_INTERNAL_BROKER_ERROR, "producer message ", ex);
reason = ex.getMessage();
status = Status.ERROR;
} finally {
if (d != null) {
d.decrementRefCount();
}
}
returnprop.put("JMQStatus", Integer.valueOf(status));
if (reason != null) {
returnprop.put("JMQReason", reason);
}
if (((IMQBasicConnection) con).getDumpPacket() || ((IMQBasicConnection) con).getDumpOutPacket()) {
returnprop.put("JMQReqID", msg.getSysMessageID().toString());
}
reply.setProperties(returnprop);
con.sendControlMessage(reply);
return true;
}
use of com.sun.messaging.jmq.jmsserver.core.DestinationUID in project openmq by eclipse-ee4j.
the class ProducerHandler method addProducer.
public Producer addProducer(DestinationUID duid, IMQConnection con, String id, boolean isIndemp) throws BrokerException {
Producer p = null;
if (isIndemp) {
p = (Producer) Producer.getProducer(id);
}
if (p == null) {
p = Producer.createProducer(duid, con.getConnectionUID(), id, con.getPartitionedStore());
assert p != null;
con.addProducer(p);
// Add to all destinations
List[] ll = DL.findMatchingIDs(con.getPartitionedStore(), duid);
List l = ll[0];
Iterator itr = l.iterator();
DestinationUID realuid = null;
Destination[] ds = null;
Destination d = null;
while (itr.hasNext()) {
realuid = (DestinationUID) itr.next();
ds = DL.getDestination(con.getPartitionedStore(), realuid);
d = ds[0];
if (duid.isWildcard() && d.isTemporary()) {
logger.log(Logger.DEBUG, "L10N-XXX: Wildcard production with destination name of " + duid + " to temporary destination " + d.getUniqueName() + " is not supported, ignoring");
continue;
}
if (duid.isWildcard() && d.isInternal()) {
logger.log(Logger.DEBUG, "L10N-XXX: Wildcard production with destination name of " + duid + " to internal destination " + d.getUniqueName() + " is not supported, ignoring");
continue;
}
if (duid.isWildcard() && d.isDMQ()) {
logger.log(Logger.DEBUG, "L10N-XXX: Wildcard production with destination name of " + duid + " to the DeadMessageQueue" + d.getUniqueName() + " is not supported, ignoring");
continue;
}
d.addProducer(p);
}
}
return p;
}
use of com.sun.messaging.jmq.jmsserver.core.DestinationUID in project openmq by eclipse-ee4j.
the class TransactionHandler method doRollback.
/**
* Rollback a transaction. This method is invoked from two places: 1) From TransactionHandler.handle() when handling a
* client ROLLBACK packet. This is the common case. 2) From the admin handler when an admin rollback request has been
* issued on a PREPARED XA transaction.
*
* @param id The TransactionUID to commit
* @param xid The Xid of the transaction to commit. Required if transaction is an XA transaction. Must be null if it is
* not an XA transaction.
* @param xaFlags xaFlags passed on COMMIT operation. Used only if an XA transaction.
* @param ts Current TransactionState of this transaction.
* @param conlist List of transactions on this connection. Will be null if commit is trigger by an admin request.
* @param con Connection client commit packet came in on or, for admin, the connection the admin request came in on.
*
* @throws BrokerException on an error. The method will have logged a message to the broker log.
*/
public void doRollback(TransactionList translist, TransactionUID id, JMQXid xid, Integer xaFlags, TransactionState ts, List conlist, IMQConnection con, RollbackReason rbreason) throws BrokerException {
int s;
int oldstate = ts.getState();
PartitionedStore pstore = translist.getPartitionedStore();
// Update transaction state
try {
if (xid == null) {
// Plain JMS transaction.
s = TransactionState.ROLLEDBACK;
} else {
// XA Transaction.
if (rbreason == RollbackReason.ADMIN || rbreason == RollbackReason.CONNECTION_CLEANUP) {
if (ts.getState() == TransactionState.STARTED) {
ts = translist.updateState(id, TransactionState.FAILED, TransactionState.STARTED, true);
String[] args = { rbreason.toString(), id.toString() + "[" + TransactionState.toString(oldstate) + "]XID=", xid.toString() };
if (rbreason != RollbackReason.ADMIN && (DEBUG || DEBUG_CLUSTER_TXN || logger.getLevel() <= Logger.DEBUG)) {
logger.log(logger.WARNING, Globals.getBrokerResources().getKString(BrokerResources.W_FORCE_ENDED_TXN, args));
}
}
}
s = ts.nextState(PacketType.ROLLBACK_TRANSACTION, xaFlags);
}
} catch (BrokerException ex) {
if (ex.getStatusCode() == Status.CONFLICT) {
logger.log(Logger.ERROR, ex.toString());
} else {
logger.log(Logger.ERROR, ex.toString() + ": TUID=" + id + " Xid=" + xid);
}
throw ex;
}
ts = translist.updateState(id, s, true);
if (Globals.isNewTxnLogEnabled() && oldstate == TransactionState.PREPARED) {
int transactionType = BaseTransaction.LOCAL_TRANSACTION_TYPE;
if (translist.isClusterTransaction(id)) {
transactionType = BaseTransaction.CLUSTER_TRANSACTION_TYPE;
}
logTxnCompletion(pstore, id, TransactionState.ROLLEDBACK, transactionType);
}
if (fi.FAULT_INJECTION) {
checkFIAfterDB(PacketType.ROLLBACK_TRANSACTION);
}
boolean processDone = true;
List list = new ArrayList(translist.retrieveSentMessages(id));
for (int i = 0; i < list.size(); i++) {
SysMessageID sysid = (SysMessageID) list.get(i);
if (DEBUG) {
logger.log(Logger.INFO, "Removing " + sysid + " because of rollback");
}
PacketReference ref = DL.get(null, sysid);
if (ref == null) {
continue;
}
DestinationUID duid = ref.getDestinationUID();
Destination[] ds = DL.getDestination(ref.getPartitionedStore(), duid);
Destination d = ds[0];
if (d != null) {
Destination.RemoveMessageReturnInfo ret = d.removeMessageWithReturnInfo(sysid, RemoveReason.ROLLBACK);
if (ret.storermerror) {
processDone = false;
}
}
}
// remove from our active connection list
if (conlist != null) {
conlist.remove(id);
}
// re-queue any orphan messages
// how we handle the orphan messages depends on a couple
// of things:
// - has the session closed ?
// if the session has closed the messages are "orphan"
// - otherwise, the messages are still "in play" and
// we dont do anything with them
//
Map m = translist.getOrphanAck(id);
if (m != null) {
Iterator itr = m.entrySet().iterator();
while (itr.hasNext()) {
Map.Entry me = (Map.Entry) itr.next();
SysMessageID sysid = (SysMessageID) me.getKey();
PacketReference ref = DL.get(null, sysid, false);
if (ref == null) {
if (DEBUG) {
logger.log(Logger.INFO, "Process transaction rollback " + id + ": orphan message already removed " + sysid);
}
continue;
}
Destination dst = ref.getDestination();
Map sids = (Map) me.getValue();
if (sids == null) {
continue;
}
Iterator siditr = sids.entrySet().iterator();
while (siditr.hasNext()) {
Map.Entry se = (Map.Entry) siditr.next();
ConsumerUID sid = (ConsumerUID) se.getKey();
if (ref.isLocal()) {
if (dst != null) {
dst.forwardOrphanMessage(ref, sid);
} else {
if (DEBUG) {
logger.log(Logger.INFO, "Process transaction rollback " + id + ": orphan consumed message destination already removed " + sysid);
}
}
continue;
}
List cids = (List) se.getValue();
if (cids == null) {
continue;
}
Iterator ciditr = cids.iterator();
while (ciditr.hasNext()) {
ConsumerUID cid = (ConsumerUID) ciditr.next();
try {
ref.acquireDestroyRemoteReadLock();
try {
if (ref.isLastRemoteConsumerUID(sid, cid)) {
if (ref.acknowledged(cid, sid, !(cid.isNoAck() || cid.isDupsOK()), false, id, translist, null, false)) {
try {
if (dst != null) {
dst.removeRemoteMessage(sysid, RemoveReason.ACKNOWLEDGED, ref);
} else {
logger.log(Logger.INFO, "Process transaction rollback " + id + ": orphan consumed remote message destination already removed " + sysid);
}
} finally {
ref.postAcknowledgedRemoval();
}
}
}
} finally {
ref.clearDestroyRemoteReadLock();
}
} catch (Exception ex) {
logger.logStack((DEBUG_CLUSTER_TXN ? Logger.WARNING : Logger.DEBUG), "Unable to cleanup orphaned remote message " + "[" + cid + "," + sid + "," + sysid + "]" + " on rollback transaction " + id, ex);
}
BrokerAddress addr = translist.getAckBrokerAddress(id, sysid, cid);
try {
HashMap prop = new HashMap();
prop.put(ClusterBroadcast.RB_RELEASE_MSG_ORPHAN, id.toString());
Globals.getClusterBroadcast().acknowledgeMessage(addr, sysid, cid, ClusterBroadcast.MSG_IGNORED, prop, false);
} catch (BrokerException e) {
Globals.getLogger().log(Logger.WARNING, "Unable to notify " + addr + " for orphaned remote message " + "[" + cid + ", " + sid + ", " + ", " + sysid + "]" + " in rollback transaction " + id);
}
}
}
}
}
// OK .. now remove the acks
translist.removeTransactionAck(id, true);
/*
* Can't really call the JMX notification code at the end of doRollback() because the call to
* translist.removeTransactionID(id) removes the MBean.
*/
Agent agent = Globals.getAgent();
if (agent != null) {
agent.notifyTransactionRollback(id);
}
try {
ts.setState(s);
cacheSetState(id, ts, con);
doRemoteRollback(translist, id, s);
translist.removeTransaction(id, !processDone);
if (rbreason == RollbackReason.ADMIN || rbreason == RollbackReason.CONNECTION_CLEANUP) {
String[] args = { rbreason.toString(), id.toString() + "[" + TransactionState.toString(oldstate) + "]", (xid == null ? "null" : xid.toString()) };
if (rbreason == RollbackReason.CONNECTION_CLEANUP) {
if (DEBUG || DEBUG_CLUSTER_TXN || logger.getLevel() <= Logger.DEBUG) {
logger.log(logger.INFO, Globals.getBrokerResources().getKString(BrokerResources.W_FORCE_ROLLEDBACK_TXN, args));
}
} else {
logger.log(logger.WARNING, Globals.getBrokerResources().getKString(BrokerResources.W_FORCE_ROLLEDBACK_TXN, args));
}
}
} catch (BrokerException ex) {
logger.logStack(logger.ERROR, br.getKString(br.X_REMOVE_TRANSACTION, id, ex.getMessage()), ex);
ex.setStackLogged();
throw ex;
}
}
Aggregations