summaryrefslogtreecommitdiff
path: root/TAO/tao/PortableServer/ServantRetentionStrategyRetain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/tao/PortableServer/ServantRetentionStrategyRetain.cpp')
-rw-r--r--TAO/tao/PortableServer/ServantRetentionStrategyRetain.cpp1106
1 files changed, 1106 insertions, 0 deletions
diff --git a/TAO/tao/PortableServer/ServantRetentionStrategyRetain.cpp b/TAO/tao/PortableServer/ServantRetentionStrategyRetain.cpp
new file mode 100644
index 00000000000..b12a5e5b324
--- /dev/null
+++ b/TAO/tao/PortableServer/ServantRetentionStrategyRetain.cpp
@@ -0,0 +1,1106 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file ServantRetentionStrategyRetain.cpp
+ *
+ * $Id$
+ *
+ */
+//=============================================================================
+
+#include "tao/ORB_Core.h"
+#include "tao/debug.h"
+#include "tao/PortableServer/ServantRetentionStrategyRetain.h"
+#include "tao/PortableServer/Non_Servant_Upcall.h"
+#include "tao/PortableServer/Servant_Upcall.h"
+#include "tao/PortableServer/POA_Current_Impl.h"
+#include "tao/PortableServer/Root_POA.h"
+#include "tao/PortableServer/Active_Object_Map.h"
+#include "tao/PortableServer/Active_Object_Map_Entry.h"
+#include "ace/Auto_Ptr.h"
+
+ACE_RCSID (PortableServer,
+ Servant_Retention_Strategy,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace TAO
+{
+ namespace Portable_Server
+ {
+ ServantRetentionStrategyRetain::ServantRetentionStrategyRetain (void) :
+ ServantRetentionStrategyNonRetain (),
+ active_object_map_ (0),
+ waiting_servant_deactivation_ (0)
+ {
+ }
+
+ void
+ ServantRetentionStrategyRetain::strategy_init (
+ TAO_Root_POA *poa
+ ACE_ENV_ARG_DECL)
+ {
+ poa_ = poa;
+
+ // Create the active object map to be used
+ TAO_Active_Object_Map *active_object_map = 0;
+ ACE_NEW_THROW_EX (active_object_map,
+ TAO_Active_Object_Map (!poa->system_id (),
+ !poa->allow_multiple_activations (),
+ poa->is_persistent (),
+ poa->orb_core().server_factory ()->active_object_map_creation_parameters ()
+ ACE_ENV_ARG_PARAMETER), CORBA::NO_MEMORY ());
+ ACE_CHECK;
+
+ // Give ownership of the new map to the auto pointer. Note, that it
+ // is important for the auto pointer to take ownership before
+ // checking for exception since we may need to delete the new map.
+ auto_ptr<TAO_Active_Object_Map> new_active_object_map (active_object_map);
+
+ // Check for exception in construction of the active object map.
+ ACE_CHECK;
+
+ // Finally everything is fine. Make sure to take ownership away
+ // from the auto pointer.
+ this->active_object_map_ = new_active_object_map.release ();
+ }
+
+ void
+ ServantRetentionStrategyRetain::strategy_cleanup(
+ ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+ {
+ // Delete the active object map.
+ delete this->active_object_map_;
+ active_object_map_ = 0;
+ }
+
+ void
+ ServantRetentionStrategyRetain::deactivate_object (
+ const PortableServer::ObjectId &id
+ ACE_ENV_ARG_DECL)
+ {
+
+ TAO_Active_Object_Map_Entry *active_object_map_entry = 0;
+ int result = this->active_object_map_->
+ find_entry_using_user_id (id,
+ active_object_map_entry);
+
+ // If there is no active object associated with the specified Object
+ // Id, the operation raises an ObjectNotActive exception.
+ if (result != 0)
+ {
+ ACE_THROW (PortableServer::POA::ObjectNotActive ());
+ }
+
+ this->deactivate_map_entry (active_object_map_entry
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+
+ void
+ ServantRetentionStrategyRetain::deactivate_map_entry (
+ TAO_Active_Object_Map_Entry *active_object_map_entry
+ ACE_ENV_ARG_DECL)
+ {
+ // Decrement the reference count.
+ CORBA::UShort const new_count = --active_object_map_entry->reference_count_;
+
+ // Inform the custom servant dispatching (CSD) strategy that the
+ // servant is deactivated. This would be called just once when the
+ // servant is deactivated the first time.
+ if (active_object_map_entry->deactivated_ == 0)
+ {
+ this->poa_->servant_deactivated_hook (
+ active_object_map_entry->servant_,
+ active_object_map_entry->user_id_
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+
+ if (new_count == 0)
+ {
+ this->poa_->cleanup_servant (active_object_map_entry->servant_,
+ active_object_map_entry->user_id_
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+ else
+ {
+ // It should be noted that there may be a period of time between
+ // an object's deactivation and the etherealization (during
+ // which outstanding requests are being processed) in which
+ // arriving requests on that object should not be passed to its
+ // servant. During this period, requests targeted for such an
+ // object act as if the POA were in holding state until
+ // etherealize completes. If etherealize is called as a
+ // consequence of a deactivate call with a etherealize_objects
+ // parameter of TRUE, incoming requests are rejected.
+
+ // Else mark entry as closed...
+ active_object_map_entry->deactivated_ = 1;
+ }
+ }
+
+ int
+ ServantRetentionStrategyRetain::unbind_using_user_id (
+ const PortableServer::ObjectId &user_id)
+ {
+ return this->active_object_map_->
+ unbind_using_user_id (user_id);
+ }
+
+ PortableServer::Servant
+ ServantRetentionStrategyRetain::find_servant (
+ const PortableServer::ObjectId &system_id
+ ACE_ENV_ARG_DECL)
+ {
+ // Find user id from system id.
+ PortableServer::ObjectId_var user_id;
+ if (active_object_map_->
+ find_user_id_using_system_id (system_id,
+ user_id.out()) != 0)
+ {
+ ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
+ 0);
+ }
+
+ // This operation returns the active servant associated with the
+ // specified system Object Id value. If the Object Id value is
+ // not active in the POA, an ObjectNotActive exception is
+ // raised.
+ TAO_Active_Object_Map_Entry *entry = 0;
+ PortableServer::Servant servant = 0;
+
+ int const result =
+ active_object_map_->
+ find_servant_using_system_id_and_user_id (system_id,
+ user_id.in(),
+ servant,
+ entry);
+
+ if (result == -1)
+ {
+ ACE_THROW_RETURN (PortableServer::POA::ObjectNotActive (),
+ 0);
+ }
+
+ return servant;
+ }
+
+ PortableServer::ObjectId *
+ ServantRetentionStrategyRetain::system_id_to_object_id (
+ const PortableServer::ObjectId &system_id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::WrongAdapter,
+ PortableServer::POA::WrongPolicy))
+ {
+ // The object denoted by the reference does not have to be
+ // active for this operation to succeed.
+ PortableServer::ObjectId_var user_id;
+ if (this->active_object_map_->
+ find_user_id_using_system_id (system_id,
+ user_id.out ()) != 0)
+ {
+ ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
+ 0);
+ }
+
+ return user_id._retn ();
+ }
+
+ PortableServer::Servant
+ ServantRetentionStrategyRetain::user_id_to_servant (
+ const PortableServer::ObjectId &id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ObjectNotActive,
+ PortableServer::POA::WrongPolicy))
+ {
+ // If the POA has the RETAIN policy and the specified ObjectId is in
+ // the Active Object Map, this operation returns the servant
+ // associated with that object in the Active Object Map.
+ PortableServer::Servant servant = 0;
+
+ int const result =
+ this->active_object_map_->find_servant_using_user_id (id,
+ servant);
+
+ if (result == -1)
+ {
+ ACE_THROW_RETURN (PortableServer::POA::ObjectNotActive (),
+ 0);
+ }
+
+ return servant;
+ }
+
+ CORBA::Object_ptr
+ ServantRetentionStrategyRetain::id_to_reference (
+ const PortableServer::ObjectId &id,
+ bool indirect
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ObjectNotActive,
+ PortableServer::POA::WrongPolicy))
+ {
+ // If an object with the specified Object Id value is currently
+ // active, a reference encapsulating the information used to
+ // activate the object is returned.
+ PortableServer::ObjectId_var system_id;
+ PortableServer::Servant servant;
+ CORBA::Short priority;
+
+ if (this->active_object_map_->
+ find_servant_and_system_id_using_user_id (id,
+ servant,
+ system_id.out (),
+ priority) == 0)
+ {
+ // Remember params for potentially invoking <key_to_object> later.
+ this->poa_->key_to_object_params_.set (system_id,
+ servant->_interface_repository_id (),
+ servant,
+ 1,
+ priority,
+ indirect);
+
+ return this->poa_->invoke_key_to_object_helper_i (servant->_interface_repository_id (),
+ id
+ ACE_ENV_ARG_PARAMETER);
+ }
+ else
+ {
+ // If the Object Id value is not active in the POA, an
+ // ObjectNotActive exception is raised.
+ ACE_THROW_RETURN (PortableServer::POA::ObjectNotActive (),
+ CORBA::Object::_nil ());
+ }
+ }
+
+ TAO_SERVANT_LOCATION
+ ServantRetentionStrategyRetain::servant_present (
+ const PortableServer::ObjectId &system_id,
+ PortableServer::Servant &servant
+ ACE_ENV_ARG_DECL)
+ {
+ // Find user id from system id.
+ PortableServer::ObjectId_var user_id;
+ if (this->active_object_map_->
+ find_user_id_using_system_id (system_id,
+ user_id.out()) != 0)
+ {
+ ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
+ TAO_SERVANT_NOT_FOUND);
+ }
+
+ TAO_Active_Object_Map_Entry *entry = 0;
+ int const result = this->active_object_map_->
+ find_servant_using_system_id_and_user_id (system_id,
+ user_id.in(),
+ servant,
+ entry);
+ if (result == 0)
+ {
+ // Success
+ return TAO_SERVANT_FOUND;
+ }
+ else
+ {
+ return TAO_SERVANT_NOT_FOUND;
+ }
+ }
+
+ PortableServer::Servant
+ ServantRetentionStrategyRetain::find_servant (
+ const PortableServer::ObjectId &system_id,
+ TAO::Portable_Server::Servant_Upcall &servant_upcall,
+ TAO::Portable_Server::POA_Current_Impl &poa_current_impl
+ ACE_ENV_ARG_DECL)
+ {
+ PortableServer::ObjectId user_id;
+ // If we have the RETAIN policy, convert/transform from system id to
+ // user id.
+ if (this->active_object_map_->
+ find_user_id_using_system_id (system_id,
+ user_id) != 0)
+ {
+ ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
+ 0);
+ }
+
+ poa_current_impl.object_id(user_id);
+ servant_upcall.user_id (&poa_current_impl.object_id());
+
+ // If the POA has the RETAIN policy, the POA looks in the Active
+ // Object Map to find if there is a servant associated with the
+ // Object Id value from the request. If such a servant exists, the
+ // POA invokes the appropriate method on the servant.
+ PortableServer::Servant servant = 0;
+ TAO_Active_Object_Map_Entry *active_object_map_entry = 0;
+ int const result = this->active_object_map_->
+ find_servant_using_system_id_and_user_id (system_id,
+ user_id,
+ servant,
+ active_object_map_entry);
+
+
+ if (result == 0)
+ {
+ servant_upcall.active_object_map_entry (active_object_map_entry);
+
+ // Increment the reference count.
+ servant_upcall.increment_servant_refcount ();
+ }
+
+ return servant;
+ }
+
+ int
+ ServantRetentionStrategyRetain::find_servant_priority (
+ const PortableServer::ObjectId &system_id,
+ CORBA::Short &priority
+ ACE_ENV_ARG_DECL)
+ {
+ PortableServer::ObjectId user_id;
+ // If we have the RETAIN policy, convert/transform from system id to
+ // user id.
+ if (this->active_object_map_->
+ find_user_id_using_system_id (system_id,
+ user_id) != 0)
+ {
+ ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
+ -1);
+ }
+
+ // If the POA has the RETAIN policy, the POA looks in the Active
+ // Object Map to find if there is a servant associated with the
+ // Object Id value from the request. If such a servant exists, the
+ // POA invokes the appropriate method on the servant.
+ PortableServer::Servant servant = 0;
+ TAO_Active_Object_Map_Entry *active_object_map_entry = 0;
+ int const result = this->active_object_map_->
+ find_servant_using_system_id_and_user_id (system_id,
+ user_id,
+ servant,
+ active_object_map_entry);
+
+ if (result == 0)
+ {
+ priority = active_object_map_entry->priority_;
+ return 0;
+ }
+
+ return -1;
+ }
+
+ int
+ ServantRetentionStrategyRetain::is_servant_in_map (
+ PortableServer::Servant servant,
+ bool &wait_occurred_restart_call)
+ {
+ bool deactivated = false;
+ int servant_in_map =
+ this->active_object_map_->is_servant_in_map (servant,
+ deactivated);
+
+ if (!servant_in_map)
+ {
+ return 0;
+ }
+ else
+ {
+ if (deactivated)
+ {
+ if (TAO_debug_level > 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) TAO_Root_POA::is_servant_in_map: waiting for servant to deactivate\n")));
+
+ // We are going to wait on this condition variable; the POA
+ // state may change by the time we get the lock again.
+ // Therefore, indicate to the caller that all conditions
+ // need to be checked again.
+ wait_occurred_restart_call = true;
+
+ ++this->waiting_servant_deactivation_;
+
+ if (this->poa_->object_adapter ().enable_locking ())
+ this->poa_->servant_deactivation_condition ().wait ();
+
+ --this->waiting_servant_deactivation_;
+
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ }
+
+ int
+ ServantRetentionStrategyRetain::is_user_id_in_map (
+ const PortableServer::ObjectId &id,
+ CORBA::Short priority,
+ bool &priorities_match,
+ bool &wait_occurred_restart_call)
+ {
+ bool deactivated = false;
+ bool user_id_in_map =
+ this->active_object_map_->is_user_id_in_map (id,
+ priority,
+ priorities_match,
+ deactivated);
+
+ if (!user_id_in_map)
+ {
+ return 0;
+ }
+ else
+ {
+ if (deactivated)
+ {
+ if (TAO_debug_level > 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) TAO_Root_POA::is_user_id_in_map: waiting for servant to deactivate\n")));
+
+ // We are going to wait on this condition variable; the POA
+ // state may change by the time we get the lock again.
+ // Therefore, indicate to the caller that all conditions
+ // need to be checked again.
+ wait_occurred_restart_call = 1;
+
+ ++this->waiting_servant_deactivation_;
+
+ if (this->poa_->object_adapter ().enable_locking ())
+ this->poa_->servant_deactivation_condition ().wait ();
+
+ --this->waiting_servant_deactivation_;
+
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ }
+
+ CORBA::ULong
+ ServantRetentionStrategyRetain::waiting_servant_deactivation (void) const
+ {
+ return waiting_servant_deactivation_;
+ }
+
+ void
+ ServantRetentionStrategyRetain::deactivate_all_objects (
+ ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::WrongPolicy))
+ {
+ // If the etherealize_objects parameter is TRUE, the POA has the
+ // RETAIN policy, and a servant manager is registered with the POA,
+ // the etherealize operation on the servant manager will be called
+ // for each active object in the Active Object Map. The apparent
+ // destruction of the POA occurs before any calls to etherealize are
+ // made. Thus, for example, an etherealize method that attempts to
+ // invoke operations on the POA will receive the OBJECT_NOT_EXIST
+ // exception.
+
+ // We must copy the map entries into a separate place since we
+ // cannot remove entries while iterating through the map.
+ ACE_Array_Base<TAO_Active_Object_Map_Entry *> map_entries
+ (this->active_object_map_->current_size ());
+
+ size_t counter = 0;
+ TAO_Active_Object_Map::user_id_map::iterator end
+ = this->active_object_map_->user_id_map_->end ();
+
+ for (TAO_Active_Object_Map::user_id_map::iterator iter
+ = this->active_object_map_->user_id_map_->begin ();
+ iter != end;
+ ++iter)
+ {
+ TAO_Active_Object_Map::user_id_map::value_type map_pair = *iter;
+ TAO_Active_Object_Map_Entry *active_object_map_entry = map_pair.second ();
+
+ if (!active_object_map_entry->deactivated_)
+ {
+ map_entries[counter] = active_object_map_entry;
+ ++counter;
+ }
+ }
+
+ for (size_t i = 0;
+ i < counter;
+ ++i)
+ {
+ this->deactivate_map_entry (map_entries[i]
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+ }
+
+ PortableServer::ObjectId *
+ ServantRetentionStrategyRetain::servant_to_user_id (
+ PortableServer::Servant servant
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ServantNotActive,
+ PortableServer::POA::WrongPolicy))
+ {
+ // This operation requires the RETAIN and either the UNIQUE_ID or
+ // IMPLICIT_ACTIVATION policies; if not present, the WrongPolicy
+ // exception is raised.
+ if (!((!this->poa_->allow_multiple_activations ()
+ || this->poa_->allow_implicit_activation ())))
+ {
+ ACE_THROW_RETURN (PortableServer::POA::WrongPolicy (),
+ 0);
+ }
+
+ /**
+ * If the POA has both the RETAIN and the UNIQUE_ID policy and the
+ * specified servant is active, the Object Id associated with that
+ * servant is returned.
+ *
+ * If the POA has both the RETAIN and the IMPLICIT_ACTIVATION policy and
+ * either the POA has the MULTIPLE_ID policy or the specified servant is
+ * not active, the servant is activated using a POA-generated Object Id
+ * and the Interface Id associated with the servant, and that Object Id
+ * is returned.
+ *
+ */
+
+ // If the POA has the UNIQUE_ID policy and the specified servant is
+ // active, the Object Id associated with that servant is returned.
+ PortableServer::ObjectId_var user_id;
+ if (!this->poa_->allow_multiple_activations () &&
+ this->active_object_map_->
+ find_user_id_using_servant (servant,
+ user_id.out ()) != -1)
+ {
+ return user_id._retn ();
+ }
+
+ // If the POA has the IMPLICIT_ACTIVATION policy and either the POA
+ // has the MULTIPLE_ID policy or the specified servant is not
+ // active, the servant is activated using a POA-generated Object Id
+ // and the Interface Id associated with the servant, and that Object
+ // Id is returned.
+ if (this->poa_->allow_implicit_activation ())
+ {
+ // If we reach here, then we either have the MULTIPLE_ID policy
+ // or we have the UNIQUE_ID policy and we are not in the active
+ // object map.
+ PortableServer::ObjectId_var user_id;
+ if (this->active_object_map_->
+ bind_using_system_id_returning_user_id (servant,
+ this->poa_->server_priority (),
+ user_id.out ()) != 0)
+ {
+ ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
+ 0);
+ }
+
+ //
+ // Everything is finally ok
+ //
+
+ // Inform the custom servant dispatching (CSD) strategy that the
+ // sevant is activated.
+ this->poa_->servant_activated_hook (servant,
+ user_id.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // ATTENTION: Trick locking here, see class header for details
+ Non_Servant_Upcall non_servant_upcall (*this->poa_);
+ ACE_UNUSED_ARG (non_servant_upcall);
+
+ // If this operation causes the object to be activated, _add_ref
+ // is invoked at least once on the Servant argument before
+ // returning. Otherwise, the POA does not increment or decrement
+ // the reference count of the Servant passed to this function.
+ servant->_add_ref (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ return user_id._retn ();
+ }
+
+ /*
+ * Otherwise, the ServantNotActive exception is raised.
+ */
+ ACE_THROW_RETURN (PortableServer::POA::ServantNotActive (),
+ 0);
+ }
+
+ PortableServer::ObjectId *
+ ServantRetentionStrategyRetain::servant_to_system_id_i (
+ PortableServer::Servant servant,
+ CORBA::Short &priority
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ServantNotActive,
+ PortableServer::POA::WrongPolicy))
+ {
+#if defined (CORBA_E_COMPACT) || defined (CORBA_E_MICRO)
+ if (this->poa_->allow_multiple_activations () ||
+ this->poa_->allow_implicit_activation ())
+ {
+ ACE_THROW_RETURN (PortableServer::POA::WrongPolicy (),
+ 0);
+ }
+
+#else
+ // This operation requires the RETAIN and either the UNIQUE_ID or
+ // IMPLICIT_ACTIVATION policies; if not present, the WrongPolicy
+ // exception is raised.
+ if (!((!this->poa_->allow_multiple_activations ()
+ || this->poa_->allow_implicit_activation ())))
+ {
+ ACE_THROW_RETURN (PortableServer::POA::WrongPolicy (),
+ 0);
+ }
+#endif
+
+ // This operation has three possible behaviors.
+
+ // If the POA has the UNIQUE_ID policy and the specified servant is
+ // active, the Object Id associated with that servant is returned.
+ PortableServer::ObjectId_var system_id;
+ if (!this->poa_->allow_multiple_activations () &&
+ this->active_object_map_->
+ find_system_id_using_servant (servant,
+ system_id.out (),
+ priority) != -1)
+ {
+ return system_id._retn ();
+ }
+
+ // If the POA has the IMPLICIT_ACTIVATION policy and either the POA
+ // has the MULTIPLE_ID policy or the specified servant is not
+ // active, the servant is activated using a POA-generated Object Id
+ // and the Interface Id associated with the servant, and that Object
+ // Id is returned.
+ if (this->poa_->allow_implicit_activation ())
+ {
+ // If we reach here, then we either have the MULTIPLE_ID policy
+ // or we have the UNIQUE_ID policy and we are not in the active
+ // object map.
+ PortableServer::ObjectId_var system_id;
+ if (this->active_object_map_->
+ bind_using_system_id_returning_system_id (servant,
+ priority,
+ system_id.out ()) != 0)
+ {
+ ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
+ 0);
+ }
+
+ //
+ // Everything is finally ok
+ //
+
+ // Inform the custom servant dispatching (CSD) strategy that the
+ // sevant is activated.
+ this->poa_->servant_activated_hook (servant,
+ system_id.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // ATTENTION: Trick locking here, see class header for details
+ Non_Servant_Upcall non_servant_upcall (*this->poa_);
+ ACE_UNUSED_ARG (non_servant_upcall);
+
+ // If this operation causes the object to be activated, _add_ref
+ // is invoked at least once on the Servant argument before
+ // returning. Otherwise, the POA does not increment or decrement
+ // the reference count of the Servant passed to this function.
+ servant->_add_ref (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ return system_id._retn ();
+ }
+
+ // Otherwise, the ServantNotActive exception is raised.
+ ACE_THROW_RETURN (PortableServer::POA::ServantNotActive (),
+ 0);
+ }
+
+ CORBA::Object_ptr
+ ServantRetentionStrategyRetain::servant_to_reference (
+ PortableServer::Servant servant
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ServantNotActive,
+ PortableServer::POA::WrongPolicy))
+ {
+ // Note: The allocation of an Object Id value and installation in
+ // the Active Object Map caused by implicit activation may actually
+ // be deferred until an attempt is made to externalize the
+ // reference. The real requirement here is that a reference is
+ // produced that will behave appropriately (that is, yield a
+ // consistent Object Id value when asked politely).
+ CORBA::Short priority =
+ this->poa_->server_priority ();
+
+ PortableServer::ObjectId_var system_id =
+ this->servant_to_system_id_i (servant,
+ priority
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (CORBA::Object::_nil ());
+
+ PortableServer::ObjectId user_id;
+
+ // This operation requires the RETAIN, therefore don't worry about
+ // the NON_RETAIN case.
+ if (this->active_object_map_->
+ find_user_id_using_system_id (system_id.in (),
+ user_id) != 0)
+ {
+ ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
+ CORBA::Object::_nil ());
+ }
+
+ // Remember params for potentially invoking <key_to_object> later.
+ this->poa_->key_to_object_params_.set (
+ system_id,
+ servant->_interface_repository_id (),
+ servant,
+ 1,
+ priority,
+ true);
+
+ // Ask the ORT to create the object.
+ // @@NOTE:There is a possible deadlock lurking here. We held the
+ // lock, and we are possibly trying to make a call into the
+ // application code. Think what would happen if the app calls us
+ // back. We need to get to this at some point.
+ return this->poa_->invoke_key_to_object_helper_i (
+ servant->_interface_repository_id (),
+ user_id
+ ACE_ENV_ARG_PARAMETER);
+ }
+
+ PortableServer::ObjectId *
+ ServantRetentionStrategyRetain::activate_object (
+ PortableServer::Servant servant,
+ CORBA::Short priority,
+ bool &wait_occurred_restart_call
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ServantAlreadyActive,
+ PortableServer::POA::WrongPolicy))
+ {
+ if (!this->poa_->has_system_id ())
+ {
+ ACE_THROW_RETURN (PortableServer::POA::WrongPolicy (),
+ 0);
+ }
+
+ bool may_activate =
+ this->poa_->is_servant_activation_allowed (servant, wait_occurred_restart_call);
+
+ if (!may_activate)
+ {
+ if (wait_occurred_restart_call)
+ {
+ return 0;
+ }
+ else
+ {
+ ACE_THROW_RETURN (PortableServer::POA::ServantAlreadyActive (),
+ 0);
+ }
+ }
+
+ // Otherwise, the activate_object operation generates an Object Id
+ // and enters the Object Id and the specified servant in the Active
+ // Object Map. The Object Id is returned.
+ PortableServer::ObjectId_var user_id;
+ if (this->active_object_map_->
+ bind_using_system_id_returning_user_id (servant,
+ priority,
+ user_id.out ()) != 0)
+ {
+ ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
+ 0);
+ }
+
+ //
+ // Everything is finally ok
+ //
+
+ // Inform the custom servant dispatching (CSD) strategy that the
+ // sevant is activated.
+ this->poa_->servant_activated_hook (servant,
+ user_id.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // ATTENTION: Trick locking here, see class header for details
+ Non_Servant_Upcall non_servant_upcall (*this->poa_);
+ ACE_UNUSED_ARG (non_servant_upcall);
+
+ // The implementation of activate_object will invoke _add_ref at
+ // least once on the Servant argument before returning. When the POA
+ // no longer needs the Servant, it will invoke _remove_ref on it the
+ // same number of times.
+ servant->_add_ref (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ return user_id._retn ();
+ }
+
+#if !defined (CORBA_E_MICRO)
+ void
+ ServantRetentionStrategyRetain::activate_object_with_id (
+ const PortableServer::ObjectId &id,
+ PortableServer::Servant servant,
+ CORBA::Short priority,
+ bool &wait_occurred_restart_call
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ServantAlreadyActive,
+ PortableServer::POA::ObjectAlreadyActive,
+ PortableServer::POA::WrongPolicy))
+ {
+ // If the POA has the SYSTEM_ID policy and it detects that the
+ // Object Id value was not generated by the system or for this POA,
+ // the activate_object_with_id operation may raise the BAD_PARAM
+ // system exception. An ORB is not required to detect all such
+ // invalid Object Id values, but a portable application must not
+ // invoke activate_object_with_id on a POA that has the SYSTEM_ID
+ // policy with an Object Id value that was not previously generated
+ // by the system for that POA, or, if the POA also has the
+ // PERSISTENT policy, for a previous instantiation of the same POA.
+ if (this->poa_->has_system_id () &&
+ !this->poa_->is_poa_generated_id (id))
+ {
+ ACE_THROW (CORBA::BAD_PARAM ());
+ }
+
+ // If the CORBA object denoted by the Object Id value is already
+ // active in this POA (there is a servant bound to it in the Active
+ // Object Map), the ObjectAlreadyActive exception is raised.
+ bool priorities_match = true;
+ bool result =
+ this->is_user_id_in_map (id,
+ priority,
+ priorities_match,
+ wait_occurred_restart_call);
+
+ // @johnny the implementation is not complete, this does the spec also say
+ // If the POA has the UNIQUE_ID policy and the servant is already
+ // in the Active Object Map, the ServantAlreadyActive exception is raised.
+ if (result)
+ {
+ ACE_THROW (PortableServer::POA::ObjectAlreadyActive ());
+ }
+ else if (wait_occurred_restart_call)
+ {
+ // 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;
+ }
+
+ // If the activate_object_with_id_and_priority operation is invoked
+ // with a different priority to an earlier invocation of one of the
+ // create reference with priority operations, for the same object,
+ // then the ORB shall raise a BAD_INV_ORDER system exception (with a
+ // Standard Minor Exception Code of 1). If the priority value is the
+ // same then the ORB shall return SUCCESS.
+ if (!priorities_match)
+ {
+ ACE_THROW (CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 1,
+ CORBA::COMPLETED_NO));
+ }
+
+ bool const may_activate =
+ this->poa_->is_servant_activation_allowed (servant, wait_occurred_restart_call);
+
+ if (!may_activate)
+ {
+ if (wait_occurred_restart_call)
+ {
+ return;
+ }
+ else
+ {
+ ACE_THROW (PortableServer::POA::ServantAlreadyActive ());
+ }
+ }
+
+ // Otherwise, the activate_object_with_id operation enters an
+ // association between the specified Object Id and the specified
+ // servant in the Active Object Map.
+ if (this->active_object_map_->bind_using_user_id (servant,
+ id,
+ priority) != 0)
+ {
+ ACE_THROW (CORBA::OBJ_ADAPTER ());
+ }
+
+ //
+ // Everything is finally ok
+ //
+
+ // Inform the custom servant dispatching (CSD) strategy that the
+ // sevant is activated.
+ this->poa_->servant_activated_hook (servant,
+ id
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // ATTENTION: Trick locking here, see class header for details
+ Non_Servant_Upcall non_servant_upcall (*this->poa_);
+ ACE_UNUSED_ARG (non_servant_upcall);
+
+ // The implementation of activate_object_with_id will invoke
+ // _add_ref at least once on the Servant argument before
+ // returning. When the POA no longer needs the Servant, it will
+ // invoke _remove_ref on it the same number of times.
+ servant->_add_ref (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+#endif
+
+ CORBA::Object_ptr
+ ServantRetentionStrategyRetain::create_reference (
+ const char *intf,
+ CORBA::Short priority
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::WrongPolicy))
+ {
+ // This operation creates an object reference that encapsulates a
+ // POA-generated Object Id value and the specified interface
+ // repository id. This operation does not cause an activation to
+ // take place. The resulting reference may be passed to clients, so
+ // that subsequent requests on those references will cause the
+ // appropriate servant manager to be invoked, if one is
+ // available. The generated Object Id value may be obtained by
+ // invoking POA::reference_to_id with the created reference.
+
+ PortableServer::ObjectId_var system_id;
+ PortableServer::ObjectId user_id;
+
+ if (this->active_object_map_->
+ bind_using_system_id_returning_system_id (0,
+ priority,
+ system_id.out ()) != 0)
+ {
+ ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
+ CORBA::Object::_nil ());
+ }
+
+ // Find user id from system id.
+ if (this->active_object_map_->
+ find_user_id_using_system_id (system_id.in (),
+ user_id) != 0)
+ {
+ ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
+ CORBA::Object::_nil ());
+ }
+
+ // Remember params for potentially invoking <key_to_object> later.
+ this->poa_->key_to_object_params_.set (system_id,
+ intf,
+ 0,
+ 1,
+ priority,
+ true);
+
+ return this->poa_->invoke_key_to_object_helper_i (intf,
+ user_id
+ ACE_ENV_ARG_PARAMETER);
+
+ }
+
+ CORBA::Object_ptr
+ ServantRetentionStrategyRetain::create_reference_with_id (
+ const PortableServer::ObjectId &oid,
+ const char *intf,
+ CORBA::Short priority
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+ {
+ // This operation creates an object reference that encapsulates the
+ // specified Object Id and interface repository Id values. This
+ // operation does not cause an activation to take place. The
+ // resulting reference may be passed to clients, so that subsequent
+ // requests on those references will cause the object to be
+ // activated if necessary, or the default servant used, depending on
+ // the applicable policies.
+
+ PortableServer::Servant servant = 0;
+ PortableServer::ObjectId_var system_id;
+
+ // @@ We need something that can find the system id using
+ // appropriate strategy, at the same time, return the servant if
+ // one is available. Before we have that function,
+ // <create_reference_with_id_i> basically generates broken
+ // collocated object when DIRECT collocation strategy is used.
+
+ if (this->active_object_map_->
+ find_system_id_using_user_id (oid,
+ priority,
+ system_id.out ()) != 0)
+ {
+ ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (),
+ CORBA::Object::_nil ());
+ }
+
+ // Remember params for potentially invoking <key_to_object> later.
+ this->poa_->key_to_object_params_.set (system_id,
+ intf,
+ servant,
+ 1,
+ priority,
+ true);
+
+ return this->poa_->invoke_key_to_object_helper_i (intf,
+ oid
+ ACE_ENV_ARG_PARAMETER);
+ }
+
+ int
+ ServantRetentionStrategyRetain::rebind_using_user_id_and_system_id (
+ PortableServer::Servant servant,
+ const PortableServer::ObjectId &user_id,
+ const PortableServer::ObjectId &system_id,
+ TAO::Portable_Server::Servant_Upcall &servant_upcall)
+ {
+ TAO_Active_Object_Map_Entry *entry = 0;
+ int result = this->active_object_map_->
+ rebind_using_user_id_and_system_id (servant,
+ user_id,
+ system_id,
+ entry);
+ servant_upcall.active_object_map_entry(entry);
+
+ return result;
+ }
+
+ CORBA::Boolean
+ ServantRetentionStrategyRetain::servant_has_remaining_activations (
+ PortableServer::Servant servant)
+ {
+ return this->active_object_map_->remaining_activations (servant);
+ }
+
+
+ ::PortableServer::ServantRetentionPolicyValue
+ ServantRetentionStrategyRetain::type() const
+ {
+ return ::PortableServer::RETAIN;
+ }
+
+ }
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL