Servant_Upcall.cpp

Go to the documentation of this file.
00001 // $Id: Servant_Upcall.cpp 77293 2007-02-21 14:48:22Z johnnyw $
00002 
00003 #include "tao/PortableServer/Object_Adapter.h"
00004 #include "tao/PortableServer/Servant_Upcall.h"
00005 #include "tao/PortableServer/Root_POA.h"
00006 #include "tao/PortableServer/Default_Servant_Dispatcher.h"
00007 #include "tao/PortableServer/Collocated_Object_Proxy_Broker.h"
00008 #include "tao/PortableServer/Active_Object_Map_Entry.h"
00009 #include "tao/PortableServer/ForwardRequestC.h"
00010 
00011 // -- TAO Include --
00012 #include "tao/ORB.h"
00013 #include "tao/ORB_Core.h"
00014 #include "tao/debug.h"
00015 
00016 #if !defined (__ACE_INLINE__)
00017 # include "tao/PortableServer/Servant_Upcall.inl"
00018 #endif /* __ACE_INLINE__ */
00019 
00020 #include "ace/OS_NS_string.h"
00021 
00022 ACE_RCSID (PortableServer,
00023            Servant_Upcall,
00024            "$Id: Servant_Upcall.cpp 77293 2007-02-21 14:48:22Z johnnyw $")
00025 
00026 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00027 
00028 namespace TAO
00029 {
00030   namespace Portable_Server
00031   {
00032     Servant_Upcall::Servant_Upcall (TAO_ORB_Core *oc)
00033       : object_adapter_ (0),
00034         poa_ (0),
00035         servant_ (0),
00036         state_ (INITIAL_STAGE),
00037         system_id_ (TAO_POA_OBJECT_ID_BUF_SIZE, 0, system_id_buf_),
00038         user_id_ (0),
00039         current_context_ (),
00040 #if (TAO_HAS_MINIMUM_POA == 0)
00041         cookie_ (0),
00042         operation_ (0),
00043 #endif /* TAO_HAS_MINIMUM_POA == 0 */
00044         active_object_map_entry_ (0)
00045     {
00046       TAO_Object_Adapter *object_adapter =
00047         dynamic_cast<TAO_Object_Adapter *>(oc->poa_adapter ());
00048       this->object_adapter_ = object_adapter;
00049     }
00050 
00051     int
00052     Servant_Upcall::prepare_for_upcall (
00053       const TAO::ObjectKey &key,
00054       const char *operation,
00055       CORBA::Object_out forward_to)
00056     {
00057       while (1)
00058         {
00059           bool wait_occurred_restart_call = false;
00060 
00061           int result =
00062             this->prepare_for_upcall_i (key,
00063                                         operation,
00064                                         forward_to,
00065                                         wait_occurred_restart_call);
00066 
00067           if (result == TAO_Adapter::DS_FAILED &&
00068               wait_occurred_restart_call)
00069             {
00070               // We ended up waiting on a condition variable.  The POA
00071               // state may have changed while we are waiting.  Therefore,
00072               // we need to call prepare_for_upcall_i() again.  We also
00073               // need to cleanup the state of the upcall object before
00074               // continuing.
00075               this->upcall_cleanup ();
00076               continue;
00077             }
00078           else
00079             {
00080               return result;
00081             }
00082         }
00083     }
00084 
00085     int
00086     Servant_Upcall::prepare_for_upcall_i (
00087       const TAO::ObjectKey &key,
00088       const char *operation,
00089       CORBA::Object_out forward_to,
00090       bool &wait_occurred_restart_call)
00091     {
00092       // Acquire the object adapter lock first.
00093       int result = this->object_adapter_->lock ().acquire ();
00094       if (result == -1)
00095         // Locking error.
00096         throw ::CORBA::OBJ_ADAPTER ();
00097 
00098       // We have acquired the object adapter lock.  Record this for later
00099       // use.
00100       this->state_ = OBJECT_ADAPTER_LOCK_ACQUIRED;
00101 
00102       // Check if a non-servant upcall is in progress.  If a non-servant
00103       // upcall is in progress, wait for it to complete.  Unless of
00104       // course, the thread making the non-servant upcall is this thread.
00105       this->object_adapter_->wait_for_non_servant_upcalls_to_complete ();
00106 
00107       // Locate the POA.
00108       this->object_adapter_->locate_poa (key, this->system_id_, this->poa_);
00109 
00110       // Check the state of the POA.
00111       this->poa_->check_state ();
00112 
00113       // Setup current for this request.
00114       this->current_context_.setup (this->poa_, key);
00115 
00116       // Increase <poa->outstanding_requests_> for the duration of finding
00117       // the POA, finding the servant, and making the upcall.
00118       this->poa_->increment_outstanding_requests ();
00119 
00120       // We have setup the POA Current.  Record this for later use.
00121       this->state_ = POA_CURRENT_SETUP;
00122 
00123 #if (TAO_HAS_MINIMUM_CORBA == 0) && !defined (CORBA_E_COMPACT) && !defined (CORBA_E_MICRO)
00124       try
00125         {
00126 #endif /* TAO_HAS_MINIMUM_CORBA */
00127           // Lookup the servant.
00128           this->servant_ =
00129             this->poa_->locate_servant_i (operation,
00130                                           this->system_id_,
00131                                           *this,
00132                                           this->current_context_,
00133                                           wait_occurred_restart_call);
00134 
00135           if (wait_occurred_restart_call)
00136             return TAO_Adapter::DS_FAILED;
00137 #if (TAO_HAS_MINIMUM_CORBA == 0) && !defined (CORBA_E_COMPACT) && !defined (CORBA_E_MICRO)
00138         }
00139       catch (const ::PortableServer::ForwardRequest& forward_request)
00140         {
00141           forward_to =
00142             CORBA::Object::_duplicate (forward_request.forward_reference.in ());
00143           return TAO_Adapter::DS_FORWARD;
00144         }
00145 #else
00146       ACE_UNUSED_ARG (forward_to);
00147 #endif /* TAO_HAS_MINIMUM_CORBA */
00148 
00149       // Now that we know the servant.
00150       this->current_context_.servant (this->servant_);
00151 
00152       // For servants from Servant Locators, there is no active object map
00153       // entry.
00154       if (this->active_object_map_entry ())
00155         this->current_context_.priority (this->active_object_map_entry ()->priority_);
00156 
00157       if (this->state_ != OBJECT_ADAPTER_LOCK_RELEASED)
00158         {
00159           // Release the object adapter lock.
00160           this->object_adapter_->lock ().release ();
00161 
00162           // We have release the object adapter lock.  Record this for
00163           // later use.
00164           this->state_ = OBJECT_ADAPTER_LOCK_RELEASED;
00165         }
00166 
00167       // Serialize servants (if appropriate).
00168       this->single_threaded_poa_setup ();
00169 
00170       // We have acquired the servant lock.  Record this for later use.
00171       this->state_ = SERVANT_LOCK_ACQUIRED;
00172 
00173       // After this point, <this->servant_> is ready for dispatching.
00174       return TAO_Adapter::DS_OK;
00175     }
00176 
00177     void
00178     Servant_Upcall::pre_invoke_remote_request (TAO_ServerRequest &req)
00179     {
00180       this->object_adapter_->servant_dispatcher_->pre_invoke_remote_request (
00181         this->poa (),
00182         this->priority (),
00183         req,
00184         this->pre_invoke_state_);
00185     }
00186 
00187     void
00188     Servant_Upcall::pre_invoke_collocated_request (void)
00189     {
00190       this->object_adapter_->servant_dispatcher_->pre_invoke_collocated_request (
00191         this->poa (),
00192         this->priority (),
00193         this->pre_invoke_state_);
00194     }
00195 
00196     void
00197     Servant_Upcall::post_invoke (void)
00198     {
00199       this->object_adapter_->servant_dispatcher_->post_invoke (
00200         this->poa (),
00201         this->pre_invoke_state_);
00202     }
00203 
00204     Servant_Upcall::Pre_Invoke_State::Pre_Invoke_State (void)
00205       : state_ (NO_ACTION_REQUIRED),
00206         original_native_priority_ (0),
00207         original_CORBA_priority_ (0)
00208     {
00209     }
00210 
00211     ::TAO_Root_POA *
00212     Servant_Upcall::lookup_POA (const TAO::ObjectKey &key)
00213     {
00214       // Acquire the object adapter lock first.
00215       if (this->object_adapter_->lock ().acquire () == -1)
00216         // Locking error.
00217         throw ::CORBA::OBJ_ADAPTER ();
00218 
00219       // We have acquired the object adapter lock.  Record this for later
00220       // use.
00221       this->state_ = OBJECT_ADAPTER_LOCK_ACQUIRED;
00222 
00223       // Check if a non-servant upcall is in progress.  If a non-servant
00224       // upcall is in progress, wait for it to complete.  Unless of
00225       // course, the thread making the non-servant upcall is this thread.
00226       this->object_adapter_->wait_for_non_servant_upcalls_to_complete ();
00227 
00228       // Locate the POA.
00229       this->object_adapter_->locate_poa (key, this->system_id_, this->poa_);
00230 
00231       return this->poa_;
00232     }
00233 
00234     Servant_Upcall::~Servant_Upcall (void)
00235     {
00236       this->upcall_cleanup ();
00237     }
00238 
00239     void
00240     Servant_Upcall::upcall_cleanup (void)
00241     {
00242       this->post_invoke ();
00243 
00244       switch (this->state_)
00245         {
00246         case SERVANT_LOCK_ACQUIRED:
00247           // Unlock servant (if appropriate).
00248           this->single_threaded_poa_cleanup ();
00249 
00250           /* FALLTHRU */
00251 
00252         case OBJECT_ADAPTER_LOCK_RELEASED:
00253           // Cleanup servant locator related state.  Note that because
00254           // this operation does not change any Object Adapter related
00255           // state, it is ok to call it outside the lock.
00256           this->post_invoke_servant_cleanup ();
00257 
00258           // Since the object adapter lock was released, we must acquire
00259           // it.
00260           //
00261           // Note that errors are ignored here since we cannot do much
00262           // with it.
00263           this->object_adapter_->lock ().acquire ();
00264 
00265           // Check if a non-servant upcall is in progress.  If a
00266           // non-servant upcall is in progress, wait for it to complete.
00267           // Unless of course, the thread making the non-servant upcall is
00268           // this thread.
00269           this->object_adapter_->wait_for_non_servant_upcalls_to_complete_no_throw ();
00270 
00271           // Cleanup servant related state.
00272           this->servant_cleanup ();
00273 
00274           /* FALLTHRU */
00275 
00276         case POA_CURRENT_SETUP:
00277           // Cleanup POA related state.
00278           this->poa_cleanup ();
00279 
00280           // Teardown current for this request.
00281           this->current_context_.teardown ();
00282 
00283           /* FALLTHRU */
00284 
00285         case OBJECT_ADAPTER_LOCK_ACQUIRED:
00286           // Finally, since the object adapter lock was acquired, we must
00287           // release it.
00288           this->object_adapter_->lock ().release ();
00289 
00290           /* FALLTHRU */
00291 
00292         case INITIAL_STAGE:
00293         default:
00294           // @@ Keep compiler happy, the states above are the only
00295           //    possible ones.
00296           break;
00297         }
00298     }
00299 
00300     void
00301     Servant_Upcall::post_invoke_servant_cleanup (void)
00302     {
00303       this->poa_->post_invoke_servant_cleanup (this->current_context_.object_id (),
00304                                                *this);
00305     }
00306 
00307     void
00308     Servant_Upcall::single_threaded_poa_setup (void)
00309     {
00310 #if (TAO_HAS_MINIMUM_POA == 0)
00311       // Serialize servants (if necessary).
00312       //
00313       // Note that this lock must be acquired *after* the object adapter
00314       // lock has been released.  This is necessary since we cannot block
00315       // waiting for the servant lock while holding the object adapter
00316       // lock.  Otherwise, the thread that wants to release this lock will
00317       // not be able to do so since it can't acquire the object adapterx
00318       // lock.
00319       if (this->poa_->enter() == -1)
00320         // Locking error.
00321         throw ::CORBA::OBJ_ADAPTER ();
00322 #endif /* !TAO_HAS_MINIMUM_POA == 0 */
00323     }
00324 
00325     void
00326     Servant_Upcall::single_threaded_poa_cleanup (void)
00327     {
00328 #if (TAO_HAS_MINIMUM_POA == 0)
00329       // Since the servant lock was acquired, we must release it.
00330       int const result = this->poa_->exit ();
00331 
00332       ACE_UNUSED_ARG (result);
00333 #endif /* TAO_HAS_MINIMUM_POA == 0 */
00334     }
00335 
00336     void
00337     Servant_Upcall::increment_servant_refcount (void)
00338     {
00339       // Cleanup servant related stuff.
00340       if (this->active_object_map_entry_ != 0)
00341         ++this->active_object_map_entry_->reference_count_;
00342     }
00343 
00344     void
00345     Servant_Upcall::servant_cleanup (void)
00346     {
00347       // Cleanup servant related stuff.
00348       if (this->active_object_map_entry_ != 0)
00349         {
00350           // Decrement the reference count.
00351           CORBA::UShort const new_count =
00352             --this->active_object_map_entry_->reference_count_;
00353 
00354           if (new_count == 0)
00355             {
00356               try
00357                 {
00358                   this->poa_->cleanup_servant (
00359                     this->active_object_map_entry_->servant_,
00360                     this->active_object_map_entry_->user_id_);
00361 
00362                 }
00363               catch (...)
00364                 {
00365                   // Ignore errors from servant cleanup ....
00366                 }
00367 
00368               if (this->poa_->waiting_servant_deactivation() > 0 &&
00369                   this->object_adapter_->enable_locking_)
00370                 {
00371                   // Wakeup all waiting threads.
00372                   this->poa_->servant_deactivation_condition_.broadcast ();
00373                 }
00374             }
00375         }
00376     }
00377 
00378     void
00379     Servant_Upcall::poa_cleanup (void)
00380     {
00381       // Decrease <poa->outstanding_requests_> now that the upcall
00382       // is complete.
00383       //
00384       // Note that the object adapter lock is acquired before
00385       // <POA::outstanding_requests_> is decreased.
00386       CORBA::ULong outstanding_requests =
00387         this->poa_->decrement_outstanding_requests ();
00388 
00389       // Check if all pending requests are over.
00390       if (outstanding_requests == 0)
00391         {
00392           // If locking is enabled and some thread is waiting in POA::destroy.
00393           if (this->object_adapter_->enable_locking_ &&
00394               this->poa_->wait_for_completion_pending_)
00395             {
00396               // Wakeup all waiting threads.
00397               this->poa_->outstanding_requests_condition_.broadcast ();
00398             }
00399 
00400           // Note that there is no need to check for
00401           // <non_servant_upcall_in_progress> since it is not possible for
00402           // non-servant upcalls to be in progress at this point.
00403           if (this->poa_->waiting_destruction_)
00404             {
00405               try
00406                 {
00407                   this->poa_->complete_destruction_i ();
00408                 }
00409               catch (const ::CORBA::Exception& ex)
00410                 {
00411                   // Ignore exceptions
00412                   ex._tao_print_exception ("TAO_POA::~complete_destruction_i");
00413                 }
00414 
00415               this->poa_ = 0;
00416             }
00417         }
00418     }
00419   }
00420 }
00421 
00422 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Sun Jan 27 13:23:44 2008 for TAO_PortableServer by doxygen 1.3.6