use of com.sun.messaging.jmq.jmsserver.util.AckEntryNotFoundException 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.util.AckEntryNotFoundException in project openmq by eclipse-ee4j.
the class TransactionHandler method handle.
/**
* Method to handle Transaction Messages
*/
@Override
public boolean handle(IMQConnection con, Packet msg) throws BrokerException {
long messagetid = 0;
TransactionUID id = null;
TransactionState ts = null;
JMQXid xid = null;
Integer xaFlags = null;
boolean redeliverMsgs = false;
boolean startNextTransaction = false;
boolean setRedeliverFlag = true;
boolean isIndemp = msg.getIndempotent();
boolean replay = false;
boolean jmqonephase = false;
Boolean jmqonephaseFlag = null;
Hashtable props = null;
String reason = null;
TransactionList[] tls = Globals.getDestinationList().getTransactionList(con.getPartitionedStore());
TransactionList translist = tls[0];
try {
props = msg.getProperties();
if (props == null) {
props = new Hashtable();
}
} catch (Exception ex) {
logger.logStack(Logger.WARNING, "Unable to retrieve " + " properties from transaction message " + msg, ex);
props = new Hashtable();
}
// performance optimisation:
// start a new transaction immediately after commit or rollback and return
// transactionID in message ack.
// The client then does not need to make a separate call to startTransaction.
Boolean startNextTransactionBool = (Boolean) props.get("JMQStartNextTransaction");
startNextTransaction = startNextTransactionBool != null && startNextTransactionBool.booleanValue();
Boolean redeliverMsgBool = (Boolean) props.get("JMQRedeliver");
redeliverMsgs = redeliverMsgBool != null && redeliverMsgBool.booleanValue();
Boolean b = (Boolean) props.get("JMQUpdateConsumed");
boolean updateConsumed = b != null && b.booleanValue();
Boolean redeliverFlag = (Boolean) props.get("JMQSetRedelivered");
setRedeliverFlag = redeliverFlag == null || redeliverFlag.booleanValue();
Integer maxRollbackFlag = (Integer) props.get("JMQMaxRollbacks");
int maxRollbacks = (maxRollbackFlag == null ? -1 : maxRollbackFlag.intValue());
/**
* if dmqOnMaxRollbacks false, and max rollbacks reached, return error to client without rollback and without redelivery
* any consumed messages
*/
Boolean dmqOnMaxRollbacksFlag = (Boolean) props.get("JMQDMQOnMaxRollbacks");
boolean dmqOnMaxRollbacks = dmqOnMaxRollbacksFlag != null && dmqOnMaxRollbacksFlag.booleanValue();
if (maxRollbacks <= 0) {
dmqOnMaxRollbacks = !(Consumer.MSG_MAX_CONSECUTIVE_ROLLBACKS <= 0);
}
jmqonephaseFlag = (Boolean) props.get("JMQXAOnePhase");
jmqonephase = jmqonephaseFlag != null && jmqonephaseFlag.booleanValue();
if (DEBUG) {
logger.log(Logger.DEBUG, PacketType.getString(msg.getPacketType()) + ": " + "TUID=" + id + ", JMQRedeliver=" + redeliverMsgBool + (jmqonephaseFlag == null ? "" : ", JMQXAOnePhase=" + jmqonephase));
}
List conlist = (List) con.getClientData(IMQConnection.TRANSACTION_LIST);
if (conlist == null) {
conlist = new ArrayList();
con.addClientData(IMQConnection.TRANSACTION_LIST, conlist);
}
// If there is a message body, then it should contain an Xid.
ByteBuffer body = msg.getMessageBodyByteBuffer();
if (body != null) {
JMQByteBufferInputStream bbis = new JMQByteBufferInputStream(body);
try {
xid = JMQXid.read(new DataInputStream(bbis));
startNextTransaction = false;
} catch (IOException e) {
logger.log(Logger.ERROR, BrokerResources.E_INTERNAL_BROKER_ERROR, "Could not decode xid from packet: " + e + " Ignoring " + PacketType.getString(msg.getPacketType()));
reason = e.getMessage();
sendReply(con, msg, msg.getPacketType() + 1, Status.BAD_REQUEST, 0, reason);
return true;
}
}
// Get XAFlags. Note, not all packets will have this -- that's OK.
xaFlags = (Integer) props.get("JMQXAFlags");
// tidMap maps an old style transaction identifier to a TransactionUID.
// In iMQ2.0 the transaction identifier in the packet was an int
// generated by the client and only unique on the connection.
// In Falcon it is a long that is unique accross the cluster.
// So for 2.0 clients we allocate a TransactionUID and map the old
// style identifier to it.
//
// Get tidMap
HashMap tidMap = null;
synchronized (con) {
tidMap = (HashMap) con.getClientData(IMQConnection.TRANSACTION_IDMAP);
if (tidMap == null) {
tidMap = new HashMap();
con.addClientData(IMQConnection.TRANSACTION_IDMAP, tidMap);
}
}
// Go ahead and get the value of "JMQTransactionID" from the packet.
// may not be used in all cases.
messagetid = getJMQTransactionID(props);
if (fi.FAULT_INJECTION) {
checkFIBeforeProcess(msg.getPacketType());
}
boolean translistResolved = false;
// else wrap the one specified in the packet
if (msg.getPacketType() == PacketType.START_TRANSACTION && (xaFlags == null || TransactionState.isFlagSet(XAResource.TMNOFLAGS, xaFlags))) {
if (isIndemp) {
// deal with indemp flag
Object[] rets = TransactionList.getTransactionByCreator(msg.getSysMessageID().toString());
if (rets == null) {
id = new TransactionUID();
} else {
translist = (TransactionList) rets[0];
id = (TransactionUID) rets[1];
replay = true;
}
} else {
id = new TransactionUID();
}
translistResolved = true;
} else if (msg.getPacketType() == PacketType.RECOVER_TRANSACTION) {
if (messagetid != 0) {
// Recovering a specific transaction.
id = new TransactionUID(messagetid);
}
xid = null;
} else {
// If only Xid was specified need to lookup TransactionUID
if (messagetid == 0 && xid != null) {
Object[] rets = TransactionList.mapXidToTid(xid, con);
if (rets != null) {
translist = (TransactionList) rets[0];
id = (TransactionUID) rets[1];
messagetid = id.longValue();
translistResolved = true;
} else {
// Hmmm...haven't seen this Xid before.
// XXX I18N
logger.log(Logger.WARNING, PacketType.getString(msg.getPacketType()) + ": Ignoring unknown XID=" + xid + " broker will " + (msg.getSendAcknowledge() ? "notify the client" : " not notify the client"));
if (msg.getSendAcknowledge()) {
reason = "Uknown XID " + xid;
sendReply(con, msg, msg.getPacketType() + 1, Status.NOT_FOUND, 0, reason);
}
return true;
}
} else if (messagetid != 0) {
if (con.getClientProtocolVersion() == PacketType.VERSION1) {
// Map old style to new
synchronized (tidMap) {
id = (TransactionUID) tidMap.get(Long.valueOf(messagetid));
}
} else {
// Wrap new style
id = new TransactionUID(messagetid);
}
}
// Get the state of the transaction
if (id == null) {
logger.log(Logger.INFO, "InternalError: " + "Transaction ID was not passed by " + "the jms api on a method that reqires an " + "existing transaction ");
sendReply(con, msg, msg.getPacketType() + 1, Status.ERROR, 0, "Internal Error: bad MQ protocol," + " missing TransactionID");
return true;
}
if (translistResolved) {
if (translist == null) {
String emsg = "XXXNo transaction list found to process " + PacketType.getString(msg.getPacketType()) + " for transaction " + id + "[" + xid + "]";
logger.log(Logger.WARNING, emsg);
if (msg.getSendAcknowledge()) {
reason = emsg;
sendReply(con, msg, msg.getPacketType() + 1, Status.GONE, 0, reason);
}
return true;
}
ts = translist.retrieveState(id);
} else {
Object[] oo = TransactionList.getTransListAndState(id, con, false, false);
if (oo != null) {
translist = (TransactionList) oo[0];
ts = (TransactionState) oo[1];
}
}
if (ts == null) {
if (isIndemp && (msg.getPacketType() == PacketType.ROLLBACK_TRANSACTION || msg.getPacketType() == PacketType.COMMIT_TRANSACTION)) {
if (msg.getSendAcknowledge()) {
sendReply(con, msg, msg.getPacketType() + 1, Status.OK, id.longValue(), reason);
return true;
}
if (fi.FAULT_INJECTION) {
checkFIAfterProcess(msg.getPacketType());
checkFIAfterReply(msg.getPacketType());
}
} else {
ts = cacheGetState(id, con);
if (ts != null) {
// XXX l10n
logger.log(Logger.ERROR, "Transaction ID " + id + " has already been resolved. Ignoring request: " + PacketType.getString(msg.getPacketType()) + ". Last state of this transaction: " + ts.toString() + " broker will " + (msg.getSendAcknowledge() ? "notify the client" : " not notify the client"));
} else {
logger.log((BrokerStateHandler.isShuttingDown() ? Logger.DEBUG : Logger.WARNING), Globals.getBrokerResources().getKString((msg.getSendAcknowledge() ? BrokerResources.W_UNKNOWN_TRANSACTIONID_NOTIFY_CLIENT : BrokerResources.W_UNKNOWN_TRANSACTIONID_NONOTIFY_CLIENT), "" + id + "(" + messagetid + ")" + (xid == null ? "" : "XID=" + xid), PacketType.getString(msg.getPacketType())) + "\n" + com.sun.messaging.jmq.io.PacketUtil.dumpPacket(msg));
}
// Only send reply if A bit is set
if (msg.getSendAcknowledge()) {
reason = "Unknown transaction " + id;
sendReply(con, msg, msg.getPacketType() + 1, Status.NOT_FOUND, id.longValue(), reason);
}
return true;
}
}
}
if (DEBUG) {
logger.log(Logger.INFO, this.getClass().getName() + ": " + PacketType.getString(msg.getPacketType()) + ": " + "TUID=" + id + " XAFLAGS=" + TransactionState.xaFlagToString(xaFlags) + (jmqonephaseFlag == null ? "" : " JMQXAOnePhase=" + jmqonephase) + " State=" + ts + " Xid=" + xid);
}
// we have in the transaction table.
if (xid != null && ts != null) {
if (ts.getXid() == null || !xid.equals(ts.getXid())) {
// This should never happen
logger.log(Logger.ERROR, BrokerResources.E_INTERNAL_BROKER_ERROR, "Transaction Xid mismatch. " + PacketType.getString(msg.getPacketType()) + " Packet has tuid=" + id + " xid=" + xid + ", transaction table has tuid=" + id + " xid=" + ts.getXid() + ". Using values from table.");
xid = ts.getXid();
}
}
if (xid == null && ts != null && ts.getXid() != null && msg.getPacketType() != PacketType.RECOVER_TRANSACTION) {
// Client forgot to put Xid in packet.
xid = ts.getXid();
logger.log(Logger.WARNING, BrokerResources.E_INTERNAL_BROKER_ERROR, "Transaction Xid " + xid + " not found in " + PacketType.getString(msg.getPacketType()) + " packet for tuid " + id + ". Will use " + xid);
}
int status = Status.OK;
// retrieve new 4.0 properties
AutoRollbackType type = null;
long lifetime = 0;
boolean sessionLess = false;
Integer typeValue = (Integer) props.get("JMQAutoRollback");
Long lifetimeValue = (Long) props.get("JMQLifetime");
Boolean sessionLessValue = (Boolean) props.get("JMQSessionLess");
if (typeValue != null) {
type = AutoRollbackType.getType(typeValue.intValue());
}
if (lifetimeValue != null) {
lifetime = lifetimeValue.longValue();
}
if (sessionLessValue != null) {
sessionLess = sessionLessValue.booleanValue();
} else {
sessionLess = xid != null;
}
switch(msg.getPacketType()) {
case PacketType.START_TRANSACTION:
{
try {
doStart(translist, id, conlist, con, type, xid, sessionLess, lifetime, messagetid, xaFlags, msg.getPacketType(), replay, msg.getSysMessageID().toString());
} catch (Exception ex) {
status = Status.ERROR;
logger.logStack(Logger.ERROR, ex.toString() + ": TUID=" + id + " Xid=" + xid, ex);
reason = ex.getMessage();
if (ex instanceof BrokerException) {
status = ((BrokerException) ex).getStatusCode();
}
}
sendReply(con, msg, PacketType.START_TRANSACTION_REPLY, status, id.longValue(), reason);
break;
}
case PacketType.END_TRANSACTION:
try {
// if the noop flag is set the we don't want to actually
// process the XA_END. See bug 12364646 and XAResourceImpl.end()
Boolean jmqnoop = (Boolean) props.get("JMQNoOp");
if (jmqnoop == null || jmqnoop == false) {
doEnd(translist, msg.getPacketType(), xid, xaFlags, ts, id);
}
} catch (Exception ex) {
status = Status.ERROR;
reason = ex.getMessage();
if (ex instanceof BrokerException) {
status = ((BrokerException) ex).getStatusCode();
}
}
sendReply(con, msg, msg.getPacketType() + 1, status, id.longValue(), reason);
break;
case PacketType.PREPARE_TRANSACTION:
BrokerException bex = null;
HashMap tmpp = null;
try {
doPrepare(translist, id, xaFlags, ts, msg.getPacketType(), jmqonephase, null, con);
} catch (Exception ex) {
status = Status.ERROR;
if ((!(ex instanceof BrokerDownException) && !(ex instanceof AckEntryNotFoundException)) || DEBUG_CLUSTER_TXN) {
logger.logStack(Logger.ERROR, ex.toString() + ": TUID=" + id + " Xid=" + xid, ex);
} else {
logger.log(((ex instanceof AckEntryNotFoundException) ? Logger.WARNING : Logger.ERROR), ex.toString() + ": TUID=" + id + " Xid=" + xid);
}
reason = ex.getMessage();
if (ex instanceof BrokerException) {
status = ((BrokerException) ex).getStatusCode();
bex = (BrokerException) ex;
}
if (ts.getState() == TransactionState.FAILED) {
tmpp = new HashMap();
tmpp.put("JMQPrepareStateFAILED", Boolean.TRUE);
}
}
sendReply(con, msg, msg.getPacketType() + 1, status, id.longValue(), reason, bex, tmpp, 0L);
break;
case PacketType.RECOVER_TRANSACTION:
Vector v = null;
if (id != null) {
// Check if specified transaction is in PREPARED state
v = new Vector();
ts = translist.retrieveState(id);
if (ts.getState() == TransactionState.PREPARED) {
v.add(id);
}
} else {
// and nothing on ENDRSCAN or NOFLAGS
if (xaFlags == null || !TransactionState.isFlagSet(XAResource.TMSTARTRSCAN, xaFlags)) {
Hashtable hash = new Hashtable();
hash.put("JMQQuantity", Integer.valueOf(0));
sendReplyBody(con, msg, PacketType.RECOVER_TRANSACTION_REPLY, Status.OK, hash, null);
break;
}
// Get list of transactions in PENDING state and marshal
// the Xid's to a byte array.
v = translist.getTransactions(TransactionState.PREPARED);
}
int nIDs = v.size();
int nWritten = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream(nIDs * JMQXid.size());
DataOutputStream dos = new DataOutputStream(bos);
for (int n = 0; n < nIDs; n++) {
TransactionUID tuid = (TransactionUID) v.get(n);
TransactionState _ts = translist.retrieveState(tuid);
if (_ts == null) {
// Should never happen
logger.log(Logger.ERROR, BrokerResources.E_INTERNAL_BROKER_ERROR, "Could not find state for TUID " + tuid);
continue;
}
JMQXid _xid = _ts.getXid();
if (_xid != null) {
try {
_xid.write(dos);
nWritten++;
} catch (Exception e) {
logger.log(Logger.ERROR, BrokerResources.E_INTERNAL_BROKER_ERROR, "Could not write Xid " + _xid + " to message body: " + e.toString());
}
}
}
Hashtable hash = new Hashtable();
hash.put("JMQQuantity", Integer.valueOf(nWritten));
if (id != null) {
hash.put("JMQTransactionID", Long.valueOf(id.longValue()));
}
// Send reply with serialized Xids as the body
sendReplyBody(con, msg, PacketType.RECOVER_TRANSACTION_REPLY, Status.OK, hash, bos.toByteArray());
break;
case PacketType.COMMIT_TRANSACTION:
try {
// doCommit will send reply if successful
if (xaFlags != null && jmqonephase) {
Integer newxaFlags = Integer.valueOf(xaFlags.intValue() & ~XAResource.TMONEPHASE);
doCommit(translist, id, xid, newxaFlags, ts, conlist, true, con, msg);
} else {
doCommit(translist, id, xid, xaFlags, ts, conlist, true, con, msg, startNextTransaction);
}
} catch (BrokerException ex) {
// doCommit has already logged error
status = ex.getStatusCode();
reason = ex.getMessage();
if (msg.getSendAcknowledge()) {
HashMap tmppp = null;
if (!jmqonephase && TransactionState.isFlagSet(XAResource.TMONEPHASE, xaFlags)) {
if (ts.getState() == TransactionState.FAILED) {
tmppp = new HashMap();
tmppp.put("JMQPrepareStateFAILED", Boolean.TRUE);
}
}
sendReply(con, msg, msg.getPacketType() + 1, status, id.longValue(), reason, ex, tmppp, 0L);
} else {
if (fi.FAULT_INJECTION) {
checkFIAfterProcess(msg.getPacketType());
checkFIAfterReply(msg.getPacketType());
}
}
}
break;
case PacketType.ROLLBACK_TRANSACTION:
{
BrokerException maxrbex = null;
try {
preRollback(translist, id, xid, xaFlags, ts);
try {
// if redeliverMsgs is true, we want to redeliver
// to both active and inactive consumers
boolean processActiveConsumers = redeliverMsgs;
redeliverUnacked(translist, id, processActiveConsumers, setRedeliverFlag, updateConsumed, maxRollbacks, dmqOnMaxRollbacks);
} catch (BrokerException ex) {
if (ex instanceof MaxConsecutiveRollbackException) {
maxrbex = ex;
} else {
logger.logStack(Logger.ERROR, "REDELIVER: " + ex.toString() + ": TUID=" + id + " Xid=" + xid, ex);
}
reason = ex.getMessage();
status = ex.getStatusCode();
}
if (!(maxrbex != null && !dmqOnMaxRollbacks)) {
try {
if (fi.checkFault(fi.FAULT_TXN_ROLLBACK_1_5_EXCEPTION, null)) {
// fi.unsetFault(fi.FAULT_TXN_ROLLBACK_1_5_EXCEPTION);
throw new BrokerException(fi.FAULT_TXN_ROLLBACK_1_5_EXCEPTION);
}
doRollback(translist, id, xid, xaFlags, ts, conlist, con, RollbackReason.APPLICATION);
} catch (BrokerException ex) {
if (!ex.isStackLogged()) {
logger.logStack(logger.WARNING, ex.getMessage(), ex);
} else {
logger.log(logger.WARNING, br.getKString(br.X_ROLLBACK_TXN, id, ex.getMessage()));
}
// doRollback has already logged error
if (maxrbex == null) {
reason = ex.getMessage();
status = ex.getStatusCode();
}
}
}
} catch (BrokerException ex) {
reason = ex.getMessage();
status = ex.getStatusCode();
}
// performance optimisation
// start next transaction and return transaction id
long nextTxnID = 0;
if (startNextTransaction) {
try {
TransactionUID nextid = new TransactionUID();
doStart(translist, nextid, conlist, con, type, xid, sessionLess, lifetime, 0, xaFlags, PacketType.START_TRANSACTION, replay, msg.getSysMessageID().toString());
nextTxnID = nextid.longValue();
} catch (Exception ex) {
logger.logStack(Logger.ERROR, ex.toString() + ": TUID=" + id + " Xid=" + xid, ex);
if (maxrbex == null) {
status = Status.ERROR;
reason = ex.getMessage();
if (ex instanceof BrokerException) {
status = ((BrokerException) ex).getStatusCode();
}
}
}
}
if (msg.getSendAcknowledge()) {
sendReply(con, msg, msg.getPacketType() + 1, status, id.longValue(), reason, null, null, nextTxnID);
} else {
if (fi.FAULT_INJECTION) {
checkFIAfterProcess(msg.getPacketType());
checkFIAfterReply(msg.getPacketType());
}
}
break;
}
}
return true;
}
use of com.sun.messaging.jmq.jmsserver.util.AckEntryNotFoundException in project openmq by eclipse-ee4j.
the class BrokerConsumers method acknowledgeMessageFromRemote2P.
public void acknowledgeMessageFromRemote2P(int ackType, SysMessageID[] sysids, com.sun.messaging.jmq.jmsserver.core.ConsumerUID[] cuids, Map optionalProps, Long txnID, com.sun.messaging.jmq.jmsserver.core.BrokerAddress txnHomeBroker) throws BrokerException {
if (txnID == null) {
throw new BrokerException("Internal Error: call with null txnID");
}
// handle 2-phase remote ack
TransactionUID tid = new TransactionUID(txnID.longValue());
if (ackType == ClusterBroadcast.MSG_PREPARE) {
PartitionedStore refpstore = null;
TransactionAcknowledgement ta = null;
ArrayList<TransactionAcknowledgement> tltas = null;
TransactionAcknowledgement[] tas = null;
HashMap<TransactionList, ArrayList<TransactionAcknowledgement>> tltasmap = new HashMap<>();
TransactionList tl = null;
AckEntry entry = null, value = null;
StringBuilder dbuf = new StringBuilder();
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;
}
PacketReference ref = value.getReference();
if (ref == null) {
deliveredMessages.remove(entry);
String emsg = "Unable to prepare [" + sysids[i] + ":" + cuids[i] + "]TID=" + tid + " because the message has been removed";
if (ae == null) {
ae = new AckEntryNotFoundException(emsg);
}
ae.addAckEntry(sysids[i], cuids[i]);
logger.log(logger.WARNING, emsg);
continue;
}
com.sun.messaging.jmq.jmsserver.core.ConsumerUID scuid = value.getStoredConsumerUID();
ta = new TransactionAcknowledgement(sysids[i], cuids[i], scuid);
if (!scuid.shouldStore() || !ref.isPersistent()) {
ta.setShouldStore(false);
}
if (!Globals.getDestinationList().isPartitionMode()) {
TransactionList[] tls = DL.getTransactionList(Globals.getStore().getPrimaryPartition());
tl = tls[0];
} else {
refpstore = ref.getPartitionedStore();
TransactionList[] tls = Globals.getDestinationList().getTransactionList(refpstore);
tl = tls[0];
if (tl == null) {
deliveredMessages.remove(entry);
String emsg = "Unable to prepare [" + sysids[i] + ":" + cuids[i] + "]TID=" + tid + " because transaction list for partition " + refpstore + " not found";
if (ae == null) {
ae = new AckEntryNotFoundException(emsg);
}
ae.addAckEntry(sysids[i], cuids[i]);
logger.log(logger.WARNING, emsg);
continue;
}
}
tltas = tltasmap.get(tl);
if (tltas == null) {
tltas = new ArrayList<>();
tltasmap.put(tl, tltas);
}
tltas.add(ta);
if (getDEBUG()) {
dbuf.append("\n\t[" + ta + "]" + tl);
}
}
if (ae != null) {
throw ae;
}
Iterator<Map.Entry<TransactionList, ArrayList<TransactionAcknowledgement>>> itr = tltasmap.entrySet().iterator();
Map.Entry<TransactionList, ArrayList<TransactionAcknowledgement>> pair = null;
while (itr.hasNext()) {
pair = itr.next();
tl = pair.getKey();
tltas = pair.getValue();
tas = tltas.toArray(new TransactionAcknowledgement[tltas.size()]);
TransactionState ts = new TransactionState(AutoRollbackType.NOT_PREPARED, 0L, true);
ts.setState(TransactionState.PREPARED);
if (getDEBUG()) {
logger.log(logger.INFO, "Preparing remote transaction " + tid + " for [" + tltas + "]" + tl + " from " + txnHomeBroker);
}
tl.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);
}
}
Iterator<TransactionList> itr = tltasmap.keySet().iterator();
while (itr.hasNext()) {
tl = itr.next();
tl.pendingStartedForRemotePreparedTransaction(tid);
}
notifyPendingCheckTimer();
if (getDEBUG()) {
logger.log(logger.INFO, "Prepared remote transaction " + tid + " from " + txnHomeBroker + dbuf.toString());
}
return;
}
if (ackType == ClusterBroadcast.MSG_ROLLEDBACK) {
if (getDEBUG()) {
logger.log(logger.INFO, "Rolling back remote transaction " + tid + " from " + txnHomeBroker);
}
List<Object[]> list = TransactionList.getTransListsAndRemoteTranStates(tid);
if (list == null) {
if (getDEBUG()) {
logger.log(logger.INFO, "Rolling back non-prepared remote transaction " + tid + " from " + txnHomeBroker);
}
List<AckEntry> entries = null;
synchronized (deliveredMessages) {
entries = getPendingConsumerUID(tid);
Iterator<AckEntry> itr = entries.iterator();
AckEntry e = null;
while (itr.hasNext()) {
e = itr.next();
if (deliveredMessages.get(e) == null) {
itr.remove();
continue;
}
if (consumers.get(e.getConsumerUID()) != null) {
itr.remove();
continue;
}
}
if (e != null) {
deliveredMessages.remove(e);
cleanupPendingConsumerUID(e.getConsumerUID(), e.getSysMessageID());
}
}
if (entries.size() == 0) {
logger.log(logger.INFO, br.getKString(br.I_ROLLBACK_REMOTE_TXN_NOT_FOUND, tid, txnHomeBroker));
return;
}
Iterator<AckEntry> itr = entries.iterator();
while (itr.hasNext()) {
AckEntry e = itr.next();
SysMessageID sysid = e.getSysMessageID();
com.sun.messaging.jmq.jmsserver.core.ConsumerUID cuid = e.getConsumerUID();
com.sun.messaging.jmq.jmsserver.core.ConsumerUID suid = e.getStoredConsumerUID();
if (suid == null) {
suid = cuid;
}
// PART
PacketReference ref = DL.get(null, sysid);
if (ref == null) {
if (getDEBUG()) {
logger.log(logger.INFO, "[" + sysid + ":" + cuid + "] reference not found in rolling back remote non-prepared transaction " + tid);
}
continue;
}
ref.removeInDelivery(suid);
ref.getDestination().forwardOrphanMessage(ref, suid);
}
return;
}
// if list == null
TransactionList tl = null;
Object[] oo = null;
for (int li = 0; li < list.size(); li++) {
oo = list.get(li);
tl = (TransactionList) oo[0];
if (!tl.updateRemoteTransactionState(tid, TransactionState.ROLLEDBACK, false, false, true)) {
return;
}
if (tl.getRecoveryRemoteTransactionAcks(tid) != null) {
rollbackRecoveryRemoteTransaction(tl, tid, txnHomeBroker);
}
RemoteTransactionAckEntry tae = tl.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 if (!tae.isLocalRemote()) {
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 (getDEBUG()) {
logger.log(logger.INFO, "[" + sysid + ":" + uid + "] not found in rolling back remote transaction " + tid);
}
continue;
}
if (value.getTUID() == null || !value.getTUID().equals(tid)) {
if (getDEBUG()) {
logger.log(logger.INFO, "[" + sysid + ":" + uid + "] with TUID=" + value.getTUID() + ", in confict for 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;
}
// PART
PacketReference ref = DL.get(null, sysid);
if (ref == null) {
if (getDEBUG()) {
logger.log(logger.INFO, "[" + sysid + ":" + cuid + "] reference not found in rolling back remote transaction " + tid);
}
continue;
}
ref.removeInDelivery(suid);
ref.getDestination().forwardOrphanMessage(ref, suid);
}
}
try {
tl.removeRemoteTransactionAck(tid);
} catch (Exception e) {
logger.log(logger.WARNING, "Unable to remove transaction ack for rolledback transaction " + tid + ": " + e.getMessage());
}
try {
tl.removeRemoteTransactionID(tid, true);
} catch (Exception e) {
logger.log(logger.WARNING, "Unable to remove rolledback remote transaction " + tid + ": " + e.getMessage());
}
}
// for
return;
}
int cLogRecordCount = 0;
ArrayList cLogDstList = null;
ArrayList cLogMsgList = null;
ArrayList cLogIntList = null;
if (ackType == ClusterBroadcast.MSG_ACKNOWLEDGED) {
if (getDEBUG()) {
logger.log(logger.INFO, "Committing remote transaction " + tid + " from " + txnHomeBroker);
}
List<Object[]> list = TransactionList.getTransListsAndRemoteTranStates(tid);
if (list == null) {
throw new BrokerException("Committing remote transaction " + tid + " not found", Status.NOT_FOUND);
}
TransactionList tl = null;
Object[] oo = null;
for (int li = 0; li < list.size(); li++) {
oo = list.get(li);
tl = (TransactionList) oo[0];
if (!tl.updateRemoteTransactionState(tid, TransactionState.COMMITTED, (sysids == null), true, true)) {
if (getDEBUG()) {
logger.log(logger.INFO, "Remote transaction " + tid + " already committed, from " + txnHomeBroker);
}
continue;
}
boolean done = true;
if (tl.getRecoveryRemoteTransactionAcks(tid) != null) {
done = commitRecoveryRemoteTransaction(tl, tid, txnHomeBroker);
}
RemoteTransactionAckEntry tae = tl.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, "No more transaction acks to process for committing remote transaction " + tid);
} else if (!tae.isLocalRemote()) {
boolean found = false;
TransactionAcknowledgement[] tas = tae.getAcks();
for (int i = 0; i < tas.length; i++) {
SysMessageID sysid = tas[i].getSysMessageID();
com.sun.messaging.jmq.jmsserver.core.ConsumerUID cuid = tas[i].getConsumerUID();
if (sysids != null && !found) {
if (sysid.equals(sysids[0]) && cuid.equals(cuids[0])) {
found = true;
}
}
String dstName = null;
if (Globals.txnLogEnabled()) {
if (cLogDstList == null) {
cLogDstList = new ArrayList();
cLogMsgList = new ArrayList();
cLogIntList = new ArrayList();
}
PacketReference ref = DL.get(null, sysid);
if (ref != null && !ref.isDestroyed() && !ref.isInvalid()) {
Destination[] ds = DL.getDestination(ref.getPartitionedStore(), ref.getDestinationUID());
Destination dst = ds[0];
dstName = dst.getUniqueName();
}
}
if (acknowledgeMessageFromRemote(ackType, sysid, cuid, optionalProps)) {
if (dstName != null) {
// keep track for consumer txn log
com.sun.messaging.jmq.jmsserver.core.ConsumerUID suid = tas[i].getStoredConsumerUID();
if (suid == null) {
suid = cuid;
}
cLogRecordCount++;
cLogDstList.add(dstName);
cLogMsgList.add(sysid);
cLogIntList.add(suid);
}
} else {
done = false;
}
}
// notify that message acks have been written to store
if (Globals.isNewTxnLogEnabled()) {
if (DL.isPartitionMode()) {
throw new BrokerException("Partition mode not supported if newTxnLog enabled");
}
((TxnLoggingStore) Globals.getStore().getPrimaryPartition()).loggedCommitWrittenToMessageStore(tid, BaseTransaction.REMOTE_TRANSACTION_TYPE);
}
if (sysids != null && !found) {
logger.log(logger.ERROR, "Internal Error: [" + sysids[0] + ":" + cuids[0] + "] not found in remote transaction " + tid);
done = false;
}
}
// tae != null
if (done) {
try {
tl.removeRemoteTransactionAck(tid);
} catch (Exception e) {
logger.logStack(logger.WARNING, "Unable to remove transaction ack for committed remote transaction " + tid, e);
}
try {
tl.removeRemoteTransactionID(tid, true);
} catch (Exception e) {
logger.logStack(logger.WARNING, "Unable to remove committed remote transaction " + tid, e);
}
} else if (Globals.getHAEnabled()) {
throw new BrokerException("Remote transaction processing incomplete, TUID=" + tid);
}
}
// log to txn log if enabled
try {
if (Globals.txnLogEnabled() && (cLogRecordCount > 0)) {
// Log all acks for consuming txn
ByteArrayOutputStream bos = new ByteArrayOutputStream((cLogRecordCount * (32 + SysMessageID.ID_SIZE + 8)) + 12);
DataOutputStream dos = new DataOutputStream(bos);
// Transaction ID (8 bytes)
dos.writeLong(tid.longValue());
// Number of acks (4 bytes)
dos.writeInt(cLogRecordCount);
for (int i = 0; i < cLogRecordCount; i++) {
String dst = (String) cLogDstList.get(i);
// Destination
dos.writeUTF(dst);
SysMessageID sysid = (SysMessageID) cLogMsgList.get(i);
// SysMessageID
sysid.writeID(dos);
long intid = ((com.sun.messaging.jmq.jmsserver.core.ConsumerUID) cLogIntList.get(i)).longValue();
// ConsumerUID
dos.writeLong(intid);
}
dos.close();
bos.close();
// PART
((TxnLoggingStore) Globals.getStore().getPrimaryPartition()).logTxn(TransactionLogType.CONSUME_TRANSACTION, bos.toByteArray());
}
} catch (IOException ex) {
logger.logStack(Logger.ERROR, Globals.getBrokerResources().E_INTERNAL_BROKER_ERROR, "Got exception while writing to transaction log", ex);
throw new BrokerException("Internal Error: Got exception while writing to transaction log", ex);
}
return;
}
throw new BrokerException("acknowledgeMessageFromRemotePriv:Unexpected ack type:" + ackType);
}
use of com.sun.messaging.jmq.jmsserver.util.AckEntryNotFoundException in project openmq by eclipse-ee4j.
the class TransactionHandler method doCommit.
/**
* Commit a transaction. This method is invoked from two places: 1) From TransactionHandler.handle() when handling a
* client COMMIT packet. This is the common case. 2) From the admin handler when an admin commit 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 sendReply True to have method send a Status.OK reply while processing transaction. This should be "true" for
* client initiated commits, "false" for admin initiated commits.
* @param con Connection client commit packet came in on or, for admin, the connection the admin request came in on.
* @param msg Client commit packet. Should be "null" for admin initiated commits.
*
* @throws BrokerException on an error. The method will have logged a message to the broker log.
*/
public void doCommit(TransactionList translist, TransactionUID id, JMQXid xid, Integer xaFlags, TransactionState ts, List conlist, boolean sendReply, IMQConnection con, Packet msg, boolean startNextTransaction) throws BrokerException {
int status = Status.OK;
HashMap cmap = null;
HashMap sToCmap = null;
List plist = null;
PartitionedStore pstore = translist.getPartitionedStore();
// local, or cluster
int transactionType = BaseTransaction.UNDEFINED_TRANSACTION_TYPE;
if (fi.checkFault(FaultInjection.FAULT_TXN_COMMIT_1_EXCEPTION, null)) {
fi.unsetFault(FaultInjection.FAULT_TXN_COMMIT_1_EXCEPTION);
throw new BrokerException(FaultInjection.FAULT_TXN_COMMIT_1_EXCEPTION);
}
// let acks get handled at a lower level since the
// lower level methods assumes only 1 ack per message
plist = translist.retrieveSentMessages(id);
cmap = translist.retrieveConsumedMessages(id);
sToCmap = translist.retrieveStoredConsumerUIDs(id);
cacheSetState(id, ts, con);
// remove from our active connection list
if (conlist != null) {
conlist.remove(id);
}
try {
Globals.getStore().txnLogSharedLock.lock();
TransactionWork txnWork = null;
if (Globals.isNewTxnLogEnabled()) {
txnWork = getTransactionWork2(translist.getPartitionedStore(), plist, cmap, sToCmap);
}
// Update transaction state
try {
int s;
if (xid == null) {
// Plain JMS transaction.
s = TransactionState.COMMITTED;
} else {
// XA Transaction.
s = ts.nextState(PacketType.COMMIT_TRANSACTION, xaFlags);
}
// After this call, returned base transaction will either be:
// a) null (for single phase LOCAL transaction)
// b) a prepared XA LOCAL transaction
// c) a prepared (XA or not) CLUSTER transaction
// currently, all cluster transactions are 2 phase
BaseTransaction baseTransaction = doRemoteCommit(translist, id, xaFlags, ts, s, msg, txnWork, con);
if (Globals.isNewTxnLogEnabled()) {
if (ts.getState() == TransactionState.PREPARED) {
// commit called (from client) on 2-phase transaction
transactionType = BaseTransaction.LOCAL_TRANSACTION_TYPE;
if (translist.isClusterTransaction(id)) {
transactionType = BaseTransaction.CLUSTER_TRANSACTION_TYPE;
}
logTxnCompletion(translist.getPartitionedStore(), id, TransactionState.COMMITTED, transactionType);
} else if ((baseTransaction != null && baseTransaction.getState() == TransactionState.PREPARED)) {
transactionType = baseTransaction.getType();
logTxnCompletion(translist.getPartitionedStore(), id, TransactionState.COMMITTED, transactionType);
} else {
// one phase commit, log all work here
transactionType = BaseTransaction.LOCAL_TRANSACTION_TYPE;
LocalTransaction localTxn = new LocalTransaction(id, TransactionState.COMMITTED, xid, txnWork);
logTxn(translist.getPartitionedStore(), localTxn);
}
} else {
// System.out.println("isFastLogTransactions=false ");
}
if (fi.FAULT_INJECTION) {
fi.checkFaultAndThrowBrokerException(FaultInjection.FAULT_TXN_COMMIT_1_1, null);
}
if (ts.getState() == TransactionState.PREPARED || (baseTransaction != null && baseTransaction.getState() == TransactionState.PREPARED)) {
translist.updateState(id, s, true);
} else {
// 1-phase commit
if (ts.getType() != AutoRollbackType.NEVER && Globals.isMinimumPersistLevel2()) {
translist.updateStateCommitWithWork(id, s, true);
} else {
translist.updateState(id, s, true);
}
}
if (fi.FAULT_INJECTION) {
checkFIAfterDB(PacketType.COMMIT_TRANSACTION);
fi.checkFaultAndExit(FaultInjection.FAULT_TXN_COMMIT_1_5, null, 2, false);
}
startTxnAndSendReply(translist, con, msg, status, startNextTransaction, conlist, xid, id, xaFlags, sendReply);
} catch (BrokerException ex) {
logger.logStack(((ex instanceof AckEntryNotFoundException) ? Logger.WARNING : Logger.ERROR), ex.toString() + ": TUID=" + id + " Xid=" + xid, ex);
throw ex;
}
try {
/*
* Can't really call the JMX notification code at the end of doCommit() because the call to
* translist.removeTransactionID(id) removes the MBean.
*/
Agent agent = Globals.getAgent();
if (agent != null) {
agent.notifyTransactionCommit(id);
}
} catch (Exception e) {
logger.log(Logger.WARNING, "JMX agent notify transaction committed failed:" + e.getMessage());
}
// OK .. handle producer transaction
int pLogRecordByteCount = 0;
ArrayList pLogMsgList = null;
for (int i = 0; plist != null && i < plist.size(); i++) {
SysMessageID sysid = (SysMessageID) plist.get(i);
PacketReference ref = DL.get(pstore, sysid);
if (ref == null) {
logger.log(Logger.WARNING, Globals.getBrokerResources().getKString(BrokerResources.W_MSG_REMOVED_BEFORE_SENDER_COMMIT, sysid));
continue;
}
// handle forwarding the message
try {
if (Globals.txnLogEnabled()) {
if (pLogMsgList == null) {
pLogMsgList = new ArrayList();
}
// keep track for producer txn log
pLogRecordByteCount += ref.getSize();
pLogMsgList.add(ref.getPacket().getBytes());
}
Destination[] ds = DL.getDestination(pstore, ref.getDestinationUID());
Destination d = ds[0];
if (fi.FAULT_INJECTION) {
fi.checkFaultAndExit(FaultInjection.FAULT_TXN_COMMIT_1_6, null, 2, false);
}
MessageDeliveryTimeInfo di = ref.getDeliveryTimeInfo();
if (di != null) {
d.routeCommittedMessageWithDeliveryTime(ref);
} else {
Set s = d.routeNewMessage(ref);
d.forwardMessage(s, ref);
}
} catch (Exception ex) {
logger.logStack((BrokerStateHandler.isShuttingDown() ? Logger.DEBUG : Logger.ERROR), ex.getMessage() + "[" + sysid + "]TUID=" + id, ex);
}
}
boolean processDone = true;
// handle consumer transaction
int cLogRecordCount = 0;
ArrayList cLogDstList = null;
ArrayList cLogMsgList = null;
ArrayList cLogIntList = null;
HashMap<TransactionBroker, Object> remoteNotified = new HashMap<>();
if (cmap != null && cmap.size() > 0) {
Iterator itr = cmap.entrySet().iterator();
while (itr.hasNext()) {
Map.Entry entry = (Map.Entry) itr.next();
SysMessageID sysid = (SysMessageID) entry.getKey();
// CANT just pull from connection
if (sysid == null) {
continue;
}
PacketReference ref = DL.get(null, sysid);
if (ref == null || ref.isDestroyed() || ref.isInvalid()) {
// already been deleted .. ignore
continue;
}
PartitionedStore refpstore = ref.getPartitionedStore();
Destination[] ds = DL.getDestination(refpstore, ref.getDestinationUID());
Destination dst = ds[0];
if (dst == null) {
if (ref.isDestroyed() || ref.isInvalid()) {
continue;
}
}
List interests = (List) entry.getValue();
for (int i = 0; i < interests.size(); i++) {
ConsumerUID intid = (ConsumerUID) interests.get(i);
ConsumerUID sid = (ConsumerUID) sToCmap.get(intid);
if (sid == null) {
sid = intid;
}
try {
Session s = Session.getSession(intid);
if (s != null) {
Consumer c = Consumer.getConsumer(intid);
if (c != null) {
c.messageCommitted(sysid);
}
PacketReference r1 = null;
if (fi.FAULT_INJECTION && fi.checkFault(FaultInjection.FAULT_TXN_COMMIT_1_7_1, null)) {
Globals.getConnectionManager().getConnection(s.getConnectionUID()).destroyConnection(true, GoodbyeReason.OTHER, "Fault injection of closing connection");
}
r1 = (PacketReference) s.ackMessage(intid, sysid, id, translist, remoteNotified, true);
try {
s.postAckMessage(intid, sysid, true);
if (r1 != null) {
if (fi.FAULT_INJECTION) {
fi.checkFaultAndExit(FaultInjection.FAULT_TXN_COMMIT_1_7, null, 2, false);
}
if (dst != null) {
dst.removeMessage(ref.getSysMessageID(), RemoveReason.ACKNOWLEDGED);
}
} else {
s = Session.getSession(intid);
}
} finally {
if (r1 != null) {
r1.postAcknowledgedRemoval();
}
}
}
if (s == null) {
// with the stored UID
try {
if (ref.acknowledged(intid, sid, true, true, id, translist, remoteNotified, true)) {
try {
if (dst != null) {
dst.removeMessage(ref.getSysMessageID(), RemoveReason.ACKNOWLEDGED);
}
} finally {
ref.postAcknowledgedRemoval();
}
}
} catch (BrokerException ex) {
// XXX improve internal error
logger.log(Logger.WARNING, "Internal error", ex);
}
}
if (Globals.txnLogEnabled()) {
if (cLogDstList == null) {
cLogDstList = new ArrayList();
cLogMsgList = new ArrayList();
cLogIntList = new ArrayList();
}
// ignore non-durable subscriber
if (dst == null || (!dst.isQueue() && !sid.shouldStore())) {
continue;
}
cLogRecordCount++;
cLogDstList.add(dst.getUniqueName());
cLogMsgList.add(sysid);
cLogIntList.add(sid);
}
} catch (Exception ex) {
processDone = false;
String[] args = { "[" + sysid + ":" + intid + ", " + dst + "]ref=" + ref.getSysMessageID(), id.toString(), con.getConnectionUID().toString() };
String emsg = Globals.getBrokerResources().getKString(BrokerResources.W_PROCCESS_COMMITTED_ACK, args);
logger.logStack(Logger.WARNING, emsg + "\n" + com.sun.messaging.jmq.io.PacketUtil.dumpPacket(msg) + "--------------------------------------------", ex);
}
}
}
}
if (Globals.isNewTxnLogEnabled()) {
// notify that transaction work has been written to message store
loggedCommitWrittenToMessageStore(translist.getPartitionedStore(), id, transactionType);
}
if (fi.FAULT_INJECTION) {
checkFIAfterDB(PacketType.COMMIT_TRANSACTION);
fi.checkFaultAndExit(FaultInjection.FAULT_TXN_COMMIT_2_1, null, 2, false);
}
// OK .. now remove the acks .. and free up the id for ues
// XXX Fixed 6383878, memory leaks because txn ack can never be removed
// from the store if the txn is removed before the ack; this is due
// to the fack that in 4.0 when removing the ack, the method check
// to see if the txn still exits in the cache. This temporary fix
// will probably break some HA functionality and need to be revisited.
translist.removeTransaction(id, (!processDone || (cmap.size() > 0 && BrokerStateHandler.isShuttingDown())));
if (conlist == null) {
// from admin
logger.log(logger.WARNING, BrokerResources.W_ADMIN_COMMITTED_TXN, id, ((xid == null) ? "null" : xid.toString()));
}
// log to txn log if enabled
try {
if (pLogRecordByteCount > 0 && cLogRecordCount > 0) {
// Log all msgs and acks for producing and consuming txn
ByteArrayOutputStream bos = new ByteArrayOutputStream((pLogRecordByteCount) + (cLogRecordCount * (32 + SysMessageID.ID_SIZE + 8)) + 16);
DataOutputStream dos = new DataOutputStream(bos);
// Transaction ID (8 bytes)
dos.writeLong(id.longValue());
// Msgs produce section
// Number of msgs (4 bytes)
dos.writeInt(pLogMsgList.size());
Iterator itr = pLogMsgList.iterator();
while (itr.hasNext()) {
// Message
dos.write((byte[]) itr.next());
}
// Msgs consume section
// Number of acks (4 bytes)
dos.writeInt(cLogRecordCount);
for (int i = 0; i < cLogRecordCount; i++) {
String dst = (String) cLogDstList.get(i);
// Destination
dos.writeUTF(dst);
SysMessageID sysid = (SysMessageID) cLogMsgList.get(i);
// SysMessageID
sysid.writeID(dos);
ConsumerUID intid = (ConsumerUID) cLogIntList.get(i);
// ConsumerUID
dos.writeLong(intid.longValue());
}
dos.close();
bos.close();
((TxnLoggingStore) pstore).logTxn(TransactionLogType.PRODUCE_AND_CONSUME_TRANSACTION, bos.toByteArray());
} else if (pLogRecordByteCount > 0) {
// Log all msgs for producing txn
ByteBuffer bbuf = ByteBuffer.allocate(pLogRecordByteCount + 12);
// Transaction ID (8 bytes)
bbuf.putLong(id.longValue());
// Number of msgs (4 bytes)
bbuf.putInt(pLogMsgList.size());
Iterator itr = pLogMsgList.iterator();
while (itr.hasNext()) {
// Message
bbuf.put((byte[]) itr.next());
}
((TxnLoggingStore) pstore).logTxn(TransactionLogType.PRODUCE_TRANSACTION, bbuf.array());
} else if (cLogRecordCount > 0) {
// Log all acks for consuming txn
ByteArrayOutputStream bos = new ByteArrayOutputStream((cLogRecordCount * (32 + SysMessageID.ID_SIZE + 8)) + 12);
DataOutputStream dos = new DataOutputStream(bos);
// Transaction ID (8 bytes)
dos.writeLong(id.longValue());
// Number of acks (4 bytes)
dos.writeInt(cLogRecordCount);
for (int i = 0; i < cLogRecordCount; i++) {
String dst = (String) cLogDstList.get(i);
// Destination
dos.writeUTF(dst);
SysMessageID sysid = (SysMessageID) cLogMsgList.get(i);
// SysMessageID
sysid.writeID(dos);
ConsumerUID intid = (ConsumerUID) cLogIntList.get(i);
// ConsumerUID
dos.writeLong(intid.longValue());
}
dos.close();
bos.close();
((TxnLoggingStore) pstore).logTxn(TransactionLogType.CONSUME_TRANSACTION, bos.toByteArray());
}
} catch (IOException ex) {
logger.logStack(Logger.ERROR, BrokerResources.E_INTERNAL_BROKER_ERROR, "Got exception while writing to transaction log", ex);
throw new BrokerException("Got exception while writing to transaction log", ex);
}
} finally {
// release lock
Globals.getStore().txnLogSharedLock.unlock();
}
}
use of com.sun.messaging.jmq.jmsserver.util.AckEntryNotFoundException in project openmq by eclipse-ee4j.
the class ClusterMessageAckInfo method getAckEntryNotFoundException.
public static AckEntryNotFoundException getAckEntryNotFoundException(GPacket ackack) {
Integer notfound = (Integer) ackack.getProp("notfound");
if (notfound == null) {
return null;
}
int cnt = notfound.intValue();
// Long tid = (Long)ackack.getProp("transactionID");
String reason = (String) ackack.getProp("reason");
AckEntryNotFoundException aee = new AckEntryNotFoundException(reason);
byte[] buf = ackack.getPayload().array();
ByteArrayInputStream bis = new ByteArrayInputStream(buf);
DataInputStream dis = new DataInputStream(bis);
SysMessageID sysid = null;
ConsumerUID intid = null;
try {
for (int i = 0; i < cnt; i++) {
sysid = new SysMessageID();
sysid.readID(dis);
intid = ClusterConsumerInfo.readConsumerUID(dis);
aee.addAckEntry(sysid, intid);
}
} catch (Exception e) {
Globals.getLogger().logStack(Globals.getLogger().WARNING, e.getMessage(), e);
}
return aee;
}
Aggregations