CurrentImplpublic class CurrentImpl extends org.omg.CORBA.LocalObject implements org.omg.CosTransactions.CurrentThe CurrentImpl class is our implementation of the standard Current
interface. It provides operations that enable the demarcation of a
transaction's scope. These operations are specified in pseudo-IDL. The
CurrentImpl ensures that the CurrentTransaction class is set up when the
CurrentImpl is created. As an instance of this class may be accessed from
multiple threads within a process, serialisation for thread-safety is
necessary in the implementation. |
Fields Summary |
---|
private int | timeOut | private static boolean | active | private TransactionFactory | factory | static Logger | _logger |
Constructors Summary |
---|
CurrentImpl()Default CurrentImpl constructor.
// Ensure the CurrentTransaction state has been initialised.
CurrentTransaction.initialise();
|
Methods Summary |
---|
public java.lang.String[] | _ids()
return null;
| public void | begin()Creates a new Control object, containing new Terminator and Coordinator
objects.
The current timeout value is passed to the Coordinator.
The Control object is made the current one for the thread on which this
method was invoked. If there is already a current Control the existing
Control that represents the parent transaction is stacked behind the new one,
which becomes the current one.
ControlImpl controlImpl = null;
// Until we need to check for resync in progress, synchronize the method.
synchronized(this) {
// If the transaction service is not active, throw an exception.
if( !active ) {
NO_PERMISSION exc = new NO_PERMISSION(0,CompletionStatus.COMPLETED_NO);
throw exc;
}
// Get a reference to the current ControlImpl object.
try {
controlImpl = CurrentTransaction.getCurrent();
} catch( SystemException exc ) {
}
// Release the lock now so that if the TransactionFactoryImpl call has to block
// (during resync), the lock does not prevent other threads from running.
}
// If there is a current Control object, then we should try to begin a
// subtransaction.
if( controlImpl != null )
try {
// Get the Coordinator reference, and use it to create a subtransaction.
// If an exception was raised, return it to the caller.
Coordinator coord = controlImpl.get_coordinator();
// Create a new Control object to represent the subtransaction.
Control control = coord.create_subtransaction();
// This control object may be remote, if the original Control object was.
// In this case we need to deal with it in the same was as we do in the
// resume method. Any exception which is thrown during this process will
// result in SubtransactionsUnavailable thrown to the caller.
JControl jcontrol = JControlHelper.narrow(control);
if( jcontrol != null )
controlImpl = ControlImpl.servant(jcontrol);
// If there is no local ControlImpl object for the transaction, we create one
// now.
if( controlImpl == null )
controlImpl = new ControlImpl(control);
} catch( Throwable exc ) {
SubtransactionsUnavailable ex2 = new SubtransactionsUnavailable();
throw ex2;
}
// If there is no current ControlImpl object, create a new top-level transaction
else {
//$ CurrentTransaction.report();
//$ RecoveryManager.report();
//$ ControlImpl.report();
//$ CoordinatorLog.report();
//$ TimeoutManager.report();
//
try {
// Get the TransactionFactory which should be used from this application.
// This block must be synchronized so that different threads do not try
// this concurrently.
synchronized(this) {
if( factory == null )
factory = Configuration.getFactory();
}
// Create the new transaction.
if (factory != null) {
if(_logger.isLoggable(Level.FINEST))
{
_logger.logp(Level.FINEST,"CurrentImpl","begin()",
"Before invoking create() on TxFactory");
}
if (Configuration.isLocalFactory()) {
controlImpl = ((TransactionFactoryImpl) factory).localCreate(timeOut);
} else {
Control control = factory.create(timeOut);
// This control object is remote.
// In this case we need to deal with it in the same was as we do in the
// resume method. Any exception which is thrown during this process will
// result in SubtransactionsUnavailable thrown to the caller.
JControl jcontrol = JControlHelper.narrow(control);
if (jcontrol != null) {
controlImpl = ControlImpl.servant(jcontrol);
}
// If there is no local ControlImpl object for the transaction, we create one
// now.
if (controlImpl == null) {
controlImpl = new ControlImpl(control);
}
}
}
} catch( Throwable exc ) {
_logger.log(Level.WARNING,
"jts.unexpected_error_in_begin",exc);
}
}
// If the new Control reference is NULL, raise an error at this point.
if( controlImpl == null ){
INVALID_TRANSACTION exc = new INVALID_TRANSACTION(MinorCode.FactoryFailed,
CompletionStatus.COMPLETED_NO);
throw exc;
}
// Make the new Control reference the current one, indicating that the
// existing one (if any) should be stacked.
else
try {
if(_logger.isLoggable(Level.FINEST))
{
_logger.logp(Level.FINEST,"CurrentImpl","begin()",
"Before invoking CurrentTransaction.setCurrent(control,true)");
}
CurrentTransaction.setCurrent(controlImpl,true);
}
// The INVALID_TRANSACTION exception at this point indicates that the transaction
// may not be started. Clean up the state of the objects in the transaction.
catch( INVALID_TRANSACTION exc ) {
controlImpl.destroy();
throw (INVALID_TRANSACTION)exc.fillInStackTrace();
}
| public void | begin(int time_out)Creates a new Control object, containing new Terminator and Coordinator
objects.
Input parameter timeout value is passed to the Coordinator.
The Control object is made the current one for the thread on which this
method was invoked. If there is already a current Control the existing
Control that represents the parent transaction is stacked behind the new one,
which becomes the current one.
ControlImpl controlImpl = null;
// Until we need to check for resync in progress, synchronize the method.
synchronized(this) {
// If the transaction service is not active, throw an exception.
if( !active ) {
NO_PERMISSION exc = new NO_PERMISSION(0,CompletionStatus.COMPLETED_NO);
throw exc;
}
// Get a reference to the current ControlImpl object.
try {
controlImpl = CurrentTransaction.getCurrent();
} catch( SystemException exc ) {
}
// Release the lock now so that if the TransactionFactoryImpl call has to block
// (during resync), the lock does not prevent other threads from running.
}
// If there is a current Control object, then we should try to begin a
// subtransaction.
if( controlImpl != null )
try {
// Get the Coordinator reference, and use it to create a subtransaction.
// If an exception was raised, return it to the caller.
Coordinator coord = controlImpl.get_coordinator();
// Create a new Control object to represent the subtransaction.
Control control = coord.create_subtransaction();
// This control object may be remote, if the original Control object was.
// In this case we need to deal with it in the same was as we do in the
// resume method. Any exception which is thrown during this process will
// result in SubtransactionsUnavailable thrown to the caller.
JControl jcontrol = JControlHelper.narrow(control);
if( jcontrol != null )
controlImpl = ControlImpl.servant(jcontrol);
// If there is no local ControlImpl object for the transaction, we create one
// now.
if( controlImpl == null )
controlImpl = new ControlImpl(control);
} catch( Throwable exc ) {
SubtransactionsUnavailable ex2 = new SubtransactionsUnavailable();
throw ex2;
}
// If there is no current ControlImpl object, create a new top-level transaction
else {
//$ CurrentTransaction.report();
//$ RecoveryManager.report();
//$ ControlImpl.report();
//$ CoordinatorLog.report();
//$ TimeoutManager.report();
//
try {
// Get the TransactionFactory which should be used from this application.
// This block must be synchronized so that different threads do not try
// this concurrently.
synchronized(this) {
if( factory == null )
factory = Configuration.getFactory();
}
// Create the new transaction.
if (factory != null) {
if(_logger.isLoggable(Level.FINEST))
{
_logger.logp(Level.FINEST,"CurrentImpl","begin()",
"Before invoking create() on TxFactory");
}
if (Configuration.isLocalFactory()) {
controlImpl = ((TransactionFactoryImpl) factory).localCreate(time_out);
} else {
Control control = factory.create(time_out);
// This control object is remote.
// In this case we need to deal with it in the same was as we do in the
// resume method. Any exception which is thrown during this process will
// result in SubtransactionsUnavailable thrown to the caller.
JControl jcontrol = JControlHelper.narrow(control);
if (jcontrol != null) {
controlImpl = ControlImpl.servant(jcontrol);
}
// If there is no local ControlImpl object for the transaction, we create one
// now.
if (controlImpl == null) {
controlImpl = new ControlImpl(control);
}
}
}
} catch( Throwable exc ) {
_logger.log(Level.WARNING,
"jts.unexpected_error_in_begin",exc);
}
}
// If the new Control reference is NULL, raise an error at this point.
if( controlImpl == null ){
INVALID_TRANSACTION exc = new INVALID_TRANSACTION(MinorCode.FactoryFailed,
CompletionStatus.COMPLETED_NO);
throw exc;
}
// Make the new Control reference the current one, indicating that the
// existing one (if any) should be stacked.
else
try {
if(_logger.isLoggable(Level.FINEST))
{
_logger.logp(Level.FINEST,"CurrentImpl","begin()",
"Before invoking CurrentTransaction.setCurrent(control,true)");
}
CurrentTransaction.setCurrent(controlImpl,true);
}
// The INVALID_TRANSACTION exception at this point indicates that the transaction
// may not be started. Clean up the state of the objects in the transaction.
catch( INVALID_TRANSACTION exc ) {
controlImpl.destroy();
throw (INVALID_TRANSACTION)exc.fillInStackTrace();
}
| public void | commit(boolean reportHeuristics)Completes the current transaction.
This operation can only be called if there is a Terminator object available.
// Get the current Control object. If there is none, raise the
// NoTransaction exception and return.
ControlImpl controlImpl = CurrentTransaction.getCurrent();
if( controlImpl == null ) {
NoTransaction exc = new NoTransaction();
throw exc;
}
// Get the local identifier from the Control object. Raise an exception if
// the transaction the Control represents has been completed.
int active = 1;
if( !controlImpl.representsRemoteControl() ) {
StatusHolder status = new StatusHolder();
Long localTID = new Long(controlImpl.getLocalTID(status));
if( status.value != Status.StatusActive ) {
// added (Ram J) to handle asynchronous aborts. If a
// thread calls commit after an asynchronous abort happens,
// end the thread-tx association before throwing
// TRANSACTION_ROLLEDBACK exception.
// In the case where someone had called terminator.commit
// directly successfully, then end the thread association,
// before throwing INVALID_TRANSACTION exception.
CurrentTransaction.endCurrent(true);
if( status.value == Status.StatusRolledBack ) {
TRANSACTION_ROLLEDBACK exc =
new TRANSACTION_ROLLEDBACK(0, CompletionStatus.COMPLETED_NO);
throw exc;
}
INVALID_TRANSACTION exc = new INVALID_TRANSACTION(MinorCode.Completed,
CompletionStatus.COMPLETED_NO);
throw exc;
}
// Check whether there are outstanding requests for this transaction, or
// other active threads.
active = controlImpl.numAssociated();
}
// If this is not the only active thread or there are outstanding requests,
// raise an exception and return.
if( (active != 1) || (controlImpl.isOutgoing()) ) {
if( active != 1 ) {
}
if( controlImpl.isOutgoing() ) {
}
INVALID_TRANSACTION exc = new INVALID_TRANSACTION(MinorCode.DeferredActivities,
CompletionStatus.COMPLETED_NO);
throw exc;
}
// Get the Terminator from the current Control object. If this fails, then
// return whatever exception was raised to the caller.
else {
Terminator term = null;
if (Configuration.isLocalFactory()) {
try {
term = controlImpl.get_localTerminator();
} catch (Throwable exc) {
NO_PERMISSION ex2 = new NO_PERMISSION(0,CompletionStatus.COMPLETED_NO);
throw ex2;
}
} else {
try {
term = controlImpl.get_terminator();
} catch( Throwable exc ) {
NO_PERMISSION ex2 = new NO_PERMISSION(0,CompletionStatus.COMPLETED_NO);
throw ex2;
}
// Tell the Terminator to commit the transaction.
// This will end the current association of the transaction, if the
// Terminator is local. If the Terminator is remote, we end the association
// ourselves, and do not request unstacking as there will be no stacked
// Control.
// End the association if the Terminator is remote. This is done under a
// local environment to ignore any exception. This must be done before
// the Terminator is called otherwise the ControlImpl object will get
// confused.
try {
if( Configuration.getProxyChecker().isProxy(term) )
CurrentTransaction.endCurrent(true);
} catch( Throwable exc ) {}
}
// Commit the transaction.
try{
term.commit(reportHeuristics);
} catch (TRANSACTION_ROLLEDBACK e) {
// ADDED (Ram J) (10/15/01) To handle asynchronous aborts. End
// thread-tx association before re-throwing exception. This is
// because commit/rollback operation by a different thread
// does not set all other thread's control's status to INACTIVE
// anymore, for performance purposes.
CurrentTransaction.endCurrent(true);
throw e;
}
// Free the ControlImpl object.
controlImpl.destroy();
}
| static void | deactivate()Prevents any further transactional activity in the process.
active = false;
| public Control | get_control()Returns the current ControlImpl object.
Control result = null;
// Get the current Control reference from the TransactionManager. If there
// is none, return a NULL pointer.
// If the current Control object indicates that the transaction has ended,
// then the current association will be ended and the TRANSACTION_ROLLEDBACK
// exception will be raised.
ControlImpl control = CurrentTransaction.getCurrent();
if (control != null) {
if (Configuration.isLocalFactory()) {
result = (Control) control;
} else {
result = control.object();
}
}
return result;
| public Status | get_status()Returns the status of the current transaction.
Status result = Status.StatusNoTransaction;
try {
Coordinator coord = CurrentTransaction.getCurrentCoordinator();
// Ask the Coordinator object for its status, and return the value.
if( coord != null )
result = coord.get_status();
} catch( Unavailable exc ) {
} catch( TRANSACTION_ROLLEDBACK exc ) {
result = Status.StatusRolledBack;
} catch( SystemException exc ) {
result = Status.StatusUnknown;
}
return result;
| public int | get_timeout()
return timeOut;
| public java.lang.String | get_transaction_name()Returns a printable string representing the current transaction.
String result = null;
try {
Coordinator coord = CurrentTransaction.getCurrentCoordinator();
// Ask the Coordinator object for its name, and return the value.
if( coord != null )
result = coord.get_transaction_name();
}
// Ignore Unavailable (return null in this case), but allow other exceptions
// to percolate up.
catch( Unavailable exc ) {}
return result;
| public void | resume(Control control)Re-associates the given Control to the calling thread.
If there is already a current ControlImpl, it is replaced as the current one.
ControlImpl contImpl = null;
// If the Control object is NULL, then this operation is actually a suspend
// operation, so end the current association with the thread.
if( control == null )
CurrentTransaction.endCurrent(false);
else {
if (Configuration.isLocalFactory()) {
contImpl = (ControlImpl) control;
} else {
// Check the ControlImpl object is valid.
JControl jcontrol = JControlHelper.narrow(control);
// Try to locate the local ControlImpl object for the transaction.
if( jcontrol != null )
contImpl = ControlImpl.servant(jcontrol);
// If there is no local ControlImpl object for the transaction, we create one
// now.
if( contImpl == null )
try {
contImpl = new ControlImpl(control);
} catch( Exception exc ) {
InvalidControl ex2 = new InvalidControl();
throw ex2;
}
}
// End the current association regardless of whether there is one.
// Attempt to make the given ControlImpl object the current one.
try {
CurrentTransaction.endCurrent(false);
CurrentTransaction.setCurrent(contImpl,false);
if(_logger.isLoggable(Level.FINEST))
{
_logger.logp(Level.FINEST,"CurrentImpl","resume(control)",
"Current thread has been associated with control :"
+contImpl);
}
}
// The INVALID_TRANSACTION exception at this point indicates that the transaction
// may not be resumed.
catch( INVALID_TRANSACTION exc ) {
throw (INVALID_TRANSACTION)exc.fillInStackTrace();
}
}
| public void | rollback()Rolls back the changes performed under the current transaction.
This operation can only be called if there is a Terminator object available.
ControlImpl controlImpl = CurrentTransaction.getCurrent();
if( controlImpl == null ) {
NoTransaction exc = new NoTransaction();
throw exc;
}
// Get the local identifier from the Control object. Raise an exception if
// the transaction the Control represents has been completed.
int active = 1;
if( !controlImpl.representsRemoteControl() ) {
StatusHolder status = new StatusHolder();
Long localTID = new Long(controlImpl.getLocalTID(status));
if( status.value != Status.StatusActive ) {
// added (Ram J) to handle asynchronous aborts. If a
// thread calls rollback after an asynchronous abort happens,
// end the thread-tx association before throwing
// TRANSACTION_ROLLEDBACK exception.
// In the case where someone had called terminator.commit
// directly successfully, then end the thread association,
// before throwing INVALID_TRANSACTION exception.
CurrentTransaction.endCurrent(true);
if( status.value == Status.StatusRolledBack ) {
/* TN - do not throw rollback exception
TRANSACTION_ROLLEDBACK exc = new TRANSACTION_ROLLEDBACK(0,CompletionStatus.COMPLETED_NO);
throw exc;
*/
return;
}
INVALID_TRANSACTION exc = new INVALID_TRANSACTION(MinorCode.Completed,
CompletionStatus.COMPLETED_NO);
throw exc;
}
// Check whether there are outstanding requests for this transaction, or
// other active threads.
active = controlImpl.numAssociated();
}
// If this is not the only active thread or there are outstanding requests,
// raise an exception and return.
if( (active != 1) || (controlImpl.isOutgoing()) ) {
if( active != 1 ) {
}
if( controlImpl.isOutgoing() ) {
}
INVALID_TRANSACTION exc = new INVALID_TRANSACTION(MinorCode.DeferredActivities,
CompletionStatus.COMPLETED_NO);
throw exc;
}
// Get the Terminator from the current Control object. If this fails, then
// return whatever exception was raised to the caller.
else {
Terminator term = null;
if (Configuration.isLocalFactory()) {
try {
term = controlImpl.get_localTerminator();
} catch( Unavailable exc ) {
NO_PERMISSION ex2 = new NO_PERMISSION(0,CompletionStatus.COMPLETED_NO);
throw ex2;
}
} else {
try {
term = controlImpl.get_terminator();
} catch( Unavailable exc ) {
NO_PERMISSION ex2 = new NO_PERMISSION(0,CompletionStatus.COMPLETED_NO);
throw ex2;
}
// Tell the Terminator to roll the transaction back.
// This will end the current association of the transaction, if the
// Terminator is local. If the Terminator is remote, we end the association
// ourselves, and do not request unstacking as there will be no stacked
// Control.
// End the association if the Terminator is remote. This is done under a
// local environment to ignore any exception. This must be done before
// the Terminator is called otherwise the ControlImpl object will get
// confused.
try {
if( Configuration.getProxyChecker().isProxy(term) )
CurrentTransaction.endCurrent(true);
} catch( Throwable exc ) {}
}
// Roll the transaction back.
try{
term.rollback();
} catch (TRANSACTION_ROLLEDBACK e) {
// ADDED (Ram J) (10/15/01) To handle asynchronous aborts. End
// thread-tx association before re-throwing exception. This is
// because commit/rollback operation by a different thread
// does not set all other thread's control's status to INACTIVE
// anymore, for performance purposes.
CurrentTransaction.endCurrent(true);
//throw e; // no need to throw this for rollback operation.
}
// Free the ControlImpl object.
controlImpl.destroy();
}
| public void | rollback_only()Marks the current transaction such that is cannot be committed and only
rolled back.
// Get the reference of the current Coordinator. If there is none, raise the
// NoTransaction exception.
try {
Coordinator coord = CurrentTransaction.getCurrentCoordinator();
// Tell the Coordinator to mark itself rollback-only.
coord.rollback_only();
} catch( Throwable exc ) {
throw new NoTransaction();
}
| public void | set_timeout(int timeout)Sets the timeout value to be used for all subsequent transactions.
// timeout < 0 will be rejected (no op).
// timeout = 0 implies tx has no timeout or a default timeout is used.
// timeout > 0 implies tx will timeout at the end of the duration.
if (timeout >= 0) {
timeOut = timeout;
}
| synchronized void | shutdown(boolean immediate)Shuts down all services.
// Inform the basic transaction services to shutdown.
CurrentTransaction.shutdown(immediate);
| public Control | suspend()Disassociates the current ControlImpl from the calling thread.
Control result = null;
ControlImpl cImpl = CurrentTransaction.endCurrent(false);
if(_logger.isLoggable(Level.FINEST))
{
_logger.logp(Level.FINEST,"CurrentImpl","suspend()",
"Current thread has been disassociated from control :"
+cImpl);
}
if (Configuration.isLocalFactory()) {
result = (Control) cImpl;
} else {
if (cImpl != null) {
result = cImpl.object();
}
}
return result;
|
|