use of com.sun.messaging.jmq.jmsserver.data.TransactionList in project openmq by eclipse-ee4j.
the class RollbackCommitHandler method handle.
/**
* Handle the incomming administration message.
*
* @param con The Connection the message came in on.
* @param cmd_msg The administration message
* @param cmd_props The properties from the administration message
*/
@Override
public boolean handle(IMQConnection con, Packet cmd_msg, Hashtable cmd_props) {
if (DEBUG) {
logger.log(Logger.DEBUG, this.getClass().getName() + ": " + "Rollback/Commit transaction " + cmd_props);
}
// Get the admin request message type
int requestType = ((Integer) cmd_props.get(MessageType.JMQ_MESSAGE_TYPE)).intValue();
int status = Status.OK;
String errMsg = null;
TransactionUID tid = null;
TransactionState ts = null;
TransactionHandler thandler = null;
// Get the packet handler that handles transaction packets
if (parent.adminPktRtr != null) {
thandler = (TransactionHandler) parent.adminPktRtr.getHandler(PacketType.ROLLBACK_TRANSACTION);
}
Long id = (Long) cmd_props.get(MessageType.JMQ_TRANSACTION_ID);
// only applies to rollback request
Boolean v = (Boolean) cmd_props.get(MessageType.JMQ_PROCESS_ACTIVE_CONSUMERS);
boolean processActiveConsumers = (v != null && v.booleanValue());
HAMonitorService hamonitor = Globals.getHAMonitorService();
if (hamonitor != null && hamonitor.inTakeover()) {
status = Status.ERROR;
errMsg = rb.getString(rb.E_CANNOT_PROCEED_TAKEOVER_IN_PROCESS);
logger.log(Logger.ERROR, this.getClass().getName() + ": " + errMsg);
}
if (id != null) {
tid = new TransactionUID(id.longValue());
} else {
status = Status.BAD_REQUEST;
}
if (status == Status.OK) {
TransactionList[] tls = DL.getTransactionList(null);
TransactionList tl = null;
for (int i = 0; i < tls.length; i++) {
tl = tls[i];
ts = tl.retrieveState(tid);
if (ts == null) {
continue;
}
break;
}
if (ts == null) {
// Specified transaction did not exist
status = Status.NOT_FOUND;
errMsg = rb.getString(rb.E_NO_SUCH_TRANSACTION, tid);
} else if (requestType == MessageType.COMMIT_TRANSACTION && ts.getState() != TransactionState.PREPARED) {
status = Status.PRECONDITION_FAILED;
errMsg = rb.getString(rb.E_TRANSACTION_NOT_PREPARED, tid);
} else if (requestType == MessageType.ROLLBACK_TRANSACTION && (ts.getState() < TransactionState.STARTED || ts.getState() > TransactionState.PREPARED)) {
status = Status.PRECONDITION_FAILED;
errMsg = rb.getString(rb.E_INVALID_TXN_STATE_FOR_ROLLBACK, tid);
} else {
JMQXid xid = tl.UIDToXid(tid);
if (xid == null && (!(Globals.getHAEnabled() && ts.getState() == TransactionState.PREPARED))) {
/*
* Need to pick the right error message: If (action is ROLLBACK and state is one of {STARTED, FAILED, INCOMPLETE,
* COMPLETE}) "Rollback of non-XA transaction 123456789 in non-PREPARED state is not supported." else
* "Could not find Xid for 123456789"
*/
if (requestType == MessageType.ROLLBACK_TRANSACTION && (ts.getState() >= TransactionState.STARTED && ts.getState() < TransactionState.PREPARED)) {
errMsg = rb.getString(rb.E_INTERNAL_BROKER_ERROR, "Rollback of non-XA transaction " + tid + " in non-PREPARED state is not supported.");
} else {
errMsg = rb.getString(rb.E_INTERNAL_BROKER_ERROR, "Could not find Xid for " + tid);
}
status = Status.ERROR;
} else if (thandler == null) {
errMsg = rb.getString(rb.E_INTERNAL_BROKER_ERROR, "Could not locate TransactionHandler");
status = Status.ERROR;
} else {
if (requestType == MessageType.ROLLBACK_TRANSACTION) {
if (DEBUG) {
logger.log(Logger.DEBUG, "Rolling back " + tid + " in state " + ts);
}
try {
if (processActiveConsumers) {
logger.log(logger.INFO, rb.getKString(rb.I_ADMIN_REDELIVER_MSGS_ON_TXN_ROLLBACK, tid));
try {
thandler.redeliverUnacked(tl, tid, true, true, true, -1, false);
} catch (Exception e) {
logger.logStack(logger.WARNING, rb.getKString(rb.X_ADMIN_REDELIVER_MSG_ON_TXN_ROLLBACK, tid, e.getMessage()), e);
}
}
thandler.doRollback(tl, tid, xid, null, ts, null, con, RollbackReason.ADMIN);
} catch (BrokerException e) {
status = Status.ERROR;
errMsg = e.getMessage();
}
} else if (requestType == MessageType.COMMIT_TRANSACTION) {
if (DEBUG) {
logger.log(Logger.DEBUG, "Committing " + tid + " in state " + ts);
}
try {
thandler.doCommit(tl, tid, xid, Integer.valueOf(XAResource.TMNOFLAGS), ts, null, false, con, null);
} catch (BrokerException e) {
status = Status.ERROR;
errMsg = e.getMessage();
}
} else {
// Should never happen.
return super.handle(con, cmd_msg, cmd_props);
}
}
}
}
sendReply(con, cmd_msg, requestType + 1, status, errMsg);
return true;
}
use of com.sun.messaging.jmq.jmsserver.data.TransactionList in project openmq by eclipse-ee4j.
the class ProtocolImpl method startTransaction.
/**
* Start a transaction.
*
* @param xid The Xid of the transaction to start. Required if transaction is an XA transaction. Must be null if it is
* not an XA transaction.
* @param xaFlags xaFlags passed on START operation. Used only if an XA transaction.
* @param con Connection client start packet came in on (or null if internal)
* @param type how rollback should be handled (e.g. only not prepared)
* @param lifetime how long the transaction should live (0 == forever)
* @return The TransactionUID started
*/
@Override
public TransactionUID startTransaction(JMQXid xid, Integer xaFlags, AutoRollbackType type, long lifetime, IMQConnection con) throws BrokerException {
if (DEBUG) {
logger.log(Logger.INFO, "ProtocolImpl.START TRANSACTION:XID=" + xid + ", xaFlags=" + TransactionState.xaFlagToString(xaFlags) + ", type=" + type + ", lifetime=" + lifetime + ", conn=@" + con.hashCode() + "[" + con.getConnectionUID() + ", " + con + "]");
}
List conlist = con.getTransactionListThreadSafe();
TransactionHandler handler = (TransactionHandler) pr.getHandler(PacketType.START_TRANSACTION);
// allocated a TID
TransactionUID id = null;
TransactionList tl = null;
if (xaFlags == null || TransactionState.isFlagSet(XAResource.TMNOFLAGS, xaFlags)) {
id = new TransactionUID();
TransactionList[] tls = DL.getTransactionList(con.getPartitionedStore());
tl = tls[0];
if (tl == null) {
throw new BrokerException("No transaction List for connection " + con + " to start new transaction " + id + (xid == null ? "" : " XID=" + xid));
}
} else if (xid != null) {
Object[] oo = TransactionList.mapXidToTid(xid, con);
if (oo == null) {
throw new BrokerException("Unknown XID " + xid, Status.NOT_FOUND);
} else {
tl = (TransactionList) oo[0];
id = (TransactionUID) oo[1];
}
} else {
// XID is null, something is wrong
throw new BrokerException("Invalid xid");
}
if (tl == null) {
Object[] oo = TransactionList.getTransListAndState(id, con, false, false);
if (oo != null) {
tl = (TransactionList) oo[0];
}
}
if (tl == null) {
throw new BrokerException("No Transaction List found for connection " + con + " to start transaction " + id + (xid == null ? "" : " XID=" + xid));
}
Object o = new Object();
handler.doStart(tl, id, conlist, con, type, xid, xid != null, lifetime, 0, xaFlags, PacketType.START_TRANSACTION, false, o.toString());
if (DEBUG) {
logger.log(Logger.INFO, "ProtocolImpl.STARTED TRANSACTION:TID=" + id + ", XID=" + xid + ", type=" + type + ", con=" + con);
}
return id;
}
use of com.sun.messaging.jmq.jmsserver.data.TransactionList in project openmq by eclipse-ee4j.
the class ProtocolImpl method verifyTransaction.
/**
* Verify a transaction is PREPARED
*
* @param tuid transaction id to verify
*/
@Override
public Map verifyTransaction(TransactionUID tuid) throws BrokerException {
// TransactionHandler handler = (TransactionHandler)
// pr.getHandler(PacketType.START_TRANSACTION);
Object[] oo = TransactionList.getTransListAndState(tuid, null, true, false);
if (oo == null) {
return null;
}
TransactionList translist = (TransactionList) oo[0];
TransactionState ts = (TransactionState) oo[1];
int realstate = ts.getState();
if (realstate != TransactionState.PREPARED) {
// GONE
return null;
}
return translist.getTransactionMap(tuid, true);
}
use of com.sun.messaging.jmq.jmsserver.data.TransactionList in project openmq by eclipse-ee4j.
the class ProtocolImpl method commitTransaction.
/**
* Commit a 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 con Connection client commit packet came in on (or null if internal)
*/
@Override
public void commitTransaction(TransactionUID id, JMQXid xid, Integer xaFlags, IMQConnection con) throws BrokerException {
if (DEBUG) {
logger.log(Logger.INFO, "ProtocolImpl.COMMIT TRANSACTION:TID=" + id + ", XID=" + xid + ", xaFlags=" + TransactionState.xaFlagToString(xaFlags) + ", conn=@" + con.hashCode() + "[" + con.getConnectionUID() + ", " + con + "]");
}
List conlist = con.getTransactionListThreadSafe();
TransactionHandler handler = (TransactionHandler) pr.getHandler(PacketType.START_TRANSACTION);
TransactionList tl = null;
if (0L == id.longValue()) {
if (xid == null) {
throw new BrokerException("Unexpected TransactionUID " + id);
}
Object[] oo = TransactionList.mapXidToTid(xid, con);
if (oo == null) {
id = null;
} else {
tl = (TransactionList) oo[0];
id = (TransactionUID) oo[1];
}
if (id == null) {
throw new BrokerException("Unknown XID " + xid, Status.NOT_FOUND);
}
}
TransactionState ts = null;
if (tl == null) {
Object[] oo = TransactionList.getTransListAndState(id, con, false, false);
if (oo != null) {
tl = (TransactionList) oo[0];
ts = (TransactionState) oo[1];
}
}
if (tl == null) {
throw new BrokerException("Unknown transaction " + id + (xid == null ? "" : " XID=" + xid), Status.NOT_FOUND);
}
if (ts == null) {
ts = tl.retrieveState(id);
if (ts == null) {
throw new BrokerException("Unknown transaction " + id + (xid == null ? "" : " XID=" + xid), Status.NOT_FOUND);
}
}
if (xid != null) {
if (ts.getXid() == null || !xid.equals(ts.getXid())) {
throw new BrokerException("Transaction XID mismatch " + xid + ", expected " + ts.getXid() + " for transaction " + id);
}
}
handler.doCommit(tl, id, xid, xaFlags, ts, conlist, false, con, null);
}
use of com.sun.messaging.jmq.jmsserver.data.TransactionList in project openmq by eclipse-ee4j.
the class ProtocolImpl method rollbackTransaction.
/**
* Rollback a transaction
*
* @param id The TransactionUID to rollback
* @param xid The Xid of the transaction to rollback. Required if transaction is an XA transaction. Must be null if it
* is not an XA transaction.
* @param redeliver should messages be redelivered
* @param setRedeliver if the messages are redelivered, should the redeliver flag be set on all messages or not
* @param con Connection client rollback packet came in on (or null if internal)
*/
@Override
public void rollbackTransaction(TransactionUID id, JMQXid xid, IMQConnection con, boolean redeliver, boolean setRedeliver, int maxRollbacks, boolean dmqOnMaxRollbacks) throws BrokerException {
if (maxRollbacks <= 0) {
dmqOnMaxRollbacks = !(Consumer.MSG_MAX_CONSECUTIVE_ROLLBACKS <= 0);
}
if (DEBUG) {
logger.log(Logger.INFO, "ProtocolImpl.ROLLBACK TRANSACTION:TID=" + id + ", XID=" + xid + ", conn=@" + con.hashCode() + "[" + con.getConnectionUID() + ", " + con + "], redeliver=" + redeliver + ", setRedeliver=" + setRedeliver);
}
List conlist = con.getTransactionListThreadSafe();
TransactionHandler handler = (TransactionHandler) pr.getHandler(PacketType.START_TRANSACTION);
TransactionList tl = null;
if (0L == id.longValue()) {
if (xid == null) {
throw new BrokerException("Unexpected TransactionUID " + id);
}
Object[] oo = TransactionList.mapXidToTid(xid, con);
if (oo == null) {
id = null;
} else {
tl = (TransactionList) oo[0];
id = (TransactionUID) oo[1];
}
if (id == null) {
throw new BrokerException("Unknown XID " + xid, Status.NOT_FOUND);
}
}
TransactionState ts = null;
if (tl == null) {
Object[] oo = TransactionList.getTransListAndState(id, con, false, false);
if (oo != null) {
tl = (TransactionList) oo[0];
ts = (TransactionState) oo[1];
}
}
if (tl == null) {
throw new BrokerException("Unknown transaction " + id + (xid == null ? "" : " XID=" + xid), Status.NOT_FOUND);
}
if (ts == null) {
ts = tl.retrieveState(id);
if (ts == null) {
throw new BrokerException("Unknown transaction " + id + (xid == null ? "" : " XID=" + xid), Status.NOT_FOUND);
}
}
if (xid != null) {
if (ts.getXid() == null || !xid.equals(ts.getXid())) {
throw new BrokerException("Transaction XID mismatch " + xid + ", expected " + ts.getXid() + " for transaction " + id);
}
}
handler.preRollback(tl, id, xid, null, /* xaFlags */
ts);
BrokerException bex = null;
if (redeliver) {
try {
handler.redeliverUnacked(tl, id, true, setRedeliver, false, maxRollbacks, dmqOnMaxRollbacks);
} catch (MaxConsecutiveRollbackException e) {
bex = e;
if (!dmqOnMaxRollbacks) {
throw bex;
}
}
}
try {
handler.doRollback(tl, id, xid, null, /* xaFlags */
ts, conlist, con, RollbackReason.APPLICATION);
} catch (BrokerException e) {
if (bex != null) {
throw bex;
}
throw e;
}
if (bex != null) {
throw bex;
}
}
Aggregations