Revert "Minor modernization of DynamicAny code"
[ACE_TAO.git] / TAO / tao / Invocation_Adapter.cpp
blobca07272ecba7743cb27e4608232527e64dca0ca3
1 // -*- C++ -*-
2 #include "tao/Invocation_Adapter.h"
3 #include "tao/Profile_Transport_Resolver.h"
4 #include "tao/operation_details.h"
5 #include "tao/Stub.h"
6 #include "tao/ORB_Core.h"
7 #include "tao/Synch_Invocation.h"
8 #include "tao/debug.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"
13 #include "tao/TAOC.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
26 namespace TAO
28 Invocation_Adapter::~Invocation_Adapter ()
32 void
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_),
41 this->args_,
42 this->number_args_,
43 this->has_in_args_,
44 ex_data,
45 ex_count);
47 this->invoke_i (stub, op_details);
50 void
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_);
64 // Initial state
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)
97 status =
98 this->invoke_remote_i (stub,
99 details,
100 effective_target,
101 max_wait_time,
102 &retry_state);
104 else
106 if (strat == TAO_CS_THRU_POA_STRATEGY)
108 (void) this->set_response_flags (stub, details);
111 status =
112 this->invoke_collocated_i (stub,
113 details,
114 effective_target,
115 strat);
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")));
132 bool
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);
138 return has_timeout;
141 TAO_Stub *
142 Invocation_Adapter::get_stub () const
144 TAO_Stub * const stub = this->target_->_stubobj ();
146 if (stub == nullptr)
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 (
157 TAO::VMCID,
158 EINVAL),
159 CORBA::COMPLETED_NO);
162 return stub;
165 Invocation_Status
166 Invocation_Adapter::invoke_collocated_i (TAO_Stub *stub,
167 TAO_Operation_Details &details,
168 CORBA::Object_var &effective_target,
169 Collocation_Strategy strat)
171 // Initial state
172 TAO::Invocation_Status status = TAO_INVOKE_START;
174 Collocated_Invocation coll_inv (this->target_,
175 effective_target.in (),
176 stub,
177 details,
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);
194 return status;
197 void
198 Invocation_Adapter::set_response_flags (
199 TAO_Stub *stub,
200 TAO_Operation_Details &details)
202 switch (this->type_)
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,
212 has_synchronization,
213 sync_scope);
214 if (has_synchronization)
215 details.response_flags (CORBA::Octet (sync_scope));
216 else
217 details.response_flags (
218 CORBA::Octet (Messaging::SYNC_WITH_TRANSPORT));
219 break;
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);
226 break;
231 Invocation_Status
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 (),
248 stub,
249 block_connect);
250 resolver.resolve (max_wait_time);
252 if (TAO_debug_level)
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 ());
264 switch (this->type_)
266 case TAO_ONEWAY_INVOCATION:
268 return this->invoke_oneway (details,
269 effective_target,
270 resolver,
271 max_wait_time);
273 case TAO_TWOWAY_INVOCATION:
275 return this->invoke_twoway (details,
276 effective_target,
277 resolver,
278 max_wait_time,
279 retry_state);
282 return TAO_INVOKE_FAILURE;
285 Invocation_Status
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 (
298 TAO::VMCID,
299 EINVAL),
300 CORBA::COMPLETED_NO);
303 TAO::Synch_Twoway_Invocation synch (this->target_, r, details,
304 true);
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,
323 r.stub (),
324 is_permanent_forward);
327 return status;
330 Invocation_Status
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,
353 r.stub (),
354 is_permanent_forward);
357 return s;
360 void
361 Invocation_Adapter::object_forwarded (CORBA::Object_var &effective_target,
362 TAO_Stub *stub,
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;
372 else
374 stubobj = effective_target->_stubobj ();
376 if (stubobj && stubobj->base_profiles ().size () == 0)
377 nil_forward_ref = true;
380 if (nil_forward_ref)
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,
391 EINVAL),
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:
421 // check opportunity
422 if (ACE_BIT_ENABLED (this->collocation_opportunity_,
423 TAO::TAO_CO_THRU_POA_STRATEGY))
425 strategy = TAO::TAO_CS_THRU_POA_STRATEGY;
427 else
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 (
439 TAO::VMCID,
440 EINVAL),
441 CORBA::COMPLETED_NO);
443 break;
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;
453 else
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
463 // or servant() == 0
464 throw ::CORBA::INTERNAL (
465 CORBA::SystemException::_tao_minor_code (
466 TAO::VMCID,
467 EINVAL),
468 CORBA::COMPLETED_NO);
470 break;
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;
485 else
487 strategy = TAO::TAO_CS_REMOTE_STRATEGY;
489 break;
495 return strategy;
498 } // End namespace TAO
500 TAO_END_VERSIONED_NAMESPACE_DECL