2 #include "tao/Invocation_Adapter.h"
3 #include "tao/Profile_Transport_Resolver.h"
4 #include "tao/operation_details.h"
6 #include "tao/ORB_Core.h"
7 #include "tao/Synch_Invocation.h"
9 #include "tao/Collocated_Invocation.h"
10 #include "tao/Transport.h"
11 #include "tao/Transport_Mux_Strategy.h"
12 #include "tao/GIOP_Utils.h"
14 #include "tao/SystemException.h"
15 #include "tao/Collocation_Resolver.h"
16 #include "tao/Invocation_Retry_State.h"
17 #include "ace/Service_Config.h"
18 #include "ace/Truncate.h"
20 #if !defined (__ACE_INLINE__)
21 # include "tao/Invocation_Adapter.inl"
22 #endif /* __ACE_INLINE__ */
24 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
28 Invocation_Adapter::~Invocation_Adapter ()
33 Invocation_Adapter::invoke (const TAO::Exception_Data
*ex_data
,
34 unsigned long ex_count
)
36 // Should stub object be refcounted here?
37 TAO_Stub
*stub
= this->get_stub ();
39 TAO_Operation_Details
op_details (this->operation_
,
40 ACE_Utils::truncate_cast
<CORBA::ULong
> (this->op_len_
),
47 this->invoke_i (stub
, op_details
);
51 Invocation_Adapter::invoke_i (TAO_Stub
*stub
, TAO_Operation_Details
&details
)
53 // The invocation has got to be within the context of the
54 // corresponding ORB's configuration. Otherwise things like
55 // timeout hooks, etc may not work as expected. Especially if
56 // there are multiple ORB instances in the process, each with its
57 // own, local configuration.
58 ACE_Service_Config_Guard
scg (stub
->orb_core ()->configuration ());
60 // Cache the target to a local variable.
61 CORBA::Object_var effective_target
=
62 CORBA::Object::_duplicate (this->target_
);
65 TAO::Invocation_Status status
= TAO_INVOKE_START
;
66 ACE_Time_Value
*max_wait_time
= nullptr;
67 ACE_Time_Value tmp_wait_time
= ACE_Time_Value::zero
;
68 if (this->get_timeout (stub
, tmp_wait_time
))
70 max_wait_time
= &tmp_wait_time
;
73 TAO::Invocation_Retry_State
retry_state (*stub
);
75 while (status
== TAO_INVOKE_START
|| status
== TAO_INVOKE_RESTART
)
77 // Default we go to remote
78 Collocation_Strategy strat
= TAO_CS_REMOTE_STRATEGY
;
80 // If we have the opportunity for collocation we maybe
81 // can use a collocated invocation. Similarly, if the
82 // target object reference contains a pointer to a servant,
83 // the object reference also refers to a collocated object.
84 // get the ORBStrategy
85 strat
= this->collocation_strategy (effective_target
.in ());
87 if (TAO_debug_level
> 2)
89 TAOLIB_DEBUG ((LM_DEBUG
,
90 ACE_TEXT("TAO (%P|%t) - Invocation_Adapter::invoke_i, ")
91 ACE_TEXT("making a %C invocation\n"),
92 TAO::translate_collocation_strategy(strat
)));
95 if (strat
== TAO_CS_REMOTE_STRATEGY
|| strat
== TAO_CS_LAST
)
98 this->invoke_remote_i (stub
,
106 if (strat
== TAO_CS_THRU_POA_STRATEGY
)
108 (void) this->set_response_flags (stub
, details
);
112 this->invoke_collocated_i (stub
,
117 if (status
== TAO_INVOKE_RESTART
)
119 details
.reset_request_service_info ();
120 details
.reset_reply_service_info ();
122 if (TAO_debug_level
> 2)
124 TAOLIB_DEBUG ((LM_DEBUG
,
125 ACE_TEXT("TAO (%P|%t) - Invocation_Adapter::invoke_i, ")
126 ACE_TEXT("handling forwarded locations\n")));
133 Invocation_Adapter::get_timeout (TAO_Stub
*stub
, ACE_Time_Value
&timeout
)
135 bool has_timeout
= false;
136 this->target_
->orb_core ()->call_timeout_hook (stub
, has_timeout
, timeout
);
142 Invocation_Adapter::get_stub () const
144 TAO_Stub
* const stub
= this->target_
->_stubobj ();
148 if (TAO_debug_level
> 0)
150 TAOLIB_ERROR ((LM_ERROR
,
151 ACE_TEXT ("Invocation_Adapter::get_stub, ")
152 ACE_TEXT ("raising CORBA::INTERNAL because of nil ")
153 ACE_TEXT ("stub.\n")));
155 throw ::CORBA::INTERNAL (
156 CORBA::SystemException::_tao_minor_code (
159 CORBA::COMPLETED_NO
);
166 Invocation_Adapter::invoke_collocated_i (TAO_Stub
*stub
,
167 TAO_Operation_Details
&details
,
168 CORBA::Object_var
&effective_target
,
169 Collocation_Strategy strat
)
172 TAO::Invocation_Status status
= TAO_INVOKE_START
;
174 Collocated_Invocation
coll_inv (this->target_
,
175 effective_target
.in (),
178 this->type_
== TAO_TWOWAY_INVOCATION
);
180 status
= coll_inv
.invoke (strat
);
182 if (status
== TAO_INVOKE_RESTART
&&
183 (coll_inv
.reply_status () == GIOP::LOCATION_FORWARD
||
184 coll_inv
.reply_status () == GIOP::LOCATION_FORWARD_PERM
))
186 CORBA::Boolean
const is_permanent_forward
=
187 (coll_inv
.reply_status () == GIOP::LOCATION_FORWARD_PERM
);
189 effective_target
= coll_inv
.steal_forwarded_reference ();
191 this->object_forwarded (effective_target
, stub
, is_permanent_forward
);
198 Invocation_Adapter::set_response_flags (
200 TAO_Operation_Details
&details
)
204 case TAO_ONEWAY_INVOCATION
:
206 // Grab the syncscope policy from the ORB.
207 Messaging::SyncScope sync_scope
;
209 bool has_synchronization
= false;
211 stub
->orb_core ()->call_sync_scope_hook (stub
,
214 if (has_synchronization
)
215 details
.response_flags (CORBA::Octet (sync_scope
));
217 details
.response_flags (
218 CORBA::Octet (Messaging::SYNC_WITH_TRANSPORT
));
221 case TAO_TWOWAY_INVOCATION
:
223 // @@note: Need to change this to something better. Too many
224 // hash defines meaning the same things.
225 details
.response_flags (TAO_TWOWAY_RESPONSE_FLAG
);
232 Invocation_Adapter::invoke_remote_i (TAO_Stub
*stub
,
233 TAO_Operation_Details
&details
,
234 CORBA::Object_var
&effective_target
,
235 ACE_Time_Value
*&max_wait_time
,
236 Invocation_Retry_State
*retry_state
)
238 (void) this->set_response_flags (stub
, details
);
240 CORBA::Octet
const rflags
= details
.response_flags ();
241 bool const block_connect
=
242 rflags
!= static_cast<CORBA::Octet
> (Messaging::SYNC_NONE
)
243 && rflags
!= static_cast<CORBA::Octet
> (TAO::SYNC_DELAYED_BUFFERING
);
244 // Create the resolver which will pick (or create) for us a
245 // transport and a profile from the effective_target.
246 Profile_Transport_Resolver
resolver (
247 effective_target
.in (),
250 resolver
.resolve (max_wait_time
);
254 if (max_wait_time
&& *max_wait_time
== ACE_Time_Value::zero
)
255 TAOLIB_DEBUG ((LM_DEBUG
,
256 ACE_TEXT ("TAO (%P|%t) - Invocation_Adapter::invoke_remote_i, ")
257 ACE_TEXT ("max wait time consumed during transport resolution\n")));
259 // Update the request id now that we have a transport
260 if (resolver
.transport ())
262 details
.request_id (resolver
.transport ()->tms ()->request_id ());
266 case TAO_ONEWAY_INVOCATION
:
268 return this->invoke_oneway (details
,
273 case TAO_TWOWAY_INVOCATION
:
275 return this->invoke_twoway (details
,
282 return TAO_INVOKE_FAILURE
;
286 Invocation_Adapter::invoke_twoway (TAO_Operation_Details
&details
,
287 CORBA::Object_var
&effective_target
,
288 Profile_Transport_Resolver
&r
,
289 ACE_Time_Value
*&max_wait_time
,
290 Invocation_Retry_State
*retry_state
)
292 // Simple sanity check
293 if (this->mode_
!= TAO_SYNCHRONOUS_INVOCATION
||
294 this->type_
!= TAO_TWOWAY_INVOCATION
)
296 throw ::CORBA::INTERNAL (
297 CORBA::SystemException::_tao_minor_code (
300 CORBA::COMPLETED_NO
);
303 TAO::Synch_Twoway_Invocation
synch (this->target_
, r
, details
,
306 // forward requested byte order
307 synch
._tao_byte_order (this->byte_order_
);
309 synch
.set_retry_state (retry_state
);
311 Invocation_Status
const status
= synch
.remote_twoway (max_wait_time
);
313 if (status
== TAO_INVOKE_RESTART
&&
314 (synch
.reply_status () == GIOP::LOCATION_FORWARD
||
315 synch
.reply_status () == GIOP::LOCATION_FORWARD_PERM
))
317 CORBA::Boolean
const is_permanent_forward
=
318 (synch
.reply_status () == GIOP::LOCATION_FORWARD_PERM
);
320 effective_target
= synch
.steal_forwarded_reference ();
322 this->object_forwarded (effective_target
,
324 is_permanent_forward
);
331 Invocation_Adapter::invoke_oneway (TAO_Operation_Details
&details
,
332 CORBA::Object_var
&effective_target
,
333 Profile_Transport_Resolver
&r
,
334 ACE_Time_Value
*&max_wait_time
)
336 TAO::Synch_Oneway_Invocation
synch (this->target_
, r
, details
);
338 // forward requested byte order
339 synch
._tao_byte_order (this->byte_order_
);
341 Invocation_Status
const s
= synch
.remote_oneway (max_wait_time
);
343 if (s
== TAO_INVOKE_RESTART
&&
344 (synch
.reply_status () == GIOP::LOCATION_FORWARD
||
345 synch
.reply_status () == GIOP::LOCATION_FORWARD_PERM
))
347 CORBA::Boolean
const is_permanent_forward
=
348 (synch
.reply_status () == GIOP::LOCATION_FORWARD_PERM
);
350 effective_target
= synch
.steal_forwarded_reference ();
352 this->object_forwarded (effective_target
,
354 is_permanent_forward
);
361 Invocation_Adapter::object_forwarded (CORBA::Object_var
&effective_target
,
363 CORBA::Boolean permanent_forward
)
365 // The object pointer has to be changed to a TAO_Stub pointer
366 // in order to obtain the profiles.
367 TAO_Stub
*stubobj
= nullptr;
369 bool nil_forward_ref
= false;
370 if (CORBA::is_nil (effective_target
.in ()))
371 nil_forward_ref
= true;
374 stubobj
= effective_target
->_stubobj ();
376 if (stubobj
&& stubobj
->base_profiles ().size () == 0)
377 nil_forward_ref
= true;
381 throw ::CORBA::TRANSIENT (
382 CORBA::SystemException::_tao_minor_code (
383 TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE
,
385 CORBA::COMPLETED_NO
);
387 if (stubobj
== nullptr)
388 throw ::CORBA::INTERNAL (
389 CORBA::SystemException::_tao_minor_code (
390 TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE
,
392 CORBA::COMPLETED_NO
);
394 // Reset the profile in the stubs
395 stub
->add_forward_profiles (stubobj
->base_profiles (), permanent_forward
);
397 if (stub
->next_profile () == nullptr)
398 throw ::CORBA::TRANSIENT (
399 CORBA::SystemException::_tao_minor_code (
400 TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE
,
402 CORBA::COMPLETED_NO
);
405 TAO::Collocation_Strategy
406 Invocation_Adapter::collocation_strategy (CORBA::Object_ptr object
)
408 TAO::Collocation_Strategy strategy
= TAO::TAO_CS_REMOTE_STRATEGY
;
409 TAO_Stub
*stub
= object
->_stubobj ();
410 if (!CORBA::is_nil (stub
->servant_orb_var ().in ()) &&
411 stub
->servant_orb_var ()->orb_core () != nullptr)
413 TAO_ORB_Core
*orb_core
= stub
->servant_orb_var ()->orb_core ();
415 if (orb_core
->collocation_resolver ().is_collocated (object
))
417 switch (orb_core
->get_collocation_strategy ())
419 case TAO_ORB_Core::TAO_COLLOCATION_THRU_POA
:
422 if (ACE_BIT_ENABLED (this->collocation_opportunity_
,
423 TAO::TAO_CO_THRU_POA_STRATEGY
))
425 strategy
= TAO::TAO_CS_THRU_POA_STRATEGY
;
429 if (TAO_debug_level
> 0)
431 TAOLIB_ERROR ((LM_ERROR
,
432 ACE_TEXT ("Invocation_Adapter::collocation_strategy, ")
433 ACE_TEXT ("request for through poa collocation ")
434 ACE_TEXT ("without needed collocation opportunity.\n")));
436 // collocation object, but no collocation_opportunity for Thru_poa
437 throw ::CORBA::INTERNAL (
438 CORBA::SystemException::_tao_minor_code (
441 CORBA::COMPLETED_NO
);
445 case TAO_ORB_Core::TAO_COLLOCATION_DIRECT
:
447 if (ACE_BIT_ENABLED (this->collocation_opportunity_
,
448 TAO::TAO_CO_DIRECT_STRATEGY
)
449 && (object
->_servant () != nullptr))
451 strategy
= TAO::TAO_CS_DIRECT_STRATEGY
;
455 if (TAO_debug_level
> 0)
457 TAOLIB_ERROR ((LM_ERROR
,
458 ACE_TEXT ("Invocation_Adapter::collocation_strategy, ")
459 ACE_TEXT ("request for direct collocation ")
460 ACE_TEXT ("without needed collocation opportunity.\n")));
462 // collocation object, but no collocation_opportunity for Direct
464 throw ::CORBA::INTERNAL (
465 CORBA::SystemException::_tao_minor_code (
468 CORBA::COMPLETED_NO
);
472 case TAO_ORB_Core::TAO_COLLOCATION_BEST
:
474 if (ACE_BIT_ENABLED (this->collocation_opportunity_
,
475 TAO::TAO_CO_DIRECT_STRATEGY
)
476 && (object
->_servant () != nullptr))
478 strategy
= TAO::TAO_CS_DIRECT_STRATEGY
;
480 else if (ACE_BIT_ENABLED (this->collocation_opportunity_
,
481 TAO::TAO_CO_THRU_POA_STRATEGY
))
483 strategy
= TAO::TAO_CS_THRU_POA_STRATEGY
;
487 strategy
= TAO::TAO_CS_REMOTE_STRATEGY
;
498 } // End namespace TAO
500 TAO_END_VERSIONED_NAMESPACE_DECL