Stub.cpp

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

Generated on Sun Jan 27 13:07:36 2008 for TAO by doxygen 1.3.6