use of com.sun.messaging.jmq.jmsserver.data.TransactionUID in project openmq by eclipse-ee4j.
the class SessionOp method close.
@Override
public void close(Connection conn) {
TransactionList[] tls = DL.getTransactionList(((IMQConnection) conn).getPartitionedStore());
TransactionList translist = tls[0];
// deal w/ old messages
synchronized (deliveredMessages) {
if (!deliveredMessages.isEmpty()) {
// get the list by IDs
HashMap openMsgs = new HashMap();
Iterator itr = deliveredMessages.entrySet().iterator();
while (itr.hasNext()) {
Map.Entry entry = (Map.Entry) itr.next();
ackEntry e = (ackEntry) entry.getValue();
ConsumerUID cuid = e.getConsumerUID();
ConsumerUID storeduid = (e.getStoredUID() == null ? cuid : e.getStoredUID());
// deal w/ orphan messages
TransactionUID tid = e.getTUID();
if (tid != null) {
JMQXid jmqxid = translist.UIDToXid(tid);
if (jmqxid != null) {
translist.addOrphanAck(tid, e.getSysMessageID(), storeduid, cuid);
itr.remove();
continue;
}
TransactionState ts = translist.retrieveState(tid, true);
if (ts != null && ts.getState() == TransactionState.PREPARED) {
translist.addOrphanAck(tid, e.getSysMessageID(), storeduid, cuid);
itr.remove();
continue;
}
if (ts != null && ts.getState() == TransactionState.COMMITTED) {
itr.remove();
continue;
}
if (ts != null && ts.getState() == TransactionState.COMPLETE && conn.getConnectionState() >= Connection.STATE_CLOSED) {
String[] args = { "" + tid, TransactionState.toString(ts.getState()), session.getConnectionUID().toString() };
logger.log(Logger.INFO, Globals.getBrokerResources().getKString(BrokerResources.I_CONN_CLEANUP_KEEP_TXN, args));
translist.addOrphanAck(tid, e.getSysMessageID(), storeduid, cuid);
itr.remove();
continue;
}
}
PacketReference ref = e.getReference();
if (ref == null) {
// PART
ref = DL.get(null, e.getSysMessageID());
}
if (ref != null && !ref.isLocal()) {
itr.remove();
try {
if ((ref = e.acknowledged(false)) != null) {
try {
Destination d = ref.getDestination();
d.removeRemoteMessage(ref.getSysMessageID(), RemoveReason.ACKNOWLEDGED, ref);
} finally {
ref.postAcknowledgedRemoval();
}
}
} catch (Exception ex) {
logger.logStack(session.DEBUG_CLUSTER_MSG ? Logger.WARNING : Logger.DEBUG, "Unable to clean up remote message " + e.getDebugMessage(false), ex);
}
continue;
}
// we arent in a transaction ID .. cool
// add to redeliver list
Set s = (Set) openMsgs.get(cuid);
if (s == null) {
s = new LinkedHashSet();
openMsgs.put(cuid, s);
}
if (ref != null) {
ref.removeInDelivery(storeduid);
}
s.add(e);
}
// OK .. see if we ack or cleanup
itr = openMsgs.entrySet().iterator();
Map.Entry pair = null;
while (itr.hasNext()) {
pair = (Map.Entry) itr.next();
ConsumerUID cuid = (ConsumerUID) pair.getKey();
Map parentmp = (Map) cleanupList.get(cuid);
ConsumerUID suid = (ConsumerUID) storeMap.get(cuid);
if (parentmp == null || parentmp.size() == 0) {
Set s = (Set) pair.getValue();
Iterator sitr = s.iterator();
while (sitr.hasNext()) {
ackEntry e = (ackEntry) sitr.next();
try {
PacketReference ref = e.acknowledged(false);
if (ref != null) {
try {
Destination d = ref.getDestination();
try {
if (ref.isLocal()) {
d.removeMessage(ref.getSysMessageID(), RemoveReason.ACKNOWLEDGED);
} else {
d.removeRemoteMessage(ref.getSysMessageID(), RemoveReason.ACKNOWLEDGED, ref);
}
} catch (Exception ex) {
Object[] args = { ref, this, ex.getMessage() };
logger.logStack(Logger.WARNING, Globals.getBrokerResources().getKString(BrokerResources.X_CLEANUP_MSG_CLOSE_SESSION, args), ex);
}
} finally {
ref.postAcknowledgedRemoval();
}
}
} catch (Exception ex) {
// ignore
}
}
} else {
Map mp = new LinkedHashMap();
Set msgs = null;
PartitionedStore ps = null;
Set s = (Set) openMsgs.get(cuid);
Iterator sitr = s.iterator();
while (sitr.hasNext()) {
ackEntry e = (ackEntry) sitr.next();
PacketReference ref = e.getReference();
if (ref != null) {
try {
if (!e.hasMarkConsumed()) {
ref.consumed(suid, !session.isUnsafeAck(cuid), session.isAutoAck(cuid));
}
} catch (Exception ex) {
logger.logStack(Logger.WARNING, "Unable to consume " + suid + ":" + ref, ex);
}
ps = ref.getPartitionedStore();
if (!ref.getDestinationUID().isQueue()) {
ps = new NoPersistPartitionedStoreImpl(suid);
}
msgs = (Set) mp.get(ps);
if (msgs == null) {
msgs = new LinkedHashSet();
mp.put(ps, msgs);
}
msgs.add(ref);
} else {
sitr.remove();
}
}
SubSet pl = null;
itr = mp.entrySet().iterator();
pair = null;
while (itr.hasNext()) {
pair = (Map.Entry) itr.next();
ps = (PartitionedStore) pair.getKey();
pl = (SubSet) parentmp.get(ps);
if (pl != null) {
((Prioritized) pl).addAllOrdered((Set) pair.getValue());
} else {
logger.log(logger.WARNING, "Message(s) " + mp.get(ps) + "[" + suid + ", " + cuid + "] parentlist not found on session closing");
}
}
}
}
deliveredMessages.clear();
cleanupList.clear();
storeMap.clear();
}
}
if (!session.isXATransacted()) {
Iterator itr = null;
synchronized (detachedRConsumerUIDs) {
itr = (new LinkedHashSet(detachedRConsumerUIDs)).iterator();
}
while (itr.hasNext()) {
Consumer c = Consumer.newInstance((ConsumerUID) itr.next());
try {
Globals.getClusterBroadcast().destroyConsumer(c, null, true);
} catch (Exception e) {
logger.log(Logger.WARNING, "Unable to send consumer [" + c + "] cleanup notification for closing of SessionOp[" + this + "].");
}
}
}
}
use of com.sun.messaging.jmq.jmsserver.data.TransactionUID in project openmq by eclipse-ee4j.
the class SessionOp method detachConsumer.
/**
* @param id last SysMessageID seen (null indicates all have been seen)
* @param redeliverAll ignore id and redeliver all
* @param redeliverPendingConsume - redeliver pending messages
*/
@Override
public boolean detachConsumer(ConsumerSpi c, SysMessageID id, boolean idInTransaction, boolean redeliverPendingConsume, boolean redeliverAll, Connection conn) {
if (Session.DEBUG || Session.DEBUG_CLUSTER_MSG) {
logger.log(logger.INFO, "detachConsumer(" + c + ", " + id + ", " + redeliverPendingConsume + ", " + redeliverAll + ", " + conn.getConnectionUID() + ")");
}
Consumer con = (Consumer) c;
ConsumerUID cuid = con.getConsumerUID();
ConsumerUID suid = con.getStoredConsumerUID();
// OK, we have 2 sets of messages:
// messages which were seen (and need the state
// set to consumed)
// messages which were NOT seen (and need the
// state reset)
// get delivered messages
Set s = new LinkedHashSet();
HashMap remotePendings = new HashMap();
boolean holdmsgs = false;
TransactionList[] tls = DL.getTransactionList(((IMQConnection) conn).getPartitionedStore());
TransactionList translist = tls[0];
TransactionUID tid = null;
// get all the messages for the consumer
synchronized (deliveredMessages) {
ackEntry startEntry = null;
// workaround for client sending ack if acknowledged
if (id != null) {
ackEntry entry = new ackEntry(id, cuid);
startEntry = (ackEntry) deliveredMessages.get(entry);
}
// make a copy of all of the data
cleanupList.put(cuid, con.getParentList());
storeMap.put(cuid, con.getStoredConsumerUID());
// OK first loop through all of the consumed
// messages and mark them consumed
Iterator itr = deliveredMessages.values().iterator();
boolean found = (startEntry == null && id != null);
while (!redeliverAll && !found && itr.hasNext()) {
ackEntry val = (ackEntry) itr.next();
if (val == startEntry) {
// we are done with consumed messages
found = true;
}
// forward port 6829773
if (!val.storedcid.equals(suid) || !val.uid.equals(cuid)) {
continue;
}
PacketReference pr = val.getReference();
tid = null;
if (session.isTransacted() || idInTransaction) {
tid = translist.getConsumedInTransaction(val.getSysMessageID(), val.uid);
if (tid == null) {
if (pr != null) {
pr.removeInDelivery(suid);
s.add(pr);
addRemotePendings(pr, val.storedcid, new TransactionUID(0), remotePendings);
}
itr.remove();
continue;
}
}
// we know the consumer saw it .. mark it consumed
if (pr != null) {
try {
pr.consumed(suid, !session.isUnsafeAck(cuid), session.isAutoAck(cuid));
val.markConsumed();
} catch (Exception ex) {
Object[] args = { "[" + pr + "," + suid + "]", cuid, ex.getMessage() };
logger.log(Logger.WARNING, Globals.getBrokerResources().getKString(BrokerResources.W_UNABLE_UPDATE_REF_STATE_ON_CLOSE_CONSUMER, args), ex);
}
}
if (redeliverPendingConsume) {
if (pr != null) {
pr.removeInDelivery(suid);
s.add(pr);
}
itr.remove();
continue;
}
if (pr != null && !pr.isLocal() && session.isValid()) {
if (addRemotePendings(pr, val.storedcid, tid, remotePendings)) {
detachedRConsumerUIDs.add(val.uid);
}
}
holdmsgs = true;
}
// now deal with re-queueing messages
while (itr.hasNext()) {
ackEntry val = (ackEntry) itr.next();
// see if we are for a different consumer
if (!val.storedcid.equals(suid) || !val.uid.equals(cuid)) {
continue;
}
PacketReference pr = val.getReference();
if (session.isTransacted()) {
tid = translist.getConsumedInTransaction(val.getSysMessageID(), val.uid);
if (tid != null) {
if (pr != null && !pr.isLocal() && session.isValid()) {
if (addRemotePendings(pr, val.storedcid, tid, remotePendings)) {
detachedRConsumerUIDs.add(val.uid);
}
}
holdmsgs = true;
continue;
}
}
if (pr != null) {
pr.removeInDelivery(suid);
s.add(pr);
}
itr.remove();
try {
if (pr != null) {
pr.removeDelivered(suid, false);
}
} catch (Exception ex) {
logger.log(Logger.WARNING, "Unable to consume " + suid + ":" + pr, ex);
}
}
}
con.destroyConsumer(s, remotePendings, (con.tobeRecreated() || (!session.isValid() && !session.isXATransacted())), false, true);
if (!holdmsgs && session.isValid()) {
synchronized (deliveredMessages) {
cleanupList.remove(cuid);
storeMap.remove(cuid);
}
return true;
}
return false;
}
use of com.sun.messaging.jmq.jmsserver.data.TransactionUID 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);
}
}
use of com.sun.messaging.jmq.jmsserver.data.TransactionUID in project openmq by eclipse-ee4j.
the class TransactionUtil method getTransactionInfo.
public static CompositeData getTransactionInfo(String transactionID) throws BrokerException, OpenDataException {
CompositeData cd = null;
TransactionUID tid = null;
BrokerResources rb = Globals.getBrokerResources();
if (transactionID == null) {
throw new IllegalArgumentException(rb.getString(rb.X_JMX_NULL_TXN_ID_SPEC));
}
long longTid = 0;
try {
longTid = Long.parseLong(transactionID);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(rb.getString(rb.X_JMX_INVALID_TXN_ID_SPEC, transactionID));
}
tid = new TransactionUID(longTid);
cd = getTransactionInfo(tid);
return (cd);
}
use of com.sun.messaging.jmq.jmsserver.data.TransactionUID in project openmq by eclipse-ee4j.
the class TransactionUtil method getTransactionIDs.
public static String[] getTransactionIDs() {
TransactionList[] tls = Globals.getDestinationList().getTransactionList(null);
// PART
TransactionList tl = tls[0];
Vector transactions = tl.getTransactions(-1);
String[] ids;
if ((transactions == null) || (transactions.size() == 0)) {
return (null);
}
ids = new String[transactions.size()];
Enumeration e = transactions.elements();
int i = 0;
while (e.hasMoreElements()) {
TransactionUID tid = (TransactionUID) e.nextElement();
long txnID = tid.longValue();
ids[i] = Long.toString(txnID);
i++;
}
return (ids);
}
Aggregations