i3.dragos.core.services.transactions.localmgr
Class LocalTransaction

java.lang.Object
  extended by i3.dragos.core.services.transactions.localmgr.LocalTransaction
All Implemented Interfaces:
Transaction

public class LocalTransaction
extends java.lang.Object
implements Transaction

Implements the LocalTransaction to be used with LocalTransactionManager.

Author:
Ernest Hammerschmidt <ernest@i3.informatik.rwth-aachen.de>, Thorsten Hermes <thermes@i3.informatik.rwth-aachen.de>

Nested Class Summary
 
Nested classes/interfaces inherited from interface i3.dragos.core.services.transactions.Transaction
Transaction.State
 
Field Summary
protected  java.util.Map<DataSourceURL,DataSourceTransaction> dataSourceTransactions
          Map of DataSourceURLs to DataSourceTransactions for all data sources we work with.
protected  LocalTransactionManager manager
          The LocalTransactionManager responsible for this transaction.
protected  java.util.LinkedList<LocalTransaction> nestedTransactions
          Child transactions (may be empty, nut is never null).
protected  LocalTransaction parentTransaction
          The parent transaction, may be null if none.
protected  Transaction.State state
          Current state of this transaction.
 
Constructor Summary
protected LocalTransaction(DataSource[] ds, LocalTransaction parentTransaction, LocalTransactionManager mgr)
          Creates a new LocalTransaction.
 
Method Summary
 void begin()
          Starts the scope of a transaction
 void commit()
          Commits the transaction.
protected  void commitHook()
          A hook for subclasses which is called after the commit of any transaction, but before the state is set to (PRE)COMMITTED or any event is fired.
 DataSourceTransaction getDataSourceTransaction(DataSourceURL dataSourceURL)
          Returns the associated DataSourceTransaction for this Transaction (or one of them if this is a distributed transaction).
 java.util.Set<GraphEntity> getDirtyGraphEntities()
          Returns the set of GraphEntities that are currently marked "dirty".
 java.util.Set<GraphEntityClass> getDirtyGraphEntityClasses()
          Returns the set of GraphEntityClasses that are currently marked "dirty".
 java.util.Collection<LocalTransaction> getNestedTransactions()
          Returns a Collection containing the nested transaction (if any).
 LocalTransaction getParentTransaction()
          Returns the parent transaction if this is a nested transaction, null otherwise.
 Transaction.State getState()
          Get the current state of this transaction
 TransactionManager getTransactionManager()
          Get the TransactionManager which manages this transaction.
 boolean isDirty()
          Returns true if there is at least one GraphEntity or GraphEntityClass in the "dirty" sets.
 void markGraphEntitiesDirty(java.util.Collection<GraphEntity> g)
          Adds the Collection of GraphEntities to the "dirty" set.
 void markGraphEntityClassDirty(GraphEntityClass g)
          Adds the specified GraphEntityClass to the "dirty" set.
 void markGraphEntityClassesDirty(java.util.Collection<GraphEntityClass> g)
          Adds the Collection of GraphEntityClasses to the "dirty" set.
 void markGraphEntityDirty(GraphEntity g)
          Adds the specified GraphEntity to the "dirty" set.
protected  void prepareCommitHook()
          A hook for subclasses which is called after the "prepare commit" stage of any transaction, between the first and second phase of the 2-phase-commit protocol.
protected  void propagateState(Transaction.State newState)
          This helper method of commit() and rollback() is responsible for setting the transaction state recursively.
protected  void propagateTransactionEvent(int type)
          This helper method of commit() and rollback() is responsible for firing TransactionEvents for nested transactions recursively in reverse order of creation and finally also for this method.
 void rollback()
          Aborts the transaction, causing a rollback of all nested transactions.
protected  void rollbackHook()
          A hook for subclasses which is called after the rollback of any transaction, but before the state is set to ROLLED_BACK or any event is fired.
 void setRollbackOnly()
          Sets the only possible outcome of this transaction to rollback.
 void unmarkAllGraphEnitiesDirty(DataSourceURL logicalURL)
          Removes all GraphEntity marked as dirty from the dirty set that belong to a GraphPool identified by the (logical) DataSourceURL.
 void unmarkAllGraphEnityClassesDirty(DataSourceURL logicalURL)
          Removes all GraphEntityClass marked as dirty from the dirty set that belong to a GraphPool identified by the (logical) DataSourceURL.
 void unmarkGraphEntitiesDirty(java.util.Collection<GraphEntity> g)
          Bulk version of Transaction.unmarkGraphEntityDirty(GraphEntity).
 void unmarkGraphEntityClassDirty(GraphEntityClass g)
          Removes the specified GraphEntityClass from the "dirty" set of the top-level transcation and all its (grand^*)children (which obviously always includes the transaction this method was called on).
 void unmarkGraphEntityClassesDirty(java.util.Collection<GraphEntityClass> g)
          Bulk version of Transaction.unmarkGraphEntityClassDirty(GraphEntityClass).
 void unmarkGraphEntityDirty(GraphEntity g)
          Removes the specified GraphEntity from the "dirty" set of the top-level transcation and all its (grand^*)children (which obviously always includes the transaction this method was called on).
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

parentTransaction

protected final LocalTransaction parentTransaction
The parent transaction, may be null if none.


manager

protected final LocalTransactionManager manager
The LocalTransactionManager responsible for this transaction.


dataSourceTransactions

protected final java.util.Map<DataSourceURL,DataSourceTransaction> dataSourceTransactions
Map of DataSourceURLs to DataSourceTransactions for all data sources we work with.


nestedTransactions

protected final java.util.LinkedList<LocalTransaction> nestedTransactions
Child transactions (may be empty, nut is never null).


state

protected Transaction.State state
Current state of this transaction.

Constructor Detail

LocalTransaction

protected LocalTransaction(DataSource[] ds,
                           LocalTransaction parentTransaction,
                           LocalTransactionManager mgr)
                    throws TransactionException
Creates a new LocalTransaction.

Parameters:
ds - DataSource to work with.
parentTransaction - parent transaction if any.
mgr - The LocalTransactionManager to work with.
Throws:
TransactionException - if the DataSourceTransaction could not be created.
Method Detail

begin

public void begin()
           throws TransactionException
Starts the scope of a transaction

Specified by:
begin in interface Transaction
Throws:
TransactionException - if the transaction could not be started

rollback

public void rollback()
              throws TransactionException
Aborts the transaction, causing a rollback of all nested transactions.

It can be called on any transaction that is either the current transaction or a (grand^n)parent of the current one. It can be called in all states but Transaction.State.COMMITTED.

If the transaction is already in state Transaction.State.ROLLED_BACK, no action is taken, otherwise this methods proceeds as follows:

  1. Make all nested transactions fire the BEFORE_ROLLBACK TransactionEvent in the reverse order of their creation (youngest transactions fire first) recursively.
  2. Fire the BEFORE_ROLLBACK TransactionEvent for this transaction.
  3. Perform the actual rollback on the datasource.
  4. Change state of this and all nested transactions to Transaction.State.ROLLED_BACK recursively (order is not specified).
  5. Remove this transaction from the parents list of nested transactions.
  6. Make all nested transactions fire the AFTER_ROLLBACK TransactionEvent in the reverse order of their creation (youngest transactions fire first) recursively.
  7. Fire the AFTER_ROLLBACK TransactionEvent for this transaction.

There are some important differences when compared to Transaction.commit(): You can call this method on transactions other than the current one, and only the transaction it is called on actually performs an action on the data source! This avoids the restauration of temporary states that will be discarded anyway, which is not necessary for the checkpoint/savepoint nested transaction implementation commonly found in databases. Of course, nothing prevents the data source transaction from replicating the user transaction hierachy as it is built up, and performing a step-by-step rollback of nested DataSourceTransactions internally.

Specified by:
rollback in interface Transaction
Throws:
TransactionException - if the transaction could not be rolled back

commit

public void commit()
            throws TransactionException
Commits the transaction.

You can only commit a transaction if it is the current one, which implies you have to commit any nested transaction first.

For a top-level transaction, this method performs performs the following steps in order:

  1. Check if this transaction is the current one and in Transaction.State.BEGUN state, throw Exception if not.
  2. Run consistency check on all GraphEntities and GraphEntityClasses marked "dirty" in this transaction or any (directly or indirectly) nested transaction, emptying those lists (see TransactionValidator).
  3. Make all nested transactions fire the BEFORE_COMMIT TransactionEvent in the reverse order of their creation (youngest transactions fire first) recursively.
  4. Fire the BEFORE_COMMIT TransactionEvent for this transaction.
  5. Run consistency check on all GraphEntities and GraphEntityClasses marked "dirty" in this transaction or any (directly or indirectly) nested transaction once more, emptying those lists. This is necessary because the graph data may be changed during event processing.
  6. Perform the actual commit to the datasource.
  7. Change state of this and all nested transactions to Transaction.State.COMMITTED recursively (order is not specified).
  8. Make all nested transactions fire the AFTER_COMMIT TransactionEvent in the reverse order of their creation (youngest transactions fire first) recursively.
  9. Fire the AFTER_COMMIT TransactionEvent for this transaction.

For a nested transaction, a call to this method performs the following steps:

  1. Check if this transaction is the current one and in Transaction.State.BEGUN state, throw Exception if not.
  2. Run consistency check on all GraphEntities and GraphEntityClasses marked "dirty" in this transaction or any (directly or indirectly) nested transaction, not emptying those lists.
  3. Fire the BEFORE_PRECOMMIT TransactionEvent.
  4. Run consistency check on all GraphEntities and GraphEntityClasses marked "dirty" in this transaction or any (directly or indirectly) nested transaction, not emptying those lists.
  5. Perform the actual commit to the datasource.
  6. Change state to Transaction.State.PRECOMMIT.
  7. Fire the AFTER_PRECOMMIT TransactionEvent.

It would be sufficient to restrict the second check to any elements that were changed in response to the BEFORE_PRECOMMIT event, but that would either require several additional methods in this class or temporary removal of checked elements and restauration after event processing, which would have the disadvantage that the list of changed elements would not be available to event listeners. So we consider this premature optimization, thus evil, and forego it for now.

This specification may seem overly detailed and restrictive, but is required to guarantee both consistency in the graph data and in the order of events generated.

Specified by:
commit in interface Transaction
Throws:
TransactionException - if the transaction could not be committed
See Also:
TransactionValidator

propagateTransactionEvent

protected void propagateTransactionEvent(int type)
                                  throws TransactionException
This helper method of commit() and rollback() is responsible for firing TransactionEvents for nested transactions recursively in reverse order of creation and finally also for this method.

Parameters:
type - the type of TransactionEvent to fire.
Throws:
TransactionException - if an exception was thrown during event handling.

propagateState

protected void propagateState(Transaction.State newState)
This helper method of commit() and rollback() is responsible for setting the transaction state recursively.

Parameters:
newState - the new transaction state.

setRollbackOnly

public void setRollbackOnly()
                     throws TransactionException
Sets the only possible outcome of this transaction to rollback. Further calls to this method have no effect. Once set to rollback only, any attempt to commit that transaction will lead to an exception. This only affects the transaction on which the method is called, not the parent transactions (if any). You can use Transaction.getParentTransaction() to set them to rollback only instead (if desired). A TransactionException will be thrown if this transaction is already in state COMMITTED or ROLLED_BACK.

Specified by:
setRollbackOnly in interface Transaction
Throws:
TransactionException - if the transaction could not be set to rollback only.

getState

public Transaction.State getState()
Get the current state of this transaction

Specified by:
getState in interface Transaction
Returns:
the current state

isDirty

public boolean isDirty()
                throws TransactionException
Returns true if there is at least one GraphEntity or GraphEntityClass in the "dirty" sets.

Specified by:
isDirty in interface Transaction
Returns:
true if there is at least one GraphEntity or GraphEntityClass in the "dirty" sets.
Throws:
TransactionException - in case of errors.

markGraphEntityDirty

public void markGraphEntityDirty(GraphEntity g)
                          throws TransactionException
Adds the specified GraphEntity to the "dirty" set. It must be called whenever a GraphEntity is changed.

Specified by:
markGraphEntityDirty in interface Transaction
Parameters:
g - The GraphEntity that was changed.
Throws:
TransactionException - in case of errors.

markGraphEntitiesDirty

public void markGraphEntitiesDirty(java.util.Collection<GraphEntity> g)
                            throws TransactionException
Adds the Collection of GraphEntities to the "dirty" set.

Specified by:
markGraphEntitiesDirty in interface Transaction
Parameters:
g - The GraphEntities that were changed.
Throws:
TransactionException - in case of errors.

unmarkGraphEntityDirty

public void unmarkGraphEntityDirty(GraphEntity g)
                            throws TransactionException
Removes the specified GraphEntity from the "dirty" set of the top-level transcation and all its (grand^*)children (which obviously always includes the transaction this method was called on). This extension of scope is necessary because the entity may already have appeared in the dirty list of a previous (nested) transaction, which would result in a stale reference access by TransactionValidator if that entry was not also removed.

It must be called whenever a GraphEntityClass previously marked dirty is deleted or for other reasons does not need to be checked anymore. If the object in question is a valid argument but was not marked before, this call will have no effect (especially it will not throw an exception).

Specified by:
unmarkGraphEntityDirty in interface Transaction
Parameters:
g - The GraphEntity that was changed.
Throws:
TransactionException - in case of errors.

unmarkGraphEntitiesDirty

public void unmarkGraphEntitiesDirty(java.util.Collection<GraphEntity> g)
                              throws TransactionException
Bulk version of Transaction.unmarkGraphEntityDirty(GraphEntity).

Specified by:
unmarkGraphEntitiesDirty in interface Transaction
Parameters:
g - The GraphEntityClasses that were changed.
Throws:
TransactionException - in case of errors.

markGraphEntityClassDirty

public void markGraphEntityClassDirty(GraphEntityClass g)
                               throws TransactionException
Adds the specified GraphEntityClass to the "dirty" set. It must be called whenever a GraphEntityClass is changed.

Specified by:
markGraphEntityClassDirty in interface Transaction
Parameters:
g - The GraphEntityClass that was changed.
Throws:
TransactionException - in case of errors.

markGraphEntityClassesDirty

public void markGraphEntityClassesDirty(java.util.Collection<GraphEntityClass> g)
                                 throws TransactionException
Adds the Collection of GraphEntityClasses to the "dirty" set.

Specified by:
markGraphEntityClassesDirty in interface Transaction
Parameters:
g - The GraphEntityClasses that were changed.
Throws:
TransactionException - in case of errors.

unmarkGraphEntityClassDirty

public void unmarkGraphEntityClassDirty(GraphEntityClass g)
                                 throws TransactionException
Removes the specified GraphEntityClass from the "dirty" set of the top-level transcation and all its (grand^*)children (which obviously always includes the transaction this method was called on). This extension of scope is necessary because the entity class may already have appeared in the dirty list of a previous (nested) transaction, which would result in a stale reference access by TransactionValidator if that entry was not also removed.

It must be called whenever a GraphEntityClass previously marked dirty is deleted or for other reasons does not need to be checked anymore. If the object in question is a valid argument but was not marked before, this call will have no effect (especially it will not throw an exception).

Specified by:
unmarkGraphEntityClassDirty in interface Transaction
Parameters:
g - The GraphEntityClass that was changed.
Throws:
TransactionException - in case of errors.

unmarkGraphEntityClassesDirty

public void unmarkGraphEntityClassesDirty(java.util.Collection<GraphEntityClass> g)
                                   throws TransactionException
Bulk version of Transaction.unmarkGraphEntityClassDirty(GraphEntityClass).

Specified by:
unmarkGraphEntityClassesDirty in interface Transaction
Parameters:
g - The GraphEntityClasses that were changed.
Throws:
TransactionException - in case of errors.

getDirtyGraphEntities

public java.util.Set<GraphEntity> getDirtyGraphEntities()
                                                 throws TransactionException
Returns the set of GraphEntities that are currently marked "dirty". The returned Collection may be empty, but never null. The returned set is not a copy, but a direct reference, so it may be manipulated. This should only be done by the consistency checkers, only to remove elements that have been checked, and only when proper synchronization is ensured through a lock. For adding elements, use the Transaction.markGraphEntityDirty(GraphEntity) method.

Specified by:
getDirtyGraphEntities in interface Transaction
Returns:
the set of GraphEntities that are currently marked "dirty".
Throws:
TransactionException - in case of errors.

getDirtyGraphEntityClasses

public java.util.Set<GraphEntityClass> getDirtyGraphEntityClasses()
                                                           throws TransactionException
Returns the set of GraphEntityClasses that are currently marked "dirty". The returned Collection may be empty, but never null. The returned set is not a copy, but a direct reference, so it may be manipulated. This should only be done by the consistency checkers, only to remove elements that have been checked, and only when proper synchronization is ensured through a lock. For adding elements, use the Transaction.markGraphEntityClassDirty(GraphEntityClass) method.

Specified by:
getDirtyGraphEntityClasses in interface Transaction
Returns:
the set of GraphEntityClasses that are currently marked "dirty".
Throws:
TransactionException - in case of errors.

unmarkAllGraphEnitiesDirty

public void unmarkAllGraphEnitiesDirty(DataSourceURL logicalURL)
                                throws TransactionException
Removes all GraphEntity marked as dirty from the dirty set that belong to a GraphPool identified by the (logical) DataSourceURL. This concernes the top-level transaction's dirty set as well as the transitive closure of its children. Its main use is for the 'shortcut' GraphPool.clear(boolean) semantics removing all elements at once.

Specified by:
unmarkAllGraphEnitiesDirty in interface Transaction
Parameters:
logicalURL - URL of the GraphPool the elements are removed from.
Throws:
TransactionException - in case of errors.

unmarkAllGraphEnityClassesDirty

public void unmarkAllGraphEnityClassesDirty(DataSourceURL logicalURL)
                                     throws TransactionException
Removes all GraphEntityClass marked as dirty from the dirty set that belong to a GraphPool identified by the (logical) DataSourceURL. This concernes the top-level transaction's dirty set as well as the transitive closure of its children. Its main use is for the 'shortcut' GraphPool.clear(boolean) semantics removing all elements at once.

Specified by:
unmarkAllGraphEnityClassesDirty in interface Transaction
Parameters:
logicalURL - URL of the GraphPool the elements are removed from.
Throws:
TransactionException - in case of errors.

getTransactionManager

public TransactionManager getTransactionManager()
Get the TransactionManager which manages this transaction.

Specified by:
getTransactionManager in interface Transaction
Returns:
the TransactionManager which manages this transaction.

getParentTransaction

public LocalTransaction getParentTransaction()
Returns the parent transaction if this is a nested transaction, null otherwise.

Specified by:
getParentTransaction in interface Transaction
Returns:
the parent transaction if this is a nested transaction, null otherwise.

getNestedTransactions

public java.util.Collection<LocalTransaction> getNestedTransactions()
                                                             throws TransactionException
Returns a Collection containing the nested transaction (if any).

The returned Collection must not be a reference to any internal data structure or shared between method calls, but a newly allocated copy, so the caller can safely read and modify it.

Specified by:
getNestedTransactions in interface Transaction
Returns:
A Collection containing the nested transaction (may be empty, but not null).
Throws:
TransactionException - in case of internal errors.

getDataSourceTransaction

public DataSourceTransaction getDataSourceTransaction(DataSourceURL dataSourceURL)
Returns the associated DataSourceTransaction for this Transaction (or one of them if this is a distributed transaction). This method should only be used by the GM implementation, not by the user application.

Specified by:
getDataSourceTransaction in interface Transaction
Parameters:
dataSourceURL - The DataSource for which you want to get the transaction.
Returns:
The corresponding DataSourceTransaction for the specified DataSource, or null if none.

commitHook

protected void commitHook()
                   throws TransactionException
A hook for subclasses which is called after the commit of any transaction, but before the state is set to (PRE)COMMITTED or any event is fired.

Throws:
TransactionException - in case of errors.

prepareCommitHook

protected void prepareCommitHook()
                          throws TransactionException
A hook for subclasses which is called after the "prepare commit" stage of any transaction, between the first and second phase of the 2-phase-commit protocol.

Throws:
TransactionException - in case of errors.

rollbackHook

protected void rollbackHook()
                     throws TransactionException
A hook for subclasses which is called after the rollback of any transaction, but before the state is set to ROLLED_BACK or any event is fired.

Throws:
TransactionException - in case of errors.


Copyright © 2002-2008 RWTH Aachen, Department of Computer Science 3 (Software Engineering). All Rights Reserved.