FileDocCategorySizeDatePackage
CoordinatorResourceImpl.javaAPI DocGlassfish v2 API37325Wed Jun 13 23:03:46 BST 2007com.sun.jts.CosTransactions

CoordinatorResourceImpl

public class CoordinatorResourceImpl extends CoordinatorResourcePOA implements CompletionHandler
The CoordinatorResourceImpl interface provides operations that allow a Coordinator to be represented among the registered Resources of a superior Coordinator, without requiring that the Coordinator support the Resource interface.
version
0.02
author
Simon Holdsworth, IBM Corporation
see

Fields Summary
private static POA
poa
private static boolean
recoverable
private CoordinatorResource
thisRef
boolean
beingForced
This flag may be set to indicate that the transaction is being forced.
private GlobalTID
globalTID
private boolean
subtransaction
private boolean
aborted
private boolean
heuristicDamage
private boolean
completed
private boolean
setAsTerminator
static Logger
_logger
Constructors Summary
CoordinatorResourceImpl(GlobalTID globalTID, CoordinatorImpl coord, boolean subtran)
Normal constructor.

Sets up the CoordinatorResourceImpl with the Coordinator reference and the local transaction identifier so that the Resource can always find the Coordinator to pass on the two-phase commit messages.

A flag is passed to indicate whether the CoordinatorResourceImpl represents a subtransaction.

param
globalTID The global transaction identifier.
param
coord The Coordinator for the transaction.
param
subtran Subtransaction indicator.
return
see

                                                                                 
            
                              
                                        


        // Set up the instance variables to those values passed in.

        subtransaction = subtran;
        this.globalTID = globalTID;

        // Inform the Coordinator that this is the object that normally terminates
        // the transaction.

        if( coord != null )
            coord.setTerminator(this);

    
CoordinatorResourceImpl(byte[] key)
Creates the CoordinatorResourceImpl with the given key. This is done when the CoordinatorResource object is recreated after the server has been restarted.

param
key The key for the object.
return
see


        // Get the global transaction identifier from the key.

        globalTID = new GlobalTID(key);

        // GDH
        // Ensure that recovery has completed so that we can get the Coordinator.
        // This is now delayed until the 2PC methods for normal resync and is
        // done as part of the superinfo.reconst

        //    RecoveryManager.waitForRecovery();

        // Check that the global transaction identifier represents a known transaction.
        // If it does not, then throw the OBJECT_NOT_EXIST exception.

        //    CoordinatorImpl coord = RecoveryManager.getCoordinator(globalTID);
        //    if( coord == null )
        //      {
        //      OBJECT_NOT_EXIST exc = new OBJECT_NOT_EXIST();
        //      if( trc != null ) trc.event(EVT_THROW).data(exc).write();
        //      throw exc;
        //      }

        // If the transaction is known, then inform the Coordinator that this is the
        // terminator for it.

        //    else
        //      coord.setTerminator(this);

        // Leave other members at the default values.

    
Methods Summary
public voidcommit()
Informs the object that the transaction is to be committed.

Passes the superior Coordinator's commit request on to the Coordinator that registered the CoordinatorResourceImpl, using a private interface.

If the Coordinator does not raise any heuristic exception, the CoordinatorResourceImpl destroys itself.

param
return
exception
HeuristicRollback The transaction has already been rolled back.
exception
HeuristicMixed At least one participant in the transaction has rolled back its changes.
exception
HeuristicHazard At least one participant in the transaction may have rolled back its changes.
exception
NotPrepared The transaction has not yet been prepared.
exception
SystemException An error occurred. The minor code indicates the reason for the exception.
see
Resource


        // If no global identifier has been set up, we can do nothing.

        if( globalTID == null ) {
            INTERNAL exc = new INTERNAL(MinorCode.NoGlobalTID,
                                        CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // Commit operations should only come in for top-level transactions.

        if( subtransaction ) {
            INTERNAL exc = new INTERNAL(MinorCode.TopForSub,
                                        CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // If the transaction that this object represents has already been completed,
        // raise a heuristic exception if necessary.  This object must wait for a
        // forget before destroying itself if it returns a heuristic exception.

        if( completed ) {
            if( aborted ) {
                heuristicDamage = true;
                HeuristicRollback exc = new HeuristicRollback();
                throw exc;
            } else if( heuristicDamage ) {
                HeuristicMixed exc = new HeuristicMixed();
                throw exc;
            }
        } else {

            // Look up the Coordinator for the transaction.

            // GDH: First of all make sure it has been recovered if necessary
	    if(_logger.isLoggable(Level.FINE))
	    {
			_logger.logp(Level.FINE,"CoordinatorResourceImpl","commit()",
					"Before invoking RecoveryManager.waitForRecovery():"+
					"GTID is: "+ globalTID.toString());

	    }
            RecoveryManager.waitForRecovery();

            TopCoordinator coord = (TopCoordinator)RecoveryManager.getCoordinator(globalTID);

            // If there is a Coordinator, lock it for the duration of this operation.
            // Tell the Coordinator to commit.
            // If the Coordinator throws HeuristicMixed or HeuristicHazard,
            // allow them to percolate to the caller.

            if( coord != null )
                synchronized( coord ) {
                    // GDH:
                    // Make sure the coordinator knows we are it's terminator
                    // (this is done here in case we are in a recovery situation)
                    // (the operation has been moved from the constructor of the
                    // this object to here as the constructor is now called
                    // to early to ensure the coordinator is present in all
                    // cases

                    // GDH:
                    // If the transaction has completed at this point the
                    // makeSureSetAsTerminator method will be unable to
                    // set the coordinators terminator and will throw
                    // an object not exist exception: This is what we want in this case.

                    makeSureSetAsTerminator();
                    coord.commit();
                }
        }

        // If and we are not being forced, we can destroy ourselves before returning.
        // Otherwise, the TopCoordinator will have called setCompleted to set up
        // the information we need should a subsequent commit or rollback request
        // arrive.

        if( !beingForced )
            destroy();

    
public voidcommit_one_phase()
Informs the object that the transaction is to be committed in one phase.

Passes the superior Coordinator's single-phase commit request on to the Coordinator that registered the CoordinatorResourceImpl, using a private interface.

The result from the Coordinator is returned to the caller. If the Coordinator did not raise any heuristic exception, the CoordinatorResourceImpl destroys itself.

param
return
exception
TRANSACTION_ROLLEDBACK The transaction could not be committed and has been rolled back.
exception
HeuristicHazard One or more resources in the transaction may have rolled back.
exception
SystemException An error occurred. The minor code indicates the reason for the exception.
see
Resource


        boolean rolledBack;


        // If no global_identifier has been set up, we can do nothing.

        if( globalTID == null ) {
            INTERNAL exc = new INTERNAL(MinorCode.NoGlobalTID,
                                        CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // Commit operations should only come in for top-level transactions.

        if( subtransaction ) {
            INTERNAL exc = new INTERNAL(MinorCode.TopForSub,
                                        CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // If the transaction that this object represents has already been completed,
        // raise an exception if necessary.

        if( completed ) {
            if( aborted ) {
                TRANSACTION_ROLLEDBACK exc = new TRANSACTION_ROLLEDBACK(0,CompletionStatus.COMPLETED_NO);
                throw exc;
            }
        } else {

            // Look up the Coordinator for the transaction.

            // GDH: First of all make sure it has been recovered if necessary
	    if(_logger.isLoggable(Level.FINE))
	    {
			_logger.logp(Level.FINE,"CoordinatorResourceImpl","commit_one_phase()",
					"Before invoking RecoveryManager.waitForRecovery(): "+
					"GTID is: " + globalTID.toString());
	    }
            RecoveryManager.waitForRecovery();

            TopCoordinator coord = (TopCoordinator)RecoveryManager.getCoordinator(globalTID);

            // If there is a Coordinator, lock it for the duration of this operation.
            // Tell the Coordinator to commit, by first doing a prepare.
            // If the Coordinator throws HeuristicMixed or HeuristicHazard,
            // allow them to percolate to the caller.

            if( coord != null ) {
                rolledBack = false;

                synchronized( coord ) {

                    // GDH:
                    // Make sure the coordinator knows we are it's terminator
                    // (this is done here in case we are in a recovery situation)
                    // (the operation has been moved from the constructor of the
                    // this object to here as the constructor is now called
                    // to early to ensure the coordinator is present in all
                    // cases
                    makeSureSetAsTerminator();

                    // The prepare operation may throw the HeuristicHazard exception.  In this case
                    // allow it to go back to the caller.

                    Vote vote = Vote.VoteRollback;
                    try {
                        vote = coord.prepare();
                    } catch( HeuristicMixed exc ) {
                        throw new HeuristicHazard();
                    }
                    try {
                        if( vote == Vote.VoteCommit )
                            coord.commit();
                        else if (vote == Vote.VoteRollback) {
                            // COMMENT (Ram J) 12/11/2000 The above if check
                            // for rollback was added to avoid throwing a
                            // rollback exception for readonly votes.
                            coord.rollback(true);
                            rolledBack = true;
                        }
                    } catch (Throwable exc) {
                        // ADDED(Ram J) percolate any system exception
                        // back to the caller.
                        if (exc instanceof INTERNAL) {
                            destroy();
                            throw (INTERNAL) exc;
                        }
                    }
                }

            } else {
                // coord is null
                // We could still find no coord that matched even after recovery
                // If there is still no coord then the process failed between
                // deleting the subordinate coordinator and the result being received
                // in the superior.   As all of the recoverable work occurred in this
                // server or in its subordinate servers (we are in cop), from a data integrity point of
                // view, it does not matter what result the CoordinatorResource returns
                // to the superior.  However, the superior may still have a client attached
                // and it would look strange if the transaction actually rolled back and
                // the TRANSACTION_ROLLEDBACK exception was not reported to the client.
                // Therefore we jump through hoops to give the best answer as possible.
                // By delaying the call to forget_superior until CoordinatorResource's
                // destructor we ensure the Coordinator and the CoordinatorResource are
                // deleted together (as much as is possible in the JAVA/CORBA environment) and
                // this occurs after the response has been sent to the superior (because
                // the ORB is holding a reference count to the CoordinatorResource).
                // Therefore, the most likely reason for this to occur is that the
                // Coordinator was timed out (and removed) just before the server
                // terminated.  In this case, the transaction rolled back, which is the
                // response that will be returned.

                rolledBack = true;

            }

            if( rolledBack ) {
                destroy();
                TRANSACTION_ROLLEDBACK exc = new TRANSACTION_ROLLEDBACK(0,CompletionStatus.COMPLETED_YES);
                throw exc;
            }
        }

        // Self-destruct before returning.

        destroy();

    
public voidcommit_subtransaction(Coordinator parent)
Informs the object that the subtransaction is to be committed.

Passes the superior Coordinator's commit request on to the SubCoordinator that registered the CoordinatorResourceImpl, using a private interface.

The result from the SubCoordinator is returned to the caller. The CoordinatorResourceImpl destroys itself.

param
parent The parent Coordinator reference.
return
exception
TRANSACTION_ROLLEDBACK The transaction could not be committed and some parts may have rolled back.
exception
SystemException An error occurred. The minor code indicates the reason for the exception.
see


        // If no global identifier has been set up, we can do nothing.

        if( globalTID == null ) {
            INTERNAL exc = new INTERNAL(MinorCode.NoGlobalTID,
                                        CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // Commit_subtransaction operations should only come in for subtransactions.

        if( !subtransaction ) {
            INTERNAL exc = new INTERNAL(MinorCode.SubForTop,
                                        CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // If the transaction that this object represents has already been rolled
        // back, raise the TRANSACTION_ROLLEDBACK exception.

        if( completed ) {
            if( aborted ) {
                destroy();
                TRANSACTION_ROLLEDBACK exc = new TRANSACTION_ROLLEDBACK(0,CompletionStatus.COMPLETED_YES);
                throw exc;
            }
        } else {

            // Look up the Coordinator for the subtransaction.

            SubCoordinator coord = (SubCoordinator)RecoveryManager.getCoordinator(globalTID);

            // If there is a Coordinator, lock it for the duration of this operation.
            // Tell the Coordinator to prepare then commit.
            // Record then ignore any exceptions - we do not expect heuristics during
            // subtransaction completion.

            if( coord != null ) {
                boolean rolledBack = false;

                synchronized( coord ) {
                    try {
                        if( coord.prepare() == Vote.VoteCommit )
                            coord.commit();
                        else {
                            coord.rollback(true);
                            rolledBack = true;
                        }
                    }
                    catch( Throwable ex ) {
                    }
                }

                if( rolledBack ) {
                    destroy();
                    TRANSACTION_ROLLEDBACK exc = new TRANSACTION_ROLLEDBACK(0,CompletionStatus.COMPLETED_YES);
                    throw exc;
                }
            }
        }

        // Destroy ourselves before returning (there is no heuristic information for
        // subtransactions).

        destroy();

    
voiddestroy()
Destroys the CoordinatorResourceImpl object.

param
return
see


        try {
            if (poa != null && thisRef != null) {
                poa.deactivate_object(poa.reference_to_id(thisRef));
                thisRef = null;
            } else {
                // BUGFIX(Ram J) It is possible that the
                // CoordinatorResource object was activated via the activation
                // daemon. In that case, there is no guarantee
                // that poa and thisRef are set to a meaningful value.
                // So, try to deactivate the CoordinatorResource object anyway.

                POA crPoa = null;
                if (poa == null) {
                    crPoa = Configuration.getPOA("CoordinatorResource"/*#Frozen*/);
                } else {
                    crPoa = poa;
                }
                if (thisRef == null) {
                    crPoa.deactivate_object(crPoa.servant_to_id(this));
                } else {
                    crPoa.deactivate_object(crPoa.reference_to_id(thisRef));
                    thisRef = null;
                }
            }
        } catch( Exception exc ) {
			 _logger.log(Level.WARNING,"jts.object_destroy_error","CoordinatorResource");
				
        }

        // finalize();
        globalTID = null;
    
voiddump()
Dumps the state of the object.

param
return
see

    
public voidforget()
Informs the object that the transaction is to be forgotten.

Informs the CoordinatorResourceImpl that it does not need to retain heuristic information any longer.

param
return
exception
SystemException An error occurred. The minor code indicates the reason for the exception.
see


        // Forget operations should only come in for top-level transactions.

        if( subtransaction ) {
            INTERNAL exc = new INTERNAL(MinorCode.TopForSub,
                                        CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // If no exception is raised, we can destroy ourselves before returning.

        destroy();
    
voidmakeSureSetAsTerminator()
Makes sure this object is set as the Coordinator Terminator

param
return
see


        if( !setAsTerminator ) {

            CoordinatorImpl coord = RecoveryManager.getCoordinator(globalTID);

            // If the transaction is not known then throw an exception,
            // otherwise inform the Coordinator that this is the
            // terminator for it.

            if( coord == null ) {
                OBJECT_NOT_EXIST exc = new OBJECT_NOT_EXIST();
                throw exc;
            } else {
                coord.setTerminator(this);
                setAsTerminator = true;
            }
        }

    
CoordinatorResourceobject()
Returns the CORBA Object which represents this object.

param
return
The CORBA object.
see

        if( thisRef == null ) {
            if( poa == null ) {
                poa = Configuration.getPOA("CoordinatorResource"/*#Frozen*/);
                recoverable = Configuration.isRecoverable();
            }

            try {
                byte[] id = null;
                if (recoverable && globalTID != null) {
                    id = globalTID.toBytes();
                    poa.activate_object_with_id(id, this);
                    org.omg.CORBA.Object obj = poa.create_reference_with_id(id, CoordinatorResourceHelper.id());
                    thisRef = CoordinatorResourceHelper.narrow(obj);
                    //thisRef = (CoordinatorResource) this;
                } else {
                    poa.activate_object(this);
                    org.omg.CORBA.Object obj = poa.servant_to_reference(this);
                    thisRef = CoordinatorResourceHelper.narrow(obj);
                    //thisRef = (CoordinatorResource) this;
                }
            } catch( ServantAlreadyActive saexc ) {
				_logger.log(Level.SEVERE,
						"jts.create_CoordinatorResource_object_error",saexc);
				String msg = LogFormatter.getLocalizedMessage(_logger,
										 "jts.create_CoordinatorResource_object_error");
				throw  new org.omg.CORBA.INTERNAL(msg);
						
            } catch( ServantNotActive snexc ) {
				_logger.log(Level.SEVERE,
						"jts.create_CoordinatorResource_object_error",snexc);
				String msg = LogFormatter.getLocalizedMessage(_logger,
										 "jts.create_CoordinatorResource_object_error");
				throw  new org.omg.CORBA.INTERNAL(msg);
						
            } catch( Exception exc ) {
				_logger.log(Level.SEVERE,
						"jts.create_CoordinatorResource_object_error",exc);
				String msg = LogFormatter.getLocalizedMessage(_logger,
										 "jts.create_CoordinatorResource_object_error");
				throw  new org.omg.CORBA.INTERNAL(msg);
						
            }
        }

        return thisRef;
    
public Voteprepare()
Requests the prepare phase vote from the object.

This uses a private interface to pass the superior Coordinator's prepare request. on to the Coordinator that registered the CoordinatorResourceImpl.

The result from the Coordinator is returned to the caller.

param
return
The Coordinators vote.
exception
SystemException The operation failed.
exception
HeuristicMixed Indicates that a participant voted to roll the transaction back, but one or more others have already heuristically committed.
exception
HeuristicHazard Indicates that a participant voted to roll the transaction back, but one or more others may have already heuristically committed.
see
Resource



        Vote result = Vote.VoteRollback;

        // If no global identifier has been set up, we can do nothing but vote for
        // the transaction to be rolled back.

        if( globalTID == null ) {
            INTERNAL exc = new INTERNAL(MinorCode.NoGlobalTID,
                                        CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // Prepare operations should only come in for top-level transactions.

        if( subtransaction ) {

            INTERNAL exc = new INTERNAL(MinorCode.TopForSub,
                                        CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // If the transaction that this object represents has already been rolled
        // back, return a rollback vote.

        if (completed) {
            if (aborted) {
                result = Vote.VoteRollback;
            } else {
                result = Vote.VoteCommit;
            }
        } else {

            // Look up the Coordinator for the transaction.

            TopCoordinator coord = (TopCoordinator)RecoveryManager.getCoordinator(globalTID);

            // If there is a Coordinator, lock it for the duration of this operation.
            // If there is no Coordinator, return a rollback vote.

            if( coord != null )
                synchronized( coord ) {

                    // Get the Coordinator's vote.
                    // If the Coordinator throws HeuristicMixed or HeuristicHazard,
                    // allow them to percolate to the caller.

                    result = coord.prepare();

                    // If the Coordinator has voted to roll the transaction back, then this
                    // CoordinatorResourceImpl will not be called again.  Ensure that the
                    // Coordinator has rolled back.
                    // If the Coordinator throws HeuristicMixed or HeuristicHazard,
                    // allow them to percolate to the caller.

                    if( result == Vote.VoteRollback )
                        coord.rollback(false);
                }
        }

        // If the Coordinator has voted to roll the transaction back, then this
        // CoordinatorResourceImpl will not be called again.
        // If a heuristic exception was thrown, this will be done in forget.

        if (result == Vote.VoteRollback) {
            destroy();
        }

        return result;
    
public voidrollback()
Informs the object that the transaction is to be rolled back.

Passes the superior Coordinator's rollback request on to the Coordinator that registered the CoordinatorResourceImpl, using a private interface.

If the Coordinator does not raise any heuristic exception, the CoordinatorResourceImpl destroys itself.

param
return
exception
HeuristicCommit The transaction has already been committed.
exception
HeuristicMixed At least one participant in the transaction has committed its changes.
exception
HeuristicHazard At least one participant in the transaction may have rolled back its changes.
exception
SystemException An error occurred. The minor code indicates the reason for the exception.
see
Resource


             // If no global identifier has been set up, we can do nothing.

             if( globalTID == null ) {
                 INTERNAL exc = new INTERNAL(MinorCode.NoGlobalTID,
                                             CompletionStatus.COMPLETED_NO);
                 throw exc;
             }

             // Rollback operations should only come in for top-level transactions.

             if( subtransaction ) {
                 INTERNAL exc = new INTERNAL(MinorCode.TopForSub,
                                             CompletionStatus.COMPLETED_NO);
                 throw exc;
             }

             // If the transaction that this object represents has already been completed,
             // raise a heuristic exception if necessary.  This object must wait for a
             // forget before destroying itself if it returns a heuristic exception.

             if( completed ) {
                 if( !aborted ) {
                     heuristicDamage = true;
                     HeuristicCommit exc = new HeuristicCommit();
                     throw exc;
                 }
                 else if( heuristicDamage ) {
                     HeuristicMixed exc = new HeuristicMixed();
                     throw exc;
                 }
             } else {

                 // Look up the Coordinator for the transaction.

                 // GDH: First of all make sure it has been recovered if necessary
	    	if(_logger.isLoggable(Level.FINE))
	    	{
				_logger.logp(Level.FINE,"CoordinatorResourceImpl","rollback()",
						"Before invoking RecoveryManager.waitForRecovery(): "+
						"GTID is : "+ globalTID.toString()); 
			
	    	}
                 RecoveryManager.waitForRecovery();

                 TopCoordinator coord = (TopCoordinator)RecoveryManager.getCoordinator(globalTID);

                 // If there is a Coordinator, lock it for the duration of this operation.
                 // Tell the Coordinator to rollback.
                 // If the Coordinator throws HeuristicMixed or HeuristicHazard,
                 // allow them to percolate to the caller.

                 if( coord != null )
                     synchronized( coord ) {

                         // GDH:
                         // Make sure the coordinator knows we are it's terminator
                         // (this is done here in case we are in a recovery situation)
                         // (the operation has been moved from the constructor of the
                         // this object to here as the constructor is now called
                         // to early to ensure the coordinator is present in all
                         // cases
                         makeSureSetAsTerminator();
                         coord.rollback(true);
                     }
             }

             // If we are not being forced, we can destroy ourselves before returning.
             // Otherwise, the TopCoordinator will have called set_completed to set up
             // the information we need should a subsequent commit or rollback request
             // arrive.

             if( !beingForced )
                 destroy();

         
public voidrollback_subtransaction()
Informs the object that the subtransaction is to be rolled back.

Passes the superior Coordinator's rollback request on to the SubCoordinator that registered the CoordinatorResourceImpl, using a private interface.

The result from the SubCoordinator is returned to the caller. The CoordinatorResourceImpl destroys itself.

param
return
exception
SystemException An error occurred. The minor code indicates the reason for the exception.
see


        // If no global identifier has been set up, we can do nothing.

        if( globalTID == null ) {
            INTERNAL exc = new INTERNAL(MinorCode.NoGlobalTID,
                                        CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // Commit_subtransaction operations should only come in for subtransactions.

        if( !subtransaction ) {
            INTERNAL exc = new INTERNAL(MinorCode.SubForTop,
                                        CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // If the transaction that this object represents has already been completed,
        // do nothing.

        if( !completed ) {

            // Look up the Coordinator for the transaction.

            SubCoordinator coord = (SubCoordinator)RecoveryManager.getCoordinator(globalTID);

            // If there is a Coordinator, lock it for the duration of this operation.
            // Tell the Coordinator to rollback.

            if( coord != null )
                synchronized( coord ) {
                    coord.rollback(true);
                }
        }

        // Destroy ourselves before returning (there is no heuristic information for
        // subtransactions).

        destroy();

    
public voidsetCompleted(boolean aborted, boolean heuristicDamage)
Informs the CoordinatorResourceImpl object that the transaction it represents has completed.

Flags indicate whether the transaction aborted, and whether there was heuristic damage.

param
aborted Indicates the transaction aborted.
param
heuristicDamage Indicates heuristic damage occurred.
return
see
CompletionHandler


        // Record the information.

        completed = true;
        this.aborted = aborted;
        this.heuristicDamage = heuristicDamage;