3 <TITLE>Smart Proxies
</TITLE>
12 <H3>Smart Proxies
</H3>
14 <P>Smart Proxies are a meta-programming extension supported by TAO
15 that provides user-defined proxy classes. By default TAO's IDL
16 compiler generates proxy classes for IDL interfaces. The proxy is an
17 exact image of the target object on whom the invocations are to be
18 made by the client, i.e., it has the same methods as the targeting
19 interface. A proxy packages the request which gets marshalled and
20 sent to the target object. A paper that describes TAO's
<A
21 HREF=
"interceptors.html">portable interceptor
</A> and smart proxy
22 support is available
<A
23 HREF=
"http://www.dre.vanderbilt.edu/~schmidt/PDF/smart_proxies.pdf">online
</A>.
</p></p>
26 <h3><a name=
"toc">Table of Contents
</a></h3>
28 <li><a href=
"#Examples">Examples
</a>
29 <li><a href=
"#Design Issues">Design Issues
</a>
30 <li><a href=
"#Design Overview">Design Overview
</a>
31 <li><a href=
"#Inheritance">Inheritance Issues
</a>
32 <li><a href=
"#Implementation Issues">Implementation Issues
</a>
33 <li><a href=
"#Options">Usage Options
</a>
34 <li><a href=
"#Acknowledgements">Acknowledgements
</a>
35 <li><a href=
"#ref">References
</a>
39 <h3><a name=
"Examples">Examples
</a></h3>
41 <P>The user may wish to manually change the proxy code for the following
44 <UL> <LI> Cache information about the remote object locally to save
45 the expense of going across the wire for every request.
<P>
47 <LI> Batch updates/accesses to the remote object.
49 Consider a remote Database which has an API which can update either a
50 single record or
10 records at one shot. To leverage performance, one
51 would want to use this method. So a user can use the smart proxy to
52 implement the
10 record update method by caching single record update
55 <P>It is not certain whether this usecase might not induce extra
56 overhead and whether the proxy can be smart enough to deduce the use
57 of this kind of batch processing. Also, this scheme wont work for
58 two-way calls.The
"cached-oneways" feature might make more sense in
59 this scenario. Thus the application programmer will have to determine
60 how this caching optimization changes the semantics of the original
63 <LI> The client can make a single request which results in a sequence
64 of invocations to one or possibly more objects.
67 The smart stub has some private methods (since this is user specific
68 this should be possible) which do validation of the request to be
69 made. The remote call could result in another call wherein the
70 validation occurs before it is shoved over the wire.
</p>
72 <LI> Quality of Service features like load-balancing can be considered
73 by the smart proxy before making the invocation on the appropriate
78 <h3><a name=
"Design Issues">Design Issues
</a></h3>
81 <LI> How will the smart proxy be created?
82 <LI> Who will create the smart proxy?
83 <LI> It has to be done before the invocations on the target object are
84 done, so when will it get created?
85 <LI> What about collocation? Will those stubs fall under this category?
86 <LI> Will smart proxies work for collocated object references?
89 <h3>Design Needs and discussion points
</h3>
91 <P>A ProxyFactory (either default or user-defined) is needed which
92 will create the stubs (either default or smart). This factory should
93 be able to create different kinds of proxies.
</p>
95 <P>The
<code>unchecked_narrow
</code> method needs to return the
98 <P>Collocated stubs need to be handled too. This means that smart
99 proxies need to be generated for collocated object references too.
</p>
101 <P>An existing function for creating stubs has to replaced by a class
102 which will handle all cases viz. default stubs, smart stubs (proxies),
105 <h2><a name=
"Design Overview">Design Overview
</a></h2>
109 <P>Classses to be generated by TAO_IDL in addition to the Default
113 <LI> <CODE>TAO_Proxy_Factory_Adapter
</CODE>
114 <p>The singleton which has the different proxies (stubs) factories
115 registered with it.
</p>
117 <LI> <CODE>TAO_Test_Default_Proxy_Factory
</CODE>
118 <p>The factory which returns the proxy_ptr which is used in the
119 <code>unchecked_narow
</code> method to create the appropriate proxy
122 <LI> <CODE>TAO_Smart_Proxy_Base
</CODE>
123 <p>The smart proxy interface which makes it easier for the
124 user to simply implement only the methods he wishes to change and also
125 provides a
<br>common interface to address remote as well as collocated
129 <P>Classes to be defined by the user:
</p>
132 <LI> <CODE>SmartFactory
</CODE> - inherits from TAO_Default_Proxy_Factory class.
133 <p>The factory which will create the smart proxy which the
134 user wants. Its necessary that an object of this class is created.
</p>
136 <LI> <CODE>SmartProxy
</CODE> - derivative of the TAO_Smart_Proxy_Base class.
137 <p>The proxy which has the user desired extra functionality.
</p>
139 <P>*Note: Names are as they are to make it easier to comprehend the
144 <h3>Detailed Example
</h3>
147 //------------------------ Generated by TAO_IDL------------------------
149 class TAO_Proxy_Factory_Adapter
152 // Behaves like a singleton and contains the
153 // factory object which is used to create the
154 // default/smart Proxys.
157 friend class ACE_Singleton
<TAO_Proxy_Factory_Adapter, TAO_SYNCH_RECURSIVE_MUTEX
>;
159 // Register the factory with the Adaptor.
160 register_proxy (TAO_Default_Proxy_Factory *df)
162 Perform Double-Checked Locking Optimisation...
164 // If there is a factory already existing, replace it.
165 this-
>unregister_proxy_factory ();
166 this-
>proxy_factory_ = df;
167 this-
>delete_proxy_factory_ =
0;
170 // Remove the factory.
171 unregister_proxy_factory (void)
173 Perform Locking to ensure exclusive access.
174 if (this-
>delete_proxy_factory_ ==
0 && this-
>proxy_factory_ !=
0)
176 // Its necessary to set
<delete_proxy_factory_> to
1 to make sure that it
177 // doesnt get into an infinite loop in
<unregister_proxy_factory> as it is
178 // invoked in the destructor of the class too.
179 this-
>delete_proxy_factory_ =
1;
180 delete this-
>proxy_factory_;
181 this-
>proxy_factory_ =
0;
185 // Delegation of the Proxy creation to the factory
186 interface_ptr create_proxy (void)
188 Verify that an
<proxy_factory_> is available else make one.
190 return this-
>factory_-
>create_proxy ();
195 TAO_Test_Default_Proxy_Factory *proxy_factory_;
196 int delete_proxy_factory_;
197 TAO_SYNCH_RECURSIVE_MUTEX lock_;
201 // This class will also be generated by TAO_IDL.
202 class TAO_Default_Proxy_Factory
205 // This class is the parent for the different Proxy factories. The
206 // Proxy could either be collocated or remote and hence here only
207 // the Proxy pointer is returned which will be created on invocation of
208 //
<unchecked_narrow>.
211 TAO_Default_Proxy_Factory (int register_proxy_factory);
213 // Unless told don't register. By default registration is done.
214 // This comes in handy while creating the TAO_Proxy_Factory_Adapter
215 // instance since we want either the user to set the factory. Only
216 // if that doesnt happen will the TAO_Default_Proxy_Factory be set
217 // to the factory delegated by the Adapter and that is done using
218 // the Lazy Evaluation Principle when the first call to
<create_proxy>
221 if (register_proxy_factory)
223 TAO_PROXY_FACTORY_ADAPTER::instance ()-
>register_proxy_factory (this);
227 ~TAO_Default_Proxy_Factory (void)
231 // By default the proxy is simply returned.
232 interface_ptr create_proxy (interface_ptr proxy)
239 // This class will be generated by the TAO_IDL.
240 class TAO_Smart_Proxy_Base : public virtual DefaultProxyInterface
243 // This class is the class from which the user will inherit
244 // and simply override the methods he requires. This extra
245 // level of indirection is necessary to be able to provide
246 // the smartProxy interface for even collocated Proxies.
249 // The delegation to which underlying proxy is decided here.
250 TAO_Smart_Proxy_Base (interface_ptr proxy)
251 : base_proxy_ (proxy)
253 // Interface operations...
256 this-
>proxy_-
>method ();
259 // @@ How are exceptions handled?
260 // This not an issue really because the actual method call is simply
261 // to the application level which is catch it as the exception is
262 // propagated upwards from the proxy level.
265 // This var member denotes the kind of proxy used:
266 // collacated-thru_poa, collocated-direct, or remote.
267 // This is decided by the collocated strategy used along
268 // with the smart Proxies. Note: the collocated Proxies
269 // themselves are smart proxies. The proxy pointer passed
270 // thru the constructor will be assigned to
<proxy_>. The
271 // pointer will actually point to the smart proxy in case
272 // of smart proxies or else to the default proxy.
273 DefaultProxyInterface_var base_proxy_;
277 // ----------------- User Implementation Begins here----------------
279 // Note: This has to be implemented by the user
280 class SmartFactory : public TAO_Default_Proxy_Factory
283 // An object of this class has to be defined by the user
284 // which will cause it to be registered with the
285 // ProxyFactoryAdaptor.
288 Smartinterface_ptr create_proxy (interface_ptr proxy)
290 return (!CORBA::is_nil (proxy) ? new SmartProxy (proxy) : proxy);
294 // This class will be implemented by the user.
295 class VerySmartProxy : public TAO_Smart_Proxy_Base
298 // This is the smart Proxy will is defined by the user
299 // to suit his needs.
302 print
"Yahoo, I am so smart"
303 this-
>proxy_-
>method ();
308 // --------------------Related Stub Changes------------------
311 // Generated by TAO_IDL. Note the changes wherein the
312 // TAO_Proxy_Factory_Adapter is used.
314 interface_ptr _unchecked_narrow (CORBA::Object obj,
315 CORBA::Environment &)
317 if (CORBA::is_nil (obj))
318 return test::_nil ();
319 TAO_Proxy* Proxy = obj-
>_stubobj ();
320 stub-
>_incr_refcnt ();
321 interface_ptr *default_proxy = interface::_nil ();
323 if (obj-
>_is_collocated () && _TAO_collocation_interface_Stub_Factory_function_pointer !=
0)
326 _TAO_collocation_interface_Stub_Factory_function_pointer (obj);
329 if (CORBA::is_nil (default_proxy))
330 ACE_NEW_RETURN (default_proxy, interface (stub), test::_nil ());
332 return TAO_PROXY_FACTORY_ADAPTER::instance ()-
>create_proxy (default_proxy);
338 <h3><a name=
"Inheritance">Inheritance Issues
</a></h3>
339 <p>The original implementation of the Smart Proxies was cumbersome
340 since when a smart proxy inherited from another the constructor
341 explicitly had to call the constructor of the base class of the other
342 proxy. To get over this issue, implementation inheritance was applied
343 by
<a href=
"mailto:brian.wallis@ot.com.au">Brian Wallis
</a> where
344 there is a higher level Smart_Proxy_Base which stores the
345 <CODE> base_proxy_
</CODE> member. This implementation was influenced
346 by a similar implementation in Orbix. Thanks to Brian Wallis for this
347 wonderful contribution to Smart Proxies in TAO.
349 <p>This design was modified slightly and now every interface smart
350 proxy base class holds a
<CODE> proxy_
</CODE> member which is the
351 narrowed version of the
<CODE> base_proxy_
</CODE>. This way every call
352 neednt have to go through the narrowing process as the
353 <CODE>base_proxy_
</CODE> is stored as a CORBA_Object_var while we need
354 the interface pointer to make the desired invocations.
357 <h3><a name=
"Implementation Issues">Implementation Issues
</a></h3>
360 <LI> Native exceptions? How are these to be handled?
</p>
361 <p> This not an issue really because the actual method call is simply
362 to the application level which will catch it as the exception is
363 propagated upwards from the proxy level.
</p>
365 <LI> What if the user wants to have a smart proxy which inherits from
367 <p> First have different smart proxies which inherit from the
368 TAO_Smart_Proxy_Base (every default smart proxy is for an interface) and
369 then have a new smart proxy inheriting from the previously created
370 smart proxies. But remember: the SmartProxyFactory should create the
371 final smart proxy thru its create_proxy () method.
</p>
373 <LI> Do I need to create a Smart Proxy Factory every time I use a
375 <p> Yes, you do. Once the Smart Proxy Factory is created, it is
376 automatically used to create the proxy and thus a smart proxy is
377 obtained instead of the default one. When the smart proxy makes its
378 first invocation, this factory is unregistered. So all the proxies
379 created from then on will be the default one.
383 <h3><a name=
"Options">Usage Options
</a></h3>
384 <p> To use this feature in TAO, one must do the following:
385 (
1) Generate smart proxy classes using the IDL compiler option of
386 -Gsp and (
2) Link client and server to the TAO_SmartProxies library, in
387 $TAO_ROOT/tao/SmartProxies.
388 A new smart proxy option has been added to the design: one-shot or
389 permanent versus per-object smart proxy. The one-shot smart proxy
390 option denotes that the smart proxy factory is registered permanently
391 and so for all object instances the same kind of proxy is used. On
392 disabling this default option one can achieve the use of different
393 smart proxies for every object instead of every interface.
394 For details please see the paper on
395 <a href=
"http://www.dre.vanderbilt.edu/~schmidt/PDF/COOTS-00.pdf">
396 Meta-programming Mechanisms for ORB Middleware as well as the test at
397 $TAO_ROOT/tests/Smart_Proxies/Policy.
400 <h3><a name=
"Acknowledgements">Acknowledgements
</a></h3>
402 <P><a href=
"mailto:nanbor@cs.wustl.edu">Nanbor Wang
</a> and
<a
403 href=
"mailto:d.schmidt@vanderbilt.edu">Dr.Schmidt
</a> for their help in
404 designing and discussing this feature.
<P>
406 <P><a href=
"mailto:brian.wallis@ot.com.au">Brian Wallis
</a> for
407 contributing the implementation inheritance feature.
410 <h3><a name=
"ref">References
</a></h3>
412 <p> CORBA Distributed Objects using Orbix - Sean Baker
</p>
413 <p> Visigenic Documentation
</p>
414 <p> Orbix Documentation
</p>
417 <p><h3>Last Update
</h3></3>
419 <p> Date:
02Jul2001
</p>
420 <p> By:
<a href=
"mailto:parsons@cs.wustl.edu">Jeff Parsons
</a></p>