throw new BrokerException("Internal Error: call with null txnID");
}
//handle 2-phase remote ack
TransactionList translist = Globals.getTransactionList();
TransactionUID tid = new TransactionUID(txnID.longValue());
if (ackType == ClusterBroadcast.MSG_PREPARE) {
TransactionAcknowledgement[] tas = new TransactionAcknowledgement[sysids.length];
ackEntry entry = null, value = null;
StringBuffer dbuf = new StringBuffer();
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;
}
com.sun.messaging.jmq.jmsserver.core.ConsumerUID scuid = value.getStoredConsumerUID();
tas[i] = new TransactionAcknowledgement(sysids[i], cuids[i], scuid);
PacketReference ref = value.getReference();
if (!scuid.shouldStore() || (ref != null && !ref.isPersistent())) {
tas[i].setShouldStore(false);
}
if (DEBUG_CLUSTER_TXN) {
dbuf.append("\n\t"+tas[i]);
}
}
if (ae != null) throw ae;
TransactionState ts = new TransactionState();
ts.setState(TransactionState.PREPARED);
if (DEBUG_CLUSTER_TXN) {
logger.log(logger.INFO, "Preparing remote transaction "+tid + " from "+txnHomeBroker+dbuf.toString());
}
Globals.getTransactionList().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);
}
}
if (DEBUG_CLUSTER_TXN) {
logger.log(logger.INFO, "Prepared remote transaction "+tid + " from "+txnHomeBroker+dbuf.toString());
}
return;
}
if (ackType == ClusterBroadcast.MSG_ROLLEDBACK) {
if (DEBUG_CLUSTER_TXN) {
logger.log(logger.INFO, "Rolling back remote transaction "+tid + " from "+txnHomeBroker);
}
if (translist.getRemoteTransactionState(tid) == null) {
if (DEBUG_CLUSTER_TXN) {
logger.log(logger.INFO, "Unknown remote transaction "+tid+ ", ignore");
}
return;
}
if (!translist.updateRemoteTransactionState(tid,
TransactionState.ROLLEDBACK, false, false, true)) {
return;
}
if (translist.getRecoveryRemoteTransactionAcks(tid) != null) {
rollbackRecoveryRemoteTransaction(tid, txnHomeBroker);
}
RemoteTransactionAckEntry tae = translist.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 {
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 (DEBUG_CLUSTER_TXN) {
logger.log(logger.INFO,
"["+sysid+":"+uid+"] not found in rolling back remote transaction "+tid);
}
continue;
}
if (value.getTUID() == null || !value.getTUID().equals(tid)) {
if (DEBUG_CLUSTER_TXN) {
logger.log(logger.INFO,
"["+sysid+":"+uid+"] with TUID="+value.getTUID()+
", in 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;
PacketReference ref = Destination.get(sysid);
if (ref == null) {
if (DEBUG_CLUSTER_TXN) {
logger.log(logger.INFO,
"["+sysid+":"+cuid+"] reference not found in rolling back remote transaction "+tid);
}
continue;
}
ref.removeInDelivery(suid);
ref.getDestination().forwardOrphanMessage(ref, suid);
}
} //tas != null
try {
Globals.getTransactionList().removeRemoteTransactionAck(tid);
} catch (Exception e) {
logger.log(logger.WARNING,
"Unable to remove transaction ack for rolledback transaction "+tid+": "+e.getMessage());
}
try {
Globals.getTransactionList().removeRemoteTransactionID(tid, true);
} catch (Exception e ) {
logger.log(logger.WARNING,
"Unable to remove rolledback remote transaction "+tid+": "+e.getMessage());
}
return;
}
int cLogRecordCount = 0;
ArrayList cLogDstList = null;
ArrayList cLogMsgList = null;
ArrayList cLogIntList = null;
if (ackType == ClusterBroadcast.MSG_ACKNOWLEDGED) {
if (DEBUG_CLUSTER_TXN) {
logger.log(logger.INFO, "Committing remote transaction "+tid + " from "+txnHomeBroker);
}
if (!Globals.getTransactionList().updateRemoteTransactionState(tid,
TransactionState.COMMITTED, (sysids == null), true, true)) {
if (DEBUG_CLUSTER_TXN) {
logger.log(logger.INFO, "Remote transaction "+tid + " already committed, from "+txnHomeBroker);
}
return;
}
boolean done = true;
if (translist.getRecoveryRemoteTransactionAcks(tid) != null) {
done = commitRecoveryRemoteTransaction(tid, txnHomeBroker);
}
RemoteTransactionAckEntry tae = translist.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,