RequestProcessingStrategyServantActivator.cpp

Go to the documentation of this file.
00001 // RequestProcessingStrategyServantActivator.cpp,v 1.8 2006/06/20 07:15:16 jwillemsen Exp
00002 #include "tao/ORB_Constants.h"
00003 #include "tao/PortableServer/ServantActivatorC.h"
00004 #include "tao/PortableServer/RequestProcessingStrategyServantActivator.h"
00005 #include "tao/PortableServer/Servant_Base.h"
00006 #include "tao/PortableServer/Non_Servant_Upcall.h"
00007 #include "tao/PortableServer/Root_POA.h"
00008 #include "tao/PortableServer/POA_Current_Impl.h"
00009 #include "tao/PortableServer/Servant_Upcall.h"
00010 
00011 ACE_RCSID (PortableServer,
00012            Request_Processing,
00013            "RequestProcessingStrategyServantActivator.cpp,v 1.8 2006/06/20 07:15:16 jwillemsen Exp")
00014 
00015 #if (TAO_HAS_MINIMUM_POA == 0) && !defined (CORBA_E_COMPACT) && !defined (CORBA_E_MICRO)
00016 
00017 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00018 
00019 namespace TAO
00020 {
00021   namespace Portable_Server
00022   {
00023     RequestProcessingStrategyServantActivator::RequestProcessingStrategyServantActivator (void) :
00024       etherealize_objects_ (1)
00025     {
00026     }
00027 
00028     void
00029     RequestProcessingStrategyServantActivator::strategy_cleanup (
00030       ACE_ENV_SINGLE_ARG_DECL)
00031     {
00032       {
00033         Non_Servant_Upcall non_servant_upcall (*this->poa_);
00034         ACE_UNUSED_ARG (non_servant_upcall);
00035 
00036         this->servant_activator_ =
00037           PortableServer::ServantActivator::_nil ();
00038       }
00039 
00040       RequestProcessingStrategy::strategy_cleanup (ACE_ENV_SINGLE_ARG_PARAMETER);
00041       ACE_CHECK;
00042     }
00043 
00044     PortableServer::ServantManager_ptr
00045     RequestProcessingStrategyServantActivator::get_servant_manager (
00046       ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
00047         ACE_THROW_SPEC ((CORBA::SystemException,
00048                          PortableServer::POA::WrongPolicy))
00049     {
00050       return PortableServer::ServantManager::_duplicate (this->servant_activator_.in ());
00051     }
00052 
00053     void
00054     RequestProcessingStrategyServantActivator::set_servant_manager (
00055       PortableServer::ServantManager_ptr imgr
00056       ACE_ENV_ARG_DECL)
00057       ACE_THROW_SPEC ((CORBA::SystemException,
00058                        PortableServer::POA::WrongPolicy))
00059     {
00060       // This operation sets the default servant manager associated with the
00061       // POA. This operation may only be invoked once after a POA has been
00062       // created. Attempting to set the servant manager after one has already
00063       // been set will result in the BAD_INV_ORDER system exception with
00064       // standard minor code 6 being raised (see 11.3.9.12 of the corba spec)
00065       if (!CORBA::is_nil (this->servant_activator_.in ()))
00066         {
00067           ACE_THROW (CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 6,
00068                                            CORBA::COMPLETED_NO));
00069         }
00070 
00071       this->servant_activator_ =
00072         PortableServer::ServantActivator::_narrow (imgr
00073                                                    ACE_ENV_ARG_PARAMETER);
00074       ACE_CHECK;
00075 
00076       this->validate_servant_manager (this->servant_activator_.in ()
00077                                       ACE_ENV_ARG_PARAMETER);
00078       ACE_CHECK;
00079     }
00080 
00081     TAO_SERVANT_LOCATION
00082     RequestProcessingStrategyServantActivator::locate_servant (
00083       const PortableServer::ObjectId &system_id,
00084       PortableServer::Servant &servant
00085       ACE_ENV_ARG_DECL)
00086     {
00087       TAO_SERVANT_LOCATION location = TAO_SERVANT_NOT_FOUND;
00088 
00089       location = this->poa_->servant_present (system_id,
00090                                               servant
00091                                               ACE_ENV_ARG_PARAMETER);
00092       ACE_CHECK_RETURN (TAO_SERVANT_NOT_FOUND);
00093 
00094       if (location == TAO_SERVANT_NOT_FOUND)
00095         {
00096           if (!CORBA::is_nil (this->servant_activator_.in ()))
00097             {
00098               location = TAO_SERVANT_MANAGER;
00099             }
00100         }
00101 
00102       return location;
00103     }
00104 
00105     PortableServer::Servant
00106     RequestProcessingStrategyServantActivator::locate_servant (
00107       const char * /*operation*/,
00108       const PortableServer::ObjectId &system_id,
00109       TAO::Portable_Server::Servant_Upcall &servant_upcall,
00110       TAO::Portable_Server::POA_Current_Impl &poa_current_impl,
00111       int &wait_occurred_restart_call
00112       ACE_ENV_ARG_DECL)
00113     {
00114       PortableServer::Servant servant = 0;
00115 
00116       servant = this->poa_->find_servant (system_id,
00117                                           servant_upcall,
00118                                           poa_current_impl
00119                                           ACE_ENV_ARG_PARAMETER);
00120       ACE_CHECK_RETURN (0);
00121 
00122       if (servant != 0)
00123         {
00124           return servant;
00125         }
00126 
00127       // If the POA has the USE_SERVANT_MANAGER policy, a servant manager
00128       // has been associated with the POA so the POA will invoke incarnate
00129       // or preinvoke on it to find a servant that may handle the
00130       // request. (The choice of method depends on the NON_RETAIN or
00131       // RETAIN policy of the POA.) If no servant manager has been
00132       // associated with the POA, the POA raises the OBJ_ADAPTER system
00133       // exception.
00134       //
00135       // If a servant manager is located and invoked, but the servant
00136       // manager is not directly capable of incarnating the object, it
00137       // (the servant manager) may deal with the circumstance in a variety
00138       // of ways, all of which are the application's responsibility.  Any
00139       // system exception raised by the servant manager will be returned
00140       // to the client in the reply. In addition to standard CORBA
00141       // exceptions, a servant manager is capable of raising a
00142       // ForwardRequest exception. This exception includes an object
00143       // reference.
00144       //
00145 
00146       this->validate_servant_manager (this->servant_activator_.in ()
00147                                       ACE_ENV_ARG_PARAMETER);
00148       ACE_CHECK_RETURN (0);
00149 
00150       servant =
00151         this->incarnate_servant (poa_current_impl.object_id ()
00152                                  ACE_ENV_ARG_PARAMETER);
00153       ACE_CHECK_RETURN (0);
00154 
00155       // If the incarnate operation returns a servant that is
00156       // already active for a different Object Id and if the POA
00157       // also has the UNIQUE_ID policy, the incarnate has violated
00158       // the POA policy and is considered to be in error. The POA
00159       // will raise an OBJ_ADAPTER system exception for the
00160       // request.
00161       bool may_activate =
00162         this->poa_->is_servant_activation_allowed (servant,
00163                                                    wait_occurred_restart_call);
00164 
00165       if (!may_activate)
00166         {
00167           // If we are not allowed to activate the servant, throw an exception
00168           // etherealize is not called because the servant is never added to
00169           // the active object map
00170           ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
00171                             0);
00172         }
00173 
00174       // The POA enters the returned Servant value into the Active
00175       // Object Map so that subsequent requests with the same
00176       // ObjectId value will be delivered directly to that servant
00177       // without invoking the servant manager.  Only run if there
00178       // are no errors or if a restart is not required.
00179       if (!wait_occurred_restart_call)
00180         {
00181           int result =
00182             this->poa_->
00183               rebind_using_user_id_and_system_id (servant,
00184                                                   poa_current_impl.object_id (),
00185                                                   system_id,
00186                                                   servant_upcall);
00187           if (result != 0)
00188             {
00189               // Throw an exception, etherealize is not called because servant
00190               // is not added to the active object map
00191               ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
00192                                 0);
00193             }
00194 
00195           // Increment the reference count on the servant upcall.
00196           servant_upcall.increment_servant_refcount ();
00197         }
00198       else
00199         {
00200           CORBA::Boolean cleanup_in_progress = 0;
00201           this->etherealize_servant (poa_current_impl.object_id (),
00202                                      servant,
00203                                      cleanup_in_progress
00204                                      ACE_ENV_ARG_PARAMETER);
00205           ACE_CHECK_RETURN (0);
00206 
00207           // We ended up waiting on a condition variable, the
00208           // POA state may have changed while we are waiting.
00209           // Therefore, we need to restart this call.
00210           return 0;
00211         }
00212 
00213       // Success
00214       return servant;
00215     }
00216 
00217     void
00218     RequestProcessingStrategyServantActivator::etherealize_servant (
00219       const PortableServer::ObjectId& object_id,
00220       PortableServer::Servant servant,
00221       CORBA::Boolean cleanup_in_progress
00222       ACE_ENV_ARG_DECL)
00223     {
00224       CORBA::Boolean remaining_activations =
00225         this->poa_->servant_has_remaining_activations (servant);
00226 
00227       // ATTENTION: Trick locking here, see class header for details
00228       Non_Servant_Upcall non_servant_upcall (*this->poa_);
00229       ACE_UNUSED_ARG (non_servant_upcall);
00230 
00231       // @todo This is not according to the spec. According to 11.3.6.2 at the
00232       // end when etherealize returns a system exception the POA ignores the
00233       // exception
00234       this->servant_activator_->etherealize (object_id,
00235                                              this->poa_,
00236                                              servant,
00237                                              cleanup_in_progress,
00238                                              remaining_activations
00239                                              ACE_ENV_ARG_PARAMETER);
00240       ACE_CHECK;
00241     }
00242 
00243     PortableServer::Servant
00244     RequestProcessingStrategyServantActivator::incarnate_servant (
00245       const PortableServer::ObjectId& object_id
00246       ACE_ENV_ARG_DECL)
00247     {
00248       PortableServer::Servant servant = 0;
00249 
00250       // ATTENTION: Trick locking here, see class header for details
00251       Non_Servant_Upcall non_servant_upcall (*this->poa_);
00252       ACE_UNUSED_ARG (non_servant_upcall);
00253 
00254       // @@
00255       // Invocations of incarnate on the servant manager are serialized.
00256       // Invocations of etherealize on the servant manager are serialized.
00257       // Invocations of incarnate and etherealize on the servant manager are mutually exclusive.
00258       servant = this->servant_activator_->incarnate (object_id,
00259                                                      this->poa_
00260                                                      ACE_ENV_ARG_PARAMETER);
00261       ACE_CHECK_RETURN (0);
00262 
00263       if (servant == 0)
00264         {
00265           ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (CORBA::OMGVMCID | 7,
00266                                                 CORBA::COMPLETED_NO),
00267                                                 0);
00268         }
00269       else
00270         {
00271           return servant;
00272         }
00273     }
00274 
00275     void
00276     RequestProcessingStrategyServantActivator::cleanup_servant (
00277       PortableServer::Servant servant,
00278       const PortableServer::ObjectId &user_id
00279       ACE_ENV_ARG_DECL)
00280     {
00281       // If a servant manager is associated with the POA,
00282       // ServantLocator::etherealize will be invoked with the oid and the
00283       // servant. (The deactivate_object operation does not wait for the
00284       // etherealize operation to complete before deactivate_object
00285       // returns.)
00286       //
00287       // Note: If the servant associated with the oid is serving multiple
00288       // Object Ids, ServantLocator::etherealize may be invoked multiple
00289       // times with the same servant when the other objects are
00290       // deactivated. It is the responsibility of the object
00291       // implementation to refrain from destroying the servant while it is
00292       // active with any Id.
00293 
00294       // If the POA has no ServantActivator associated with it, the POA
00295       // implementation calls _remove_ref when all operation invocations
00296       // have completed. If there is a ServantActivator, the Servant is
00297       // consumed by the call to ServantActivator::etherealize instead.
00298 
00299       // @bala, is this order correct, see 11.3.9.17 of the spec, it
00300       // says first remove from the map, then etherealize. not the
00301       // other way around
00302       // @@ Johnny, you are right! This will not show up until a
00303       // thread is trying to activate the object in another thread
00304       // using activate_object_with_id (). A test case is a must for
00305       // atleast this issue.
00306       if (servant)
00307         {
00308           if (this->etherealize_objects_ &&
00309               !CORBA::is_nil (this->servant_activator_.in ()))
00310             {
00311               this->etherealize_servant (user_id,
00312                                          servant,
00313                                          this->poa_->cleanup_in_progress ()
00314                                          ACE_ENV_ARG_PARAMETER);
00315               ACE_CHECK;
00316             }
00317           else
00318             {
00319               // ATTENTION: Trick locking here, see class header for details
00320               Non_Servant_Upcall non_servant_upcall (*this->poa_);
00321               ACE_UNUSED_ARG (non_servant_upcall);
00322 
00323               servant->_remove_ref (ACE_ENV_SINGLE_ARG_PARAMETER);
00324               ACE_CHECK;
00325             }
00326         }
00327 
00328       // This operation causes the association of the Object Id specified
00329       // by the oid parameter and its servant to be removed from the
00330       // Active Object Map.
00331       int result = this->poa_->unbind_using_user_id (user_id);
00332 
00333       if (result != 0)
00334         ACE_THROW (CORBA::OBJ_ADAPTER ());
00335     }
00336 
00337     void
00338     RequestProcessingStrategyServantActivator::etherealize_objects (
00339       CORBA::Boolean etherealize_objects)
00340     {
00341       this->etherealize_objects_ = etherealize_objects;
00342     }
00343 
00344     void
00345     RequestProcessingStrategyServantActivator::post_invoke_servant_cleanup(
00346       const PortableServer::ObjectId &/*system_id*/,
00347       const TAO::Portable_Server::Servant_Upcall &/*servant_upcall*/)
00348     {
00349     }
00350   }
00351 }
00352 
00353 TAO_END_VERSIONED_NAMESPACE_DECL
00354 
00355 #endif /* TAO_HAS_MINIMUM_POA == 0 */

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