i3.dragos.core.services.transactions
Interface Transaction

All Known Implementing Classes:
LocalTransaction

public interface Transaction

Specifies transactions to be used with the transaction management service. These are the transactions to be used by the application, each mapping to one or more (in case of nested or distributed transactions) DataSourceTransactions.

Transactions maintain two lists of GraphEntities and GraphEntityClasses marked "dirty", indicating that there have been changes to these since the last consistency check. These lists are typically filled by the EventManager (who because of practical reasons also serves in this role), and cleared by the consistency checkers. While it is preferable to realize those lists as a Set (in the Set sense) to reduce memory consumption and time for consistency checking, and the documentation refers to them as sets, neither the interface nor the specification forces you to do so.

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

Nested Class Summary
static class Transaction.State
          Specifies the different state transactions can be in.
 
Method Summary
 void begin()
          Starts the scope of a transaction
 void commit()
          Commits the transaction.
 DataSourceTransaction getDataSourceTransaction(DataSourceURL dataSourceURL)
          Returns the associated DataSourceTransaction for this Transaction (or one of them if this is a distributed transaction).
 java.util.Collection<GraphEntity> getDirtyGraphEntities()
          Returns the set of GraphEntities that are currently marked "dirty".
 java.util.Collection<GraphEntityClass> getDirtyGraphEntityClasses()
          Returns the set of GraphEntityClasses that are currently marked "dirty".
 java.util.Collection<? extends Transaction> getNestedTransactions()
          Returns a Collection containing the nested transaction (if any).
 Transaction 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.
 void rollback()
          Aborts the transaction, causing a rollback of all nested transactions.
 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 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 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).
 

Method Detail

begin

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

Throws:
TransactionException - if the transaction could not be started

rollback

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 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.

Throws:
TransactionException - if the transaction could not be rolled back

commit

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.

Throws:
TransactionException - if the transaction could not be committed
See Also:
TransactionValidator

setRollbackOnly

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 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.

Throws:
TransactionException - if the transaction could not be set to rollback only.

getState

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

Returns:
the current state
Throws:
TransactionException - in case of internal errors.

markGraphEntityDirty

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

Parameters:
g - The GraphEntity that was changed.
Throws:
TransactionException - in case of errors.

markGraphEntitiesDirty

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

Parameters:
g - The GraphEntities that were changed.
Throws:
TransactionException - in case of errors.

unmarkGraphEntityDirty

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).

Parameters:
g - The GraphEntity that was changed.
Throws:
TransactionException - in case of errors.

unmarkGraphEntitiesDirty

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

Parameters:
g - The GraphEntityClasses that were changed.
Throws:
TransactionException - in case of errors.

markGraphEntityClassDirty

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

Parameters:
g - The GraphEntityClass that was changed.
Throws:
TransactionException - in case of errors.

markGraphEntityClassesDirty

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

Parameters:
g - The GraphEntityClasses that were changed.
Throws:
TransactionException - in case of errors.

unmarkGraphEntityClassDirty

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).

Parameters:
g - The GraphEntityClass that was changed.
Throws:
TransactionException - in case of errors.

unmarkGraphEntityClassesDirty

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

Parameters:
g - The GraphEntityClasses that were changed.
Throws:
TransactionException - in case of errors.

unmarkAllGraphEnitiesDirty

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.

Parameters:
logicalURL - URL of the GraphPool the elements are removed from.
Throws:
TransactionException - in case of errors.

unmarkAllGraphEnityClassesDirty

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.

Parameters:
logicalURL - URL of the GraphPool the elements are removed from.
Throws:
TransactionException - in case of errors.

isDirty

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

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

getDirtyGraphEntities

java.util.Collection<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 markGraphEntityDirty(GraphEntity) method.

Returns:
the set of GraphEntities that are currently marked "dirty".
Throws:
TransactionException - in case of errors.

getDirtyGraphEntityClasses

java.util.Collection<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 markGraphEntityClassDirty(GraphEntityClass) method.

Returns:
the set of GraphEntityClasses that are currently marked "dirty".
Throws:
TransactionException - in case of errors.

getTransactionManager

TransactionManager getTransactionManager()
                                         throws TransactionException
Get the TransactionManager which manages this transaction.

Returns:
the TransactionManager which manages this transaction.
Throws:
TransactionException - in case of errors.

getParentTransaction

Transaction getParentTransaction()
                                 throws TransactionException
Returns the parent transaction if this is a nested transaction, null otherwise.

Returns:
the parent transaction if this is a nested transaction, null otherwise.
Throws:
TransactionException - in case of internal errors.

getNestedTransactions

java.util.Collection<? extends Transaction> 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.

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

getDataSourceTransaction

DataSourceTransaction getDataSourceTransaction(DataSourceURL dataSourceURL)
                                               throws TransactionException
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.

Parameters:
dataSourceURL - The DataSource for which you want to get the transaction.
Returns:
The corresponding DataSourceTransaction for the specified DataSource, or null if none.
Throws:
TransactionException - in case of errors.


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