Stub.cpp

Go to the documentation of this file.
00001 // $Id: Stub.cpp 81682 2008-05-12 16:00:19Z vzykov $
00002 
00003 // Portions Copyright 1995 by Sun Microsystems Inc.
00004 // Portions Copyright 1997-2002 by Washington University
00005 // All Rights Reserved
00006 //
00007 // Some CORBA::Object and other operations are specific to this STUB
00008 // based implementation, and can neither be used by other kinds of
00009 // objref nor have a default implementation.
00010 
00011 #include "tao/Stub.h"
00012 #include "tao/Profile.h"
00013 #include "tao/ORB_Core.h"
00014 #include "tao/Client_Strategy_Factory.h"
00015 #include "tao/Remote_Object_Proxy_Broker.h"
00016 #include "tao/Transport_Queueing_Strategies.h"
00017 #include "tao/debug.h"
00018 #include "tao/Policy_Manager.h"
00019 #include "tao/SystemException.h"
00020 #include "tao/CDR.h"
00021 
00022 #if !defined (__ACE_INLINE__)
00023 # include "tao/Stub.inl"
00024 #endif /* ! __ACE_INLINE__ */
00025 
00026 #include "ace/Auto_Ptr.h"
00027 #include "ace/CORBA_macros.h"
00028 
00029 
00030 ACE_RCSID (tao,
00031            TAO_Stub,
00032            "$Id: Stub.cpp 81682 2008-05-12 16:00:19Z vzykov $")
00033 
00034 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00035 
00036 TAO_Stub::TAO_Stub (const char *repository_id,
00037                     const TAO_MProfile &profiles,
00038                     TAO_ORB_Core *orb_core)
00039   : type_id (repository_id)
00040   , orb_core_ (orb_core)
00041   , orb_ ()
00042   , is_collocated_ (false)
00043   , servant_orb_ ()
00044   , collocated_servant_ (0)
00045   , object_proxy_broker_ (the_tao_remote_object_proxy_broker ())
00046   , base_profiles_ ((CORBA::ULong) 0)
00047   , forward_profiles_ (0)
00048   , forward_profiles_perm_ (0)
00049   , profile_in_use_ (0)
00050   , profile_lock_ptr_ (0)
00051   , profile_success_ (false)
00052   , refcount_ (1)
00053 #if (TAO_HAS_CORBA_MESSAGING == 1)
00054   , policies_ (0)
00055 #endif /* TAO_HAS_CORBA_MESSAGING == 1 */
00056   , ior_info_ (0)
00057   , forwarded_ior_info_ (0)
00058   , collocation_opt_ (orb_core->optimize_collocation_objects ())
00059 {
00060   if (this->orb_core_.get() == 0)
00061     {
00062       if (TAO_debug_level > 0)
00063         {
00064           ACE_DEBUG ((LM_DEBUG,
00065                       ACE_TEXT ("TAO: (%P|%t) TAO_Stub created with default ")
00066                       ACE_TEXT ("ORB core\n")));
00067         }
00068 
00069       this->orb_core_.reset (TAO_ORB_Core_instance ());
00070     }
00071 
00072   // Duplicate the ORB_Core, otherwise the allocators and other
00073   // resources that this class references (directly or indirectly)
00074   // could be destroyed before it is time.
00075   (void) this->orb_core_->_incr_refcnt ();
00076 
00077   // Cache the ORB pointer to respond faster to certain queries.
00078   this->orb_ = CORBA::ORB::_duplicate (this->orb_core_->orb ());
00079 
00080   this->profile_lock_ptr_ =
00081     this->orb_core_->client_factory ()->create_profile_lock ();
00082 
00083   this->base_profiles (profiles);
00084 }
00085 
00086 TAO_Stub::~TAO_Stub (void)
00087 {
00088   ACE_ASSERT (this->refcount_ == 0);
00089 
00090   if (this->forward_profiles_)
00091     reset_profiles ();
00092 
00093   // reset_profiles doesn't delete forward_profiles_perm_.
00094   delete this->forward_profiles_perm_;
00095 
00096   if (this->profile_in_use_ != 0)
00097     {
00098       // decrease reference count on profile
00099       this->profile_in_use_->_decr_refcnt ();
00100       this->profile_in_use_ = 0;
00101     }
00102 
00103   delete this->profile_lock_ptr_;
00104 
00105 #if (TAO_HAS_CORBA_MESSAGING == 1)
00106 
00107   delete this->policies_;
00108 
00109 #endif /* TAO_HAS_CORBA_MESSAGING == 1 */
00110 
00111   if (this->ior_info_)
00112     delete this->ior_info_;
00113 
00114   if (this->forwarded_ior_info_)
00115     delete this->forwarded_ior_info_;
00116 }
00117 
00118 void
00119 TAO_Stub::add_forward_profiles (const TAO_MProfile &mprofiles,
00120                                 const CORBA::Boolean permanent_forward)
00121 {
00122   // we assume that the profile_in_use_ is being
00123   // forwarded!  Grab the lock so things don't change.
00124   ACE_MT (ACE_GUARD (ACE_Lock,
00125                      guard,
00126                      *this->profile_lock_ptr_));
00127 
00128   if (permanent_forward)
00129     {
00130       // paranoid, reset the bookmark, then clear the forward-stack
00131       this->forward_profiles_perm_ = 0;
00132 
00133       this->reset_forward ();
00134     }
00135 
00136   TAO_MProfile *now_pfiles = this->forward_profiles_;
00137   if (now_pfiles == 0)
00138     now_pfiles = &this->base_profiles_;
00139 
00140   ACE_NEW (this->forward_profiles_,
00141            TAO_MProfile (mprofiles));
00142 
00143   if (permanent_forward)
00144     // bookmark the new element at bottom of stack
00145     this->forward_profiles_perm_ = this->forward_profiles_;
00146 
00147   // forwarded profile points to the new IOR (profiles)
00148   this->profile_in_use_->forward_to (this->forward_profiles_);
00149 
00150   // new profile list points back to the list which was forwarded.
00151   this->forward_profiles_->forward_from (now_pfiles);
00152 
00153   // make sure we start at the beginning of mprofiles
00154   this->forward_profiles_->rewind ();
00155 
00156   // Since we have been forwarded, we must set profile_success_ to false
00157   // since we are starting a new with a new set of profiles!
00158   this->profile_success_ = false;
00159 }
00160 
00161 int
00162 TAO_Stub::create_ior_info (IOP::IOR *&ior_info, CORBA::ULong &index)
00163 {
00164   // We are creating the IOR info. Let us not be disturbed. So grab a
00165   // lock.
00166   ACE_MT (ACE_GUARD_RETURN (ACE_Lock,
00167                             guard,
00168                             *this->profile_lock_ptr_,
00169                             -1));
00170 
00171   IOP::IOR *tmp_info = 0;
00172 
00173   if (this->forward_profiles_ != 0)
00174     {
00175       if (this->forwarded_ior_info_ == 0)
00176         {
00177           this->get_profile_ior_info (*this->forward_profiles_, tmp_info);
00178 
00179           this->forwarded_ior_info_ = tmp_info;
00180         }
00181 
00182       // First we look at the forward profiles to see whether the
00183       // profile_in_use is any of it.
00184       for (CORBA::ULong i = 0;
00185            i < this->forward_profiles_->profile_count ();
00186            ++i)
00187         {
00188           if (this->forward_profiles_->get_profile (i)
00189               == this->profile_in_use_)
00190             {
00191               ior_info = this->forwarded_ior_info_;
00192               index = i;
00193               return 0;
00194             }
00195         }
00196     }
00197 
00198   // Else we look at the base profiles
00199   if (this->ior_info_ == 0)
00200     {
00201       this->get_profile_ior_info (this->base_profiles_, tmp_info);
00202 
00203       this->ior_info_ = tmp_info;
00204     }
00205 
00206 
00207   for (CORBA::ULong ind = 0;
00208        ind < this->base_profiles_.profile_count ();
00209        ++ind)
00210     {
00211       if (this->base_profiles_.get_profile (ind) == this->profile_in_use_)
00212         {
00213           index = ind;
00214           ior_info = this->ior_info_;
00215           return 0;
00216         }
00217     }
00218 
00219   // Error, there was no match
00220   return -1;
00221 }
00222 
00223 const TAO::ObjectKey &
00224 TAO_Stub::object_key (void) const
00225 {
00226   // Return the profile in use's object key if you see one.
00227   if (this->profile_in_use_)
00228     return this->profile_in_use_->object_key ();
00229 
00230   if (this->forward_profiles_)
00231     {
00232       // Double-checked
00233       ACE_Guard<ACE_Lock> obj (*this->profile_lock_ptr_);
00234 
00235       if (obj.locked () != 0 &&  this->forward_profiles_ != 0)
00236         return this->forward_profiles_->get_profile (0)->object_key ();
00237     }
00238 
00239   // If no forwarded profiles, just use the base profile
00240   return this->base_profiles_.get_profile (0)->object_key ();
00241 }
00242 
00243 int
00244 TAO_Stub::get_profile_ior_info (TAO_MProfile &profiles, IOP::IOR *&ior_info)
00245 {
00246   ACE_NEW_THROW_EX (ior_info,
00247                     IOP::IOR (),
00248                     CORBA::NO_MEMORY ());
00249 
00250   // Get the number of elements
00251   CORBA::ULong const count = profiles.profile_count ();
00252 
00253   // Set the number of elements in the sequence of tagged_profile
00254   ior_info->profiles.length (count);
00255 
00256   // Call the create_tagged_profile one every member of the
00257   // profile and make the sequence
00258   for (CORBA::ULong index = 0; index < count; ++index)
00259     {
00260       TAO_Profile *prof = profiles.get_profile (index);
00261 
00262       IOP::TaggedProfile *tp = prof->create_tagged_profile ();
00263 
00264       if (tp == 0)
00265         throw ::CORBA::NO_MEMORY ();
00266       ior_info->profiles[index] = *tp;
00267     }
00268 
00269   return 0;
00270 }
00271 
00272 void
00273 TAO_Stub::is_collocated (CORBA::Boolean collocated)
00274 {
00275   if (this->is_collocated_ != collocated)
00276     {
00277       if (collocated &&
00278           _TAO_Object_Proxy_Broker_Factory_function_pointer != 0)
00279         {
00280           this->object_proxy_broker_ =
00281             _TAO_Object_Proxy_Broker_Factory_function_pointer ();
00282         }
00283       else
00284         {
00285           this->object_proxy_broker_ = the_tao_remote_object_proxy_broker ();
00286         }
00287       this->is_collocated_ = collocated;
00288     }
00289 }
00290 
00291 // Quick'n'dirty hash of objref data, for partitioning objrefs into
00292 // sets.
00293 //
00294 // NOTE that this must NOT go across the network!
00295 
00296 CORBA::ULong
00297 TAO_Stub::hash (CORBA::ULong max)
00298 {
00299   // we rely on the profile objects that its address info
00300   return this->base_profiles_.hash (max);
00301 }
00302 
00303 // Expensive comparison of objref data, to see if two objrefs
00304 // certainly point at the same object. (It's quite OK for this to
00305 // return FALSE, and yet have the two objrefs really point to the same
00306 // object.)
00307 //
00308 // NOTE that this must NOT go across the network!
00309 // @@ Two object references are the same if any two profiles are the
00310 //    same! This function is only test the profile in use!!!
00311 CORBA::Boolean
00312 TAO_Stub::is_equivalent (CORBA::Object_ptr other_obj)
00313 {
00314   if (CORBA::is_nil (other_obj))
00315     return false;
00316 
00317   TAO_Profile * const other_profile = other_obj->_stubobj ()->profile_in_use_;
00318   TAO_Profile * const this_profile = this->profile_in_use_;
00319 
00320   if (other_profile == 0 || this_profile == 0)
00321     return false;
00322 
00323   // Compare the profiles
00324   return this_profile->is_equivalent (other_profile);
00325 }
00326 
00327 // Memory managment
00328 
00329 TAO_Profile *
00330 TAO_Stub::set_profile_in_use_i (TAO_Profile *pfile)
00331 {
00332   TAO_Profile *const old = this->profile_in_use_;
00333 
00334   // Since we are actively using this profile we dont want
00335   // it to disappear, so increase the reference count by one!!
00336   if (pfile && (pfile->_incr_refcnt () == 0))
00337     {
00338       ACE_ERROR_RETURN ((LM_ERROR,
00339                         ACE_TEXT ("(%P|%t) unable to increment profile ref!\n")),
00340                         0);
00341     }
00342 
00343   this->profile_in_use_ = pfile;
00344 
00345   if (old)
00346     old->_decr_refcnt ();
00347 
00348   return this->profile_in_use_;
00349 }
00350 
00351 void
00352 TAO_Stub::forward_back_one (void)
00353 {
00354   TAO_MProfile *from = forward_profiles_->forward_from ();
00355 
00356   // Only delete the forward location if it is not permanent
00357   if (this->forward_profiles_ != this->forward_profiles_perm_)
00358     delete this->forward_profiles_;
00359 
00360   // the current profile in this profile list is no
00361   // longer being forwarded, so set the reference to zero.
00362   if (from == &this->base_profiles_)
00363     {
00364       this->base_profiles_.get_current_profile ()->forward_to (0);
00365       this->forward_profiles_ = 0;
00366     }
00367   else
00368     {
00369       from->get_current_profile ()->forward_to (0);
00370       this->forward_profiles_ = from;
00371     }
00372 }
00373 
00374 
00375 // Note that if the repository ID (typeID) is NULL, it will make
00376 // narrowing rather expensive, though it does ensure that type-safe
00377 // narrowing code gets thoroughly exercised/debugged!  Without a
00378 // typeID, the _narrow will be required to make an expensive remote
00379 // "is_a" call.
00380 
00381 // THREADING NOTE: Code below this point is of course thread-safe (at
00382 // least on supported threaded platforms), so the caller of these
00383 // routines need only ensure that the data being passed in is not
00384 // being modified by any other thread.
00385 //
00386 // ****************************************************************
00387 
00388 #if (TAO_HAS_CORBA_MESSAGING == 1)
00389 
00390 // Some policies can only be set locally on the client, while others
00391 // can only be exported in the IOR by the server, and yet others can
00392 // be set by both by client and server.  Furthermore, reconciliation
00393 // between client-set values and the ones exported in the IOR is
00394 // policy-specific.  Therefore, with the current state of things, it
00395 // isn't possible to write generic code for <get_policy> that will
00396 // work for any policy type.  Currently, we take specific action for
00397 // each of the known client-exposed policies (above), and simply look
00398 // up effective override for any other policy type (below).  Later, if
00399 // there is a need/desire for generic code, it can be done by pushing
00400 // the smarts into the policies implementations, and will involve
00401 // modifying PolicyC* and friends, e.g., to add methods for policy
00402 // specific reconciliation, etc.
00403 
00404 CORBA::Policy_ptr
00405 TAO_Stub::get_policy (CORBA::PolicyType type)
00406 {
00407   // No need to lock, the stub only changes its policies at
00408   // construction time...
00409 
00410   CORBA::Policy_var result;
00411   if (this->policies_ != 0)
00412     {
00413       result = this->policies_->get_policy (type);
00414     }
00415 
00416   if (CORBA::is_nil (result.in ()))
00417     {
00418       result = this->orb_core_->get_policy_including_current (type);
00419     }
00420 
00421   return result._retn ();
00422 }
00423 
00424 CORBA::Policy_ptr
00425 TAO_Stub::get_cached_policy (TAO_Cached_Policy_Type type)
00426 {
00427   // No need to lock, the stub only changes its policies at
00428   // construction time...
00429 
00430   CORBA::Policy_var result;
00431   if (this->policies_ != 0)
00432     {
00433       result = this->policies_->get_cached_policy (type);
00434     }
00435 
00436   if (CORBA::is_nil (result.in ()))
00437     {
00438       result = this->orb_core_->get_cached_policy_including_current (type);
00439     }
00440 
00441   return result._retn ();
00442 }
00443 
00444 TAO_Stub *
00445 TAO_Stub::set_policy_overrides (const CORBA::PolicyList & policies,
00446                                 CORBA::SetOverrideType set_add)
00447 {
00448   // Notice the use of an explicit constructor....
00449   auto_ptr<TAO_Policy_Set> policy_manager (
00450     new TAO_Policy_Set (TAO_POLICY_OBJECT_SCOPE));
00451 
00452   if (set_add == CORBA::SET_OVERRIDE)
00453     {
00454       policy_manager->set_policy_overrides (policies, set_add);
00455     }
00456   else if (this->policies_ == 0)
00457     {
00458       policy_manager->set_policy_overrides (policies, CORBA::SET_OVERRIDE);
00459     }
00460   else
00461     {
00462       policy_manager->copy_from (this->policies_);
00463 
00464       policy_manager->set_policy_overrides (policies, set_add);
00465     }
00466 
00467   TAO_Stub* stub = this->orb_core_->create_stub (this->type_id.in (),
00468                                                  this->base_profiles_);
00469 
00470   stub->policies_ = policy_manager.release ();
00471 
00472   // Copy the servant ORB if it is present.
00473   stub->servant_orb (this->servant_orb_var ().in ());
00474 
00475   return stub;
00476 }
00477 
00478 CORBA::PolicyList *
00479 TAO_Stub::get_policy_overrides (const CORBA::PolicyTypeSeq &types)
00480 {
00481   if (this->policies_ == 0)
00482     {
00483       CORBA::PolicyList *policy_list_ptr = 0;
00484       ACE_NEW_THROW_EX (policy_list_ptr,
00485                         CORBA::PolicyList (),
00486                         CORBA::NO_MEMORY ());
00487 
00488       return policy_list_ptr;
00489     }
00490   else
00491     {
00492       return this->policies_->get_policy_overrides (types);
00493     }
00494 }
00495 
00496 #endif /* TAO_HAS_CORBA_MESSAGING == 1 */
00497 
00498 CORBA::Boolean
00499 TAO_Stub::marshal (TAO_OutputCDR &cdr)
00500 {
00501   // do as many outside of locked else-branch as posssible
00502 
00503   // STRING, a type ID hint
00504   if ((cdr << this->type_id.in()) == 0)
00505     return 0;
00506 
00507   if ( ! this->forward_profiles_perm_)
00508     {
00509       const TAO_MProfile& mprofile = this->base_profiles_;
00510 
00511       CORBA::ULong const profile_count = mprofile.profile_count ();
00512       if ((cdr << profile_count) == 0)
00513         return 0;
00514 
00515     // @@ The MProfile should be locked during this iteration, is there
00516     // anyway to achieve that?
00517     for (CORBA::ULong i = 0; i < profile_count; ++i)
00518       {
00519         const TAO_Profile* p = mprofile.get_profile (i);
00520         if (p->encode (cdr) == 0)
00521           return 0;
00522       }
00523     }
00524   else
00525     {
00526       ACE_MT (ACE_GUARD_RETURN (ACE_Lock,
00527                                 guard,
00528                                 *this->profile_lock_ptr_,
00529                                 0));
00530 
00531       ACE_ASSERT(this->forward_profiles_ !=0);
00532 
00533       // paranoid - in case of FT the basic_profiles_ would do, too,
00534       // but might be dated
00535       const TAO_MProfile& mprofile =
00536           this->forward_profiles_perm_
00537         ? *(this->forward_profiles_perm_)
00538         : this->base_profiles_;
00539 
00540       CORBA::ULong const profile_count = mprofile.profile_count ();
00541       if ((cdr << profile_count) == 0)
00542            return 0;
00543 
00544       // @@ The MProfile should be locked during this iteration, is there
00545       // anyway to achieve that?
00546       for (CORBA::ULong i = 0; i < profile_count; ++i)
00547         {
00548           const TAO_Profile* p = mprofile.get_profile (i);
00549           if (p->encode (cdr) == 0)
00550             return 0;
00551         }
00552 
00553       // release ACE_Lock
00554     }
00555 
00556   return (CORBA::Boolean) cdr.good_bit ();
00557 }
00558 
00559 void
00560 TAO_Stub::_incr_refcnt (void)
00561 {
00562   ++this->refcount_;
00563 }
00564 
00565 void
00566 TAO_Stub::_decr_refcnt (void)
00567 {
00568   if (--this->refcount_ == 0)
00569     delete this;
00570 }
00571 
00572 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Tue Feb 2 17:37:52 2010 for TAO by  doxygen 1.4.7