Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / TAO / tao / PortableServer / RequestProcessingStrategyServantActivator.cpp
blobe07d39daf81bcd8a8439455282281762bbc57ad4
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
16 namespace TAO
18 namespace Portable_Server
20 void
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 ());
39 void
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 ());
59 TAO_Servant_Location
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;
76 return location;
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,
90 servant_upcall,
91 poa_current_impl);
93 if (servant != 0)
95 return servant;
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
104 // exception.
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
114 // reference.
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
126 // request.
127 bool may_activate =
128 this->poa_->is_servant_activation_allowed (servant,
129 wait_occurred_restart_call);
131 if (!may_activate)
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)
146 int const result =
147 this->poa_->
148 rebind_using_user_id_and_system_id (servant,
149 poa_current_impl.object_id (),
150 system_id,
151 servant_upcall);
152 if (result != 0)
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 ();
162 else
164 CORBA::Boolean cleanup_in_progress = 0;
165 this->etherealize_servant (poa_current_impl.object_id (),
166 servant,
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.
172 return 0;
175 // Success
176 return servant;
179 void
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
194 // exception
195 this->servant_activator_->etherealize (object_id,
196 this->poa_,
197 servant,
198 cleanup_in_progress,
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);
212 // @@
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_);
218 if (servant == 0)
220 throw ::CORBA::OBJ_ADAPTER (CORBA::OMGVMCID | 7, CORBA::COMPLETED_NO);
222 else
224 return servant;
228 void
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
237 // returns.)
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
253 // other way around
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.
258 if (servant)
260 if (this->etherealize_objects_ &&
261 !CORBA::is_nil (this->servant_activator_.in ()))
263 this->etherealize_servant (user_id,
264 servant,
265 this->poa_->cleanup_in_progress ());
267 else
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 ();
277 catch (...)
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 ();
291 void
292 RequestProcessingStrategyServantActivator::etherealize_objects (
293 CORBA::Boolean etherealize_objects)
295 this->etherealize_objects_ = etherealize_objects;
298 void
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 */