use of org.omg.CosTransactions.RecoveryCoordinator in project narayana by jbosstm.
the class ArjunaTransactionImple method register_resource.
/**
* Resources are only registered with the current transaction, whereas
* subtransaction aware resources are registered with their parents when the
* current transaction ends.
*/
public RecoveryCoordinator register_resource(Resource r) throws SystemException, Inactive {
if (jtsLogger.logger.isTraceEnabled()) {
jtsLogger.logger.trace("ArjunaTransactionImple::register_resource ( " + r + " ) - called for " + get_uid());
}
if (r == null)
throw new BAD_PARAM(0, CompletionStatus.COMPLETED_NO);
currentStatus = determineStatus(this);
if (currentStatus != Status.StatusActive) {
if (jtsLogger.logger.isTraceEnabled()) {
jtsLogger.logger.trace("ArjunaTransactionImple::register_resource - transaction not active: " + Utility.stringStatus(currentStatus));
}
if (currentStatus == Status.StatusMarkedRollback) {
throw new TRANSACTION_ROLLEDBACK(ExceptionCodes.MARKED_ROLLEDBACK, CompletionStatus.COMPLETED_NO);
} else
throw new Inactive();
}
AbstractRecord corbaRec = null;
BasicAction registerIn = this;
if (jtsLogger.logger.isTraceEnabled()) {
jtsLogger.logger.trace("ArjunaTransactionImple " + get_uid() + " ::register_resource: ");
}
//
// Creation of recovery coordinator (DBI)
//
//
// Pack the params:
// [0] = Transaction* this
//
int index = 0;
Object[] params = new Object[10];
params[index++] = this;
RecoveryCoordinator recoveryCoordinator = null;
Uid recoveryCoordinatorUid = null;
try {
recoveryCoordinator = RecoveryCreator.createRecoveryCoordinator(r, params);
if (recoveryCoordinator == null)
throw new BAD_OPERATION("RecoveryCoordinator " + jtsLogger.i18NLogger.get_orbspecific_coordinator_rcnotcreated());
} catch (NO_IMPLEMENT ex) {
/*
* This is legal, and is meant to show that this ORB or
* configuration simply doesn't support crash recovery.
*/
recoveryCoordinator = null;
} catch (SystemException e) {
jtsLogger.i18NLogger.warn_orbspecific_coordinator_rccreate(get_uid(), e);
try {
rollback_only();
} catch (Inactive ex1) {
} catch (SystemException ex2) {
jtsLogger.i18NLogger.warn_orbspecific_coordinator_rbofail("ArjunaTransactionImple.register_resource", get_uid(), ex2);
throw ex2;
}
throw e;
}
if (recoveryCoordinator != null) {
//
// We got a RecoveryCoordinator, so unpack the other return values:
// [0] = RecoveryCoordinator Uid*
//
index = 0;
recoveryCoordinatorUid = (Uid) params[index++];
} else {
//
// We didn't get a RecoveryCoordinator, so we don't assume that
// the other return values have been populated.
//
recoveryCoordinatorUid = Uid.nullUid();
}
try {
SubtransactionAwareResource staResource = org.omg.CosTransactions.SubtransactionAwareResourceHelper.narrow(r);
if (staResource != null) {
if (jtsLogger.logger.isTraceEnabled()) {
jtsLogger.logger.trace("ArjunaTransactionImple::register_resource for " + get_uid() + " - subtransaction aware resource: YES");
}
/*
* If here the narrow was ok so we have a subtran aware
* resource.
*/
Coordinator coord = null;
if (parentHandle != null) {
/*
* If we are a SubTranResource then we get registered with
* the current transaction and its parents upon completion.
* The first parameter to the record indicates whether we
* should be propagated (registered) with the parent
* transaction.
*/
coord = parentHandle.get_coordinator();
}
corbaRec = createOTSRecord(true, r, coord, recoveryCoordinatorUid);
coord = null;
staResource = null;
} else
throw new BAD_PARAM(0, CompletionStatus.COMPLETED_NO);
} catch (BAD_PARAM ex) {
if (jtsLogger.logger.isTraceEnabled()) {
jtsLogger.logger.trace("ArjunaTransactionImple::register_resource for " + get_uid() + " - subtransaction aware resource: NO");
}
if (jtsLogger.logger.isTraceEnabled()) {
jtsLogger.logger.trace("ArjunaTransactionImple " + get_uid() + " ::register_resource: Simple resource - " + ex);
}
corbaRec = createOTSRecord(true, r, null, recoveryCoordinatorUid);
} catch (Unavailable e1) {
throw new Inactive();
} catch (SystemException e2) {
if (jtsLogger.logger.isTraceEnabled()) {
jtsLogger.logger.trace("ArjunaTransactionImple::register_resource for " + get_uid() + " : catch (SystemException) - " + e2);
}
throw e2;
} catch (Exception e3) {
if (jtsLogger.logger.isTraceEnabled()) {
jtsLogger.logger.trace("ArjunaTransactionImple::register_resource for " + get_uid() + " : catch (...) - " + e3);
}
throw new UNKNOWN(e3.toString(), ExceptionCodes.UNKNOWN_EXCEPTION, CompletionStatus.COMPLETED_NO);
}
if (jtsLogger.logger.isTraceEnabled()) {
jtsLogger.logger.trace("ArjunaTransactionImple::register_resource for " + get_uid() + " : try end");
}
if (registerIn.add(corbaRec) != AddOutcome.AR_ADDED) {
corbaRec = null;
throw new INVALID_TRANSACTION(ExceptionCodes.ADD_FAILED, CompletionStatus.COMPLETED_NO);
} else {
if (jtsLogger.logger.isTraceEnabled()) {
jtsLogger.logger.trace("ArjunaTransactionImple::register_resource for " + get_uid() + " : resource registered");
}
}
return recoveryCoordinator;
}
use of org.omg.CosTransactions.RecoveryCoordinator in project narayana by jbosstm.
the class JavaIdlRCManager method makeRC.
/**
* We create a RecoveryCoordinator reference, but without (we think)
* actually making the implementation object available to the orb.
* The data needed to construct the RecoveryCoordinator is put in
* the ObjectId. If a replay_completion is received, it will be sent,
* via the locationd daemon, to the RecoveryManager.
*/
public RecoveryCoordinator makeRC(Uid RCUid, Uid tranUid, Uid processUid, boolean isServerTransaction) {
initialise();
RecoveryCoordinator rc = null;
try {
String rcObjectId = GenericRecoveryCoordinator.makeId(RCUid, tranUid, processUid, isServerTransaction);
if (ref_ReCoo != null) {
// New for IOR template
String new_ior = RecoverIOR.getIORFromString(ORBManager.getORB().orb(), ref_ReCoo, rcObjectId);
org.omg.CORBA.Object rcAsObject = ORBManager.getORB().orb().string_to_object(new_ior);
// End for IOR Template
rc = RecoveryCoordinatorHelper.narrow(rcAsObject);
if (jtsLogger.logger.isDebugEnabled()) {
jtsLogger.logger.debug("JavaIdlRCManager: Created reference for tran " + tranUid + " = " + rc);
}
} else {
if (JavaIdlRCManager._runWithoutDaemon)
throw new NO_IMPLEMENT();
else {
jtsLogger.i18NLogger.warn_orbspecific_jacorb_recoverycoordinators_JacOrbRCManager_3();
rc = null;
}
}
} catch (Exception ex) {
jtsLogger.i18NLogger.warn_orbspecific_jacorb_recoverycoordinators_JacOrbRCManager_2(ex);
}
return rc;
}
use of org.omg.CosTransactions.RecoveryCoordinator in project narayana by jbosstm.
the class GenericRecoveryCreator method create.
/**
* Create a new RecoveryCoordinator for Resource res. The params
* array is used to pass additional data. Currently params[0] is
* the ArjunaTransactionImple ref. When create returns additional data is
* passed back using params. Currently returned params[0] is the
* RecoveryCoordinator Uid.
*/
public RecoveryCoordinator create(Resource res, Object[] params) throws SystemException {
RecoveryCoordinator recoveryCoordinator = null;
if (jtsLogger.logger.isDebugEnabled()) {
jtsLogger.logger.debug("GenericRecoveryCreator.create()");
}
// we dont use the res parameter in this version
if ((params != null) && (params[0] != null)) {
int index = 0;
ArjunaTransactionImple otsTransaction = (ArjunaTransactionImple) params[index++];
// Get the Uid of the top-level transaction. This will be
// the top-level interposed transaction in the case of
// interposition.
BasicAction rootAction = otsTransaction;
while ((rootAction.parent()) != null) rootAction = rootAction.parent();
Uid rootActionUid = rootAction.getSavingUid();
// Uid processUid = Utility.getProcessUid();
Uid processUid = com.arjuna.ats.arjuna.utils.Utility.getProcessUid();
// Create a Uid for the new RecoveryCoordinator
Uid RCUid = new Uid();
// Is this transaction a ServerTransaction?
boolean isServerTransaction = (otsTransaction instanceof ServerTransaction);
// Now ask the orb-specific bit to make the RecoveryCoordinator IOR
// (it may or may not actually make the RC itself)
recoveryCoordinator = _orbSpecificManager.makeRC(RCUid, rootActionUid, processUid, isServerTransaction);
// Tidy up
otsTransaction = null;
rootAction = null;
// Pass the RecoveryCoordinator Uid back
params[0] = RCUid;
} else {
jtsLogger.i18NLogger.warn_recovery_recoverycoordinators_GenericRecoveryCreator_1();
}
return recoveryCoordinator;
}
use of org.omg.CosTransactions.RecoveryCoordinator in project narayana by jbosstm.
the class TransactionImple method enlistResource.
public boolean enlistResource(XAResource xaRes, Object[] params) throws RollbackException, IllegalStateException, javax.transaction.SystemException {
if (jtaxLogger.logger.isTraceEnabled()) {
jtaxLogger.logger.trace("TransactionImple.enlistResource ( " + xaRes + " )");
}
if (xaRes == null)
throw new javax.transaction.SystemException("TransactionImple.enlistResource - " + jtaxLogger.i18NLogger.get_jtax_transaction_jts_nullparam());
int status = getStatus();
switch(status) {
case javax.transaction.Status.STATUS_MARKED_ROLLBACK:
throw new RollbackException("TransactionImple.enlistResource - " + jtaxLogger.i18NLogger.get_jtax_transaction_jts_markedrollback());
case javax.transaction.Status.STATUS_ACTIVE:
break;
default:
throw new IllegalStateException(jtaxLogger.i18NLogger.get_jtax_transaction_jts_inactivetx());
}
XAModifier theModifier = null;
if (params != null) {
if (params.length > XAMODIFIER) {
if (params[XAMODIFIER] instanceof XAModifier) {
theModifier = (XAModifier) params[XAMODIFIER];
}
}
}
try {
/*
* For each transaction we maintain a list of resources registered
* with it. Each element on this list also contains a list of
* threads which have registered this resource, and what their XID
* was for that registration.
*/
TxInfo info = null;
try {
synchronized (this) {
info = (TxInfo) _resources.get(xaRes);
if (info == null) {
/*
* Null info means it's not in the main resources list,
* but may be in the duplicates.
*/
info = (TxInfo) _duplicateResources.get(xaRes);
}
}
if (info != null) {
switch(info.getState()) {
case TxInfo.ASSOCIATION_SUSPENDED:
{
/*
* Have seen resource before, so do a resume. The
* Resource instance will still be registered with the
* transaction though.
*/
xaRes.start(info.xid(), XAResource.TMRESUME);
info.setState(TxInfo.ASSOCIATED);
synchronized (this) {
_suspendCount--;
}
// already registered resource with this
return true;
// transaction!
}
case TxInfo.ASSOCIATED:
{
return true;
}
case TxInfo.NOT_ASSOCIATED:
{
/*
* Resource was associated, but was presumably delisted.
*/
xaRes.start(info.xid(), XAResource.TMJOIN);
info.setState(TxInfo.ASSOCIATED);
return true;
}
default:
{
// block
throw new IllegalStateException("TransactionImple.enlistResource - " + jtaxLogger.i18NLogger.get_jtax_transaction_jts_illegalstate() + info.getState());
}
}
}
} catch (IllegalStateException ex) {
// we threw it in the first place
throw ex;
} catch (XAException exp) {
if (info != null)
info.setState(TxInfo.FAILED);
jtaxLogger.i18NLogger.warn_jtax_transaction_jts_xaerror("TransactionImple.enlistResource", XAHelper.printXAErrorCode(exp), exp);
return false;
}
// if (threadIsActive(xaRes))
// return true; // this thread has already registered a resource for
// this db
/*
* We definitely haven't seen this specific resource instance
* before, but that doesn't mean that we haven't seen the RM it is
* connected to.
*/
Xid xid = null;
TxInfo existingRM = isNewRM(xaRes);
if (existingRM == null) {
/*
* New RM, so create xid with new branch.
*/
boolean branchRequired = true;
synchronized (this) {
if (// first ever, so no need for
_resources.size() == 0) // branch
{
// branchRequired = false;
branchRequired = true;
}
}
xid = createXid(branchRequired, theModifier);
boolean associatedWork = false;
int retry = 20;
while (!associatedWork) {
try {
if (_xaTransactionTimeoutEnabled) {
int timeout = _theTransaction.getTimeout();
if (timeout > 0) {
try {
xaRes.setTransactionTimeout(timeout);
} catch (XAException te) {
jtaxLogger.i18NLogger.warn_jtax_transaction_jts_timeouterror("TransactionImple.enlistResource", XAHelper.printXAErrorCode(te), XAHelper.xidToString(xid), te);
}
}
}
// Pay attention now, this bit is hairy. We need to add a new XAResourceRecord
// to the transaction, which will thereafter drive its completion. However, the transaction
// core is not directly XA aware, so it's our job to start the XAResource. Problem is, if
// adding the record fails, the tx will never end the resource via the XAResourceRecord,
// so we must do so directly. start may fail due to dupl xid or other reason, and transactions
// may rollback async, for which reasons we can't call add before start.
// The xid will change on each pass of the loop, so we need to create a new record on each pass.
// The registerResource will fail in the case of multiple last resources being disallowed.
// see JBTM-362 and JBTM-363
XAResourceRecord xaResourceRecord = createRecord(xaRes, params, xid);
if (xaResourceRecord != null) {
xaRes.start(xid, XAResource.TMNOFLAGS);
try {
RecoveryCoordinator recCoord = _theTransaction.registerResource(xaResourceRecord.getResource());
xaResourceRecord.setRecoveryCoordinator(recCoord);
if (jtaxLogger.logger.isTraceEnabled()) {
jtaxLogger.logger.tracef("TransactionImple.enlistResource: " + "resource_trace: txn uid=%s XAReource=%s resource uid=%s\n", get_uid(), xaRes, xaResourceRecord.get_uid());
}
} catch (Exception e) {
// we called start on the resource, but _theTransaction did not accept it.
// we therefore have a mess which we must now clean up by ensuring the start is undone:
xaResourceRecord.rollback();
markRollbackOnly();
jtaxLogger.logger.debug("Can't set recovery coordinator for xa resource record: " + xaResourceRecord + ", " + e.getClass().getName() + ": " + e.getMessage(), e);
return false;
}
_resources.put(xaRes, new TxInfo(xid));
// dive out, no need to set associatedWork = true;
return true;
}
// if we get to here, something other than a failure of xaRes.start probably went wrong.
// so we don't loop and retry, we just give up.
markRollbackOnly();
return false;
} catch (XAException e) {
/* We get this from Oracle instead of DUPID. */
if (e.errorCode == XAException.XAER_RMERR) {
if (retry > 0)
xid = createXid(true, theModifier);
retry--;
} else if (e.errorCode == XAException.XAER_DUPID) {
if (retry > 0)
xid = createXid(true, theModifier);
retry--;
} else {
/*
* Can't do start, so set transaction to
* rollback only.
*/
jtaxLogger.i18NLogger.warn_jtax_transaction_jts_starterror("TransactionImple.enlistResource - XAResource.start", XAHelper.printXAErrorCode(e), XAHelper.xidToString(xid), e);
markRollbackOnly();
throw e;
}
if (retry < 0) {
jtaxLogger.i18NLogger.warn_jtax_transaction_jts_starterror("TransactionImple.enlistResource - XAResource.start", XAHelper.printXAErrorCode(e), XAHelper.xidToString(xid), e);
markRollbackOnly();
throw new UNKNOWN();
}
}
}
} else {
/*
* Have seen this RM before, so ignore this instance. The first
* registered RM instance will be used to drive the transaction
* completion. We add it to the duplicateResource list so we can
* delist it correctly later though.
*/
/*
* Re-create xid.
*/
xid = existingRM.xid();
try {
xaRes.start(xid, XAResource.TMJOIN);
} catch (XAException ex) {
jtaxLogger.i18NLogger.warn_jtax_transaction_jts_xaerror("TransactionImple.enlistResource - xa_start: ", XAHelper.printXAErrorCode(ex), ex);
markRollbackOnly();
throw ex;
}
/*
* Add to duplicate resources list so we can keep track of it
* (particularly if we later have to delist).
*/
_duplicateResources.put(xaRes, new TxInfo(xid));
return true;
}
return false;
} catch (Exception e) {
/*
* Some exceptional condition arose and we probably could not enlist
* the resouce. So, for safety mark the transaction as rollback
* only.
*/
jtaxLogger.i18NLogger.warn_could_not_enlist_xar(xaRes, params, e);
markRollbackOnly();
return false;
}
}
use of org.omg.CosTransactions.RecoveryCoordinator in project narayana by jbosstm.
the class JacOrbRCManager method makeRC.
/**
* We create a RecoveryCoordinator reference, but without (we think)
* actually making the implementation object available to the orb.
* The data needed to construct the RecoveryCoordinator is put in
* the ObjectId. If a replay_completion is received, it will be sent,
* via the locationd daemon, to the RecoveryManager.
*/
public RecoveryCoordinator makeRC(Uid RCUid, Uid tranUid, Uid processUid, boolean isServerTransaction) {
initialise();
RecoveryCoordinator rc = null;
try {
String rcObjectId = GenericRecoveryCoordinator.makeId(RCUid, tranUid, processUid, isServerTransaction);
if (ref_ReCoo != null) {
// New for IOR template
String new_ior = RecoverIOR.newObjectKey(ref_ReCoo, rcObjectId);
org.omg.CORBA.Object rcAsObject = ORBManager.getORB().orb().string_to_object(new_ior);
// End for IOR Template
rc = RecoveryCoordinatorHelper.narrow(rcAsObject);
if (jtsLogger.logger.isDebugEnabled()) {
jtsLogger.logger.debug("JacOrbRCManager: Created reference for tran " + tranUid + " = " + rc);
}
} else {
if (JacOrbRCManager._runWithoutDaemon)
throw new NO_IMPLEMENT();
else {
jtsLogger.i18NLogger.warn_orbspecific_jacorb_recoverycoordinators_JacOrbRCManager_3();
rc = null;
}
}
} catch (Exception ex) {
jtsLogger.i18NLogger.warn_orbspecific_jacorb_recoverycoordinators_JacOrbRCManager_2(ex);
}
return rc;
}
Aggregations