summaryrefslogtreecommitdiff
path: root/trunk/TAO/tao/PortableServer/RequestProcessingStrategyServantActivator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/TAO/tao/PortableServer/RequestProcessingStrategyServantActivator.cpp')
-rw-r--r--trunk/TAO/tao/PortableServer/RequestProcessingStrategyServantActivator.cpp357
1 files changed, 357 insertions, 0 deletions
diff --git a/trunk/TAO/tao/PortableServer/RequestProcessingStrategyServantActivator.cpp b/trunk/TAO/tao/PortableServer/RequestProcessingStrategyServantActivator.cpp
new file mode 100644
index 00000000000..ab9874f5e5d
--- /dev/null
+++ b/trunk/TAO/tao/PortableServer/RequestProcessingStrategyServantActivator.cpp
@@ -0,0 +1,357 @@
+// $Id$
+#include "tao/orbconf.h"
+
+ACE_RCSID (PortableServer,
+ Request_Processing,
+ "$Id$")
+
+#if (TAO_HAS_MINIMUM_POA == 0) && !defined (CORBA_E_COMPACT) && !defined (CORBA_E_MICRO)
+
+#include "tao/ORB_Constants.h"
+#include "tao/PortableServer/ServantActivatorC.h"
+#include "tao/PortableServer/RequestProcessingStrategyServantActivator.h"
+#include "tao/PortableServer/Servant_Base.h"
+#include "tao/PortableServer/Non_Servant_Upcall.h"
+#include "tao/PortableServer/Root_POA.h"
+#include "tao/PortableServer/POA_Current_Impl.h"
+#include "tao/PortableServer/Servant_Upcall.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace TAO
+{
+ namespace Portable_Server
+ {
+ RequestProcessingStrategyServantActivator::RequestProcessingStrategyServantActivator (void) :
+ etherealize_objects_ (1)
+ {
+ }
+
+ void
+ RequestProcessingStrategyServantActivator::strategy_cleanup (
+ ACE_ENV_SINGLE_ARG_DECL)
+ {
+ {
+ Non_Servant_Upcall non_servant_upcall (*this->poa_);
+ ACE_UNUSED_ARG (non_servant_upcall);
+
+ this->servant_activator_ =
+ PortableServer::ServantActivator::_nil ();
+ }
+
+ RequestProcessingStrategy::strategy_cleanup (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+
+ PortableServer::ServantManager_ptr
+ RequestProcessingStrategyServantActivator::get_servant_manager (
+ ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::WrongPolicy))
+ {
+ return PortableServer::ServantManager::_duplicate (this->servant_activator_.in ());
+ }
+
+ void
+ RequestProcessingStrategyServantActivator::set_servant_manager (
+ PortableServer::ServantManager_ptr imgr
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::WrongPolicy))
+ {
+ // This operation sets the default servant manager associated with the
+ // POA. This operation may only be invoked once after a POA has been
+ // created. Attempting to set the servant manager after one has already
+ // been set will result in the BAD_INV_ORDER system exception with
+ // standard minor code 6 being raised (see 11.3.9.12 of the corba spec)
+ if (!CORBA::is_nil (this->servant_activator_.in ()))
+ {
+ ACE_THROW (CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 6,
+ CORBA::COMPLETED_NO));
+ }
+
+ this->servant_activator_ =
+ PortableServer::ServantActivator::_narrow (imgr
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ this->validate_servant_manager (this->servant_activator_.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+
+ TAO_SERVANT_LOCATION
+ RequestProcessingStrategyServantActivator::locate_servant (
+ const PortableServer::ObjectId &system_id,
+ PortableServer::Servant &servant
+ ACE_ENV_ARG_DECL)
+ {
+ TAO_SERVANT_LOCATION location = TAO_SERVANT_NOT_FOUND;
+
+ location = this->poa_->servant_present (system_id,
+ servant
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (TAO_SERVANT_NOT_FOUND);
+
+ if (location == TAO_SERVANT_NOT_FOUND)
+ {
+ if (!CORBA::is_nil (this->servant_activator_.in ()))
+ {
+ location = TAO_SERVANT_MANAGER;
+ }
+ }
+
+ return location;
+ }
+
+ PortableServer::Servant
+ RequestProcessingStrategyServantActivator::locate_servant (
+ const char * /*operation*/,
+ const PortableServer::ObjectId &system_id,
+ TAO::Portable_Server::Servant_Upcall &servant_upcall,
+ TAO::Portable_Server::POA_Current_Impl &poa_current_impl,
+ bool &wait_occurred_restart_call
+ ACE_ENV_ARG_DECL)
+ {
+ PortableServer::Servant servant = 0;
+
+ servant = this->poa_->find_servant (system_id,
+ servant_upcall,
+ poa_current_impl
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ if (servant != 0)
+ {
+ return servant;
+ }
+
+ // If the POA has the USE_SERVANT_MANAGER policy, a servant manager
+ // has been associated with the POA so the POA will invoke incarnate
+ // or preinvoke on it to find a servant that may handle the
+ // request. (The choice of method depends on the NON_RETAIN or
+ // RETAIN policy of the POA.) If no servant manager has been
+ // associated with the POA, the POA raises the OBJ_ADAPTER system
+ // exception.
+ //
+ // If a servant manager is located and invoked, but the servant
+ // manager is not directly capable of incarnating the object, it
+ // (the servant manager) may deal with the circumstance in a variety
+ // of ways, all of which are the application's responsibility. Any
+ // system exception raised by the servant manager will be returned
+ // to the client in the reply. In addition to standard CORBA
+ // exceptions, a servant manager is capable of raising a
+ // ForwardRequest exception. This exception includes an object
+ // reference.
+ //
+
+ this->validate_servant_manager (this->servant_activator_.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ servant =
+ this->incarnate_servant (poa_current_impl.object_id ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // If the incarnate operation returns a servant that is
+ // already active for a different Object Id and if the POA
+ // also has the UNIQUE_ID policy, the incarnate has violated
+ // the POA policy and is considered to be in error. The POA
+ // will raise an OBJ_ADAPTER system exception for the
+ // request.
+ bool may_activate =
+ this->poa_->is_servant_activation_allowed (servant,
+ wait_occurred_restart_call);
+
+ if (!may_activate)
+ {
+ // If we are not allowed to activate the servant, throw an exception
+ // etherealize is not called because the servant is never added to
+ // the active object map
+ ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
+ 0);
+ }
+
+ // The POA enters the returned Servant value into the Active
+ // Object Map so that subsequent requests with the same
+ // ObjectId value will be delivered directly to that servant
+ // without invoking the servant manager. Only run if there
+ // are no errors or if a restart is not required.
+ if (!wait_occurred_restart_call)
+ {
+ int result =
+ this->poa_->
+ rebind_using_user_id_and_system_id (servant,
+ poa_current_impl.object_id (),
+ system_id,
+ servant_upcall);
+ if (result != 0)
+ {
+ // Throw an exception, etherealize is not called because servant
+ // is not added to the active object map
+ ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
+ 0);
+ }
+
+ // Increment the reference count on the servant upcall.
+ servant_upcall.increment_servant_refcount ();
+ }
+ else
+ {
+ CORBA::Boolean cleanup_in_progress = 0;
+ this->etherealize_servant (poa_current_impl.object_id (),
+ servant,
+ cleanup_in_progress
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // We ended up waiting on a condition variable, the
+ // POA state may have changed while we are waiting.
+ // Therefore, we need to restart this call.
+ return 0;
+ }
+
+ // Success
+ return servant;
+ }
+
+ void
+ RequestProcessingStrategyServantActivator::etherealize_servant (
+ const PortableServer::ObjectId& object_id,
+ PortableServer::Servant servant,
+ CORBA::Boolean cleanup_in_progress
+ ACE_ENV_ARG_DECL)
+ {
+ CORBA::Boolean remaining_activations =
+ this->poa_->servant_has_remaining_activations (servant);
+
+ // ATTENTION: Trick locking here, see class header for details
+ Non_Servant_Upcall non_servant_upcall (*this->poa_);
+ ACE_UNUSED_ARG (non_servant_upcall);
+
+ // @todo This is not according to the spec. According to 11.3.6.2 at the
+ // end when etherealize returns a system exception the POA ignores the
+ // exception
+ this->servant_activator_->etherealize (object_id,
+ this->poa_,
+ servant,
+ cleanup_in_progress,
+ remaining_activations
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+
+ PortableServer::Servant
+ RequestProcessingStrategyServantActivator::incarnate_servant (
+ const PortableServer::ObjectId& object_id
+ ACE_ENV_ARG_DECL)
+ {
+ PortableServer::Servant servant = 0;
+
+ // ATTENTION: Trick locking here, see class header for details
+ Non_Servant_Upcall non_servant_upcall (*this->poa_);
+ ACE_UNUSED_ARG (non_servant_upcall);
+
+ // @@
+ // Invocations of incarnate on the servant manager are serialized.
+ // Invocations of etherealize on the servant manager are serialized.
+ // Invocations of incarnate and etherealize on the servant manager are mutually exclusive.
+ servant = this->servant_activator_->incarnate (object_id,
+ this->poa_
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ if (servant == 0)
+ {
+ ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (CORBA::OMGVMCID | 7,
+ CORBA::COMPLETED_NO),
+ 0);
+ }
+ else
+ {
+ return servant;
+ }
+ }
+
+ void
+ RequestProcessingStrategyServantActivator::cleanup_servant (
+ PortableServer::Servant servant,
+ const PortableServer::ObjectId &user_id
+ ACE_ENV_ARG_DECL)
+ {
+ // If a servant manager is associated with the POA,
+ // ServantLocator::etherealize will be invoked with the oid and the
+ // servant. (The deactivate_object operation does not wait for the
+ // etherealize operation to complete before deactivate_object
+ // returns.)
+ //
+ // Note: If the servant associated with the oid is serving multiple
+ // Object Ids, ServantLocator::etherealize may be invoked multiple
+ // times with the same servant when the other objects are
+ // deactivated. It is the responsibility of the object
+ // implementation to refrain from destroying the servant while it is
+ // active with any Id.
+
+ // If the POA has no ServantActivator associated with it, the POA
+ // implementation calls _remove_ref when all operation invocations
+ // have completed. If there is a ServantActivator, the Servant is
+ // consumed by the call to ServantActivator::etherealize instead.
+
+ // @bala, is this order correct, see 11.3.9.17 of the spec, it
+ // says first remove from the map, then etherealize. not the
+ // other way around
+ // @@ Johnny, you are right! This will not show up until a
+ // thread is trying to activate the object in another thread
+ // using activate_object_with_id (). A test case is a must for
+ // atleast this issue.
+ if (servant)
+ {
+ if (this->etherealize_objects_ &&
+ !CORBA::is_nil (this->servant_activator_.in ()))
+ {
+ this->etherealize_servant (user_id,
+ servant,
+ this->poa_->cleanup_in_progress ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+ else
+ {
+ // ATTENTION: Trick locking here, see class header for details
+ Non_Servant_Upcall non_servant_upcall (*this->poa_);
+ ACE_UNUSED_ARG (non_servant_upcall);
+
+ servant->_remove_ref (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+ }
+
+ // This operation causes the association of the Object Id specified
+ // by the oid parameter and its servant to be removed from the
+ // Active Object Map.
+ int result = this->poa_->unbind_using_user_id (user_id);
+
+ if (result != 0)
+ ACE_THROW (CORBA::OBJ_ADAPTER ());
+ }
+
+ void
+ RequestProcessingStrategyServantActivator::etherealize_objects (
+ CORBA::Boolean etherealize_objects)
+ {
+ this->etherealize_objects_ = etherealize_objects;
+ }
+
+ void
+ RequestProcessingStrategyServantActivator::post_invoke_servant_cleanup(
+ const PortableServer::ObjectId &/*system_id*/,
+ const TAO::Portable_Server::Servant_Upcall &/*servant_upcall*/)
+ {
+ }
+ }
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* TAO_HAS_MINIMUM_POA == 0 */