[Ericsson AB]

4 cosTransactions Examples

4.1 A Tutorial on How to Create a Simple Service

4.1.1 Interface design

To use the cosTransactions application participants must be implemented. There are two types of participants:

The interfaces for these participants are defined in CosTransactions.idl

4.1.2 Generating a Participant Interface

We start by creating an interface which inherits from CosTransactions::Resource. Hence, we must also implement all operations defined in the Resource interface. The IDL-file could look like:

#ifndef _OWNRESOURCEIMPL_IDL
#define _OWNRESOURCEIMPL_IDL
#include <CosTransactions.idl>

module ownResourceImpl {

  interface ownInterface:CosTransactions::Resource {

    void ownFunctions(in any NeededArguments)
       raises(Systemexceptions,OwnExceptions);

  };
};

#endif
      

Run the IDL compiler on this file by calling the ic:gen/1 function. This will produce the API named ownResourceImpl_ownInterface.erl. After generating the API stubs and the server skeletons it is time to implement the servers and if no special options are sent to the IDl compiler the file name is ownResourceImpl_ownInterface_impl.erl.

4.1.3 Implementation of Participant interface

If the participant is intended to be a plain Resource, we must implement the following operations:

If the participant wants to be notified when a subtransaction commits, we must also implement the following operations (besides the operations above):

Note!

The results of a commited subtransaction are reltive to the completion of its ancestor transactions, that is, these results can be undone if any ancestor transaction is rolled back.

4.1.4 Particapant Operations Behavior

Each application participant must behave in a certain way to ensure that the two-phase commit protocol can complete the transactions correctly.

4.1.4.1 prepare

This operation ask the participant to vote on the outcome of the transaction. Possible replies are:

Note!

Before replying to the prepare operation, the Resource must record the prepare state, the reference of its superior RecoveryCoordinator in stable storage. The RecoveryCoordinator is obtained when registering as a participant in a transaction.

4.1.4.2 rollback

The Resource should, if necessary, rollback all changes made as part of the transaction. If the Resource is not aware of the transaction it should do nothing, e.g., recovered after a failure and have no data in stable storage. Heuristic Decisions must be handled as described above.

4.1.4.3 commit

The Resource should, if necessary, commit all changes made as part of the transaction. If the Resource is not aware of the transaction it should do nothing, e.g., recovered after a failure and have no data in stable storage. Heuristic Decisions must be handled as described above.

4.1.4.4 commit_one_phase

If possible, the Resource should commit all changes made as part of the transaction. If it cannot, it should raise the TRANSACTION_ROLLEDBACK exception. This operation can only be used if the Resource is the only child of its parent. If a failure occurs the completion of the operation must be retried when the failure is repaired. Heuristic Decisions must be handled as described above.

4.1.4.5 forget

If the Resource raised a Heuristic Exception to commit, rollback or commit_one_phase this operation will be performed. The Resource can forget all knowledge of the transaction and terminate.

4.1.4.6 commit_subtransaction

If the SubtransactionAwareResource have been registered with a subtransaction using the operation CosTransactions_Coordinator:register_subtran_aware/2 it will be notified when the transaction has committed. The Resource may raise the exception 'TRANSACTION_ROLLEDBACK'.

Note!

The result of a commited subtransaction is reltive to the completion of its ancestor transactions, that is, these results can be undone if any ancestor transaction is rolled back.

4.1.4.7 rollback_subtransaction

If the SubtransactionAwareResource have been registered with a subtransaction using the operation CosTransactions_Coordinator:register_subtran_aware/2 it will be notified when the subtransaction has rolled back.

4.1.5 How to Run Everything

Below is a short transcript on how to run cosTransactions.


%% Start Mnesia and Orber
mnesia:delete_schema([node()]),
mnesia:create_schema([node()]),
orber:install([node()]),
application:start(mnesia),
application:start(orber),

%% Register CosTransactions in the IFR.
'oe_CosTransactions':'oe_register'(), 

%% Register the application specific Resource implementations
%% in the IFR.
'oe_ownResourceImpl':'oe_register'(), 

%%-- Set parameters --
%% Timeout can be either 0 (no timeout) or an integer N > 0.
%% The later state that the transaction should be rolled 
%% back if the transaction have not completed within N seconds.
TimeOut = 0,

%% Do we want the transaction to report Heuristic Exceptions?
%% This variable must be boolean and indicates the way the
%% Terminator should behave.
Heuristics = true,

%% Start the cosTransactions application.
cosTransactions:start(),  %% or application:start(cosTransactions),

%% Start a factory using the default configuration
TrFac = cosTransactions:start_factory(),
%% ... or use configuration parameters.
TrFac = cosTransactions:start_factory([{typecheck, false}, {hash_max, 3013}]),

%% Create a new top-level transaction.
Control = 'CosTransactions_TransactionFactory':create(TrFac, TimeOut),

%% Retrieve the Coordinator and Terminator object references from
%% the Control Object.
Term = 'CosTransactions_Control':get_terminator(Control),
Coord = 'CosTransactions_Control':get_coordinator(Control),

%% Create two SubTransactions with the root-Coordinator as parent.
SubCont1 = 'CosTransactions_Coordinator':create_subtransaction(Coord),
SubCont2 = 'CosTransactions_Coordinator':create_subtransaction(Coord),

%% Retrieve the Coordinator references from the Control Objects.
SubCoord1 = 'CosTransactions_Control':get_coordinator(SubCont1),
SubCoord2 = 'CosTransactions_Control':get_coordinator(SubCont2),

%% Create application Resources. We can, for example, start the Resources 
%% our selves or look them up in the naming service. This is application
%% specific.
Res1 = ...
Res2 = ...
Res3 = ...
Res4 = ...

%% Register Resources with respective Coordinator. Each call returns
%% a RecoveryCoordinator object reference.
RC1 = 'CosTransactions_Coordinator':register_resource(SubCoord1, Res1),
RC2 = 'CosTransactions_Coordinator':register_resource(SubCoord1, Res2),
RC3 = 'CosTransactions_Coordinator':register_resource(SubCoord2, Res3),
RC4 = 'CosTransactions_Coordinator':register_resource(SubCoord2, Res4),

%% Register Resource 4 with SubCoordinator 1 so that the Resource will be 
%% informed when the SubCoordinator commits or roll-back.
'CosTransactions_Coordinator':register_subtran_aware(SubCoord1, Res4),

%% We are now ready to try to commit the transaction. The second argument
%% must be a boolean
Outcome = (catch 'CosTransactions_Terminator':commit(Term, Heuristics)),
      

Note!

For the cosTransaction application to be able to recognize if a Resource is dead or in the process of restarting the Resource must be started as persistent, e.g., 'OwnResource':oe_create_link(Env, [{regname, {global, RegName}}, {persistent, true}]). For more information see the Orber documentation.

The outcome of the transaction can be:


Copyright © 1991-2006 Ericsson AB