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
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
|
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<title>Introduction - Improving the Server</title>
<!-- -->
</head>
<BODY text = "#000000"
link="#000fff"
vlink="#ff0f0f"
bgcolor="#ffffff">
<h3>Introduction - Improving the Server</h3>
<P>In this section we will improve over the
<A HREF="../Server/index.html">simple server</A> described
before.
We will discuss how to use POA policies to assign our own object
ids.
</P>
<P>In our previous example we used two fields of the
<CODE>Quoter_Stock_Factory_i</CODE> to represent the stock quotes.
If we wish to create hundreds of stock objects this approach
would not scale. We need to use some collection to keep track of
the Stock objects, possibly indexed by the stock symbol.
One solution is to use an STL map or something similar, but this
is clearly wasteful. After all, the ORB is also keeping a
collection of objects, indexed by the object ids.
If we only could choose the ids ourselves, then our problem would
be solved.
The good news is that the POA allows this,
the bad news is that we must create a child POA for that.
Why? Because the Root POA ids are assigned by the ORB, and we
don't want to conflict with those.
Furthermore, creating a separate POA is easier to manage, as
multiple components of the application can get their own POA,
that they can treat as a private namespace.
</P>
<H3>Child POA creation</H3>
<P>As before, we gain access to the RootPOA:
</P>
<PRE>
CORBA::Object_var poa_object =
orb->resolve_initial_references ("RootPOA");
PortableServer::POA_var poa =
PortableServer::POA::_narrow (poa_object.in ());
</PRE>
<P>Now we create the policies for the child poa.
In this case we want the <CODE>USER_ID</CODE> policy so we can
assign our own ids.
We also want the <CODE>NO_IMPLICIT_ACTIVATION</CODE> policy, to
have more control over additions to our POA.
The POA has more policies that we can control, but we will use
the defaults in this example.
There are many examples in <CODE>$TAO_ROOT/examples/POA/</CODE> that
show how to use other policies in the POA.
</P>
<P>The policies are stored in a sequence, so we first create the
sequence and initialize its length:
</P>
<PRE>
CORBA::PolicyList policies (2);
policies.length (2);
</PRE>
<P>now we create the policies:
</P>
<PRE>
policies[0] =
poa->create_id_assignment_policy (PortableServer::USER_ID);
policies[1] =
poa->create_implicit_activation_policy (PortableServer::NO_IMPLICIT_ACTIVATION);
</PRE>
<P>now we can create the child POA;
</P>
<PRE>
PortableServer::POA_var stock_factory_poa =
poa->create_POA ("Stock_Factory_POA",
poa_manager.in (),
policies);
</PRE>
<P>Notice that we shared the POA manager with the RootPOA, so we
only need to use a single POA manager to control the state of
both.
The new POA makes a copy of the policies, so we need to destroy
them to avoid memory leaks:
</P>
<PRE>
for (CORBA::ULong i = 0; i != policies.length (); ++i) {
policies[i]->destroy ();
}
</PRE>
<H3>Activating objects in the child POA</H3>
<P>Now we must use this POA to activate the stock objects.
To keep the example simple, we will assume that we read the list
of stocks from the stdin, as in:
</P>
<PRE>
while (!std::cin.eof () && std::cin.peek () != EOF) {
const int max_symbol_length = 8;
char symbol[max_symbol_length];
const int max_full_name_length = 64;
char full_name[max_full_name_length];
double price;
std::cin.getline (symbol, max_symbol_length, '\n');
std::cin.getline (full_name, max_full_name, '\n');
std::cin >> price;
std::cin.ignore (1, '\n');
// The interesting stuff goes here!
}
</PRE>
<P>For each trio of symbol, full name, and price, we create a stock
implementation object:
</P>
<PRE>
PortableServer::ServantBase_var servant =
new Quoter_Stock_i (symbol, full_name, price);
</PRE>
<P>The <CODE>ServantBase_var</CODE> acts like an auto pointer and
will take care of deallocation in case there is an exception.
This time we cannot use <CODE>_this()</CODE> to activate the servant
though, because we want to create our own ids:
</P>
<PRE>
PortableServer::ObjectId_var oid =
PortableServer::string_to_ObjectId (symbol);
</PRE>
<P>and then activate the object with that id:
</P>
<PRE>
stock_factory_poa->activate_object_with_id (oid.in (),
servant.in ());
</PRE>
<P>Be careful not to invoke <CODE>_this()</CODE> on any of these
objects, as that would activate them in the RootPOA, ending with
two activations! It is perfectly legal to activate the same
servant multiple times in different POAs (and sometimes even in
the same POA!), but this is not what we want in this case.
</P>
<H3>Modifying the Stock Factory</H3>
<P>Now we need to implement a different version of the stock
factory. We pass a reference to the child POA into the constructor
and keep a reference to it:
</P>
<PRE>
class Quoter_Stock_Factory_i : public POA_Quoter::Stock_Factory
{
public:
Quoter_Stock_Factory (PortableServer::POA_ptr stock_factory_poa)
: stock_factory_poa_ (PortableServer::POA::_duplicate (stock_factory_poa))
{}
Quoter::Stock_ptr get_stock (const char *symbol)
throw (Quoter::Invalid_Stock_Symbol);
private:
PortableServer::POA_var stock_factory_poa_;
};
</PRE>
<P>Notice that we duplicate the POA, following the usual CORBA
memory rules for input arguments. Since the constructor is not a
CORBA operation, we could use any rules we wished, but it is less
confusing if we stick to the CORBA set.
</P>
<P>The implementation of the <CODE>get_stock</CODE> operation is more
interesting. First we create an object id based on the symbol:
</P>
<PRE>
Quoter::Stock_ptr
Quoter_Stock_Factory_i::get_stock (const char *symbol)
throw (Quoter::Invalid_Stock_Symbol)
{
PortableServer::ObjectId_var oid =
PortableServer::string_to_ObjectId (symbol);
</PRE>
<P>next we look up that object id in the POA:
</P>
<PRE>
try {
CORBA::Object_var tmp =
this->stock_factory_poa_->id_to_reference (oid.in ());
</PRE>
<P>then narrow the object reference to the right type and return
it:
</P>
<PRE>
return Quoter::Stock::_narrow (tmp.in ());
}
</PRE>
<P>If the symbol was invalid, the POA will not find the right
object id and raise an exception:
</P>
<PRE>
catch (PortableServer::POA::ObjectNotActive &) {
throw Quoter::Invalid_Stock_Symbol ();
}
}
</PRE>
<H3>Memory management for the Stock objects</H3>
<P>So far we have not discussed memory management for servants.
This is a good opportunity to do it, because the stock objects
are completely controlled by the POA.
The POA provides reference counting for the Servants. You are
<STRONG>not</STRONG> required to use reference counting, but if
you do, most of the memory management is extremely simple.
So why is reference counting not used all the time? Because some
applications do not require it. For example,
our previous simple server did not require any complex memory
management, as the objects were all created on the stack.
</P>
<P>To use the reference counting features in the POA, you must
override the <CODE>_add_ref()</CODE> and <CODE>_remove_ref()</CODE>
methods, to increase and decrease the reference count. Once the
count reaches 0, you can safely remove the object (but remember
to start the count at 1!).
Implementing these methods in a thread safe way is a tedious
task. To simplify the task, we use a mixin with the
<CODE>PortableServer::RefCountServantBase</CODE> class, as in:
</P>
<PRE>
class Quoter_Stock_i
: public virtual POA_Quoter::Stock,
public virtual PortableServer::RefCountServantBase
{
public:
Quoter_Stock_i (const char *symbol,
const char *full_name,
CORBA::Double price);
// as before
};
</PRE>
<P>TAO's implementation of the <CODE>RefCountServantBase</CODE> is
even thread safe, so you can use this technique in your
multi-threaded servers to dynamically destroy objects.
You simply delegate control to the POA.
Once you deactivate the object, the POA will only invoke
<CODE>_remove_ref()</CODE> once all the threads performing calls on
an object terminate,
so the object is not removed if it is still in use.
Just remember to increment the reference count if you need to
use it, too.
</P>
<H3>Exersice</H3>
<P>Modify the following files in the simple server as follows:
<UL>
<LI> <A HREF="../Server/Stock_i.h">Stock_i.h</A>:
Use the reference counted servant to control memory management.
</LI>
<LI> <A HREF="../Server/Stock_Factory_i.h">Stock_Factory_i.h</A>:
Apply the changes described above to use a child POA with the
appropriate policies.
</LI>
<LI> <A HREF="../Server/Stock_Factory_i.cpp">Stock_Factory_i.cpp</A>:
Apply the changes described above to use a child POA with the
appropriate policies.
</LI>
<LI> <A HREF="../Server/server.cpp">server.cpp</A>:
Create the child POA,
initialize the stock objects from the stdin, and create the
right stock factory class.
</LI>
</UL>
You can use the same
<A HREF="../Quoter.idl">Quoter.idl</A>,
<A HREF="../Server/Stock_i.cpp">Stock_i.cpp</A>
and
<A HREF="Quoter_Simple_ImprovedServer">MPC file</A>.
</P>
<H4>Solution</H4>
<P>Compare your solution with the following files:
<UL>
<LI> <A HREF="Stock_i.h">Stock_i.h</A>
</LI>
<LI> <A HREF="Stock_i.cpp">Stock_i.cpp</A>
</LI>
<LI> <A HREF="Stock_Factory_i.h">Stock_Factory_i.h</A>
</LI>
<LI> <A HREF="Stock_Factory_i.cpp">Stock_Factory_i.cpp</A>
</LI>
<LI> <A HREF="server.cpp">server.cpp</A>
</LI>
</UL>
</P>
<P>Does this solution scale when the number of stock symbols is in
the thousands or millions? Find out about Servant Locators and
Servant Activators in the POA!
</P>
<H3>Testing</H3>
<P>A sample
<A HREF="stock_list.txt">input file</A>
is available. You can use the
<A HREF="../Client/index.html">simple client</A> to check the
results,
as follows:
<PRE>
$ server < stock_list.txt > ior_file
$ client file://ior_file AAAA BBBB MSFT RHAT CCCC
</PRE>
Also test invalid symbols!
</P>
<H3>More Reading</H3>
<P>The <A
HREF="http://www.triodia.com/staff/michi-henning.html">Henning</A> and
<A HREF="http://www.iona.com/hyplan/vinoski/">Vinoski</A> <A HREF="http://www.iona.com/hyplan/vinoski/#book">CORBA book</A> discusses POA policies in detail. Likewise,
the Schmidt and Vinoski
<A HREF="http://www.cs.wustl.edu/~schmidt/report-doc.html">columns
</A>
in C++ Report also include several articles about the POA. Finally,
the <A HREF="http://www.dre.vanderbilt.edu/~schmidt/TAO.html">TAO</a> distribution includes
<A
HREF="../../../../../examples/POA">examples</A>
that illustrate how to use the POA policies.
</P>
<hr>
<address><a href="mailto:coryan@cs.wustl.edu">Carlos O'Ryan</a></address>
<!-- Created: Sat Nov 27 15:47:01 CST 1999 -->
<!-- hhmts start -->
Last modified: Sun Apr 1 18:11:01 PDT 2001
<!-- hhmts end -->
</body>
</html>
|