Stub.cpp

Go to the documentation of this file.
00001 // Stub.cpp,v 1.174 2006/05/05 20:43:15 schmidt Exp
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.i"
00024 #endif /* ! __ACE_INLINE__ */
00025 
00026 #include "ace/Auto_Ptr.h"
00027 
00028 
00029 ACE_RCSID (tao,
00030            TAO_Stub,
00031            "Stub.cpp,v 1.174 2006/05/05 20:43:15 schmidt Exp")
00032 
00033 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00034 
00035 TAO_Stub::TAO_Stub (const char *repository_id,
00036                     const TAO_MProfile &profiles,
00037                     TAO_ORB_Core *orb_core)
00038   : type_id (repository_id)
00039   , orb_core_ (orb_core)
00040   , orb_ ()
00041   , is_collocated_ (false)
00042   , servant_orb_ ()
00043   , collocated_servant_ (0)
00044   , object_proxy_broker_ (the_tao_remote_object_proxy_broker ())
00045   , base_profiles_ ((CORBA::ULong) 0)
00046   , forward_profiles_ (0)
00047   , forward_profiles_perm_ (0)
00048   , profile_in_use_ (0)
00049   , profile_lock_ptr_ (0)
00050   , profile_success_ (false)
00051   , refcount_ (1)
00052 #if (TAO_HAS_CORBA_MESSAGING == 1)
00053   , policies_ (0)
00054 #endif /* TAO_HAS_CORBA_MESSAGING == 1 */
00055   , ior_info_ (0)
00056   , forwarded_ior_info_ (0)
00057   , collocation_opt_ (orb_core->optimize_collocation_objects ())
00058 {
00059   if (this->orb_core_.get() == 0)
00060     {
00061       if (TAO_debug_level > 0)
00062         {
00063           ACE_DEBUG ((LM_DEBUG,
00064                       ACE_TEXT ("TAO: (%P|%t) TAO_Stub created with default ")
00065                       ACE_TEXT ("ORB core\n")));
00066         }
00067 
00068       this->orb_core_.reset (TAO_ORB_Core_instance ());
00069     }
00070 
00071   // Duplicate the ORB_Core, otherwise the allocators and other
00072   // resources that this class references (directly or indirectly)
00073   // could be destroyed before it is time.
00074   (void) this->orb_core_->_incr_refcnt ();
00075 
00076   // Cache the ORB pointer to respond faster to certain queries.
00077   this->orb_ = CORBA::ORB::_duplicate (this->orb_core_->orb ());
00078 
00079   this->profile_lock_ptr_ =
00080     this->orb_core_->client_factory ()->create_profile_lock ();
00081 
00082   this->base_profiles (profiles);
00083 }
00084 
00085 TAO_Stub::~TAO_Stub (void)
00086 {
00087   ACE_ASSERT (this->refcount_ == 0);
00088 
00089   if (this->forward_profiles_)
00090     reset_profiles ();
00091 
00092   if (this->profile_in_use_ != 0)
00093     {
00094       // decrease reference count on profile
00095       this->profile_in_use_->_decr_refcnt ();
00096       this->profile_in_use_ = 0;
00097     }
00098 
00099   delete this->profile_lock_ptr_;
00100 
00101 #if (TAO_HAS_CORBA_MESSAGING == 1)
00102 
00103   delete this->policies_;
00104 
00105 #endif /* TAO_HAS_CORBA_MESSAGING == 1 */
00106 
00107   if (this->ior_info_)
00108     delete this->ior_info_;
00109 
00110   if (this->forwarded_ior_info_)
00111     delete this->forwarded_ior_info_;
00112 }
00113 
00114 void
00115 TAO_Stub::add_forward_profiles (const TAO_MProfile &mprofiles,
00116                                 const CORBA::Boolean permanent_forward)
00117 {
00118   // we assume that the profile_in_use_ is being
00119   // forwarded!  Grab the lock so things don't change.
00120   ACE_MT (ACE_GUARD (ACE_Lock,
00121                      guard,
00122                      *this->profile_lock_ptr_));
00123 
00124   if (permanent_forward)
00125     {
00126       // paranoid, reset the bookmark, then clear the forward-stack
00127       this->forward_profiles_perm_ = 0;
00128 
00129       this->reset_forward ();
00130     }
00131 
00132   TAO_MProfile *now_pfiles = this->forward_profiles_;
00133   if (now_pfiles == 0)
00134     now_pfiles = &this->base_profiles_;
00135 
00136   ACE_NEW (this->forward_profiles_,
00137            TAO_MProfile (mprofiles));
00138 
00139   if (permanent_forward)
00140     // bookmark the new element at bottom of stack
00141     this->forward_profiles_perm_ = this->forward_profiles_;
00142 
00143   // forwarded profile points to the new IOR (profiles)
00144   this->profile_in_use_->forward_to (this->forward_profiles_);
00145 
00146   // new profile list points back to the list which was forwarded.
00147   this->forward_profiles_->forward_from (now_pfiles);
00148 
00149   // make sure we start at the beginning of mprofiles
00150   this->forward_profiles_->rewind ();
00151 
00152   // Since we have been forwarded, we must set profile_success_ to false
00153   // since we are starting a new with a new set of profiles!
00154   this->profile_success_ = false;
00155 
00156   // Reset any flags that may be appropriate in the services that
00157   // selects profiles for invocation
00158   this->orb_core_->reset_service_profile_flags ();
00159 }
00160 
00161 int
00162 TAO_Stub::create_ior_info (IOP::IOR *&ior_info,
00163                            CORBA::ULong &index
00164                            ACE_ENV_ARG_DECL)
00165 {
00166   // We are creating the IOR info. Let us not be disturbed. So grab a
00167   // lock.
00168   ACE_MT (ACE_GUARD_RETURN (ACE_Lock,
00169                             guard,
00170                             *this->profile_lock_ptr_,
00171                             -1));
00172 
00173   IOP::IOR *tmp_info = 0;
00174 
00175   if (this->forward_profiles_ != 0)
00176     {
00177       if (this->forwarded_ior_info_ == 0)
00178         {
00179           this->get_profile_ior_info (*this->forward_profiles_,
00180                                       tmp_info
00181                                        ACE_ENV_ARG_PARAMETER);
00182           ACE_CHECK_RETURN (-1);
00183 
00184           this->forwarded_ior_info_ = tmp_info;
00185         }
00186 
00187       // First we look at the forward profiles to see whether the
00188       // profile_in_use is any of it.
00189       for (CORBA::ULong i = 0;
00190            i < this->forward_profiles_->profile_count ();
00191            ++i)
00192         {
00193           if (this->forward_profiles_->get_profile (i)
00194               == this->profile_in_use_)
00195             {
00196               ior_info = this->forwarded_ior_info_;
00197               index = i;
00198               return 0;
00199             }
00200         }
00201     }
00202 
00203   // Else we look at the base profiles
00204   if (this->ior_info_ == 0)
00205     {
00206       this->get_profile_ior_info (this->base_profiles_,
00207                                   tmp_info
00208                                    ACE_ENV_ARG_PARAMETER);
00209       ACE_CHECK_RETURN (-1);
00210 
00211       this->ior_info_ = tmp_info;
00212     }
00213 
00214 
00215   for (CORBA::ULong ind = 0;
00216        ind < this->base_profiles_.profile_count ();
00217        ++ind)
00218     {
00219       if (this->base_profiles_.get_profile (ind) ==
00220           this->profile_in_use_)
00221         {
00222           index = ind;
00223           ior_info = this->ior_info_;
00224           return 0;
00225         }
00226     }
00227 
00228   // Error, there was no match
00229   return -1;
00230 }
00231 
00232 const TAO::ObjectKey &
00233 TAO_Stub::object_key (void) const
00234 {
00235   // Return the profile in use's object key if you see one.
00236   if (this->profile_in_use_)
00237     return this->profile_in_use_->object_key ();
00238 
00239   if (this->forward_profiles_)
00240     {
00241       // Double-checked
00242       ACE_Guard<ACE_Lock> obj (*this->profile_lock_ptr_);
00243 
00244       if (obj.locked () != 0 &&  this->forward_profiles_ != 0)
00245         return this->forward_profiles_->get_profile (0)->object_key ();
00246     }
00247 
00248   // If no forwarded profiles, just use the base profile
00249   return this->base_profiles_.get_profile (0)->object_key ();
00250 }
00251 
00252 int
00253 TAO_Stub::get_profile_ior_info (TAO_MProfile &profiles,
00254                                 IOP::IOR *&ior_info
00255                                 ACE_ENV_ARG_DECL)
00256 {
00257 
00258 
00259   ACE_NEW_THROW_EX (ior_info,
00260                     IOP::IOR (),
00261                     CORBA::NO_MEMORY ());
00262   ACE_CHECK_RETURN (-1);
00263 
00264 
00265   // Get the number of elements
00266   CORBA::ULong count = profiles.profile_count ();
00267 
00268   // Set the number of elements in the sequence of tagged_profile
00269   ior_info->profiles.length (count);
00270 
00271   // Call the create_tagged_profile one every member of the
00272   // profile and make the sequence
00273   for (CORBA::ULong index = 0; index < count; ++index)
00274     {
00275       TAO_Profile *prof = profiles.get_profile (index);
00276 
00277       IOP::TaggedProfile *tp =
00278         prof->create_tagged_profile ();
00279 
00280       if (tp == 0)
00281         ACE_THROW_RETURN (CORBA::NO_MEMORY (),
00282                           -1);
00283       ior_info->profiles[index] = *tp;
00284     }
00285 
00286   return 0;
00287 }
00288 
00289 void
00290 TAO_Stub::is_collocated (CORBA::Boolean collocated)
00291 {
00292   if (this->is_collocated_ != collocated)
00293     {
00294       if (collocated &&
00295           _TAO_Object_Proxy_Broker_Factory_function_pointer != 0)
00296         {
00297           this->object_proxy_broker_ =
00298             _TAO_Object_Proxy_Broker_Factory_function_pointer ();
00299         }
00300       else
00301         {
00302           this->object_proxy_broker_ =
00303             the_tao_remote_object_proxy_broker ();
00304         }
00305       this->is_collocated_ = collocated;
00306     }
00307 }
00308 
00309 // Quick'n'dirty hash of objref data, for partitioning objrefs into
00310 // sets.
00311 //
00312 // NOTE that this must NOT go across the network!
00313 
00314 CORBA::ULong
00315 TAO_Stub::hash (CORBA::ULong max
00316                 ACE_ENV_ARG_DECL)
00317 {
00318   // we rely on the profile objects that its address info
00319   return this->base_profiles_.hash (max ACE_ENV_ARG_PARAMETER);
00320 }
00321 
00322 // Expensive comparison of objref data, to see if two objrefs
00323 // certainly point at the same object. (It's quite OK for this to
00324 // return FALSE, and yet have the two objrefs really point to the same
00325 // object.)
00326 //
00327 // NOTE that this must NOT go across the network!
00328 // @@ Two object references are the same if any two profiles are the
00329 //    same! This function is only test the profile in use!!!
00330 CORBA::Boolean
00331 TAO_Stub::is_equivalent (CORBA::Object_ptr other_obj)
00332 {
00333   if (CORBA::is_nil (other_obj))
00334     return false;
00335 
00336   TAO_Profile * const other_profile = other_obj->_stubobj ()->profile_in_use_;
00337   TAO_Profile * const this_profile = this->profile_in_use_;
00338 
00339   if (other_profile == 0 || this_profile == 0)
00340     return false;
00341 
00342   // Compare the profiles
00343   return this_profile->is_equivalent (other_profile);
00344 }
00345 
00346 // Memory managment
00347 
00348 void
00349 TAO_Stub::_incr_refcnt (void)
00350 {
00351   ++this->refcount_;
00352 }
00353 
00354 void
00355 TAO_Stub::_decr_refcnt (void)
00356 {
00357   const CORBA::ULong new_count = --this->refcount_;
00358 
00359   if (new_count == 0)
00360     delete this;
00361 }
00362 
00363 TAO_Profile *
00364 TAO_Stub::set_profile_in_use_i (TAO_Profile *pfile)
00365 {
00366   TAO_Profile *const old = this->profile_in_use_;
00367 
00368   // Since we are actively using this profile we dont want
00369   // it to disappear, so increase the reference count by one!!
00370   if (pfile && (pfile->_incr_refcnt () == 0))
00371     {
00372       ACE_ERROR_RETURN ((LM_ERROR,
00373                         ACE_TEXT ("(%P|%t) unable to increment profile ref!\n")),
00374                         0);
00375     }
00376 
00377   this->profile_in_use_ = pfile;
00378 
00379   if (old)
00380     old->_decr_refcnt ();
00381 
00382   return this->profile_in_use_;
00383 }
00384 
00385 void
00386 TAO_Stub::forward_back_one (void)
00387 {
00388   TAO_MProfile *from = forward_profiles_->forward_from ();
00389 
00390   delete this->forward_profiles_;
00391 
00392   // the current profile in this profile list is no
00393   // longer being forwarded, so set the reference to zero.
00394   if (from == &this->base_profiles_)
00395     {
00396       this->base_profiles_.get_current_profile ()->forward_to (0);
00397       this->forward_profiles_ = 0;
00398     }
00399   else
00400     {
00401       from->get_current_profile ()->forward_to (0);
00402       this->forward_profiles_ = from;
00403     }
00404 }
00405 
00406 
00407 // Note that if the repository ID (typeID) is NULL, it will make
00408 // narrowing rather expensive, though it does ensure that type-safe
00409 // narrowing code gets thoroughly exercised/debugged!  Without a
00410 // typeID, the _narrow will be required to make an expensive remote
00411 // "is_a" call.
00412 
00413 // THREADING NOTE: Code below this point is of course thread-safe (at
00414 // least on supported threaded platforms), so the caller of these
00415 // routines need only ensure that the data being passed in is not
00416 // being modified by any other thread.
00417 //
00418 // As an _experiment_ (to estimate the performance cost) remote calls
00419 // are currently deemed "cancel-safe".  That means that they can be
00420 // called by threads when they're in asynchronous cancellation mode.
00421 // The only effective way to do this is to disable async cancellation
00422 // for the duration of the call.  There are numerous rude interactions
00423 // with code generators for C++ ... cancellation handlers just do
00424 // normal stack unwinding like exceptions, but exceptions are purely
00425 // synchronous and sophisticated code generators rely on that to
00426 // generate better code, which in some cases may be very hard to
00427 // unwind.
00428 
00429 class TAO_Synchronous_Cancellation_Required
00430 // = TITLE
00431 //     Stick one of these at the beginning of a block that can't
00432 //     support asynchronous cancellation, and which must be
00433 //     cancel-safe.
00434 //
00435 // = EXAMPLE
00436 //     somefunc()
00437 //     {
00438 //       TAO_Synchronous_Cancellation_Required NOT_USED;
00439 //       ...
00440 //     }
00441 {
00442 public:
00443   // These should probably be in a separate inline file, but they're
00444   // only used within this one file right now, and we always want them
00445   // inlined, so here they sit.
00446   TAO_Synchronous_Cancellation_Required (void)
00447     : old_type_ (0)
00448   {
00449 #if !defined (VXWORKS)
00450     ACE_OS::thr_setcanceltype (THR_CANCEL_DEFERRED, &old_type_);
00451 #endif /* ! VXWORKS */
00452   }
00453 
00454   ~TAO_Synchronous_Cancellation_Required (void)
00455   {
00456 #if !defined (VXWORKS)
00457     int dont_care;
00458     ACE_OS::thr_setcanceltype(old_type_, &dont_care);
00459 #endif /* ! VXWORKS */
00460   }
00461 private:
00462   int old_type_;
00463 };
00464 
00465 // ****************************************************************
00466 
00467 #if (TAO_HAS_CORBA_MESSAGING == 1)
00468 
00469 // Some policies can only be set locally on the client, while others
00470 // can only be exported in the IOR by the server, and yet others can
00471 // be set by both by client and server.  Furthermore, reconciliation
00472 // between client-set values and the ones exported in the IOR is
00473 // policy-specific.  Therefore, with the current state of things, it
00474 // isn't possible to write generic code for <get_policy> that will
00475 // work for any policy type.  Currently, we take specific action for
00476 // each of the known client-exposed policies (above), and simply look
00477 // up effective override for any other policy type (below).  Later, if
00478 // there is a need/desire for generic code, it can be done by pushing
00479 // the smarts into the policies implementations, and will involve
00480 // modifying PolicyC* and friends, e.g., to add methods for policy
00481 // specific reconciliation, etc.
00482 
00483 CORBA::Policy_ptr
00484 TAO_Stub::get_policy (CORBA::PolicyType type
00485                       ACE_ENV_ARG_DECL)
00486 {
00487   // No need to lock, the stub only changes its policies at
00488   // construction time...
00489 
00490   CORBA::Policy_var result;
00491   if (this->policies_ != 0)
00492     {
00493       result =
00494         this->policies_->get_policy (type
00495                                      ACE_ENV_ARG_PARAMETER);
00496       ACE_CHECK (CORBA::Policy::_nil ());
00497     }
00498 
00499   if (CORBA::is_nil (result.in ()))
00500     {
00501       result =
00502         this->orb_core_->get_policy_including_current (type
00503                                                        ACE_ENV_ARG_PARAMETER);
00504       ACE_CHECK (CORBA::Policy::_nil ());
00505     }
00506 
00507   return result._retn ();
00508 }
00509 
00510 CORBA::Policy_ptr
00511 TAO_Stub::get_cached_policy (TAO_Cached_Policy_Type type
00512                              ACE_ENV_ARG_DECL)
00513 {
00514   // No need to lock, the stub only changes its policies at
00515   // construction time...
00516 
00517   CORBA::Policy_var result;
00518   if (this->policies_ != 0)
00519     {
00520       result =
00521         this->policies_->get_cached_policy (type
00522                                             ACE_ENV_ARG_PARAMETER);
00523 
00524       ACE_CHECK_RETURN (CORBA::Policy::_nil ());
00525 
00526     }
00527 
00528   if (CORBA::is_nil (result.in ()))
00529     {
00530       result =
00531         this->orb_core_->get_cached_policy_including_current (type
00532                                                               ACE_ENV_ARG_PARAMETER);
00533       ACE_CHECK_RETURN (CORBA::Policy::_nil ());
00534     }
00535 
00536   return result._retn ();
00537 }
00538 
00539 TAO_Stub *
00540 TAO_Stub::set_policy_overrides (const CORBA::PolicyList & policies,
00541                                 CORBA::SetOverrideType set_add
00542                                 ACE_ENV_ARG_DECL)
00543 {
00544   // Notice the use of an explicit constructor....
00545   auto_ptr<TAO_Policy_Set> policy_manager (
00546     new TAO_Policy_Set (TAO_POLICY_OBJECT_SCOPE));
00547 
00548   if (set_add == CORBA::SET_OVERRIDE)
00549     {
00550       policy_manager->set_policy_overrides (policies,
00551                                             set_add
00552                                             ACE_ENV_ARG_PARAMETER);
00553       ACE_CHECK_RETURN (0);
00554     }
00555   else if (this->policies_ == 0)
00556     {
00557       policy_manager->set_policy_overrides (policies,
00558                                             CORBA::SET_OVERRIDE
00559                                             ACE_ENV_ARG_PARAMETER);
00560       ACE_CHECK_RETURN (0);
00561     }
00562   else
00563     {
00564       policy_manager->copy_from (this->policies_
00565                                   ACE_ENV_ARG_PARAMETER);
00566       ACE_CHECK_RETURN (0);
00567 
00568       policy_manager->set_policy_overrides (policies,
00569                                             set_add
00570                                             ACE_ENV_ARG_PARAMETER);
00571       ACE_CHECK_RETURN (0);
00572     }
00573 
00574   TAO_Stub* stub = this->orb_core_->create_stub (this->type_id.in (),
00575                                                  this->base_profiles_
00576                                                  ACE_ENV_ARG_PARAMETER);
00577   ACE_CHECK_RETURN (0);
00578 
00579   stub->policies_ = policy_manager.release ();
00580 
00581   // Copy the servant ORB if it is present.
00582   stub->servant_orb (this->servant_orb_var ().in ());
00583 
00584   return stub;
00585 }
00586 
00587 CORBA::PolicyList *
00588 TAO_Stub::get_policy_overrides (const CORBA::PolicyTypeSeq &types
00589                                 ACE_ENV_ARG_DECL)
00590 {
00591   if (this->policies_ == 0)
00592     return 0;
00593 
00594   return this->policies_->get_policy_overrides (types
00595                                                 ACE_ENV_ARG_PARAMETER);
00596 }
00597 
00598 #endif /* TAO_HAS_CORBA_MESSAGING == 1 */
00599 
00600 TAO::Transport_Queueing_Strategy &
00601 TAO_Stub::transport_queueing_strategy (void)
00602 {
00603 #if (TAO_HAS_BUFFERING_CONSTRAINT_POLICY == 1)
00604 
00605   bool has_synchronization;
00606   Messaging::SyncScope scope;
00607 
00608   this->orb_core_->call_sync_scope_hook (this,
00609                                          has_synchronization,
00610                                          scope);
00611 
00612   if (has_synchronization == true)
00613     return this->orb_core_->get_transport_queueing_strategy  (this,
00614                                                               scope);
00615 
00616 #endif /* TAO_HAS_BUFFERING_CONSTRAINT_POLICY == 1 */
00617 
00618   return this->orb_core_->default_transport_queueing_strategy ();
00619 }
00620 
00621 CORBA::Boolean
00622 TAO_Stub::marshal (TAO_OutputCDR &cdr)
00623 {
00624   // do as many outside of locked else-branch as posssible
00625 
00626   // STRING, a type ID hint
00627   if ((cdr << this->type_id.in()) == 0)
00628     return 0;
00629 
00630   if ( ! this->forward_profiles_perm_)
00631     {
00632       const TAO_MProfile& mprofile = this->base_profiles_;
00633 
00634       CORBA::ULong profile_count = mprofile.profile_count ();
00635       if ((cdr << profile_count) == 0)
00636         return 0;
00637 
00638     // @@ The MProfile should be locked during this iteration, is there
00639     // anyway to achieve that?
00640     for (CORBA::ULong i = 0; i < profile_count; ++i)
00641       {
00642         const TAO_Profile* p = mprofile.get_profile (i);
00643         if (p->encode (cdr) == 0)
00644           return 0;
00645       }
00646     }
00647   else
00648     {
00649         ACE_MT (ACE_GUARD_RETURN (ACE_Lock,
00650                                 guard,
00651                                 *this->profile_lock_ptr_,
00652                                 0));
00653 
00654       ACE_ASSERT(this->forward_profiles_ !=0);
00655 
00656       // paranoid - in case of FT the basic_profiles_ would do, too,
00657       // but might be dated
00658       const TAO_MProfile& mprofile =
00659           this->forward_profiles_perm_
00660         ? *(this->forward_profiles_perm_)
00661         : this->base_profiles_;
00662 
00663       CORBA::ULong profile_count = mprofile.profile_count ();
00664       if ((cdr << profile_count) == 0)
00665            return 0;
00666 
00667       // @@ The MProfile should be locked during this iteration, is there
00668       // anyway to achieve that?
00669       for (CORBA::ULong i = 0; i < profile_count; ++i)
00670         {
00671           const TAO_Profile* p = mprofile.get_profile (i);
00672           if (p->encode (cdr) == 0)
00673             return 0;
00674         }
00675 
00676       // release ACE_Lock
00677     }
00678 
00679   return (CORBA::Boolean) cdr.good_bit ();
00680 }
00681 
00682 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 11:54:22 2006 for TAO by doxygen 1.3.6