1 #include "tao/orbconf.h"
3 #if (TAO_HAS_MINIMUM_POA == 0) && !defined (CORBA_E_COMPACT) && !defined (CORBA_E_MICRO)
5 #include "tao/ORB_Constants.h"
6 #include "tao/PortableServer/ServantActivatorC.h"
7 #include "tao/PortableServer/RequestProcessingStrategyServantActivator.h"
8 #include "tao/PortableServer/Servant_Base.h"
9 #include "tao/PortableServer/Non_Servant_Upcall.h"
10 #include "tao/PortableServer/Root_POA.h"
11 #include "tao/PortableServer/POA_Current_Impl.h"
12 #include "tao/PortableServer/Servant_Upcall.h"
14 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
18 namespace Portable_Server
21 RequestProcessingStrategyServantActivator::strategy_cleanup ()
24 Non_Servant_Upcall
non_servant_upcall (*this->poa_
);
25 ACE_UNUSED_ARG (non_servant_upcall
);
27 this->servant_activator_
= PortableServer::ServantActivator::_nil ();
30 RequestProcessingStrategy::strategy_cleanup ();
33 PortableServer::ServantManager_ptr
34 RequestProcessingStrategyServantActivator::get_servant_manager ()
36 return PortableServer::ServantManager::_duplicate (this->servant_activator_
.in ());
40 RequestProcessingStrategyServantActivator::set_servant_manager (
41 PortableServer::ServantManager_ptr imgr
)
43 // This operation sets the default servant manager associated with the
44 // POA. This operation may only be invoked once after a POA has been
45 // created. Attempting to set the servant manager after one has already
46 // been set will result in the BAD_INV_ORDER system exception with
47 // standard minor code 6 being raised (see 11.3.9.12 of the corba spec)
48 if (!CORBA::is_nil (this->servant_activator_
.in ()))
50 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 6, CORBA::COMPLETED_NO
);
53 this->servant_activator_
=
54 PortableServer::ServantActivator::_narrow (imgr
);
56 this->validate_servant_manager (this->servant_activator_
.in ());
60 RequestProcessingStrategyServantActivator::locate_servant (
61 const PortableServer::ObjectId
&system_id
,
62 PortableServer::Servant
&servant
)
64 TAO_Servant_Location location
= TAO_Servant_Location::Not_Found
;
66 location
= this->poa_
->servant_present (system_id
, servant
);
68 if (location
== TAO_Servant_Location::Not_Found
)
70 if (!CORBA::is_nil (this->servant_activator_
.in ()))
72 location
= TAO_Servant_Location::Servant_Manager
;
79 PortableServer::Servant
80 RequestProcessingStrategyServantActivator::locate_servant (
81 const char * /*operation*/,
82 const PortableServer::ObjectId
&system_id
,
83 TAO::Portable_Server::Servant_Upcall
&servant_upcall
,
84 TAO::Portable_Server::POA_Current_Impl
&poa_current_impl
,
85 bool &wait_occurred_restart_call
)
87 PortableServer::Servant servant
= 0;
89 servant
= this->poa_
->find_servant (system_id
,
98 // If the POA has the USE_SERVANT_MANAGER policy, a servant manager
99 // has been associated with the POA so the POA will invoke incarnate
100 // or preinvoke on it to find a servant that may handle the
101 // request. (The choice of method depends on the NON_RETAIN or
102 // RETAIN policy of the POA.) If no servant manager has been
103 // associated with the POA, the POA raises the OBJ_ADAPTER system
106 // If a servant manager is located and invoked, but the servant
107 // manager is not directly capable of incarnating the object, it
108 // (the servant manager) may deal with the circumstance in a variety
109 // of ways, all of which are the application's responsibility. Any
110 // system exception raised by the servant manager will be returned
111 // to the client in the reply. In addition to standard CORBA
112 // exceptions, a servant manager is capable of raising a
113 // ForwardRequest exception. This exception includes an object
117 this->validate_servant_manager (this->servant_activator_
.in ());
119 servant
= this->incarnate_servant (poa_current_impl
.object_id ());
121 // If the incarnate operation returns a servant that is
122 // already active for a different Object Id and if the POA
123 // also has the UNIQUE_ID policy, the incarnate has violated
124 // the POA policy and is considered to be in error. The POA
125 // will raise an OBJ_ADAPTER system exception for the
128 this->poa_
->is_servant_activation_allowed (servant
,
129 wait_occurred_restart_call
);
133 // If we are not allowed to activate the servant, throw an exception
134 // etherealize is not called because the servant is never added to
135 // the active object map
136 throw ::CORBA::OBJ_ADAPTER ();
139 // The POA enters the returned Servant value into the Active
140 // Object Map so that subsequent requests with the same
141 // ObjectId value will be delivered directly to that servant
142 // without invoking the servant manager. Only run if there
143 // are no errors or if a restart is not required.
144 if (!wait_occurred_restart_call
)
148 rebind_using_user_id_and_system_id (servant
,
149 poa_current_impl
.object_id (),
154 // Throw an exception, etherealize is not called because servant
155 // is not added to the active object map
156 throw ::CORBA::OBJ_ADAPTER ();
159 // Increment the reference count on the servant upcall.
160 servant_upcall
.increment_servant_refcount ();
164 CORBA::Boolean cleanup_in_progress
= 0;
165 this->etherealize_servant (poa_current_impl
.object_id (),
167 cleanup_in_progress
);
169 // We ended up waiting on a condition variable, the
170 // POA state may have changed while we are waiting.
171 // Therefore, we need to restart this call.
180 RequestProcessingStrategyServantActivator::etherealize_servant (
181 const PortableServer::ObjectId
& object_id
,
182 PortableServer::Servant servant
,
183 CORBA::Boolean cleanup_in_progress
)
185 CORBA::Boolean
const remaining_activations
=
186 this->poa_
->servant_has_remaining_activations (servant
);
188 // ATTENTION: Trick locking here, see class header for details
189 Non_Servant_Upcall
non_servant_upcall (*this->poa_
);
190 ACE_UNUSED_ARG (non_servant_upcall
);
192 // @todo This is not according to the spec. According to 11.3.6.2 at the
193 // end when etherealize returns a system exception the POA ignores the
195 this->servant_activator_
->etherealize (object_id
,
199 remaining_activations
);
202 PortableServer::Servant
203 RequestProcessingStrategyServantActivator::incarnate_servant (
204 const PortableServer::ObjectId
& object_id
)
206 PortableServer::Servant servant
= 0;
208 // ATTENTION: Trick locking here, see class header for details
209 Non_Servant_Upcall
non_servant_upcall (*this->poa_
);
210 ACE_UNUSED_ARG (non_servant_upcall
);
213 // Invocations of incarnate on the servant manager are serialized.
214 // Invocations of etherealize on the servant manager are serialized.
215 // Invocations of incarnate and etherealize on the servant manager are mutually exclusive.
216 servant
= this->servant_activator_
->incarnate (object_id
, this->poa_
);
220 throw ::CORBA::OBJ_ADAPTER (CORBA::OMGVMCID
| 7, CORBA::COMPLETED_NO
);
229 RequestProcessingStrategyServantActivator::cleanup_servant (
230 PortableServer::Servant servant
,
231 const PortableServer::ObjectId
&user_id
)
233 // If a servant manager is associated with the POA,
234 // ServantLocator::etherealize will be invoked with the oid and the
235 // servant. (The deactivate_object operation does not wait for the
236 // etherealize operation to complete before deactivate_object
239 // Note: If the servant associated with the oid is serving multiple
240 // Object Ids, ServantLocator::etherealize may be invoked multiple
241 // times with the same servant when the other objects are
242 // deactivated. It is the responsibility of the object
243 // implementation to refrain from destroying the servant while it is
244 // active with any Id.
246 // If the POA has no ServantActivator associated with it, the POA
247 // implementation calls _remove_ref when all operation invocations
248 // have completed. If there is a ServantActivator, the Servant is
249 // consumed by the call to ServantActivator::etherealize instead.
251 // @bala, is this order correct, see 11.3.9.17 of the spec, it
252 // says first remove from the map, then etherealize. not the
254 // @@ Johnny, you are right! This will not show up until a
255 // thread is trying to activate the object in another thread
256 // using activate_object_with_id (). A test case is a must for
257 // atleast this issue.
260 if (this->etherealize_objects_
&&
261 !CORBA::is_nil (this->servant_activator_
.in ()))
263 this->etherealize_servant (user_id
,
265 this->poa_
->cleanup_in_progress ());
269 // ATTENTION: Trick locking here, see class header for details
270 Non_Servant_Upcall
non_servant_upcall (*this->poa_
);
271 ACE_UNUSED_ARG (non_servant_upcall
);
275 servant
->_remove_ref ();
279 // Ignore exceptions from servant cleanup.
284 // This operation causes the association of the Object Id specified
285 // by the oid parameter and its servant to be removed from the
286 // Active Object Map.
287 if (this->poa_
->unbind_using_user_id (user_id
) != 0)
288 throw ::CORBA::OBJ_ADAPTER ();
292 RequestProcessingStrategyServantActivator::etherealize_objects (
293 CORBA::Boolean etherealize_objects
)
295 this->etherealize_objects_
= etherealize_objects
;
299 RequestProcessingStrategyServantActivator::post_invoke_servant_cleanup(
300 const PortableServer::ObjectId
&/*system_id*/,
301 const TAO::Portable_Server::Servant_Upcall
&/*servant_upcall*/)
307 TAO_END_VERSIONED_NAMESPACE_DECL
309 #endif /* TAO_HAS_MINIMUM_POA == 0 */