Revert "Minor modernization of DynamicAny code"
[ACE_TAO.git] / TAO / tao / Stub.cpp
blobc66e874e6138b1cc1269d0cde81a07a90b024056
1 // Portions Copyright 1995 by Sun Microsystems Inc.
2 // Portions Copyright 1997-2002 by Washington University
3 // All Rights Reserved
4 //
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.
9 #include "tao/Stub.h"
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"
19 #include "tao/CDR.h"
21 #if !defined (__ACE_INLINE__)
22 # include "tao/Stub.inl"
23 #endif /* ! __ACE_INLINE__ */
25 #include <memory>
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)
35 , orb_ ()
36 , is_collocated_ (false)
37 , servant_orb_ ()
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)
45 , refcount_ (1)
46 #if (TAO_HAS_CORBA_MESSAGING == 1)
47 , policies_ (nullptr)
48 #endif
49 , ior_info_ (nullptr)
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
76 // an upcall
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_)
87 reset_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_;
101 #endif
103 delete this->ior_info_;
105 delete this->forwarded_ior_info_;
108 void
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,
115 guard,
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"),
122 this));
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
164 // lock.
165 ACE_MT (ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
166 guard,
167 this->profile_lock_,
168 -1));
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"),
174 this));
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 ();
193 ++i)
195 if (this->forward_profiles_->get_profile (i)
196 == this->profile_in_use_)
198 ior_info = this->forwarded_ior_info_;
199 index = i;
200 return 0;
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 ();
216 ++ind)
218 if (this->base_profiles_.get_profile (ind) == this->profile_in_use_)
220 index = ind;
221 ior_info = this->ior_info_;
222 return 0;
226 // Error, there was no match
227 return -1;
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_)
239 // Double-checked
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,
257 IOP::IOR (),
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 ();
274 if (tp == nullptr)
275 throw ::CORBA::NO_MEMORY ();
276 ior_info->profiles[index] = *tp;
279 return 0;
282 void
283 TAO_Stub::is_collocated (CORBA::Boolean collocated)
285 if (this->is_collocated_ != collocated)
287 if (collocated &&
288 _TAO_Object_Proxy_Broker_Factory_function_pointer != nullptr)
290 this->object_proxy_broker_ =
291 _TAO_Object_Proxy_Broker_Factory_function_pointer ();
293 else
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
302 // sets.
304 // NOTE that this must NOT go across the network!
306 CORBA::ULong
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
316 // object.)
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!!!
321 CORBA::Boolean
322 TAO_Stub::is_equivalent (CORBA::Object_ptr other_obj)
324 if (CORBA::is_nil (other_obj))
325 return false;
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)
331 return false;
333 // Compare the profiles
334 return this_profile->is_equivalent (other_profile);
337 // Memory management
339 TAO_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;
355 if (old)
356 old->_decr_refcnt ();
358 return this->profile_in_use_;
361 void
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;
377 else
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
389 // "is_a" call.
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.
414 CORBA::Policy_ptr
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 ();
434 CORBA::Policy_ptr
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 ();
454 TAO_Stub *
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);
469 else
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 ());
484 return stub;
487 CORBA::PolicyList *
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;
499 else
501 return this->policies_->get_policy_overrides (types);
504 #endif
506 CORBA::Boolean
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)
513 return 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)
521 return 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)
529 return 0;
532 else
534 ACE_MT (ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
535 guard,
536 this->profile_lock_,
537 0));
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"),
543 this));
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)
558 return 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)
566 return 0;
569 // release ACE_Lock
572 return cdr.good_bit ();
575 TAO_END_VERSIONED_NAMESPACE_DECL