1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
|
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">
<chapter>
<header>
<copyright>
<year>1999</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
</legalnotice>
<title>cosTransactions Examples</title>
<prepared></prepared>
<docno></docno>
<date>1999-04-27</date>
<rev>A</rev>
<file>ch_example.xml</file>
</header>
<section>
<title>A Tutorial on How to Create a Simple Service</title>
<section>
<title>Interface design</title>
<p>To use the cosTransactions application <em>participants</em> must be implemented.
There are two types of participants: </p>
<list type="bulleted">
<item><seealso marker="CosTransactions_Resource">CosTransactions_Resource</seealso> - operations used to commit or rollback resources.</item>
<item><seealso marker="CosTransactions_SubtransactionAwareResource">CosTransactions_SubtransactionAwareResource</seealso> -
operations used when the resources want to be notified when a subtransaction commits.
This interface inherits the CosTransactions_Resource</item>
</list>
<p>The interfaces for these participants are defined in <em>CosTransactions.idl</em></p>
</section>
<section>
<title>Generating a Participant Interface</title>
<p>We start by creating an interface which inherits from <em>CosTransactions::Resource</em>. Hence,
we must also implement all operations defined in the Resource interface. The IDL-file could look like: </p>
<code type="c"><![CDATA[
#ifndef _OWNRESOURCEIMPL_IDL
#define _OWNRESOURCEIMPL_IDL
#include <CosTransactions.idl>
module ownResourceImpl {
interface ownInterface:CosTransactions::Resource {
void ownFunctions(in any NeededArguments)
raises(Systemexceptions,OwnExceptions);
};
};
#endif
]]></code>
<p>Run the IDL compiler on this file by calling the <c>ic:gen/1</c> function.
This will produce the API named <c>ownResourceImpl_ownInterface.erl</c>.
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 <c>ownResourceImpl_ownInterface_impl.erl</c>.</p>
</section>
<section>
<title>Implementation of Participant interface</title>
<p>If the participant is intended to be a plain Resource, we must implement the following operations:</p>
<list type="bulleted">
<item><c>prepare/1</c> - this operation is invoked on the Resource to begin the two-phase commit protocol.</item>
<item><c>rollback/1</c> - this operation instructs the Resource to rollback all changes made as a part of the transaction. </item>
<item><c>commit/1</c> - this operation instructs the Resource to commit all changes made as a part of the transaction.</item>
<item><c>commit_one_phase/1</c> - if possible, the Resource should commit all changes made as part of the transaction.
This operation can only be used if the Resource is the only child of its parent. </item>
<item><c>forget/1</c> - this operation informs the Resource that it is safe to forget any
<term id="Heuristic decisions"><termdef>Heuristic decisions is a unilateral decision by a participant to commit
or rollback without receiving the true outcome of the transaction from its parent's coordinator.</termdef></term>
and the knowledge of the transaction.</item>
<item><c>ownFunctions</c> - all application specific operations.</item>
</list>
<p>If the participant wants to be notified when a subtransaction commits, we must also implement the following operations
(besides the operations above):</p>
<list type="bulleted">
<item><c>commit_subtransaction/2</c> - if the <c>SubtransactionAwareResource</c> have been registered
with a transactions using the operation <c>CosTransactions_Coordinator:register_subtran_aware/2</c> it will
be notified when the transaction has
committed. </item>
<item><c>rollback_subtransaction/1</c> - if the <c>SubtransactionAwareResource</c> have been registered
with a transactions using the operation <c>CosTransactions_Coordinator:register_subtran_aware/2</c>
it will be notified when the transaction has
rolled back. </item>
</list>
<note>
<p>The results of a committed subtransaction are relative to the completion of its ancestor transactions,
that is, these results can be undone if any ancestor transaction is rolled back. </p>
</note>
</section>
<section>
<title>Participant Operations Behavior</title>
<p>Each application participant must behave in a certain way to ensure that the two-phase commit protocol
can complete the transactions correctly.</p>
<section>
<title>prepare</title>
<p>This operation ask the participant to vote on the outcome of the transaction. Possible replies are:</p>
<list type="bulleted">
<item><em>'VoteReadOnly'</em> - if no data associated with the transaction has been modified VoteReadOnly may be returned.
The Resource can forget all knowledge of the transaction and terminate.</item>
<item><em>'VoteCommit'</em> - if the Resource is able to write all the data needed to commit the transaction to a stable storage,
VoteCommit may be returned. The Resource will then wait until it is informed of the outcome of the transaction.
The Resource may, however, make a unilateral decision (Heuristic) to commit or rollback changes associated
with the transaction. When the Resource is informed of the true outcome (rollback/commit) and it is equal to
the Heuristic decision the Resource just return 'ok'. But, if there is a mismatch and the commit-operation is irreversible,
the Resource must raise a <seealso marker="CosTransactions_Resource">Heuristic Exception</seealso> and wait
until the <c>forget</c> operation is invoked. The Heuristic Decision must be recorded in stable storage.</item>
<item><em>'VoteRollback'</em> - the Resource may vote VoteRollback under any circumstances.
The Resource can forget all knowledge of the transaction and terminate.</item>
</list>
<note>
<p>Before replying to the prepare operation, the Resource must record the prepare state, the reference of its
superior <seealso marker="CosTransactions_RecoveryCoordinator">RecoveryCoordinator</seealso> in stable storage.
The RecoveryCoordinator is obtained when registering as a participant in a transaction.</p>
</note>
</section>
<section>
<title>rollback</title>
<p>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.</p>
</section>
<section>
<title>commit</title>
<p>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.</p>
</section>
<section>
<title>commit_one_phase</title>
<p>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.</p>
</section>
<section>
<title>forget</title>
<p>If the Resource raised a Heuristic Exception to <c>commit</c>, <c>rollback</c> or <c>commit_one_phase</c> this operation
will be performed. The Resource can forget all knowledge of the transaction and terminate.</p>
</section>
<section>
<title>commit_subtransaction</title>
<p>If the <c>SubtransactionAwareResource</c> have been registered with a <em>subtransaction</em>
using the operation <c>CosTransactions_Coordinator:register_subtran_aware/2</c>
it will be notified when the transaction has committed. The Resource may raise the exception
<c>'TRANSACTION_ROLLEDBACK'</c>.</p>
<note>
<p>The result of a committed subtransaction is relative to the completion of its ancestor
transactions, that is, these results can be undone if any ancestor transaction is rolled back.</p>
</note>
</section>
<section>
<title>rollback_subtransaction</title>
<p>If the <c>SubtransactionAwareResource</c> have been registered with a <em>subtransaction</em>
using the operation <c>CosTransactions_Coordinator:register_subtran_aware/2</c>
it will be notified when the subtransaction has rolled back.</p>
</section>
</section>
<section>
<title>How to Run Everything</title>
<p>Below is a short transcript on how to run cosTransactions. </p>
<code type="none">
%% 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)),
</code>
<note>
<p>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.</p>
</note>
<p>The outcome of the transaction can be:</p>
<list type="bulleted">
<item>ok - the transaction was successfully committed.</item>
<item>{'EXCEPTION', HeuristicExc} - at least one participant made a
Heuristic decision or, due to a failure, one or more participants
where unreachable.</item>
<item>{'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{}} -
the transaction was successfully rolled back.</item>
<item>Any system exception -
the transaction failed with unknown reason.</item>
</list>
</section>
</section>
</chapter>
|