1 #include "tao/PortableServer/Object_Adapter.h"
2 #include "tao/PortableServer/Servant_Upcall.h"
3 #include "tao/PortableServer/Root_POA.h"
4 #include "tao/PortableServer/Default_Servant_Dispatcher.h"
5 #include "tao/PortableServer/Collocated_Object_Proxy_Broker.h"
6 #include "tao/PortableServer/Active_Object_Map_Entry.h"
7 #include "tao/PortableServer/ForwardRequestC.h"
11 #include "tao/ORB_Core.h"
12 #include "tao/debug.h"
14 #if !defined (__ACE_INLINE__)
15 # include "tao/PortableServer/Servant_Upcall.inl"
16 #endif /* __ACE_INLINE__ */
18 #include "ace/OS_NS_string.h"
20 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
24 namespace Portable_Server
26 Servant_Upcall::Servant_Upcall (TAO_ORB_Core
*oc
)
27 : object_adapter_ (0),
30 state_ (INITIAL_STAGE
),
31 system_id_ (TAO_POA_OBJECT_ID_BUF_SIZE
, 0, system_id_buf_
),
34 #if (TAO_HAS_MINIMUM_POA == 0)
37 #endif /* TAO_HAS_MINIMUM_POA == 0 */
38 active_object_map_entry_ (0)
40 TAO_Object_Adapter
*object_adapter
=
41 dynamic_cast<TAO_Object_Adapter
*>(oc
->poa_adapter ());
42 this->object_adapter_
= object_adapter
;
46 Servant_Upcall::prepare_for_upcall (
47 const TAO::ObjectKey
&key
,
48 const char *operation
,
49 CORBA::Object_out forward_to
)
53 bool wait_occurred_restart_call
= false;
56 this->prepare_for_upcall_i (key
,
59 wait_occurred_restart_call
);
61 if (result
== TAO_Adapter::DS_FAILED
&&
62 wait_occurred_restart_call
)
64 // We ended up waiting on a condition variable. The POA
65 // state may have changed while we are waiting. Therefore,
66 // we need to call prepare_for_upcall_i() again. We also
67 // need to cleanup the state of the upcall object before
69 this->upcall_cleanup ();
80 Servant_Upcall::prepare_for_upcall_i (
81 const TAO::ObjectKey
&key
,
82 const char *operation
,
83 CORBA::Object_out forward_to
,
84 bool &wait_occurred_restart_call
)
86 // Acquire the object adapter lock first.
87 int result
= this->object_adapter_
->lock ().acquire ();
90 throw ::CORBA::OBJ_ADAPTER ();
92 // We have acquired the object adapter lock. Record this for later
94 this->state_
= OBJECT_ADAPTER_LOCK_ACQUIRED
;
96 // Check if a non-servant upcall is in progress. If a non-servant
97 // upcall is in progress, wait for it to complete. Unless of
98 // course, the thread making the non-servant upcall is this thread.
99 this->object_adapter_
->wait_for_non_servant_upcalls_to_complete ();
102 this->object_adapter_
->locate_poa (key
, this->system_id_
, this->poa_
);
104 // Check the state of the POA.
105 this->poa_
->check_state ();
107 // Setup current for this request.
108 this->current_context_
.setup (this->poa_
, key
);
110 // Increase <poa->outstanding_requests_> for the duration of finding
111 // the POA, finding the servant, and making the upcall.
112 this->poa_
->increment_outstanding_requests ();
114 // We have setup the POA Current. Record this for later use.
115 this->state_
= POA_CURRENT_SETUP
;
117 #if (TAO_HAS_MINIMUM_CORBA == 0) && !defined (CORBA_E_COMPACT) && !defined (CORBA_E_MICRO)
120 #endif /* TAO_HAS_MINIMUM_CORBA */
121 // Lookup the servant.
123 this->poa_
->locate_servant_i (operation
,
126 this->current_context_
,
127 wait_occurred_restart_call
);
129 if (wait_occurred_restart_call
)
130 return TAO_Adapter::DS_FAILED
;
131 #if (TAO_HAS_MINIMUM_CORBA == 0) && !defined (CORBA_E_COMPACT) && !defined (CORBA_E_MICRO)
133 catch (const ::PortableServer::ForwardRequest
& forward_request
)
136 CORBA::Object::_duplicate (forward_request
.forward_reference
.in ());
137 return TAO_Adapter::DS_FORWARD
;
140 ACE_UNUSED_ARG (forward_to
);
141 #endif /* TAO_HAS_MINIMUM_CORBA */
143 // Now that we know the servant.
144 this->current_context_
.servant (this->servant_
);
146 // For servants from Servant Locators, there is no active object map
148 if (this->active_object_map_entry ())
149 this->current_context_
.priority (this->active_object_map_entry ()->priority_
);
151 if (this->state_
!= OBJECT_ADAPTER_LOCK_RELEASED
)
153 // Release the object adapter lock.
154 this->object_adapter_
->lock ().release ();
156 // We have release the object adapter lock. Record this for
158 this->state_
= OBJECT_ADAPTER_LOCK_RELEASED
;
161 // Serialize servants (if appropriate).
162 this->single_threaded_poa_setup ();
164 // We have acquired the servant lock. Record this for later use.
165 this->state_
= SERVANT_LOCK_ACQUIRED
;
167 // After this point, <this->servant_> is ready for dispatching.
168 return TAO_Adapter::DS_OK
;
172 Servant_Upcall::pre_invoke_remote_request (TAO_ServerRequest
&req
)
174 this->object_adapter_
->servant_dispatcher_
->pre_invoke_remote_request (
178 this->pre_invoke_state_
);
182 Servant_Upcall::pre_invoke_collocated_request ()
184 this->object_adapter_
->servant_dispatcher_
->pre_invoke_collocated_request (
187 this->pre_invoke_state_
);
191 Servant_Upcall::post_invoke ()
193 this->object_adapter_
->servant_dispatcher_
->post_invoke (
195 this->pre_invoke_state_
);
198 Servant_Upcall::Pre_Invoke_State::Pre_Invoke_State ()
199 : state_ (NO_ACTION_REQUIRED
),
200 original_native_priority_ (0),
201 original_CORBA_priority_ (0)
206 Servant_Upcall::lookup_POA (const TAO::ObjectKey
&key
)
208 // Acquire the object adapter lock first.
209 if (this->object_adapter_
->lock ().acquire () == -1)
211 throw ::CORBA::OBJ_ADAPTER ();
213 // We have acquired the object adapter lock. Record this for later
215 this->state_
= OBJECT_ADAPTER_LOCK_ACQUIRED
;
217 // Check if a non-servant upcall is in progress. If a non-servant
218 // upcall is in progress, wait for it to complete. Unless of
219 // course, the thread making the non-servant upcall is this thread.
220 this->object_adapter_
->wait_for_non_servant_upcalls_to_complete ();
223 this->object_adapter_
->locate_poa (key
, this->system_id_
, this->poa_
);
228 Servant_Upcall::~Servant_Upcall ()
230 this->upcall_cleanup ();
234 Servant_Upcall::upcall_cleanup ()
236 this->post_invoke ();
238 switch (this->state_
)
240 case SERVANT_LOCK_ACQUIRED
:
241 // Unlock servant (if appropriate).
242 this->single_threaded_poa_cleanup ();
246 case OBJECT_ADAPTER_LOCK_RELEASED
:
247 // Cleanup servant locator related state. Note that because
248 // this operation does not change any Object Adapter related
249 // state, it is ok to call it outside the lock.
250 this->post_invoke_servant_cleanup ();
252 // Since the object adapter lock was released, we must acquire
255 // Note that errors are ignored here since we cannot do much
257 this->object_adapter_
->lock ().acquire ();
259 // Check if a non-servant upcall is in progress. If a
260 // non-servant upcall is in progress, wait for it to complete.
261 // Unless of course, the thread making the non-servant upcall is
263 this->object_adapter_
->wait_for_non_servant_upcalls_to_complete_no_throw ();
265 // Cleanup servant related state.
266 this->servant_cleanup ();
270 case POA_CURRENT_SETUP
:
271 // Cleanup POA related state.
272 this->poa_cleanup ();
274 // Teardown current for this request.
275 this->current_context_
.teardown ();
279 case OBJECT_ADAPTER_LOCK_ACQUIRED
:
280 // Finally, since the object adapter lock was acquired, we must
282 this->object_adapter_
->lock ().release ();
288 // @@ Keep compiler happy, the states above are the only
295 Servant_Upcall::post_invoke_servant_cleanup ()
297 this->poa_
->post_invoke_servant_cleanup (this->current_context_
.object_id (),
302 Servant_Upcall::single_threaded_poa_setup ()
304 #if (TAO_HAS_MINIMUM_POA == 0)
305 // Serialize servants (if necessary).
307 // Note that this lock must be acquired *after* the object adapter
308 // lock has been released. This is necessary since we cannot block
309 // waiting for the servant lock while holding the object adapter
310 // lock. Otherwise, the thread that wants to release this lock will
311 // not be able to do so since it can't acquire the object adapterx
313 if (this->poa_
->enter() == -1)
315 throw ::CORBA::OBJ_ADAPTER ();
316 #endif /* !TAO_HAS_MINIMUM_POA == 0 */
320 Servant_Upcall::single_threaded_poa_cleanup ()
322 #if (TAO_HAS_MINIMUM_POA == 0)
323 // Since the servant lock was acquired, we must release it.
324 int const result
= this->poa_
->exit ();
326 ACE_UNUSED_ARG (result
);
327 #endif /* TAO_HAS_MINIMUM_POA == 0 */
331 Servant_Upcall::increment_servant_refcount ()
333 // Cleanup servant related stuff.
334 if (this->active_object_map_entry_
!= 0)
335 ++this->active_object_map_entry_
->reference_count_
;
339 Servant_Upcall::servant_cleanup ()
341 // Cleanup servant related stuff.
342 if (this->active_object_map_entry_
!= 0)
344 // Decrement the reference count.
345 CORBA::UShort
const new_count
=
346 --this->active_object_map_entry_
->reference_count_
;
352 this->poa_
->cleanup_servant (
353 this->active_object_map_entry_
->servant_
,
354 this->active_object_map_entry_
->user_id_
);
358 // Ignore errors from servant cleanup ....
361 if (this->poa_
->waiting_servant_deactivation() > 0)
363 // Wakeup all waiting threads.
364 this->poa_
->servant_deactivation_condition_
.broadcast ();
371 Servant_Upcall::poa_cleanup ()
373 // Decrease <poa->outstanding_requests_> now that the upcall
376 // Note that the object adapter lock is acquired before
377 // <POA::outstanding_requests_> is decreased.
378 CORBA::ULong outstanding_requests
=
379 this->poa_
->decrement_outstanding_requests ();
381 // Check if all pending requests are over.
382 if (outstanding_requests
== 0)
384 // If locking is enabled and some thread is waiting in POA::destroy.
385 if (this->poa_
->wait_for_completion_pending_
)
387 // Wakeup all waiting threads.
388 this->poa_
->outstanding_requests_condition_
.broadcast ();
391 // Note that there is no need to check for
392 // <non_servant_upcall_in_progress> since it is not possible for
393 // non-servant upcalls to be in progress at this point.
394 if (this->poa_
->waiting_destruction_
)
398 this->poa_
->complete_destruction_i ();
400 catch (const ::CORBA::Exception
& ex
)
403 ex
._tao_print_exception ("TAO_POA::~complete_destruction_i");
406 this->poa_
= nullptr;
413 TAO_END_VERSIONED_NAMESPACE_DECL