use of com.sun.messaging.jmq.jmsserver.data.TransactionBroker in project openmq by eclipse-ee4j.
the class TransactionHandler method retrieveConsumedRemoteMessages.
private HashMap[] retrieveConsumedRemoteMessages(TransactionList translist, TransactionUID id, boolean checkOnly) throws BrokerException {
HashMap mcmap = translist.retrieveConsumedMessages(id);
HashMap sToCmap = translist.retrieveStoredConsumerUIDs(id);
if (DEBUG_CLUSTER_TXN) {
logger.log(logger.INFO, "retrieveConsumedRemoteMessages(" + translist + ",TID=" + id + ") retrieveConsumedMessages: " + mcmap);
}
if (mcmap == null || mcmap.size() == 0) {
return null;
}
HashMap[] rets = new HashMap[2];
HashMap<BrokerAddress, ArrayList[]> bmmap = new HashMap<>();
HashMap<TransactionBroker, ArrayList<TransactionAcknowledgement>> tbmmap = new HashMap<>();
ArrayList[] bmcll = null;
ArrayList<TransactionAcknowledgement> tbmcl = null;
boolean hasRemote = false;
BrokerAddress myba = Globals.getMyAddress();
UID tranpid = translist.getPartitionedStore().getPartitionID();
UID refpid = null;
ConsumerUID cuid = null, scuid = null;
TransactionAcknowledgement ta = null;
Iterator<Map.Entry> itr = mcmap.entrySet().iterator();
Map.Entry pair = null;
while (itr.hasNext()) {
pair = itr.next();
SysMessageID sysid = (SysMessageID) pair.getKey();
if (sysid == null) {
continue;
}
PacketReference ref = DL.get(null, sysid, false);
if (checkRefRequeued(translist, id, ref, sysid)) {
BrokerException bex = new BrokerException(Globals.getBrokerResources().getKString(BrokerResources.X_MESSAGE_MAYBE_REROUTED, sysid) + ", TUID=" + id, Status.GONE);
bex.setRemote(true);
StringBuilder buf = new StringBuilder();
List interests = (List) pair.getValue();
for (int i = 0; i < interests.size(); i++) {
buf.append(String.valueOf(((ConsumerUID) interests.get(i)).longValue()));
buf.append(' ');
}
bex.setRemoteConsumerUIDs(buf.toString());
throw bex;
}
if (ref == null) {
throw new BrokerException(Globals.getBrokerResources().getKString(BrokerResources.X_MESSAGE_REF_GONE, sysid) + ", TUID=" + id, Status.CONFLICT);
}
BrokerAddress ba = ref.getBrokerAddress();
if (ba == null) {
if (!DL.isPartitionMode()) {
ba = myba;
} else {
refpid = ref.getPartitionedStore().getPartitionID();
ba = (BrokerAddress) myba.clone();
ba.setStoreSessionUID(refpid);
if (!refpid.equals(tranpid)) {
hasRemote = true;
}
}
} else if (!hasRemote) {
hasRemote = true;
}
if (hasRemote && checkOnly) {
return rets;
}
TransactionBroker tba = new TransactionBroker(ba);
bmcll = bmmap.get(tba.getBrokerAddress());
tbmcl = tbmmap.get(tba);
if (bmcll == null) {
bmcll = new ArrayList[2];
bmcll[0] = new ArrayList();
bmcll[1] = new ArrayList();
bmmap.put(tba.getBrokerAddress(), bmcll);
}
if (tbmcl == null) {
tbmcl = new ArrayList<>();
tbmmap.put(tba, tbmcl);
}
List interests = (List) mcmap.get(sysid);
for (int i = 0; i < interests.size(); i++) {
cuid = (ConsumerUID) interests.get(i);
bmcll[0].add(sysid);
bmcll[1].add(cuid);
scuid = (ConsumerUID) sToCmap.get(cuid);
ta = new TransactionAcknowledgement(sysid, cuid, scuid);
if (!scuid.shouldStore() || !ref.isPersistent()) {
ta.setShouldStore(false);
}
tbmcl.add(ta);
}
if (DEBUG_CLUSTER_TXN) {
logger.log(logger.INFO, "retrieveConsumedRemoteMessages() for broker " + tba + ": " + Arrays.toString(bmcll) + ", " + tbmcl);
}
}
if (!hasRemote) {
return null;
}
rets[0] = bmmap;
rets[1] = tbmmap;
return rets;
}
use of com.sun.messaging.jmq.jmsserver.data.TransactionBroker in project openmq by eclipse-ee4j.
the class TransactionHandler method doRemotePrepare.
private ClusterTransaction doRemotePrepare(TransactionList translist, TransactionUID id, TransactionState nextState, TransactionWork txnWork) throws BrokerException {
if (nextState.getState() != TransactionState.PREPARED) {
throw new BrokerException("Unexpected state " + nextState + " for transactionID:" + id);
}
HashMap[] rets = retrieveConsumedRemoteMessages(translist, id, false);
if (DEBUG_CLUSTER_TXN) {
logger.log(logger.INFO, "doRemotePrepare(" + translist + ", " + id + "): retrievedConsumedRemoteMsgs:" + (rets == null ? "null" : rets[0] + ", " + rets[1]));
}
if (fi.FAULT_INJECTION) {
if (fi.checkFault(fi.FAULT_MSG_REMOTE_ACK_C_TXNPREPARE_0_5, null)) {
fi.unsetFault(fi.FAULT_MSG_REMOTE_ACK_C_TXNPREPARE_0_5);
throw new BrokerException(fi.FAULT_MSG_REMOTE_ACK_C_TXNPREPARE_0_5);
}
}
if (rets == null) {
return null;
}
if (Globals.getClusterBroadcast().getClusterVersion() < ClusterBroadcast.VERSION_410) {
return null;
}
HashMap<BrokerAddress, ArrayList[]> bmmap = rets[0];
TransactionBroker[] tranbas = (TransactionBroker[]) rets[1].keySet().toArray(new TransactionBroker[rets[1].size()]);
BrokerAddress[] bas = bmmap.keySet().toArray(new BrokerAddress[bmmap.size()]);
boolean persist = true;
ClusterTransaction clusterTransaction = null;
if (Globals.isNewTxnLogEnabled()) {
// create a cluster transaction which will be logged
clusterTransaction = new ClusterTransaction(id, nextState, txnWork, tranbas);
translist.logClusterTransaction(id, nextState, tranbas, true, persist, clusterTransaction);
} else {
translist.logClusterTransaction(id, nextState, tranbas, true, persist);
}
if (DEBUG_CLUSTER_TXN) {
StringBuilder buf = new StringBuilder();
buf.append("Preparing transaction ").append(id).append(", brokers");
for (TransactionBroker tranba : tranbas) {
buf.append("\n\t").append(tranba);
}
logger.log(logger.INFO, buf.toString());
}
UID tranpid = null;
if (Globals.getDestinationList().isPartitionMode()) {
tranpid = translist.getPartitionedStore().getPartitionID();
ArrayList<TransactionAcknowledgement> mcl = null;
TransactionBroker tba = null;
UID tbapid = null;
TransactionAcknowledgement[] tas = null;
TransactionList tl = null;
for (int i = 0; i < tranbas.length; i++) {
tba = tranbas[i];
if (!tba.getBrokerAddress().equals(Globals.getMyAddress())) {
continue;
}
tbapid = tba.getBrokerAddress().getStoreSessionUID();
if (tbapid.equals(tranpid)) {
continue;
}
mcl = (ArrayList<TransactionAcknowledgement>) rets[1].get(tba);
tas = mcl.toArray(new TransactionAcknowledgement[mcl.size()]);
tl = TransactionList.getTransListByPartitionID(tbapid);
if (tl == null) {
throw new BrokerException("Can't prepare transaction " + id + " because " + "transaction list for partition " + tbapid + " not found");
}
BrokerAddress home = (BrokerAddress) Globals.getMyAddress().clone();
home.setStoreSessionUID(tranpid);
tl.logLocalRemoteTransaction(id, nextState, tas, home, false, true, persist);
}
}
// handle remote brokers
ArrayList[] mcll = null;
BrokerAddress ba = null;
for (int i = 0; i < bas.length; i++) {
ba = bas[i];
if (ba == Globals.getMyAddress() || ba.equals(Globals.getMyAddress())) {
continue;
}
mcll = bmmap.get(ba);
try {
Globals.getClusterBroadcast().acknowledgeMessage2P(ba, (SysMessageID[]) mcll[0].toArray(new SysMessageID[mcll[0].size()]), (ConsumerUID[]) mcll[1].toArray(new ConsumerUID[mcll[1].size()]), ClusterBroadcast.MSG_PREPARE, null, Long.valueOf(id.longValue()), tranpid, true, false);
} catch (BrokerException e) {
if (!(e instanceof BrokerDownException) && !(e instanceof AckEntryNotFoundException)) {
throw e;
}
HashMap sToCmap = translist.retrieveStoredConsumerUIDs(id);
ArrayList remoteConsumerUIDa = new ArrayList();
StringBuilder remoteConsumerUIDs = new StringBuilder();
String uidstr = null;
StringBuilder debugbuf = new StringBuilder();
for (int j = 0; j < mcll[0].size(); j++) {
SysMessageID sysid = (SysMessageID) mcll[0].get(j);
ConsumerUID uid = (ConsumerUID) mcll[1].get(j);
ConsumerUID suid = (ConsumerUID) sToCmap.get(uid);
if (suid == null || suid.equals(uid)) {
continue;
}
if (e.isRemote()) {
uidstr = String.valueOf(uid.longValue());
if (!remoteConsumerUIDa.contains(uidstr)) {
remoteConsumerUIDa.add(uidstr);
remoteConsumerUIDs.append(uidstr);
remoteConsumerUIDs.append(' ');
Consumer c = Consumer.getConsumer(uid);
if (c != null) {
c.recreationRequested();
} else {
logger.log(logger.WARNING, "Consumer " + uid + " not found in processing remote exception on preparing transaction " + id);
}
}
}
debugbuf.append("\n\t[").append(sysid).append(':').append(uid).append(']');
}
if (e.isRemote()) {
e.setRemoteConsumerUIDs(remoteConsumerUIDs.toString());
if (DEBUG_CLUSTER_TXN) {
logger.log(logger.INFO, "doRemotePrepare: JMQRemote Exception:remoteConsumerUIDs=" + remoteConsumerUIDs + ", remote broker " + ba);
}
}
try {
translist.updateState(id, TransactionState.FAILED, false, TransactionState.PREPARED, true);
} catch (Exception ex) {
logger.logStack(logger.WARNING, "Unable to update transaction " + id + " state to FAILED on PREPARE failure from " + ba + ": " + ex.getMessage() + debugbuf.toString(), ex);
throw e;
}
if (e instanceof AckEntryNotFoundException) {
mcll = ((AckEntryNotFoundException) e).getAckEntries();
}
for (int j = 0; j < mcll[0].size(); j++) {
SysMessageID sysid = (SysMessageID) mcll[0].get(j);
ConsumerUID uid = (ConsumerUID) mcll[1].get(j);
boolean remove = true;
if (e instanceof BrokerDownException) {
ConsumerUID suid = (ConsumerUID) sToCmap.get(uid);
if (suid == null || suid.equals(uid)) {
if (DEBUG_CLUSTER_TXN) {
logger.log(logger.INFO, "doRemotePrepare: no remove txnack " + sysid + ", " + uid + " for BrokerDownException from " + ba);
}
remove = false;
}
}
if (remove) {
try {
translist.removeAcknowledgement(id, sysid, uid, (e instanceof AckEntryNotFoundException));
if (DEBUG_CLUSTER_TXN) {
logger.log(logger.INFO, "doRemotePrepare: removed txnack " + sysid + ", " + uid + " for BrokerDownException from " + ba);
}
} catch (Exception ex) {
logger.logStack(logger.WARNING, "Unable to remove transaction " + id + " ack [" + sysid + ":" + uid + "] on PREPARE failure from " + ba + ": " + ex.getMessage(), ex);
}
}
}
logger.log(logger.WARNING, "Preparing transaction " + id + " failed from " + ba + ": " + e.getMessage() + debugbuf.toString());
throw e;
}
}
return clusterTransaction;
}
use of com.sun.messaging.jmq.jmsserver.data.TransactionBroker in project openmq by eclipse-ee4j.
the class RaptorProtocol method sendRemoteTransactionInfo.
private void sendRemoteTransactionInfo(TransactionUID tid, BrokerAddress to, Long xid, boolean ownerWaitingFor) {
List<Object[]> list = TransactionList.getTransListsAndRemoteTranStates(tid);
TransactionList tl = null;
TransactionState ts = null;
Object[] oo = null;
if (list != null) {
oo = list.get(0);
tl = (TransactionList) oo[0];
ts = (TransactionState) oo[1];
}
if (ts == null && !ownerWaitingFor) {
if (DEBUG_CLUSTER_TXN) {
logger.log(logger.INFO, "Remote transaction " + tid + " not found");
}
return;
}
UID tlss = null;
boolean partitionmode = Globals.getDestinationList().isPartitionMode();
int loop = (list == null ? 1 : list.size());
for (int i = 0; i < loop; i++) {
if (list != null) {
oo = list.get(i);
tl = (TransactionList) oo[0];
ts = (TransactionState) oo[1];
}
if (ts != null && ts.getState() != TransactionState.ROLLEDBACK && ts.getState() != TransactionState.COMMITTED) {
continue;
}
tlss = null;
if (tl != null && partitionmode) {
tlss = tl.getPartitionedStore().getPartitionID();
}
int s = (ts == null ? TransactionState.NULL : ts.getState());
TransactionBroker txnhome = null;
if (s == TransactionState.ROLLEDBACK || s == TransactionState.COMMITTED) {
if (tl != null) {
txnhome = tl.getRemoteTransactionHomeBroker(tid);
}
}
ClusterTxnInfoInfo ii = ClusterTxnInfoInfo.newInstance(Long.valueOf(tid.longValue()), s, null, null, (txnhome == null ? null : txnhome.getBrokerAddress()), false, tlss, c, xid);
if (DEBUG_CLUSTER_TXN) {
logger.log(logger.INFO, Globals.getBrokerResources().getKString(BrokerResources.I_SEND_REMOTE_TXN_INFO, to, 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().getString(BrokerResources.W_SEND_REMOTE_TXN_INFO_FAIL, args));
}
}
// for
}
use of com.sun.messaging.jmq.jmsserver.data.TransactionBroker in project openmq by eclipse-ee4j.
the class RaptorProtocol method sendPreparedTransactionInquiries.
private void sendPreparedTransactionInquiries(List<TransactionUID> tidsonly, BrokerAddress broker, UID partitionID) {
TransactionList[] tls = Globals.getDestinationList().getTransactionList(null);
TransactionList tl = null;
ArrayList tids = null;
TransactionUID tid = null;
ClusterTxnInquiryInfo cii = null;
TransactionBroker txnhome = null;
UID txnhomess = null;
for (int i = 0; i < tls.length; i++) {
tl = tls[i];
if (tl == null) {
continue;
}
tids = tl.getPreparedRemoteTransactions(null);
Iterator itr = tids.iterator();
while (itr.hasNext()) {
tid = (TransactionUID) itr.next();
if (tidsonly != null && !tidsonly.contains(tid)) {
continue;
}
txnhome = tl.getRemoteTransactionHomeBroker(tid);
if (broker == null && txnhome == null) {
continue;
}
txnhomess = null;
if (txnhome != null) {
txnhomess = txnhome.getBrokerAddress().getStoreSessionUID();
}
if (partitionID == null || txnhomess == null || txnhomess.equals(partitionID)) {
cii = ClusterTxnInquiryInfo.newInstance(Long.valueOf(tid.longValue()), ((txnhome == null) ? null : txnhome.getCurrentBrokerAddress()), null);
if (DEBUG_CLUSTER_TXN) {
logger.log(Logger.INFO, "Sending transaction inquiry: " + cii + " to " + broker);
}
BrokerAddress tobroker = (broker == null ? txnhome.getCurrentBrokerAddress() : broker);
try {
c.unicast(tobroker, cii.getGPacket());
} catch (Exception e) {
logger.log(Logger.WARNING, "Sending transaction inquiry " + cii + " to " + tobroker + " failed");
}
}
}
}
}
use of com.sun.messaging.jmq.jmsserver.data.TransactionBroker in project openmq by eclipse-ee4j.
the class PacketReference method acknowledged.
/**
* If this method return true, caller is responsible to call postAcknowledgedRemoval()
*
* @param ackack whether client requested ackack
*
* If the ack is a remote non-transacted ack, waits for remote ack reply only if sync == true {@literal &&} notIgnored {@literal &&} ackack
*/
public boolean acknowledged(ConsumerUID intid, ConsumerUID storedid, boolean sync, boolean notIgnored, TransactionUID tuid, TransactionList translist, HashMap<TransactionBroker, Object> remoteNotified, boolean ackack) throws BrokerException, IOException {
Long txn = (tuid == null ? null : Long.valueOf(tuid.longValue()));
try {
if (destroyed || invalid) {
// destroyed
return true;
}
removeInDelivery(storedid);
ConsumerMessagePair cmp = getAck(storedid);
// something went wrong, ignore
if (cmp == null) {
// nothing to do
Globals.getLogger().log(Logger.ERROR, "Internal Error: Received Unknown ack " + intid + " for message " + getSysMessageID());
Globals.getLogger().log(Logger.ERROR, "AckInfo" + ackInfo.toString());
boolean rm = false;
synchronized (this) {
rm = (ackCnt + deadCnt) >= interestCnt;
}
if (!isLocal() && rm) {
acquireDestroyRemoteReadLock();
synchronized (this) {
rm = (ackCnt + deadCnt) >= interestCnt;
}
if (!rm) {
clearDestroyRemoteReadLock();
}
}
return rm;
}
// acked so do nothing
if (cmp.setState(ACKED)) {
if (cmp.isStored()) {
boolean acked = false;
if (Globals.getStore().isJDBCStore()) {
acked = pstore.hasMessageBeenAcked(destination, msgid);
}
if (!acked) {
try {
// This test may fail to spot that this really is
// the last ack because another thread processing an
// ack for the same message may not have yet
// incremented ackCnt.
// However, it should not return a false positive so
// should be safe
boolean isLastAck = false;
synchronized (this) {
isLastAck = (ackCnt + 1 + deadCnt) >= interestCnt;
}
pstore.updateInterestState(destination, msgid, storedid, PartitionedStore.INTEREST_STATE_ACKNOWLEDGED, Destination.PERSIST_SYNC && sync, tuid, isLastAck);
} catch (Exception ex) {
if (ex instanceof BrokerException && ((BrokerException) ex).getStatusCode() != Status.NOT_ALLOWED && ((BrokerException) ex).getStatusCode() != Status.NOT_FOUND) {
Globals.getLogger().log(Logger.WARNING, "Update consumer " + storedid + " state failed for message " + msgid + ": " + ex.getMessage());
throw ex;
} else {
Globals.getLogger().log(Logger.DEBUGHIGH, "Update consumer " + storedid + " state failed for message " + msgid + ": " + ex.getMessage());
}
}
}
}
if (!isLocal()) {
// not local
if (notIgnored) {
if (Globals.getClusterBroadcast().getClusterVersion() < ClusterBroadcast.VERSION_410) {
Globals.getClusterBroadcast().acknowledgeMessage(getBrokerAddress(), getSysMessageID(), intid, ClusterBroadcast.MSG_ACKNOWLEDGED, null, false);
} else if (txn == null) {
Globals.getClusterBroadcast().acknowledgeMessage(getBrokerAddress(), getSysMessageID(), intid, ClusterBroadcast.MSG_ACKNOWLEDGED, null, (sync && ackack));
} else {
BrokerAddress raddr = getBrokerAddress();
TransactionBroker traddr = new TransactionBroker(raddr);
if (remoteNotified.get(traddr) == null) {
SysMessageID[] mysysids = { this.getSysMessageID() };
ConsumerUID[] myintids = { intid };
try {
UID txnss = translist.getPartitionedStore().getPartitionID();
Globals.getClusterBroadcast().acknowledgeMessage2P(raddr, mysysids, myintids, ClusterBroadcast.MSG_ACKNOWLEDGED, null, txn, txnss, true, !commit2pwait);
remoteNotified.put(traddr, String.valueOf(""));
if (commit2pwait) {
translist.completeClusterTransactionBrokerState(tuid, TransactionState.COMMITTED, raddr, true);
}
} catch (Exception e) {
if (e instanceof BrokerDownException) {
remoteNotified.put(traddr, String.valueOf(""));
}
if (DEBUG_CLUSTER_TXN) {
Globals.getLogger().logStack(Logger.WARNING, "Notify commit transaction [" + this.getSysMessageID() + ", " + intid + "]TUID=" + txn + " got response: " + e.toString(), e);
} else {
Globals.getLogger().log(Logger.WARNING, "Notify commit transaction [" + this.getSysMessageID() + ", " + intid + "]TUID=" + txn + " got response: " + e.toString(), e);
}
}
// catch
}
// if
}
} else {
try {
Globals.getClusterBroadcast().acknowledgeMessage(getBrokerAddress(), getSysMessageID(), intid, ClusterBroadcast.MSG_IGNORED, null, false);
} catch (BrokerException e) {
Globals.getLogger().log(Logger.DEBUG, e.getMessage());
}
}
}
} else {
Consumer c = Consumer.getConsumer(intid);
if (c == null || !c.isValid() || !isLocal()) {
// do we want to add a debug level message here
// got it while cleaning up
// this can only happen on topics and is a
// non-fatal error
// fixing the timing problem through synchronization
// adds too much overhead <- same to !isLocal case
boolean rm = false;
synchronized (this) {
rm = ((ackCnt + deadCnt) >= interestCnt);
}
if (!isLocal() && rm) {
acquireDestroyRemoteReadLock();
synchronized (this) {
rm = ((ackCnt + deadCnt) >= interestCnt);
}
if (!rm) {
clearDestroyRemoteReadLock();
}
}
return rm;
} else {
Exception e = new Exception("double ack " + cmp);
e.fillInStackTrace();
Globals.getLogger().logStack(Logger.ERROR, "Received ack twice " + " on " + msgid + " for " + intid + " state is = " + cmp, e);
boolean rm = false;
synchronized (this) {
rm = ((ackCnt + deadCnt) >= interestCnt);
}
if (!isLocal() && rm) {
acquireDestroyRemoteReadLock();
synchronized (this) {
rm = ((ackCnt + deadCnt) >= interestCnt);
}
if (!rm) {
clearDestroyRemoteReadLock();
}
}
return rm;
}
}
boolean rm = false;
synchronized (this) {
ackCnt++;
rm = ((ackCnt + deadCnt) >= interestCnt);
}
if (!isLocal() && rm) {
acquireDestroyRemoteReadLock();
synchronized (this) {
rm = ((ackCnt + deadCnt) >= interestCnt);
}
if (!rm) {
clearDestroyRemoteReadLock();
}
}
return rm;
} catch (Throwable thr) {
if (thr instanceof BrokerDownException) {
Globals.getLogger().log(Logger.WARNING, Globals.getBrokerResources().getKString(BrokerResources.W_UNABLE_PROCESS_REMOTE_ACK_BECAUSE, "[" + msgid + "]" + intid + ":" + storedid, thr.getMessage()));
} else {
Globals.getLogger().logStack(Logger.ERROR, "Error in processing ack" + " on " + msgid + " for " + intid, thr);
}
if (thr instanceof BrokerException) {
throw (BrokerException) thr;
}
throw new BrokerException("Unable to process ack", thr);
}
}
Aggregations