RegisteredResourcespublic class RegisteredResources extends Object The RegisteredResources class provides operations that manage a list
of Resource objects involved in a transaction, and their states relative
to the transaction. Resource references are stored in lists as there is no
way to perform Resource reference comparisons. As an instance of this
class may be accessed from multiple threads within a process,
serialisation for thread-safety is necessary in the implementation.
The information recorded in an instance of this class needs to be
reconstructible in the case of a system failure. |
Fields Summary |
---|
private ArrayList | resourceObjects | private ArrayList | resourceStates | private CoordinatorLog | logRecord | private Object | logSection | private Object | heuristicLogSection | private Resource | laoResource | private CoordinatorImpl | coord | private static boolean | lastXAResCommit | private int | nRes | private static final String | LOG_SECTION_NAME | private static final String | HEURISTIC_LOG_SECTION_NAME | static Logger | _logger |
Constructors Summary |
---|
RegisteredResources(CoordinatorLog log, CoordinatorImpl coord)Defines the CoordinatorLog which is to be used for recovery.
The CoordinatorLog for the transaction is updated with empty sections
for RegisteredResources and RegisteredResourcesHeuristic created.
Initialises the list of RegisteredResources to be empty.
The CoordinatorLog is used as the basis for recovering the
RegisteredResources and RegisteredResourcesHeuristic information at
restart.
resourceObjects = new ArrayList();
resourceStates = new ArrayList();
// Create two sections in the CoordinatorLog object for Resources.
logRecord = log;
if (log != null) {
// Create section for Resources registered as part of transaction
// logSection = log.createSection(LOG_SECTION_NAME);
// Create section for Resources with heuristic actions taken
// heuristicLogSection = log.createSection(HEURISTIC_LOG_SECTION_NAME);
}
this.coord = coord;
| RegisteredResources(CoordinatorImpl coord)Default RegisteredResources constructor. this.coord = coord;
|
Methods Summary |
---|
int | addRes(Resource obj)Adds a reference to a Resource object to the list in the
registered state.
//int result;
// Add the reference to the list (which was created when this object
// was created), with the "registered" status.
resourceObjects.add(obj);
nRes++;
resourceStates.add(ResourceStatus.Registered);
//result =nRes;
// Dont add the reference to the log record at this point
// as it may vote read-only.
return nRes;
| void | commitOnePhase()Distributes the one phase commit.
boolean infiniteRetry = true;
boolean heuristicRaisedSetStatus = false;
boolean heuristicExceptionFlowForget = false;
boolean isProxy = false;
boolean heuristicMixed = false;
boolean heuristicHazard = false;
boolean rollback_occurred = false;
boolean outstanding_resources = true;
int retry_limit;
int no_of_attempts;
// First, get the retry count.
/**
if (commitRetries == -1 && commitRetryVar != null) {
try {
commitRetries = Integer.parseInt(commitRetryVar);
} catch (Throwable exc) {
_logger.log(Level.SEVERE,"jts.exception_on_resource_operation",
new java.lang.Object[]
{ exc.toString(), "CommitOnePhase commitRetryVar" });
String msg = LogFormatter.getLocalizedMessage(_logger,
"jts.exception_on_resource_operation",
new java.lang.Object[]
{ exc.toString(), "CommitOnePhase commitRetryVar" });
throw new org.omg.CORBA.INTERNAL(msg);
}
infiniteRetry = false;
}
**/
int commitRetries = Configuration.getRetries();
if (commitRetries >= 0)
infiniteRetry = false;
// Check we only have one resource!
// If not return
if (nRes > 1) {
_logger.log(Level.SEVERE,"jts.exception_on_resource_operation",
new java.lang.Object[] { "commitOnePhase", ">1 Resource"});
String msg = LogFormatter.getLocalizedMessage(_logger,
"jts.exception_on_resource_operation",
new java.lang.Object[]
{ "commitOnePhase", ">1 Resource"});
throw new org.omg.CORBA.INTERNAL(msg);
}
// Now we know we have one resource we can use similar
// logic to the 'commit' method
Resource currResource = (Resource) resourceObjects.get(0);
// If the single resource is not in the registered state,
// we can return too!
// (Ram Jeyaraman) Should this condition check be != and then return ?
// Previously the IF block had '==' operator and empty block
if ((ResourceStatus) resourceStates.get(0) !=
ResourceStatus.Registered) {
return;
}
// We determine here whether the object is a proxy because
// the object may not exist when the commit returns.
// COMMENT(Ram J) the instanceof operation should be replaced
// by a is_local() call, once the local object contract is
// implemented.
if(!(currResource instanceof com.sun.jts.jtsxa.OTSResourceImpl)) {
ProxyChecker checkProxy = Configuration.getProxyChecker();
isProxy = checkProxy.isProxy(currResource);
}
// Change the current Resource's state to completing.
resourceStates.set(0,ResourceStatus.Completing);
// Tell the resource to commit.
// Catch any exceptions here; keep going until no exception is left.
int commitRetriesLeft = commitRetries;
boolean exceptionThrownTryAgain = true;
while (exceptionThrownTryAgain) {
try {
if(_logger.isLoggable(Level.FINEST))
{
_logger.logp(Level.FINEST,"RegisteredResources","commitOnePhase()",
"Before invoking commit_one_phase() on resource:" +
currResource );
}
currResource.commit_one_phase();
if(_logger.isLoggable(Level.FINEST))
{
_logger.logp(Level.FINEST,"RegisteredResources","commitOnePhase()",
"After invoking commit_one_phase() on resource:" +
currResource );
}
resourceStates.set(0,ResourceStatus.Completed);
exceptionThrownTryAgain = false;
} catch (Throwable exc) {
if (exc instanceof TRANSACTION_ROLLEDBACK) {
//
// The resource rolled back - remember this.
//
rollback_occurred = true;
resourceStates.set(0,ResourceStatus.Completed);
exceptionThrownTryAgain = false;
} else if (exc instanceof HeuristicHazard) {
// If the exception is Heuristic Rollback,
// Mixed or Hazard, remember that a heuristic exception
// has been raised, and also that damage has occurred.
//IASRI START 4722883
/**
heuristicExceptionFlowForget = true;
heuristicRaisedSetStatus = true;
exceptionThrownTryAgain = false;
heuristicMixed = false;
**/
XAException e = (XAException) ((Throwable)exc).getCause();
if ((e!= null) && (e.errorCode >= XAException.XA_RBBASE && e.errorCode <= XAException.XA_RBEND)) {
rollback_occurred = true;
resourceStates.set(0,ResourceStatus.Completed);
exceptionThrownTryAgain = false;
}
else {
heuristicExceptionFlowForget = true;
heuristicRaisedSetStatus = true;
exceptionThrownTryAgain = false;
heuristicMixed = false;
}
//IASRI END 4722883
} else if (exc instanceof INV_OBJREF ||
exc instanceof OBJECT_NOT_EXIST) {
// If the exception is INV_OBJREF, then the target Resource
// object must have already committed. (Probably contacted
// the resource on a previous attempt but its OK response
// was lost due to a failure.)
resourceStates.set(0,ResourceStatus.Completed);
exceptionThrownTryAgain = false;
} else if (exc instanceof NotPrepared) {
// If the exception is NotPrepared, then the target
// Resource is probably trying to indicate that it does not
// support one phase commit. Considered switching to
// 2PC commit for a retry here but as commit one phase is
// part of our specification then something is fishy
// if it is not supported: Throw an error.
_logger.log(Level.SEVERE,"jts.exception_on_resource_operation",
new java.lang.Object[] { exc.toString(),
"commit one phase"});
String msg = LogFormatter.getLocalizedMessage(_logger,
"jts.exception_on_resource_operation",
new java.lang.Object[] { exc.toString(),
"commit one phase"});
throw new org.omg.CORBA.INTERNAL(msg);
} else if (!(exc instanceof TRANSIENT) &&
!(exc instanceof COMM_FAILURE)) {
// If the exception has not been mentione yet and is
// neither of the two below, it is unexpected,
// so display a message and give up with this Resource.
_logger.log(Level.SEVERE,"jts.exception_on_resource_operation",
new java.lang.Object[] { exc.toString(),
"commit one phase"});
String msg = LogFormatter.getLocalizedMessage(_logger,
"jts.exception_on_resource_operation",
new java.lang.Object[] { exc.toString(),
"commit one phase"});
throw new org.omg.CORBA.INTERNAL(msg);
} else if (commitRetriesLeft > 0 || infiniteRetry) {
// For TRANSIENT or COMM_FAILURE, wait for a while,
// then retry the commit.
if (!infiniteRetry) {
commitRetriesLeft--;
}
try {
Thread.sleep(Configuration.COMMIT_RETRY_WAIT);
} catch (Throwable e) {}
} else {
// If the retry limit has been exceeded, end the
// process with a fatal error.
// GDH Did consider carefully here whether the exception
// should be perculated back to the client. With 2PC
// because we can take action on the other resources we
// carry on and subsequently pass an exception to the
// client. But here there is little point in doing
// this as all recoverable work has either
// been done or not by this point - we have a
// serious problem so stop now. If the JTS was built
// into an application server (rather than being a
// toolkit for standalone apps) then we would replace
// all the FATAL_ERROR actions such as the one below
// with the actino required by the application server.
_logger.log(Level.SEVERE,"jts.retry_limit_exceeded",
new java.lang.Object[] { new Integer(commitRetries),
"commitOnePhase"});
String msg = LogFormatter.getLocalizedMessage(_logger,
"jts.retry_limit_exceeded",
new java.lang.Object[] {
new Integer(commitRetries),"commitOnePhase"});
throw new org.omg.CORBA.INTERNAL(msg);
}
} // end of catch block for exceptions
} // end while exception being raised (GDH)
// Either mark the participant as having raised a heuristic exception,
// or as completed.
if (heuristicRaisedSetStatus) {
resourceStates.set(0,ResourceStatus.Heuristic);
if (logRecord != null) {
// (The distributeForget method forces the log)
if (!(currResource instanceof OTSResourceImpl)) {
if (heuristicLogSection == null)
heuristicLogSection =
logRecord.createSection(HEURISTIC_LOG_SECTION_NAME);
logRecord.addObject(heuristicLogSection,currResource);
}
}
} else {
// Otherwise we are completed, if the object is a proxy,
// release the proxy now.
resourceStates.set(0,ResourceStatus.Completed);
if (isProxy) {
currResource._release();
}
}
// If a heuristic exception was raised, perform forget processing.
// This will then throw the appropriate heuristic exception
// to the caller.
if (heuristicExceptionFlowForget) {
distributeForget(commitRetries, infiniteRetry, heuristicMixed);
// throw is done in method above
}
if (rollback_occurred) {
throw new TRANSACTION_ROLLEDBACK(0,
CompletionStatus.COMPLETED_YES);
}
// Otherwise just return normally.
| void | distributeCommit()Distributes commit messages to all Resources in the registered state
(i.e. not including those that voted VoteReadOnly). All Resources that
return successfully have their state set to completed; those that
raise heuristic exceptions are added to the
RegisteredResourcesHeuristic section of the CoordinatorLog and have
their state set to heuristic.
All Resources in the heuristic state are then told to forget,
their state is set to completed, and the CoordinatorLog object
is forced to the physical log.
boolean infiniteRetry = true;
boolean isProxy = false;
boolean heuristicException = false;
boolean heuristicMixed = false;
// First, get the retry count.
/**
if (commitRetries == -1 && commitRetryVar != null) {
try {
commitRetries = Integer.parseInt(commitRetryVar);
} catch (Throwable e) {}
infiniteRetry = false;
}
**/
int commitRetries = Configuration.getRetries();
if (commitRetries >= 0)
infiniteRetry = false;
// Browse through the participants, committing them. The following is
// intended to be done asynchronously as a group of operations.
boolean transactionCompleted = true;
String msg = null;
for (int i = 0; i < nRes; i++) {
Resource currResource = (Resource) resourceObjects.get(i);
// If the current Resource in the browse is not in the registered
// state, skip over it.
if ((ResourceStatus) resourceStates.get(i) ==
ResourceStatus.Registered) {
boolean heuristicRaised = false;
// We determine here whether the object is a proxy because the
// object may not exist when the commit returns.
// COMMENT(Ram J) the instanceof operation should be replaced
// by a is_local() call, once the local object contract is
// implemented.
if(!(currResource instanceof com.sun.jts.jtsxa.OTSResourceImpl)) {
ProxyChecker checkProxy = Configuration.getProxyChecker();
isProxy = checkProxy.isProxy(currResource);
}
// Change the current Resource's state to completing.
resourceStates.set(i,ResourceStatus.Completing);
// Tell the resource to commit.
// Catch any exceptions here; keep going until
// no exception is left.
int commitRetriesLeft = commitRetries;
boolean exceptionThrown = true;
while (exceptionThrown) {
try {
if(_logger.isLoggable(Level.FINER))
{
_logger.logp(Level.FINER,"RegisteredResources",
"distributeCommit()",
"Before invoking commit on resource = " +
currResource);
}
currResource.commit();
if(_logger.isLoggable(Level.FINER))
{
_logger.logp(Level.FINER,"RegisteredResources",
"distributeCommit()",
"After invoking commit on resource = "+
currResource);
}
exceptionThrown = false;
} catch (Throwable exc) {
if (exc instanceof HeuristicCommit) {
// If the exception is Heuristic Commit, remember
// that a heuristic exception has been raised.
heuristicException = true;
heuristicRaised = true;
exceptionThrown = false;
} else if (exc instanceof HeuristicRollback ||
exc instanceof HeuristicHazard ||
exc instanceof HeuristicMixed) {
// If the exception is Heuristic Rollback,
// Mixed or Hazard, remember that a heuristic
// exception has been raised, and also that
// damage has occurred.
heuristicException = true;
heuristicMixed = !(exc instanceof HeuristicHazard);
heuristicRaised = true;
exceptionThrown = false;
} else if (exc instanceof INV_OBJREF ||
exc instanceof OBJECT_NOT_EXIST) {
// If the exception is INV_OBJREF, then the target
// Resource object must have already committed.
exceptionThrown = false;
} else if (exc instanceof NotPrepared) {
// If the exception is NotPrepared, then the target
// Resource has not recorded the fact that it has
// been called for prepare, or some internal glitch
// has happened inside the RegisteredResources /
// TopCoordinator. In this case the only sensible
// action is to end the process with a fatal error
// message.
_logger.log(Level.SEVERE,
"jts.exception_on_resource_operation",
new java.lang.Object[] {exc.toString(),"commit"});
throw (NotPrepared)exc;
/**
msg = LogFormatter.getLocalizedMessage(_logger,
"jts.exception_on_resource_operation",
new java.lang.Object[] {exc.toString(),
"commit"});
throw new org.omg.CORBA.INTERNAL(msg);
**/
} else if (!(exc instanceof TRANSIENT) &&
!(exc instanceof COMM_FAILURE)) {
// If the exception is neither TRANSIENT or
// COMM_FAILURE, it is unexpected, so display a
// message and give up with this Resource.
//$ CHECK WITH DSOM FOLKS FOR OTHER EXCEPTIONS
_logger.log(Level.SEVERE,
"jts.exception_on_resource_operation",
new java.lang.Object[] {exc.toString(),"commit"});
exceptionThrown = false;
transactionCompleted = false;
msg = LogFormatter.getLocalizedMessage(_logger,
"jts.exception_on_resource_operation",
new java.lang.Object[] {exc.toString(),
"commit"});
} else if (commitRetriesLeft > 0 || infiniteRetry) {
// For TRANSIENT or COMM_FAILURE, wait
// for a while, then retry the commit.
if (!infiniteRetry) {
commitRetriesLeft--;
}
try {
Thread.sleep(Configuration.COMMIT_RETRY_WAIT);
} catch( Throwable e ) {}
} else {
// If the retry limit has been exceeded,
// end the process with a fatal error.
_logger.log(Level.SEVERE,"jts.retry_limit_exceeded",
new java.lang.Object[] {
new Integer(commitRetries), "commit"});
exceptionThrown = false;
transactionCompleted = false;
msg = LogFormatter.getLocalizedMessage(_logger,
"jts.retry_limit_exceeded",
new java.lang.Object[] {
new Integer(commitRetries), "commit"});
}
}
}
if (heuristicRaised) {
// Either mark the participant as having raised a heuristic
// exception, or as completed.
resourceStates.set(i,ResourceStatus.Heuristic);
if (logRecord != null) {
if (!(currResource instanceof OTSResourceImpl)) {
if (heuristicLogSection == null)
heuristicLogSection =
logRecord.createSection(HEURISTIC_LOG_SECTION_NAME);
logRecord.addObject(heuristicLogSection, currResource);
}
}
} else {
// If completed, and the object is a proxy,
// release the proxy now.
resourceStates.set(i,ResourceStatus.Completed);
if (isProxy) {
currResource._release();
}
}
}
}
// The browse is complete.
// If a heuristic exception was raised, perform forget processing. This
// will then throw the appropriate heuristic exception to the caller.
if (heuristicException)
distributeForget(commitRetries, infiniteRetry, heuristicMixed);
if (!transactionCompleted) {
if (coord != null)
RecoveryManager.addToIncompleTx(coord, true);
if (msg != null)
throw new org.omg.CORBA.INTERNAL(msg);
else
throw new org.omg.CORBA.INTERNAL();
}
// Otherwise just return normally.
| private void | distributeForget(int retries, boolean infinite, boolean heuristicMixed)Distributes forget messages to all Resources in the heuristic state.
(i.e. only those which have thrown heuristic exceptions on prepare,
commit or rollback).
All Resources then have their state set to completed.
boolean isProxy = false;
// Force the log record to ensure that all
// heuristic Resources are logged.
if (logRecord != null) {
logRecord.write(true);
}
// Browse through the remaining participants, informing them that they
// may forget the heuristic information at this point
for (int i = 0; i < nRes; i++) {
// If the current Resource in the browse is not in the heuristic
// state, skip over it.
if ((ResourceStatus)resourceStates.get(i) ==
ResourceStatus.Heuristic) {
Resource currResource = (Resource)resourceObjects.get(i);
// We determine here whether the object is a proxy because
// the object may not exist when the forget returns.
// COMMENT(Ram J) the instanceof operation should be replaced
// by a is_local() call, once the local object contract is
// implemented.
if(!(currResource instanceof com.sun.jts.jtsxa.OTSResourceImpl)) {
ProxyChecker checkProxy = Configuration.getProxyChecker();
isProxy = checkProxy.isProxy(currResource);
}
// Tell the resource to forget.
int retriesLeft = retries;
boolean exceptionThrown = true;
while (exceptionThrown) {
try {
currResource.forget();
exceptionThrown = false;
} catch (Throwable exc) {
if (exc instanceof INV_OBJREF ||
exc instanceof OBJECT_NOT_EXIST) {
// If the exception is INV_OBJREF, then the target
// Resource object must have already forgotten.
exceptionThrown = false;
} else if (!(exc instanceof COMM_FAILURE) &&
!(exc instanceof TRANSIENT)) {
// If the exception is neither TRANSIENT or
// COMM_FAILURE, it is unexpected, so display
// a message and give up with this Resource.
//$ CHECK WITH DSOM FOLKS FOR OTHER EXCEPTIONS
exceptionThrown = false;
} else if (retriesLeft > 0 || infinite) {
// For TRANSIENT or COMM_FAILURE, wait for a while,
// then retry the forget.
if (!infinite) {
retriesLeft--;
}
try {
Thread.sleep(Configuration.COMMIT_RETRY_WAIT);
} catch( Throwable e ) {}
} else {
// If the retry limit has been exceeded,
// end the process with a fatal error.
_logger.log(Level.SEVERE,"jts.retry_limit_exceeded",
new java.lang.Object[] { new Integer(retries),
"forget"});
String msg = LogFormatter.getLocalizedMessage(_logger,
"jts.retry_limit_exceeded",
new java.lang.Object[]
{ new Integer(retries), "forget"});
throw new org.omg.CORBA.INTERNAL(msg);
}
}
}
// Set the state of the Resource to completed
// after a successful forget. If the
// Resource is a proxy, release the reference.
resourceStates.set(i,ResourceStatus.Completed);
if (isProxy) {
currResource._release();
}
}
}
// If the original commit or rollback threw a HeuristicHazard
// or HeuristicMixed exception was raised, throw it now.
if (heuristicMixed) {
HeuristicMixed exc = new HeuristicMixed();
throw exc;
} else {
HeuristicHazard exc = new HeuristicHazard();
throw exc;
}
| Vote | distributePrepare()Distributes prepare messages to all Resources in the registered state.
Resource objects that vote to commit the transaction are added to the
RegisteredResources section in the CoordinatorLog.
All Resources that return VoteReadOnly have their state set to
completed. The consolidated result is returned.
boolean isProxy = false;
Vote result = Vote.VoteReadOnly;
int laoIndex = -1;
boolean rmErr = false;
// Browse through the participants, preparing them, and obtain
// a consolidated result. The following is intended to be done
// asynchronously as a group of perations, however if done
// sequentially, it should stop after the first rollback vote.
// If there are no Resource references, return the a read-only vote.
for (int i = 0;
i < nRes && result != Vote.VoteRollback;
i++) {
Resource currResource = (Resource) resourceObjects.get(i);
if ((i == nRes - 1) && lastXAResCommit && (laoResource == null) &&
result == Vote.VoteCommit) {
try {
if(_logger.isLoggable(Level.FINER))
{
_logger.logp(Level.FINER,"RegisteredResources",
"distributePrepare()",
"Before invoking commit on LA resource = " +
currResource);
}
currResource.commit_one_phase();
resourceStates.set(i, ResourceStatus.Completed);
if(_logger.isLoggable(Level.FINER))
{
_logger.logp(Level.FINER,"RegisteredResources",
"distributePrepare()",
"After invoking commit on LA resource = "+
currResource);
}
} catch (Throwable exc) {
result = Vote.VoteRollback;
resourceStates.set(i,ResourceStatus.Completed);
}
return result;
}
// We determine here whether the object is subordinate or proxy
// because the object may not exist when the prepare returns.
//String crid = CoordinatorResourceHelper.id();
//boolean isSubordinate = currResource._is_a( crid );
// COMMENT(Ram J) the instanceof operation should be replaced
// by a is_local() call, once the local object contract is
// implemented.
if(!(currResource instanceof OTSResourceImpl)) {
ProxyChecker checkProxy = Configuration.getProxyChecker();
isProxy = checkProxy.isProxy(currResource);
}
Vote currResult = Vote.VoteRollback;
try {
if(_logger.isLoggable(Level.FINER))
{
_logger.logp(Level.FINER,"RegisteredResources","prepare()",
"Before invoking prepare() on resource:" +
currResource);
}
currResult = currResource.prepare();
//Mark this resource as LA if vote is null
if(currResult == null) {
if(_logger.isLoggable(Level.FINER))
{
_logger.logp(Level.FINER,"RegisteredResources","prepare()",
"Marking the current resource as LAO:" +
currResource);
}
laoResource = currResource;
laoIndex = i;
continue;
}
if(_logger.isLoggable(Level.FINER))
{
_logger.logp(Level.FINER,"RegisteredResources","prepare()",
"After invoking prepare() on resource:" +
currResource + ";This resource voted : "+
currResult);
}
} catch (Throwable exc) {
// If a heuristic exception is thrown, this is because the
// Resource represents a subordinate which is voting to
// rollback; one of its Resources voted to roll back after
// others had voted to commit, and one of the commit voters
// then raised a heuristic exception when told to roll back.
// In this situation, we need to go back through all Resources
// and try to roll them back, not including the one
// which raised the exception.
boolean hazard = exc instanceof HeuristicHazard;
if (exc instanceof HeuristicMixed || hazard) {
// Mark the Resource which threw the exception as
// heuristic so that we do not
// try to roll it back, but we do send it a forget.
resourceStates.set(i,ResourceStatus.Heuristic);
try {
distributeRollback(true);
} catch (Throwable ex2) {
// If the rollback threw an exception, change
// HeuristicHazard to HeuristicMixed if necessary.
if (ex2 instanceof HeuristicMixed && hazard) {
hazard = false;
}
}
// Now throw the appropriate exception.
if (hazard) {
HeuristicHazard ex2 = new HeuristicHazard();
throw ex2;
} else {
HeuristicMixed ex2 = new HeuristicMixed();
throw ex2;
}
} else if (exc instanceof RuntimeException) {
rmErr = true;
}
// If any other exception is raised, assume the vote
// is rollback.
//$Check for specific exceptions ?
_logger.log(Level.WARNING,"jts.exception_on_resource_operation",
new java.lang.Object[] {exc.toString(),"prepare"});
}
// Record the outcome from the participant
// Take an action depending on the participant's vote.
if (currResult == Vote.VoteCommit) {
if (logRecord != null) {
if (!(currResource instanceof OTSResourceImpl)) {
if (logSection == null)
logSection = logRecord.createSection(LOG_SECTION_NAME);
logRecord.addObject(logSection, currResource);
}
}
if (result == Vote.VoteReadOnly) {
result = Vote.VoteCommit;
}
} else {
// If a participant votes readonly, don't change the overall
// vote. If a participant votes to rollback the transaction,
// change the consolidated result to rollback.
// Dont bother writing the reference to the log.
// The state of the Resource object is set
// to completed as we must not call it after it has voted
// to rollback the transaction. Set the state of a participant
// that votes read-only to completed as it
// replies. The consolidated vote does not change.
if (!rmErr)
resourceStates.set(i,ResourceStatus.Completed);
if (isProxy) {
currResource._release();
}
if (currResult == Vote.VoteRollback) {
result = currResult;
}
}
}
if (result == Vote.VoteCommit && laoResource != null) {
try {
if(_logger.isLoggable(Level.FINER))
{
_logger.logp(Level.FINER,"RegisteredResources",
"distributePrepare()",
"Before invoking commit on LA resource = " +
laoResource);
}
// laoResource.commit();
resourceStates.set(laoIndex, ResourceStatus.Completed);
if(_logger.isLoggable(Level.FINER))
{
_logger.logp(Level.FINER,"RegisteredResources",
"distributePrepare()",
"After invoking commit on LA resource = "+
laoResource);
}
} catch (Throwable exc) {
result = Vote.VoteRollback;
resourceStates.set(laoIndex,ResourceStatus.Completed);
}
}
return result;
| void | distributeRollback(boolean heuristicException)Distributes rollback messages to all Resources in the registered state.
(i.e. not including those that voted VoteReadOnly). All Resources that
return successfully have their state set to completed; those that raise
heuristic exceptions are added to the RegisteredResourcesHeuristic
section of the CoordinatorLog and have their state set to heuristic.
All Resources in the heuristic state are then told to forget,
their state is set to completed, and the CoordinatorLog object
is forced to the physical log.
boolean infiniteRetry = true;
boolean heuristicMixed = false;
boolean isProxy = false;
// First, get the retry count.
/**
if (commitRetries == -1 && commitRetryVar != null) {
try {
commitRetries = Integer.parseInt(commitRetryVar);
} catch (Throwable e) {}
infiniteRetry = false;
}
**/
int commitRetries = Configuration.getRetries();
if (commitRetries >= 0)
infiniteRetry = false;
// Browse through the participants, committing them. The following is
// intended to be done asynchronously as a group of operations.
boolean transactionCompleted = true;
String msg = null;
for (int i = 0; i < nRes; i++) {
Resource currResource = (Resource)resourceObjects.get(i);
// If the current Resource in the browse is not in the registered
// state, skip over it.
if (resourceStates.get(i).equals(
ResourceStatus.Registered)) {
boolean heuristicRaised = false;
// We determine here whether the object is a proxy because
// the object may not exist when the commit returns.
// COMMENT(Ram J) the instanceof operation should be replaced
// by a is_local() call, once the local object contract is
// implemented.
if (!(currResource instanceof com.sun.jts.jtsxa.OTSResourceImpl)) {
ProxyChecker checkProxy = Configuration.getProxyChecker();
isProxy = checkProxy.isProxy(currResource);
}
// Change the current Resource's state to completing.
resourceStates.set(i,ResourceStatus.Completing);
// Tell the resource to commit.
// Catch any exceptions here; keep going
// until no exception is left.
int rollbackRetriesLeft = commitRetries;
boolean exceptionThrown = true;
while (exceptionThrown) {
try {
if(_logger.isLoggable(Level.FINER))
{
_logger.logp(Level.FINER,"RegisteredResources",
"distributeRollback()",
"Before invoking rollback on resource = "+
currResource);
}
currResource.rollback();
if(_logger.isLoggable(Level.FINER))
{
_logger.logp(Level.FINER,"RegisteredResources",
"distributeRollback()",
"After invoking rollback on resource = "+
currResource);
}
exceptionThrown = false;
} catch (Throwable exc) {
if (exc instanceof TRANSACTION_ROLLEDBACK) {
// If the exception is TRANSACTION_ROLLED back,
// then continue.
exceptionThrown = false;
}
if (exc instanceof HeuristicRollback) {
// If the exception is Heuristic Rollback,
// remember that a heuristic exception
// has been raised.
heuristicException = true;
heuristicRaised = true;
exceptionThrown = false;
} else if (exc instanceof HeuristicCommit ||
exc instanceof HeuristicHazard ||
exc instanceof HeuristicMixed) {
// If the exception is Heuristic Rollback, Mixed
// or Hazard, remember that a heuristic exception
// has been raised, and also that damage has
// occurred.
heuristicException = true;
heuristicMixed = !(exc instanceof HeuristicHazard);
heuristicRaised = true;
exceptionThrown = false;
} else if (exc instanceof INV_OBJREF ||
exc instanceof OBJECT_NOT_EXIST){
//GDH added NOT_EXIST
// If the exception is INV_OBJREF, then the target
// Resource object must have already rolled back.
exceptionThrown = false;
} else if (!(exc instanceof TRANSIENT) &&
!(exc instanceof COMM_FAILURE)) {
// If the exception is neither TRANSIENT or
// COMM_FAILURE, it is unexpected, so display
// a message and give up with this Resource.
_logger.log(Level.SEVERE,
"jts.exception_on_resource_operation",
new java.lang.Object[]
{ exc.toString(), "rollback"});
msg = LogFormatter.getLocalizedMessage(_logger,
"jts.exception_on_resource_operation",
new java.lang.Object[] { exc.toString(),
"rollback"});
exceptionThrown = false;
transactionCompleted = false;
} else if (rollbackRetriesLeft > 0 || infiniteRetry) {
// For TRANSIENT or COMM_FAILURE, wait for a while,
// then retry the rollback.
if (!infiniteRetry) {
rollbackRetriesLeft--;
}
try {
Thread.sleep(Configuration.COMMIT_RETRY_WAIT);
} catch( Throwable e ) {}
} else {
// If the retry limit has been exceeded, end the
// process with a fatal error.
_logger.log(Level.SEVERE,"jts.retry_limit_exceeded",
new java.lang.Object[]
{ new Integer(commitRetries), "rollback"});
msg = LogFormatter.getLocalizedMessage(_logger,
"jts.retry_limit_exceeded",
new java.lang.Object[]
{ new Integer(commitRetries), "rollback"});
exceptionThrown = false;
transactionCompleted = false;
}
}
}
if (heuristicRaised) {
// Either mark the participant as having raised a
// heuristic exception, or as completed.
resourceStates.set(i,ResourceStatus.Heuristic);
if (logRecord != null) {
if (!(currResource instanceof OTSResourceImpl)) {
if (heuristicLogSection == null)
heuristicLogSection =
logRecord.createSection(HEURISTIC_LOG_SECTION_NAME);
logRecord.addObject(heuristicLogSection,currResource);
}
}
} else {
// If completed, and the object is a proxy,
// release the proxy now.
resourceStates.set(i,ResourceStatus.Completed);
if (isProxy) {
currResource._release();
}
}
}
}
// The browse is complete.
// If a heuristic exception was raised, perform forget processing.
// This will then throw the appropriate heuristic exception
// to the caller.
if (heuristicException)
distributeForget(commitRetries, infiniteRetry, heuristicMixed);
if (!transactionCompleted) {
if (coord != null)
RecoveryManager.addToIncompleTx(coord, false);
if (msg != null)
throw new org.omg.CORBA.INTERNAL(msg);
else
throw new org.omg.CORBA.INTERNAL();
}
// Otherwise just return normally.
| void | distributeSubcommit(Coordinator parent)Distributes commitSubtransaction messages to all registered
SubtransactionAwareResources.
boolean exceptionRaised = false;
boolean isProxy = false;
// Browse through the participants, committing them. The following is
// intended to be done asynchronously as a group of operations.
for (int i = 0; i < nRes; i++) {
SubtransactionAwareResource currResource =
(SubtransactionAwareResource)resourceObjects.get(i);
// COMMENT(Ram J) the instanceof operation should be replaced
// by a is_local() call, once the local object contract is
// implemented.
if(!(currResource instanceof com.sun.jts.jtsxa.OTSResourceImpl)) {
ProxyChecker checkProxy = Configuration.getProxyChecker();
isProxy = checkProxy.isProxy(currResource);
}
// Tell the object to commit.
try {
currResource.commit_subtransaction(parent);
} catch (Throwable exc) {
// Check for exceptions.
// If the TRANSACTION_ROLLEDBACK exception was raised,
// remember it.
if (exc instanceof TRANSACTION_ROLLEDBACK) {
exceptionRaised = true;
}
}
// Change the state of the object.
resourceStates.set(i,ResourceStatus.Completed);
// If the Resource is a proxy, release it.
if (isProxy) {
currResource._release();
}
}
// If an exception was raised, return it to the caller.
if (exceptionRaised) {
throw new TRANSACTION_ROLLEDBACK(0,CompletionStatus.COMPLETED_YES);
}
| void | distributeSubrollback()Distributes rollbackSubtransaction messages to all registered
SubtransactionAwareResources.
boolean isProxy = false;
// Browse through the participants, rolling them back. The following is
// intended to be done asynchronously as a group of operations.
for (int i = 0; i < nRes; i++) {
SubtransactionAwareResource currResource =
(SubtransactionAwareResource) resourceObjects.get(i);
// COMMENT(Ram J) the instanceof operation should be replaced
// by a is_local() call, once the local object contract is
// implemented.
if(!(currResource instanceof com.sun.jts.jtsxa.OTSResourceImpl)) {
ProxyChecker checkProxy = Configuration.getProxyChecker();
isProxy = checkProxy.isProxy(currResource);
}
// Tell the object to roll back.
try {
currResource.rollback_subtransaction();
} catch (Throwable exc) {}
resourceStates.set(i,ResourceStatus.Completed);
// If the Resource is a proxy, release it.
if (isProxy) {
currResource._release();
}
}
| Resource | getLAOResource()
return laoResource;
| boolean | involved()Checks whether there are any Resource objects registered.
If there are, the operation returns true, otherwise false.
boolean result = (nRes != 0 );
return result;
| int | numRegistered()Returns the number of Resources currently in the list.
return nRes;
| void | reconstruct(CoordinatorLog log)Directs the RegisteredResources to recover its state after a failure.
This is based on the given CoordinatorLog object. The participant list
and heuristic information is reconstructed.
// Set up the instance variables.
resourceObjects = new ArrayList();
resourceStates = new ArrayList();
boolean infiniteRetry = true;
// First, get the retry count.
/**
if (commitRetries == -1 && commitRetryVar != null) {
try {
commitRetries = Integer.parseInt(commitRetryVar);
} catch (Throwable e) {}
infiniteRetry = false;
}
**/
int commitRetries = Configuration.getRetries();
if (commitRetries >= 0)
infiniteRetry = false;
// Reconstruct our state from CoordinatorLog object.
// Get the Registered Resources and the Registered Resources that had
// Heuristic results. Return the list of Registered Resources that did
// not have any Heuristic results.
heuristicLogSection = log.createSection(HEURISTIC_LOG_SECTION_NAME);
java.lang.Object[] resources = log.getObjects(heuristicLogSection);
for(int i = 0; i < resources.length; i++) {
boolean exceptionThrown=true;
int commitRetriesLeft = commitRetries;
while(exceptionThrown){
try {
Resource res =
ResourceHelper.narrow((org.omg.CORBA.Object)resources[i]);
if (res != null) {
resourceObjects.add(res);
nRes++;
resourceStates.add(ResourceStatus.Heuristic);
}
exceptionThrown=false;
} catch (Throwable exc) {
if(exc instanceof TRANSIENT || exc instanceof COMM_FAILURE) {
// If the exception is either TRANSIENT or
// COMM_FAILURE, keep retrying
//$ CHECK WITH DSOM FOLKS FOR OTHER EXCEPTIONS
_logger.log(Level.WARNING,"jts.exception_on_resource_operation",
new java.lang.Object[]{exc.toString(),
"reconstruct"});
if (commitRetriesLeft > 0 || infiniteRetry) {
// For TRANSIENT or COMM_FAILURE, wait
// for a while, then retry the commit.
if (!infiniteRetry) {
commitRetriesLeft--;
}
try {
Thread.sleep(Configuration.COMMIT_RETRY_WAIT);
} catch( Throwable e ) {}
} else {
// If the retry limit has been exceeded,
// end the process with a fatal error.
_logger.log(Level.SEVERE,"jts.retry_limit_exceeded",
new java.lang.Object[] {
new Integer(commitRetries), "commit"});
String msg = LogFormatter.getLocalizedMessage(_logger,
"jts.retry_limit_exceeded",
new java.lang.Object[] {
new Integer(commitRetries), "commit"});
throw new org.omg.CORBA.INTERNAL(msg);
//exceptionThrown=false;
//Commented out code as this statement is not
//reachable
}
}
else{
exceptionThrown=false;
}
}
}
}
// Resources that did not have Heuristic outcomes are added to the list
// Get section id for Resources registered as part of transaction
logSection = log.createSection(LOG_SECTION_NAME);
resources = log.getObjects(logSection);
for (int i = 0; i < resources.length; i++) {
boolean exceptionThrown=true;
int commitRetriesLeft = commitRetries;
while(exceptionThrown){
try {
Resource res =
ResourceHelper.narrow((org.omg.CORBA.Object)resources[i]);
if (res != null) {
resourceObjects.add(res);
nRes++;
resourceStates.add(ResourceStatus.Registered);
}
exceptionThrown=false;
} catch (Throwable exc) {
if(exc instanceof TRANSIENT || exc instanceof COMM_FAILURE) {
// If the exception is either TRANSIENT or
// COMM_FAILURE, keep retrying
//$ CHECK WITH DSOM FOLKS FOR OTHER EXCEPTIONS
_logger.log(Level.WARNING,"jts.exception_on_resource_operation",
new java.lang.Object[] {exc.toString(),"reconstruct"});
if (commitRetriesLeft > 0 || infiniteRetry) {
// For TRANSIENT or COMM_FAILURE, wait
// for a while, then retry the commit.
if (!infiniteRetry) {
commitRetriesLeft--;
}
try {
Thread.sleep(Configuration.COMMIT_RETRY_WAIT);
} catch( Throwable e ) {}
} else {
// If the retry limit has been exceeded,
// end the process with a fatal error.
_logger.log(Level.SEVERE,"jts.retry_limit_exceeded",
new java.lang.Object[] {new Integer(commitRetries),
"commit"});
String msg = LogFormatter.getLocalizedMessage(_logger,
"jts.retry_limit_exceeded",
new java.lang.Object[] {
new Integer(commitRetries),
"commit"});
throw new org.omg.CORBA.INTERNAL(msg);
// exceptionThrown=false;
//Commented out as this will not be executed
}
}
else{
exceptionThrown=false;
}
}
}
}
logRecord = log;
|
|