1 // Portions Copyright 1995 by Sun Microsystems Inc.
2 // Portions Copyright 1997-2002 by Washington University
5 // Some CORBA::Object and other operations are specific to this STUB
6 // based implementation, and can neither be used by other kinds of
7 // objref nor have a default implementation.
10 #include "tao/Profile.h"
11 #include "tao/ORB_Core.h"
12 #include "tao/Client_Strategy_Factory.h"
13 #include "tao/Remote_Object_Proxy_Broker.h"
14 #include "tao/Transport_Queueing_Strategies.h"
15 #include "tao/debug.h"
16 #include "tao/Policy_Manager.h"
17 #include "tao/Policy_Set.h"
18 #include "tao/SystemException.h"
21 #if !defined (__ACE_INLINE__)
22 # include "tao/Stub.inl"
23 #endif /* ! __ACE_INLINE__ */
26 #include "ace/CORBA_macros.h"
28 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
30 TAO_Stub::TAO_Stub (const char *repository_id
,
31 const TAO_MProfile
&profiles
,
32 TAO_ORB_Core
*orb_core
)
33 : type_id (repository_id
)
34 , orb_core_ (orb_core
)
36 , is_collocated_ (false)
38 , collocated_servant_ (nullptr)
39 , object_proxy_broker_ (the_tao_remote_object_proxy_broker ())
40 , base_profiles_ ((CORBA::ULong
) 0)
41 , forward_profiles_ (nullptr)
42 , forward_profiles_perm_ (nullptr)
43 , profile_in_use_ (nullptr)
44 , profile_success_ (false)
46 #if (TAO_HAS_CORBA_MESSAGING == 1)
50 , forwarded_ior_info_ (nullptr)
51 , collocation_opt_ (orb_core
->optimize_collocation_objects ())
52 , forwarded_on_exception_ (false)
54 if (this->orb_core_
.get() == nullptr)
56 if (TAO_debug_level
> 0)
58 TAOLIB_DEBUG ((LM_DEBUG
,
59 ACE_TEXT ("TAO: (%P|%t) TAO_Stub created with default ")
60 ACE_TEXT ("ORB core\n")));
63 this->orb_core_
.reset (TAO_ORB_Core_instance ());
66 // Duplicate the ORB_Core, otherwise the allocators and other
67 // resources that this class references (directly or indirectly)
68 // could be destroyed before it is time.
69 (void) this->orb_core_
->_incr_refcnt ();
71 // Cache the ORB pointer to respond faster to certain queries.
72 this->orb_
= CORBA::ORB::_duplicate (this->orb_core_
->orb ());
74 // Explicit trigger the loading of the client strategy factory at this moment.
75 // Not doing it here could lead to a problem loading it later on during
77 (void) this->orb_core_
->client_factory ();
79 this->base_profiles (profiles
);
82 TAO_Stub::~TAO_Stub ()
84 ACE_ASSERT (this->refcount_
== 0);
86 if (this->forward_profiles_
)
89 // reset_profiles doesn't delete forward_profiles_perm_.
90 delete this->forward_profiles_perm_
;
92 if (this->profile_in_use_
!= nullptr)
94 // decrease reference count on profile
95 this->profile_in_use_
->_decr_refcnt ();
96 this->profile_in_use_
= nullptr;
99 #if (TAO_HAS_CORBA_MESSAGING == 1)
100 delete this->policies_
;
103 delete this->ior_info_
;
105 delete this->forwarded_ior_info_
;
109 TAO_Stub::add_forward_profiles (const TAO_MProfile
&mprofiles
,
110 const CORBA::Boolean permanent_forward
)
112 // we assume that the profile_in_use_ is being
113 // forwarded! Grab the lock so things don't change.
114 ACE_MT (ACE_GUARD (TAO_SYNCH_MUTEX
,
116 this->profile_lock_
));
117 if (TAO_debug_level
> 5)
119 TAOLIB_DEBUG ((LM_DEBUG
,
120 ACE_TEXT ("TAO (%P|%t) - Stub::add_forward_profiles, ")
121 ACE_TEXT ("acquired profile lock this = 0x%x\n"),
125 if (permanent_forward
)
127 // paranoid, reset the bookmark, then clear the forward-stack
128 this->forward_profiles_perm_
= nullptr;
130 this->reset_forward ();
133 TAO_MProfile
*now_pfiles
= this->forward_profiles_
;
134 if (now_pfiles
== nullptr)
135 now_pfiles
= &this->base_profiles_
;
137 ACE_NEW (this->forward_profiles_
,
138 TAO_MProfile (mprofiles
));
140 if (permanent_forward
)
142 // bookmark the new element at bottom of stack
143 this->forward_profiles_perm_
= this->forward_profiles_
;
146 // forwarded profile points to the new IOR (profiles)
147 this->profile_in_use_
->forward_to (this->forward_profiles_
);
149 // new profile list points back to the list which was forwarded.
150 this->forward_profiles_
->forward_from (now_pfiles
);
152 // make sure we start at the beginning of mprofiles
153 this->forward_profiles_
->rewind ();
155 // Since we have been forwarded, we must set profile_success_ to false
156 // since we are starting a new with a new set of profiles!
157 this->profile_success_
= false;
161 TAO_Stub::create_ior_info (IOP::IOR
*&ior_info
, CORBA::ULong
&index
)
163 // We are creating the IOR info. Let us not be disturbed. So grab a
165 ACE_MT (ACE_GUARD_RETURN (TAO_SYNCH_MUTEX
,
169 if (TAO_debug_level
> 5)
171 TAOLIB_DEBUG ((LM_DEBUG
,
172 ACE_TEXT ("TAO (%P|%t) - Stub::create_ior_info, acquired ")
173 ACE_TEXT ("profile lock this = 0x%x\n"),
178 IOP::IOR
*tmp_info
= nullptr;
180 if (this->forward_profiles_
!= nullptr)
182 if (this->forwarded_ior_info_
== nullptr)
184 this->get_profile_ior_info (*this->forward_profiles_
, tmp_info
);
186 this->forwarded_ior_info_
= tmp_info
;
189 // First we look at the forward profiles to see whether the
190 // profile_in_use is any of it.
191 for (CORBA::ULong i
= 0;
192 i
< this->forward_profiles_
->profile_count ();
195 if (this->forward_profiles_
->get_profile (i
)
196 == this->profile_in_use_
)
198 ior_info
= this->forwarded_ior_info_
;
205 // Else we look at the base profiles
206 if (this->ior_info_
== nullptr)
208 this->get_profile_ior_info (this->base_profiles_
, tmp_info
);
210 this->ior_info_
= tmp_info
;
214 for (CORBA::ULong ind
= 0;
215 ind
< this->base_profiles_
.profile_count ();
218 if (this->base_profiles_
.get_profile (ind
) == this->profile_in_use_
)
221 ior_info
= this->ior_info_
;
226 // Error, there was no match
230 const TAO::ObjectKey
&
231 TAO_Stub::object_key () const
233 // Return the profile in use's object key if you see one.
234 if (this->profile_in_use_
)
235 return this->profile_in_use_
->object_key ();
237 if (this->forward_profiles_
)
240 // FUZZ: disable check_for_ACE_Guard
241 ACE_Guard
<TAO_SYNCH_MUTEX
> obj (
242 const_cast <TAO_SYNCH_MUTEX
&>(this->profile_lock_
));
243 // FUZZ: enable check_for_ACE_Guard
245 if (obj
.locked () != 0 && this->forward_profiles_
!= nullptr)
246 return this->forward_profiles_
->get_profile (0)->object_key ();
249 // If no forwarded profiles, just use the base profile
250 return this->base_profiles_
.get_profile (0)->object_key ();
254 TAO_Stub::get_profile_ior_info (TAO_MProfile
&profiles
, IOP::IOR
*&ior_info
)
256 ACE_NEW_THROW_EX (ior_info
,
258 CORBA::NO_MEMORY ());
260 // Get the number of elements
261 CORBA::ULong
const count
= profiles
.profile_count ();
263 // Set the number of elements in the sequence of tagged_profile
264 ior_info
->profiles
.length (count
);
266 // Call the create_tagged_profile one every member of the
267 // profile and make the sequence
268 for (CORBA::ULong index
= 0; index
< count
; ++index
)
270 TAO_Profile
*prof
= profiles
.get_profile (index
);
272 IOP::TaggedProfile
*tp
= prof
->create_tagged_profile ();
275 throw ::CORBA::NO_MEMORY ();
276 ior_info
->profiles
[index
] = *tp
;
283 TAO_Stub::is_collocated (CORBA::Boolean collocated
)
285 if (this->is_collocated_
!= collocated
)
288 _TAO_Object_Proxy_Broker_Factory_function_pointer
!= nullptr)
290 this->object_proxy_broker_
=
291 _TAO_Object_Proxy_Broker_Factory_function_pointer ();
295 this->object_proxy_broker_
= the_tao_remote_object_proxy_broker ();
297 this->is_collocated_
= collocated
;
301 // Quick'n'dirty hash of objref data, for partitioning objrefs into
304 // NOTE that this must NOT go across the network!
307 TAO_Stub::hash (CORBA::ULong max
)
309 // we rely on the profile objects that its address info
310 return this->base_profiles_
.hash (max
);
313 // Expensive comparison of objref data, to see if two objrefs
314 // certainly point at the same object. (It's quite OK for this to
315 // return FALSE, and yet have the two objrefs really point to the same
318 // NOTE that this must NOT go across the network!
319 // @@ Two object references are the same if any two profiles are the
320 // same! This function is only test the profile in use!!!
322 TAO_Stub::is_equivalent (CORBA::Object_ptr other_obj
)
324 if (CORBA::is_nil (other_obj
))
327 TAO_Profile
* const other_profile
= other_obj
->_stubobj ()->profile_in_use_
;
328 TAO_Profile
* const this_profile
= this->profile_in_use_
;
330 if (other_profile
== nullptr || this_profile
== nullptr)
333 // Compare the profiles
334 return this_profile
->is_equivalent (other_profile
);
340 TAO_Stub::set_profile_in_use_i (TAO_Profile
*pfile
)
342 TAO_Profile
*const old
= this->profile_in_use_
;
344 // Since we are actively using this profile we dont want
345 // it to disappear, so increase the reference count by one!!
346 if (pfile
&& (pfile
->_incr_refcnt () == 0))
348 TAOLIB_ERROR_RETURN ((LM_ERROR
,
349 ACE_TEXT ("(%P|%t) unable to increment profile ref!\n")),
353 this->profile_in_use_
= pfile
;
356 old
->_decr_refcnt ();
358 return this->profile_in_use_
;
362 TAO_Stub::forward_back_one ()
364 TAO_MProfile
*from
= forward_profiles_
->forward_from ();
366 // Only delete the forward location if it is not permanent
367 if (this->forward_profiles_
!= this->forward_profiles_perm_
)
368 delete this->forward_profiles_
;
370 // the current profile in this profile list is no
371 // longer being forwarded, so set the reference to zero.
372 if (from
== &this->base_profiles_
)
374 this->base_profiles_
.get_current_profile ()->forward_to (nullptr);
375 this->forward_profiles_
= nullptr;
379 from
->get_current_profile ()->forward_to (nullptr);
380 this->forward_profiles_
= from
;
385 // Note that if the repository ID (typeID) is NULL, it will make
386 // narrowing rather expensive, though it does ensure that type-safe
387 // narrowing code gets thoroughly exercised/debugged! Without a
388 // typeID, the _narrow will be required to make an expensive remote
391 // THREADING NOTE: Code below this point is of course thread-safe (at
392 // least on supported threaded platforms), so the caller of these
393 // routines need only ensure that the data being passed in is not
394 // being modified by any other thread.
396 // ****************************************************************
398 #if (TAO_HAS_CORBA_MESSAGING == 1)
400 // Some policies can only be set locally on the client, while others
401 // can only be exported in the IOR by the server, and yet others can
402 // be set by both by client and server. Furthermore, reconciliation
403 // between client-set values and the ones exported in the IOR is
404 // policy-specific. Therefore, with the current state of things, it
405 // isn't possible to write generic code for <get_policy> that will
406 // work for any policy type. Currently, we take specific action for
407 // each of the known client-exposed policies (above), and simply look
408 // up effective override for any other policy type (below). Later, if
409 // there is a need/desire for generic code, it can be done by pushing
410 // the smarts into the policies implementations, and will involve
411 // modifying PolicyC* and friends, e.g., to add methods for policy
412 // specific reconciliation, etc.
415 TAO_Stub::get_policy (CORBA::PolicyType type
)
417 // No need to lock, the stub only changes its policies at
418 // construction time...
420 CORBA::Policy_var result
;
421 if (this->policies_
!= nullptr)
423 result
= this->policies_
->get_policy (type
);
426 if (CORBA::is_nil (result
.in ()))
428 result
= this->orb_core_
->get_policy_including_current (type
);
431 return result
._retn ();
435 TAO_Stub::get_cached_policy (TAO_Cached_Policy_Type type
)
437 // No need to lock, the stub only changes its policies at
438 // construction time...
440 CORBA::Policy_var result
;
441 if (this->policies_
!= nullptr)
443 result
= this->policies_
->get_cached_policy (type
);
446 if (CORBA::is_nil (result
.in ()))
448 result
= this->orb_core_
->get_cached_policy_including_current (type
);
451 return result
._retn ();
455 TAO_Stub::set_policy_overrides (const CORBA::PolicyList
& policies
,
456 CORBA::SetOverrideType set_add
)
458 // Notice the use of an explicit constructor....
459 std::unique_ptr
<TAO_Policy_Set
> policy_manager (new TAO_Policy_Set (TAO_POLICY_OBJECT_SCOPE
));
461 if (set_add
== CORBA::SET_OVERRIDE
)
463 policy_manager
->set_policy_overrides (policies
, set_add
);
465 else if (this->policies_
== nullptr)
467 policy_manager
->set_policy_overrides (policies
, CORBA::SET_OVERRIDE
);
471 policy_manager
->copy_from (this->policies_
);
473 policy_manager
->set_policy_overrides (policies
, set_add
);
476 TAO_Stub
* stub
= this->orb_core_
->create_stub (this->type_id
.in (),
477 this->base_profiles_
);
479 stub
->policies_
= policy_manager
.release ();
481 // Copy the servant ORB if it is present.
482 stub
->servant_orb (this->servant_orb_var ().in ());
488 TAO_Stub::get_policy_overrides (const CORBA::PolicyTypeSeq
&types
)
490 if (this->policies_
== nullptr)
492 CORBA::PolicyList
*policy_list_ptr
= nullptr;
493 ACE_NEW_THROW_EX (policy_list_ptr
,
494 CORBA::PolicyList (),
495 CORBA::NO_MEMORY ());
497 return policy_list_ptr
;
501 return this->policies_
->get_policy_overrides (types
);
507 TAO_Stub::marshal (TAO_OutputCDR
&cdr
)
509 // do as many outside of locked else-branch as posssible
511 // STRING, a type ID hint
512 if ((cdr
<< this->type_id
.in()) == 0)
515 if ( ! this->forward_profiles_perm_
)
517 const TAO_MProfile
& mprofile
= this->base_profiles_
;
519 CORBA::ULong
const profile_count
= mprofile
.profile_count ();
520 if ((cdr
<< profile_count
) == 0)
523 // @@ The MProfile should be locked during this iteration, is there
524 // anyway to achieve that?
525 for (CORBA::ULong i
= 0; i
< profile_count
; ++i
)
527 const TAO_Profile
* p
= mprofile
.get_profile (i
);
528 if (p
->encode (cdr
) == 0)
534 ACE_MT (ACE_GUARD_RETURN (TAO_SYNCH_MUTEX
,
538 if (TAO_debug_level
> 5)
540 TAOLIB_DEBUG ((LM_DEBUG
,
541 ACE_TEXT ("TAO (%P|%t) - Stub::marshal, acquired ")
542 ACE_TEXT ("profile lock this = 0x%x\n"),
547 ACE_ASSERT(this->forward_profiles_
!=nullptr);
549 // paranoid - in case of FT the basic_profiles_ would do, too,
550 // but might be dated
551 const TAO_MProfile
& mprofile
=
552 this->forward_profiles_perm_
553 ? *(this->forward_profiles_perm_
)
554 : this->base_profiles_
;
556 CORBA::ULong
const profile_count
= mprofile
.profile_count ();
557 if ((cdr
<< profile_count
) == 0)
560 // @@ The MProfile should be locked during this iteration, is there
561 // anyway to achieve that?
562 for (CORBA::ULong i
= 0; i
< profile_count
; ++i
)
564 const TAO_Profile
* p
= mprofile
.get_profile (i
);
565 if (p
->encode (cdr
) == 0)
572 return cdr
.good_bit ();
575 TAO_END_VERSIONED_NAMESPACE_DECL