summaryrefslogtreecommitdiff
path: root/TAO/docs/tutorials/Quoter/Simple/ImprovedServer/index.html
blob: 5c150bc540fb59f948cbbc7070d7240c8dfa2458 (plain)
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>
    <!-- $Id$ -->
  </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> policies 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, 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 in 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 operations we could use are rules we wised, 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 lookup 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 where 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 on 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="../Server/Makefile">Makefile</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 in 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">simpl 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.cs.wustl.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: Mon Apr  3 02:28:22 CDT 2000
<!-- hhmts end -->
  </body>
</html>