Servant_Upcall.cpp

Go to the documentation of this file.
00001 // Servant_Upcall.cpp,v 1.9 2006/06/20 07:16:51 jwillemsen Exp
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            "Servant_Upcall.cpp,v 1.9 2006/06/20 07:16:51 jwillemsen Exp")
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_ (),
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       ACE_ENV_ARG_DECL)
00057     {
00058       while (1)
00059         {
00060           int wait_occurred_restart_call = 0;
00061 
00062           int result =
00063             this->prepare_for_upcall_i (key,
00064                                         operation,
00065                                         forward_to,
00066                                         wait_occurred_restart_call
00067                                         ACE_ENV_ARG_PARAMETER);
00068           ACE_CHECK_RETURN (TAO_Adapter::DS_FAILED);
00069 
00070           if (result == TAO_Adapter::DS_FAILED &&
00071               wait_occurred_restart_call)
00072             {
00073               // We ended up waiting on a condition variable.  The POA
00074               // state may have changed while we are waiting.  Therefore,
00075               // we need to call prepare_for_upcall_i() again.  We also
00076               // need to cleanup the state of the upcall object before
00077               // continuing.
00078               this->upcall_cleanup ();
00079               continue;
00080             }
00081           else
00082             {
00083               return result;
00084             }
00085         }
00086     }
00087 
00088     int
00089     Servant_Upcall::prepare_for_upcall_i (
00090       const TAO::ObjectKey &key,
00091       const char *operation,
00092       CORBA::Object_out forward_to,
00093       int &wait_occurred_restart_call
00094       ACE_ENV_ARG_DECL)
00095     {
00096       // Acquire the object adapter lock first.
00097       int result = this->object_adapter_->lock ().acquire ();
00098       if (result == -1)
00099         // Locking error.
00100         ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
00101                           TAO_Adapter::DS_FAILED);
00102 
00103       // We have acquired the object adapter lock.  Record this for later
00104       // use.
00105       this->state_ = OBJECT_ADAPTER_LOCK_ACQUIRED;
00106 
00107       // Check if a non-servant upcall is in progress.  If a non-servant
00108       // upcall is in progress, wait for it to complete.  Unless of
00109       // course, the thread making the non-servant upcall is this thread.
00110       this->object_adapter_->wait_for_non_servant_upcalls_to_complete (
00111         ACE_ENV_SINGLE_ARG_PARAMETER);
00112       ACE_CHECK_RETURN (TAO_Adapter::DS_FAILED);
00113 
00114       // Locate the POA.
00115       this->object_adapter_->locate_poa (key,
00116                                          this->system_id_,
00117                                          this->poa_
00118                                          ACE_ENV_ARG_PARAMETER);
00119       ACE_CHECK_RETURN (TAO_Adapter::DS_FAILED);
00120 
00121       // Check the state of the POA.
00122       this->poa_->check_state (ACE_ENV_SINGLE_ARG_PARAMETER);
00123       ACE_CHECK_RETURN (TAO_Adapter::DS_FAILED);
00124 
00125       // Setup current for this request.
00126       this->current_context_.setup (this->poa_,
00127                                     key);
00128 
00129       // Increase <poa->outstanding_requests_> for the duration of finding
00130       // the POA, finding the servant, and making the upcall.
00131       this->poa_->increment_outstanding_requests ();
00132 
00133       // We have setup the POA Current.  Record this for later use.
00134       this->state_ = POA_CURRENT_SETUP;
00135 
00136       ACE_TRY
00137         {
00138           // Lookup the servant.
00139           this->servant_ =
00140             this->poa_->locate_servant_i (operation,
00141                                           this->system_id_,
00142                                           *this,
00143                                           this->current_context_,
00144                                           wait_occurred_restart_call
00145                                           ACE_ENV_ARG_PARAMETER);
00146           ACE_TRY_CHECK;
00147 
00148           if (wait_occurred_restart_call)
00149             return TAO_Adapter::DS_FAILED;
00150         }
00151 #if (TAO_HAS_MINIMUM_CORBA == 0) && !defined (CORBA_E_COMPACT) && !defined (CORBA_E_MICRO)
00152       ACE_CATCH (PortableServer::ForwardRequest, forward_request)
00153         {
00154           forward_to =
00155             CORBA::Object::_duplicate (forward_request.forward_reference.in ());
00156           return TAO_Adapter::DS_FORWARD;
00157         }
00158 #else
00159       ACE_CATCHANY
00160         {
00161           ACE_UNUSED_ARG (forward_to);
00162           ACE_RE_THROW;
00163         }
00164 #endif /* TAO_HAS_MINIMUM_CORBA */
00165       ACE_ENDTRY;
00166 
00167       // Now that we know the servant.
00168       this->current_context_.servant (this->servant_);
00169 
00170       // For servants from Servant Locators, there is no active object map
00171       // entry.
00172       if (this->active_object_map_entry ())
00173         this->current_context_.priority (this->active_object_map_entry ()->priority_);
00174 
00175       if (this->state_ != OBJECT_ADAPTER_LOCK_RELEASED)
00176         {
00177           // Release the object adapter lock.
00178           this->object_adapter_->lock ().release ();
00179 
00180           // We have release the object adapter lock.  Record this for
00181           // later use.
00182           this->state_ = OBJECT_ADAPTER_LOCK_RELEASED;
00183         }
00184 
00185       // Serialize servants (if appropriate).
00186       this->single_threaded_poa_setup (ACE_ENV_SINGLE_ARG_PARAMETER);
00187       ACE_CHECK_RETURN (TAO_Adapter::DS_FAILED);
00188 
00189       // We have acquired the servant lock.  Record this for later use.
00190       this->state_ = SERVANT_LOCK_ACQUIRED;
00191 
00192       // After this point, <this->servant_> is ready for dispatching.
00193       return TAO_Adapter::DS_OK;
00194     }
00195 
00196     void
00197     Servant_Upcall::pre_invoke_remote_request (
00198       TAO_ServerRequest &req
00199       ACE_ENV_ARG_DECL)
00200     {
00201       this->object_adapter_->servant_dispatcher_->pre_invoke_remote_request (
00202         this->poa (),
00203         this->priority (),
00204         req,
00205         this->pre_invoke_state_
00206         ACE_ENV_ARG_PARAMETER);
00207       ACE_CHECK;
00208     }
00209 
00210     void
00211     Servant_Upcall::pre_invoke_collocated_request (
00212       ACE_ENV_SINGLE_ARG_DECL)
00213     {
00214       this->object_adapter_->servant_dispatcher_->pre_invoke_collocated_request (
00215         this->poa (),
00216         this->priority (),
00217         this->pre_invoke_state_
00218         ACE_ENV_ARG_PARAMETER);
00219       ACE_CHECK;
00220     }
00221 
00222     void
00223     Servant_Upcall::post_invoke (void)
00224     {
00225       this->object_adapter_->servant_dispatcher_->post_invoke (
00226         this->poa (),
00227         this->pre_invoke_state_);
00228     }
00229 
00230     Servant_Upcall::Pre_Invoke_State::Pre_Invoke_State (void)
00231       : state_ (NO_ACTION_REQUIRED),
00232         original_native_priority_ (0),
00233         original_CORBA_priority_ (0)
00234     {
00235     }
00236 
00237     ::TAO_Root_POA *
00238     Servant_Upcall::lookup_POA (const TAO::ObjectKey &key
00239                                 ACE_ENV_ARG_DECL)
00240     {
00241       // Acquire the object adapter lock first.
00242       int result = this->object_adapter_->lock ().acquire ();
00243       if (result == -1)
00244         // Locking error.
00245         ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
00246                           0);
00247 
00248       // We have acquired the object adapter lock.  Record this for later
00249       // use.
00250       this->state_ = OBJECT_ADAPTER_LOCK_ACQUIRED;
00251 
00252       // Check if a non-servant upcall is in progress.  If a non-servant
00253       // upcall is in progress, wait for it to complete.  Unless of
00254       // course, the thread making the non-servant upcall is this thread.
00255       this->object_adapter_->wait_for_non_servant_upcalls_to_complete (
00256         ACE_ENV_SINGLE_ARG_PARAMETER);
00257       ACE_CHECK_RETURN (0);
00258 
00259       // Locate the POA.
00260       this->object_adapter_->locate_poa (key,
00261                                          this->system_id_,
00262                                          this->poa_
00263                                          ACE_ENV_ARG_PARAMETER);
00264       ACE_CHECK_RETURN (0);
00265 
00266       return this->poa_;
00267     }
00268 
00269     Servant_Upcall::~Servant_Upcall (void)
00270     {
00271       this->upcall_cleanup ();
00272     }
00273 
00274     void
00275     Servant_Upcall::upcall_cleanup (void)
00276     {
00277       this->post_invoke ();
00278 
00279       switch (this->state_)
00280         {
00281         case SERVANT_LOCK_ACQUIRED:
00282           // Unlock servant (if appropriate).
00283           this->single_threaded_poa_cleanup ();
00284 
00285           /* FALLTHRU */
00286 
00287         case OBJECT_ADAPTER_LOCK_RELEASED:
00288           // Cleanup servant locator related state.  Note that because
00289           // this operation does not change any Object Adapter related
00290           // state, it is ok to call it outside the lock.
00291           this->post_invoke_servant_cleanup ();
00292 
00293           // Since the object adapter lock was released, we must acquire
00294           // it.
00295           //
00296           // Note that errors are ignored here since we cannot do much
00297           // with it.
00298           this->object_adapter_->lock ().acquire ();
00299 
00300           // Check if a non-servant upcall is in progress.  If a
00301           // non-servant upcall is in progress, wait for it to complete.
00302           // Unless of course, the thread making the non-servant upcall is
00303           // this thread.
00304           this->object_adapter_->wait_for_non_servant_upcalls_to_complete ();
00305 
00306           // Cleanup servant related state.
00307           this->servant_cleanup ();
00308 
00309           /* FALLTHRU */
00310 
00311         case POA_CURRENT_SETUP:
00312           // Cleanup POA related state.
00313           this->poa_cleanup ();
00314 
00315           // Teardown current for this request.
00316           this->current_context_.teardown ();
00317 
00318           /* FALLTHRU */
00319 
00320         case OBJECT_ADAPTER_LOCK_ACQUIRED:
00321           // Finally, since the object adapter lock was acquired, we must
00322           // release it.
00323           this->object_adapter_->lock ().release ();
00324 
00325           /* FALLTHRU */
00326 
00327         case INITIAL_STAGE:
00328         default:
00329           // @@ Keep compiler happy, the states above are the only
00330           //    possible ones.
00331           break;
00332         }
00333     }
00334 
00335     void
00336     Servant_Upcall::post_invoke_servant_cleanup (void)
00337     {
00338       this->poa_->post_invoke_servant_cleanup (this->current_context_.object_id (),
00339                                                *this);
00340     }
00341 
00342     void
00343     Servant_Upcall::single_threaded_poa_setup (ACE_ENV_SINGLE_ARG_DECL)
00344     {
00345 #if (TAO_HAS_MINIMUM_POA == 0)
00346       // Serialize servants (if necessary).
00347       //
00348       // Note that this lock must be acquired *after* the object adapter
00349       // lock has been released.  This is necessary since we cannot block
00350       // waiting for the servant lock while holding the object adapter
00351       // lock.  Otherwise, the thread that wants to release this lock will
00352       // not be able to do so since it can't acquire the object adapterx
00353       // lock.
00354         int result = this->poa_->enter();
00355 
00356         if (result == -1)
00357           // Locking error.
00358           ACE_THROW (CORBA::OBJ_ADAPTER ());
00359 #else
00360         ACE_ENV_ARG_NOT_USED; // FUZZ: ignore check_for_ace_check
00361 #endif /* !TAO_HAS_MINIMUM_POA == 0 */
00362     }
00363 
00364     void
00365     Servant_Upcall::single_threaded_poa_cleanup (void)
00366     {
00367 #if (TAO_HAS_MINIMUM_POA == 0)
00368       int result = 0;
00369 
00370       // Since the servant lock was acquired, we must release it.
00371       result = this->poa_->exit ();
00372 
00373       ACE_UNUSED_ARG (result);
00374 #endif /* TAO_HAS_MINIMUM_POA == 0 */
00375     }
00376 
00377     void
00378     Servant_Upcall::increment_servant_refcount (void)
00379     {
00380       // Cleanup servant related stuff.
00381       if (this->active_object_map_entry_ != 0)
00382         ++this->active_object_map_entry_->reference_count_;
00383     }
00384 
00385     void
00386     Servant_Upcall::servant_cleanup (void)
00387     {
00388       // Cleanup servant related stuff.
00389       if (this->active_object_map_entry_ != 0)
00390         {
00391           // Decrement the reference count.
00392           CORBA::UShort new_count =
00393             --this->active_object_map_entry_->reference_count_;
00394 
00395           if (new_count == 0)
00396             {
00397               ACE_DECLARE_NEW_CORBA_ENV;
00398               ACE_TRY
00399                 {
00400                   this->poa_->cleanup_servant (
00401                     this->active_object_map_entry_->servant_,
00402                     this->active_object_map_entry_->user_id_
00403                     ACE_ENV_ARG_PARAMETER);
00404 
00405                   ACE_TRY_CHECK;
00406                 }
00407               ACE_CATCHALL
00408                 {
00409                   // Ignore errors from servant cleanup ....
00410                 }
00411               ACE_ENDTRY;
00412 
00413               if (this->poa_->waiting_servant_deactivation() > 0 &&
00414                   this->object_adapter_->enable_locking_)
00415                 {
00416                   // Wakeup all waiting threads.
00417                   this->poa_->servant_deactivation_condition_.broadcast ();
00418                 }
00419             }
00420         }
00421     }
00422 
00423     void
00424     Servant_Upcall::poa_cleanup (void)
00425     {
00426       // Decrease <poa->outstanding_requests_> now that the upcall
00427       // is complete.
00428       //
00429       // Note that the object adapter lock is acquired before
00430       // <POA::outstanding_requests_> is decreased.
00431       CORBA::ULong outstanding_requests =
00432         this->poa_->decrement_outstanding_requests ();
00433 
00434       // Check if all pending requests are over.
00435       if (outstanding_requests == 0)
00436         {
00437           // If locking is enabled and some thread is waiting in POA::destroy.
00438           if (this->object_adapter_->enable_locking_ &&
00439               this->poa_->wait_for_completion_pending_)
00440             {
00441               // Wakeup all waiting threads.
00442               this->poa_->outstanding_requests_condition_.broadcast ();
00443             }
00444 
00445           // Note that there is no need to check for
00446           // <non_servant_upcall_in_progress> since it is not possible for
00447           // non-servant upcalls to be in progress at this point.
00448           if (this->poa_->waiting_destruction_)
00449             {
00450               ACE_DECLARE_NEW_CORBA_ENV;
00451 
00452               ACE_TRY
00453                 {
00454                   this->poa_->complete_destruction_i (ACE_ENV_SINGLE_ARG_PARAMETER);
00455                   ACE_TRY_CHECK;
00456                 }
00457               ACE_CATCHANY
00458                 {
00459                   // Ignore exceptions
00460                   ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,
00461                                        "TAO_POA::~complete_destruction_i");
00462                 }
00463               ACE_ENDTRY;
00464               ACE_CHECK;
00465 
00466               this->poa_ = 0;
00467             }
00468         }
00469     }
00470   }
00471 }
00472 
00473 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 12:40:44 2006 for TAO_PortableServer by doxygen 1.3.6