use of com.sun.messaging.jmq.jmsserver.data.ClusterTransaction 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.ClusterTransaction in project openmq by eclipse-ee4j.
the class ClusterTransaction2PCompleteEvent method readFromBytes.
@Override
void readFromBytes(byte[] data) throws IOException, BrokerException {
ByteArrayInputStream bais = new ByteArrayInputStream(data);
DataInputStream dis = new DataInputStream(bais);
clusterTransaction = new ClusterTransaction();
dis.skip(2);
clusterTransaction.getTransactionDetails().readContent(dis);
dis.close();
bais.close();
}
use of com.sun.messaging.jmq.jmsserver.data.ClusterTransaction in project openmq by eclipse-ee4j.
the class ClusterTransaction2PPrepareEvent method readFromBytes.
@Override
public void readFromBytes(byte[] data) throws IOException, BrokerException {
if (Store.getDEBUG()) {
Globals.getLogger().log(Logger.DEBUG, getPrefix() + "readFromBytes");
}
ByteArrayInputStream bais = new ByteArrayInputStream(data);
DataInputStream dis = new DataInputStream(bais);
clusterTransaction = new ClusterTransaction();
dis.skip(2);
clusterTransaction.getTransactionDetails().readContent(dis);
if (Store.getDEBUG()) {
Globals.getLogger().log(Logger.DEBUG, getPrefix() + "read details " + clusterTransaction.getTransactionDetails());
}
TransactionWork work = new TransactionWork();
work.readWork(dis);
clusterTransaction.setTransactionWork(work);
int objectBodySize = dis.readInt();
byte[] objectBody = new byte[objectBodySize];
dis.read(objectBody);
ByteArrayInputStream bais2 = new ByteArrayInputStream(objectBody);
ObjectInputStream ois = new FilteringObjectInputStream(bais2);
try {
clusterTransaction.setTransactionState((TransactionState) ois.readObject());
clusterTransaction.setTransactionBrokers((TransactionBroker[]) ois.readObject());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
ois.close();
bais2.close();
dis.close();
bais.close();
}
use of com.sun.messaging.jmq.jmsserver.data.ClusterTransaction in project openmq by eclipse-ee4j.
the class ClusterTransactionManager method replayTransactionEvent.
@Override
void replayTransactionEvent(TransactionEvent txnEvent, HashSet dstLoadedSet) throws BrokerException, IOException {
if (Store.getDEBUG()) {
Globals.getLogger().log(Logger.DEBUG, getPrefix() + " replayTransactionEvent");
}
ClusterTransactionEvent clusterTxnEvent = (ClusterTransactionEvent) txnEvent;
// replay to store on commit
ClusterTransaction clusterTxn = clusterTxnEvent.clusterTransaction;
int state = clusterTxn.getState();
TransactionUID tid = clusterTxn.getTid();
if (clusterTxnEvent.getSubType() == ClusterTransactionEvent.Type2PPrepareEvent) {
// in prepared txn store and resetting the transaction log
if (incompleteStored.containsKey(tid)) {
if (Store.getDEBUG()) {
String msg = getPrefix() + " found matching txn in prepared store on replay " + clusterTxn;
Globals.getLogger().log(Logger.DEBUG, msg);
}
} else {
addToIncompleteUnstored(clusterTxn);
}
} else if (clusterTxnEvent.getSubType() == ClusterTransactionEvent.Type2PCompleteEvent) {
// we are completing a transaction
// the transaction could be
// a) unstored (prepare replayed earlier)
// b) stored incomplete (prepare occurred before last checkpoint,
// completion not written to prepared store yet)
// This should therefore be the last entry in log.
// c) stored complete (prepare occurred before last checkpoint,
// and failure occurred after completion stored in prepared store
BaseTransaction existingWork = null;
if (incompleteUnstored.containsKey(tid)) {
// a) unstored (prepare replayed earlier)
if (state == TransactionState.ROLLEDBACK) {
existingWork = removeFromIncompleteUnstored(tid);
} else if (state == TransactionState.COMMITTED) {
existingWork = incompleteUnstored.get(tid);
existingWork.getTransactionDetails().setState(state);
existingWork.getTransactionState().setState(state);
}
} else if (incompleteStored.containsKey(tid)) {
// b) stored incomplete (prepare occurred before last checkpoint,
// completion not written to prepared store yet)
existingWork = removeFromIncompleteStored(tid);
updateStoredState(tid, state);
addToCompleteStored(existingWork);
} else if (completeStored.containsKey(tid)) {
// c) stored complete (prepare occurred before last checkpoint,
// and failure occurred after completion stored in prepared store
existingWork = completeStored.get(tid);
}
if (existingWork != null) {
if (state == TransactionState.COMMITTED) {
transactionLogManager.transactionLogReplayer.replayTransactionWork(existingWork.getTransactionWork(), tid, dstLoadedSet);
}
} else {
logger.log(Logger.ERROR, "Could not find prepared work for completing two-phase transaction " + clusterTxn.getTid());
}
}
}
use of com.sun.messaging.jmq.jmsserver.data.ClusterTransaction in project openmq by eclipse-ee4j.
the class ClusterTransactionManager method updateTransactionBrokerState.
void updateTransactionBrokerState(TransactionUID tid, int expectedTxnState, TransactionBroker txnBkr, boolean sync) throws BrokerException {
if (Store.getDEBUG()) {
String msg = getPrefix() + " updateTransactionBrokerState: tx = " + tid + " txnBkr=" + txnBkr;
Globals.getLogger().log(Logger.DEBUG, msg);
}
// store txnBroker state update in txn log
// if txn is complete then mark this also
// clustered txnUpdate record
// TO DO
// first look in unstored
ClusterTransaction clusterTxn = null;
boolean stored = false;
clusterTxn = (ClusterTransaction) incompleteUnstored.get(tid);
if (clusterTxn == null) {
clusterTxn = (ClusterTransaction) incompleteStored.get(tid);
if (clusterTxn != null) {
stored = true;
}
}
if (clusterTxn != null) {
boolean allComplete = updateTransactionBrokerState(txnBkr, clusterTxn);
if (Store.getDEBUG()) {
Globals.getLogger().log(Logger.DEBUG, getPrefix() + " allComplete: = " + allComplete);
}
if (allComplete) {
clusterTxn.getTransactionDetails().setComplete(true);
if (!stored) {
removeFromIncompleteUnstored(tid);
} else {
removeFromIncompleteStored(tid);
addToCompleteStored(clusterTxn);
try {
this.updateStoredCompletion(tid, true);
} catch (IOException ioe) {
throw new BrokerException("Could not update completion state of stored cluster transaction " + tid, ioe);
}
}
}
} else {
logger.log(Logger.ERROR, "Could not find matching cluster transaction for " + tid);
}
}
Aggregations