VisiTransact Guide : Implementing Synchronization objects

Implementing Synchronization objects
This section provides information about how you can implement Synchronization objects.
What are Synchronization objects?
A Synchronization object enables an object to be notified before the start of, and after the end of, the transaction's completion. The figure below shows how typical Synchronization objects fit into the architecture of a transactional application.
Figure 18
The before_completion() method is invoked after the application invokes commit(), but before the VisiTransact Transaction Service begins transaction completion. The before_completion() method is not invoked for a rollback request. The after_completion() method is always invoked during normal processing.
Synchronization objects are not recoverable. If an instance of the VisiTransact Transaction Service fails, Synchronization objects will not be contacted.
Using Synchronization objects before the commit protocol
With the before_completion() method, Synchronization objects can perform processing after the work of a transaction has been done, but before the commit protocol starts (i.e. before prepare() or commit_one_phase). For example, you can:
Improve performance. You can cache changes during interactions with a transactional object, and then use the Synchronization object to flush the changes to disk, and even register a Resource. The advantage is that you do not have a Resource object or an open database connection until you need one.
Trigger additional work. For example, you can write a record to an audit database and register that database as a Resource from the Synchronization object.
Check the transaction's integrity. You can verify that all of the necessary operations were performed. For example, you might verify that the balance of an account was updated, and that the balance change was recorded in a history table.
Using Synchronization objects after rollback or commit
With the after_completion() method, Synchronization objects can do work after the transaction has been completed; that is, after the Terminator tells Resources to commit(), rollback(), or commit_one_phase(). You might use Synchronization objects to perform the following types of actions:
Perform cleanup. For example, you might release memory objects.
Notify other processes of the transaction completion. For example, the Synchronization object might send the results of the transaction as an event to an event channel, or communicate the results of the transaction to another object whose processing depends on the outcome of the transaction. The status condition is either StatusCommitted or StatusRolledBack.
Registering Synchronization objects
You register a Synchronization object with the CosTransactions::Coordinator using one of the following methods:
Irrespective of whether the transactional application uses VisiTransact-managed or explicitly propagated transactions, the VisiTransact Transaction Service uses implicit propagation to pass transaction information to Synchronization objects.
When a Synchronization object has been registered and a request to commit the transaction is made, the Terminator automatically invokes before_completion() on any Synchronization objects before actually performing the completion. You determine what happens during the before_completion() invocation from within your Synchronization object. When all registered Synchronization objects have completed, the Terminator proceeds with its transaction completion. A rollback can be ensured by invoking rollback_only() (on the VISTransactions::Current or CosTransactions::Coordinator) from a before_completion() method. Additionally, any exception thrown by a before_completion() method (including CORBA::TRANSACTION_ROLLEDBACK) will cause the transaction to be rolled back.
If any of the Synchronization objects mark the transaction for rollback, the Terminator stops invoking before_completion() on the remaining Synchronization objects. Because any Synchronization object can invoke rollback_only(), invoking commit() does not guarantee the transaction will commit.
The next time the Terminator interacts with Synchronization objects is after transaction completion; that is, it has received all commit(), commit_one_phase(), or rollback() responses from Resource objects. At this time, the Terminator automatically invokes after_completion() on all registered Synchronization objects and passes them the transaction outcome as status. You determine what happens during the after_completion() invocation from within your Synchronization object.
The following figure shows a time line for the various invocations during the two-phase commit process when Synchronization objects involved.
Figure 19
How failures affect Synchronization objects
If a Synchronization object is unavailable when the Terminator attempts to invoke its before_completion() method, the transaction will be rolled back. Any Synchronization objects that have not been contacted will not have before_completion() invoked on them. If any Synchronization object is unavailable when the VisiTransact Transaction Service tries to invoke after_completion(), it is ignored.
When the VisiTransact Transaction Service instance recovers, it does not remember Synchronization objects, and will only replay completion and not Synchronization objects.
The role of Synchronization objects in transaction objects
If you want your transactional object to be notified of the outcome of a transaction, it must provide a Synchronization interface. The VisiTransact Transaction Service notifies Synchronization objects of how a transaction completed when it invokes the after_completion() method.