1 #include "tao/Synch_Invocation.h"
2 #include "tao/Invocation_Retry_State.h"
3 #include "tao/Profile_Transport_Resolver.h"
4 #include "tao/Profile.h"
5 #include "tao/Synch_Reply_Dispatcher.h"
6 #include "tao/Transport.h"
8 #include "tao/Bind_Dispatcher_Guard.h"
9 #include "tao/operation_details.h"
10 #include "tao/Wait_Strategy.h"
11 #include "tao/debug.h"
12 #include "tao/ORB_Constants.h"
13 #include "tao/Messaging_SyncScopeC.h"
14 #include "tao/ORB_Core.h"
15 #include "tao/Service_Context.h"
16 #include "tao/SystemException.h"
17 #include "ace/Intrusive_Auto_Ptr.h"
19 #if TAO_HAS_INTERCEPTORS == 1
20 # include "tao/PortableInterceptorC.h"
21 #endif /*TAO_HAS_INTERCEPTORS */
24 #include "ace/OS_NS_string.h"
25 #include "tao/ORB_Time_Policy.h"
27 #if !defined (__ACE_INLINE__)
28 # include "tao/Synch_Invocation.inl"
29 #endif /* __ACE_INLINE__ */
31 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
36 excep_for_type (const char *tid
)
38 if (ACE_OS::strcmp (tid
, "IDL:omg.org/CORBA/TRANSIENT:1.0") == 0)
40 return TAO::FOE_TRANSIENT
;
42 else if (ACE_OS::strcmp (tid
, "IDL:omg.org/CORBA/COMM_FAILURE:1.0") == 0)
44 return TAO::FOE_COMM_FAILURE
;
46 else if (ACE_OS::strcmp (tid
, "IDL:omg.org/CORBA/OBJECT_NOT_EXIST:1.0") == 0)
48 return TAO::FOE_OBJECT_NOT_EXIST
;
50 else if (ACE_OS::strcmp (tid
, "IDL:omg.org/CORBA/INV_OBJREF:1.0") == 0)
52 return TAO::FOE_INV_OBJREF
;
54 else if (ACE_OS::strcmp (tid
, "IDL:omg.org/CORBA/OBJ_ADAPTER:1.0") == 0)
56 return TAO::FOE_OBJ_ADAPTER
;
58 else if (ACE_OS::strcmp (tid
, "IDL:omg.org/CORBA/NO_RESPONSE:1.0") == 0)
60 return TAO::FOE_NO_RESPONSE
;
69 Synch_Twoway_Invocation::Synch_Twoway_Invocation (
70 CORBA::Object_ptr otarget
,
71 Profile_Transport_Resolver
&resolver
,
72 TAO_Operation_Details
&detail
,
73 bool response_expected
)
74 : Remote_Invocation (otarget
,
78 , retry_state_ (nullptr)
83 Synch_Twoway_Invocation::set_retry_state (Invocation_Retry_State
*retry_state
)
85 this->retry_state_
= retry_state
;
89 Synch_Twoway_Invocation::remote_twoway (ACE_Time_Value
*max_wait_time
)
91 TAO::ORB_Countdown_Time
countdown (max_wait_time
);
93 TAO_Synch_Reply_Dispatcher
*rd_p
=
94 new (std::nothrow
) TAO_Synch_Reply_Dispatcher (this->resolver_
.stub ()->orb_core (),
95 this->details_
.reply_service_info ());
98 throw ::CORBA::NO_MEMORY ();
101 ACE_Intrusive_Auto_Ptr
<TAO_Synch_Reply_Dispatcher
> rd(rd_p
, false);
103 Invocation_Status s
= TAO_INVOKE_FAILURE
;
105 #if TAO_HAS_INTERCEPTORS == 1
106 // Start the interception point here..
107 s
= this->send_request_interception ();
109 if (s
!= TAO_INVOKE_SUCCESS
)
112 // We have started the interception flow. We need to call the
113 // ending interception flow if things go wrong. The purpose of the
114 // try block is to do just this.
117 #endif /*TAO_HAS_INTERCEPTORS */
118 TAO_Transport
* const transport
= this->resolver_
.transport ();
122 if (this->retry_state_
&&
123 this->retry_state_
->forward_on_exception_increment(FOE_TRANSIENT
))
125 if (TAO_debug_level
> 0)
126 TAOLIB_DEBUG ((LM_INFO
,
127 ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::")
128 ACE_TEXT ("remote_twoway retrying on TRANSIENT ")
129 ACE_TEXT ("exception\n")));
130 this->retry_state_
->next_profile_retry (*this->stub ());
131 #if TAO_HAS_INTERCEPTORS == 1
132 s
= this->receive_other_interception ();
133 #endif /* TAO_HAS_INTERCEPTORS */
134 return TAO_INVOKE_RESTART
;
138 // Way back, we failed to find a profile we could connect to.
139 // We've come this far only so we reach the interception points
140 // in case they can fix things. Time to bail....
141 throw CORBA::TRANSIENT (CORBA::OMGVMCID
| 2, CORBA::COMPLETED_NO
);
146 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX
, ace_mon
,
147 transport
->output_cdr_lock (), TAO_INVOKE_FAILURE
);
149 TAO_OutputCDR
&cdr
= transport
->out_stream ();
151 CDR_Byte_Order_Guard
cdr_guard (cdr
, this->_tao_byte_order ());
153 cdr
.message_attributes (this->details_
.request_id (),
154 this->resolver_
.stub (),
155 TAO_Message_Semantics (),
158 this->write_header (cdr
);
160 this->marshal_data (cdr
);
162 // Register a reply dispatcher for this invocation. Use the
163 // preallocated reply dispatcher.
164 TAO_Bind_Dispatcher_Guard
dispatch_guard (
165 this->details_
.request_id (),
169 if (dispatch_guard
.status () != 0)
171 // @@ What is the right way to handle this error? Why should
172 // we close the connection?
173 transport
->close_connection ();
175 throw ::CORBA::INTERNAL (0, CORBA::COMPLETED_NO
);
180 s
= this->send_message (cdr
,
181 TAO_Message_Semantics (),
184 cdr_guard
.reset (); // CDR_Byte_Order_Guard
188 #if TAO_HAS_INTERCEPTORS == 1
189 // @@NOTE: Too much code repetition.
190 // If the above call returns a restart due to connection
191 // failure then call the receive_other interception point
193 if (s
== TAO_INVOKE_RESTART
)
195 Invocation_Status
const tmp
= this->receive_other_interception ();
197 if (tmp
!= TAO_INVOKE_SUCCESS
)
200 #endif /* TAO_HAS_INTERCEPTORS */
202 if (s
!= TAO_INVOKE_SUCCESS
)
207 // For some strategies one may want to release the transport
208 // back to cache. If the idling is successful let the
209 // resolver about that.
210 if (transport
->idle_after_send ())
211 this->resolver_
.transport_released ();
213 // @@ In all MT environments, there's a cancellation point lurking
214 // here; need to investigate. Client threads would frequently be
215 // canceled sometime during recv_request ... the correct action to
216 // take on being canceled is to issue a CancelRequest message to the
217 // server and then immediately let other client-side cancellation
218 // handlers do their jobs.
220 // In C++, that basically means to unwind the stack using almost
221 // normal procedures: all destructors should fire, and some "catch"
222 // blocks should probably be able to handle things like releasing
223 // pointers. (Without unwinding the C++ stack, resources that must
224 // be freed by thread cancellation won't be freed, and the process
225 // won't continue to function correctly.) The tricky part is that
226 // according to POSIX, all C stack frames must also have their
227 // (explicitly coded) handlers called. We assume a POSIX.1c/C/C++
230 s
= this->wait_for_reply (max_wait_time
, *rd
.get (), dispatch_guard
);
232 #if TAO_HAS_INTERCEPTORS == 1
233 if (s
== TAO_INVOKE_RESTART
)
235 Invocation_Status
const tmp
= this->receive_other_interception ();
237 // Push the latest values for the return..
238 if (tmp
!= TAO_INVOKE_SUCCESS
)
241 #endif /* TAO_HAS_INTERCEPTORS */
243 if (s
!= TAO_INVOKE_SUCCESS
)
246 // What happens when the above call returns an error through
247 // the return value? That would be bogus as per the contract
248 // in the interface. The call violated the contract
249 s
= this->check_reply_status (*rd
.get ());
251 // For some strategies one may want to release the transport
252 // back to cache after receiving the reply.
253 if (transport
->idle_after_reply ())
254 this->resolver_
.transport_released ();
256 #if TAO_HAS_INTERCEPTORS == 1
257 Invocation_Status tmp
= TAO_INVOKE_FAILURE
;
258 if (s
== TAO_INVOKE_RESTART
)
260 tmp
= this->receive_other_interception ();
262 else if (s
== TAO_INVOKE_SUCCESS
)
264 tmp
= this->receive_reply_interception ();
266 if (tmp
!= TAO_INVOKE_SUCCESS
)
269 catch ( ::CORBA::Exception
& ex
)
271 PortableInterceptor::ReplyStatus
const status
=
272 this->handle_any_exception (&ex
);
274 if (status
== PortableInterceptor::LOCATION_FORWARD
||
275 status
== PortableInterceptor::TRANSPORT_RETRY
)
276 s
= TAO_INVOKE_RESTART
;
277 else if (status
== PortableInterceptor::SYSTEM_EXCEPTION
278 || status
== PortableInterceptor::USER_EXCEPTION
)
283 // Notify interceptors of non-CORBA exception, and propagate
284 // that exception to the caller.
286 PortableInterceptor::ReplyStatus
const st
=
287 this->handle_all_exception ();
289 if (st
== PortableInterceptor::LOCATION_FORWARD
||
290 st
== PortableInterceptor::TRANSPORT_RETRY
)
291 s
= TAO_INVOKE_RESTART
;
295 #endif /* TAO_HAS_INTERCEPTORS */
301 Synch_Twoway_Invocation::wait_for_reply (ACE_Time_Value
*max_wait_time
,
302 TAO_Synch_Reply_Dispatcher
&rd
,
303 TAO_Bind_Dispatcher_Guard
&bd
)
306 * Precondition: The call went to the remote
307 * peer. <ACE_Thread::self> is waiting for the reply.
309 * Postcondition: Any error during a wait is marked by raising an
310 * exception. Success alone is returned through the return value.
314 expired
= (max_wait_time
&& ACE_Time_Value::zero
== *max_wait_time
);
318 reply_error
= expired
? -1 :
319 this->resolver_
.transport ()->wait_strategy ()->wait (max_wait_time
, rd
);
321 if (TAO_debug_level
> 0 && max_wait_time
)
323 TAOLIB_DEBUG ((LM_DEBUG
,
324 ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::wait_for_reply, ")
325 ACE_TEXT ("timeout after recv is <%u> status <%d>\n"),
326 max_wait_time
->msec (),
330 // Check the reply error.
331 if (reply_error
== -1)
333 // Unbind the dispatcher, since its of no use at this point of
335 if (TAO_debug_level
> 3)
337 TAOLIB_DEBUG ((LM_DEBUG
,
338 ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::")
339 ACE_TEXT ("wait_for_reply, ")
340 ACE_TEXT ("recovering after an error\n")));
343 // You the smarty, don't try to moving the unbind_dispatcher
344 // () call since it looks like it is repeated twice. That
345 // could land you in trouble. If you don't believe this
346 // warning go ahead and try. Try running tests to see what is
350 // If the unbind succeeds then thrown an exception to the
351 // application, else just collect the reply and dispatch
352 // that to the application.
354 // NOTE: A fragile synchronization is provided when using
355 // the Muxed Transport strategy. We could infact be a
356 // follower thread getting timedout in the LF whereas the
357 // dispatching thread could be on the reply_dispatcher
358 // that we created. This would lead bad crashes. To get
359 // around that, the call to unbind_dispatcher () will wait
360 // on the lock on the Muxed_Transport_Strategy if
361 // dispatching has started. This is fragile.
362 if (bd
.unbind_dispatcher () == 0)
364 // Just a timeout with completed_maybe, don't close
365 // the connection or anything
366 throw ::CORBA::TIMEOUT (
367 CORBA::SystemException::_tao_minor_code (
368 TAO_TIMEOUT_RECV_MINOR_CODE
,
370 CORBA::COMPLETED_MAYBE
);
375 (void) bd
.unbind_dispatcher ();
376 this->resolver_
.transport ()->close_connection ();
378 if (this->retry_state_
&&
379 this->resolver_
.transport ()->connection_closed_on_read() &&
380 this->retry_state_
->forward_on_reply_closed_increment ())
382 if (TAO_debug_level
> 4)
383 TAOLIB_DEBUG ((LM_DEBUG
,
384 ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::")
385 ACE_TEXT ("wait_for_reply, forward profile on ")
386 ACE_TEXT ("connection closed\n")));
387 this->retry_state_
->next_profile_retry (*this->stub ());
388 return TAO_INVOKE_RESTART
;
394 this->stub()->orb_core ()->service_raise_comm_failure (
395 this->details_
.request_service_context ().service_info (),
396 this->resolver_
.profile ());
398 catch (const ::CORBA::Exception
&)
400 if (this->retry_state_
== nullptr ||
401 !this->retry_state_
->forward_on_exception_limit_used ())
403 this->resolver_
.stub ()->reset_profiles ();
410 return TAO_INVOKE_SUCCESS
;
414 Synch_Twoway_Invocation::check_reply_status (TAO_Synch_Reply_Dispatcher
&rd
)
417 * Precondition: We probably got a reply. <ACE_Thread::self> is
418 * checking the status of the reply
420 * Postcondition: Any error while reading the reply is marked by
421 * raising an exception. LOCATION_FORWARDED replies are marked by
422 * returning a restart since that is what needed to be done by the
425 TAO_InputCDR
&cdr
= rd
.reply_cdr ();
427 // Set the translators
428 this->resolver_
.transport ()->assign_translators (&cdr
, nullptr);
430 // At this point it can be assumed that the GIOP/whatever protocol
431 // header and the reply header are already handled. Further it
432 // can be assumed that the reply body contains the details
433 // required for further processing. All the other details should
434 // have been handled in the reply dispatcher/protocol framework.
435 switch (rd
.reply_status ())
437 case GIOP::NO_EXCEPTION
:
439 Reply_Guard
mon (this, TAO_INVOKE_FAILURE
);
440 if (this->details_
.demarshal_args (cdr
) == false)
442 throw ::CORBA::MARSHAL ();
445 mon
.set_status (TAO_INVOKE_SUCCESS
);
448 case GIOP::LOCATION_FORWARD
:
449 return this->location_forward (cdr
);
450 case GIOP::LOCATION_FORWARD_PERM
:
452 // Unmarshal the location forward object and set the
453 // variable this->forward_to_.
454 Invocation_Status
const s
= this->location_forward (cdr
);
455 if (s
!= TAO_INVOKE_FAILURE
)
457 // de-marshalling of permanent object reference was successfull
458 CORBA::Boolean
const permanent_forward_condition
=
459 this->stub ()->orb_core ()->is_permanent_forward_condition
460 (this->forwarded_to_
.in (),
461 this->request_service_context ());
463 if (!permanent_forward_condition
)
465 // permanent condition not given
466 if (TAO_debug_level
> 3)
467 TAOLIB_DEBUG ((LM_DEBUG
,
468 ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::")
469 ACE_TEXT ("check_reply_status: unexpected ")
470 ACE_TEXT ("LOCATION_FORWARD_PERM reply\n")));
472 throw ::CORBA::INTERNAL (0, CORBA::COMPLETED_NO
);
475 // This is the only place where we set in permanent forward state.
476 this->reply_status (GIOP::LOCATION_FORWARD_PERM
);
481 case GIOP::USER_EXCEPTION
:
482 return this->handle_user_exception (cdr
);
483 case GIOP::SYSTEM_EXCEPTION
:
484 return this->handle_system_exception (cdr
);
486 case GIOP::NEEDS_ADDRESSING_MODE
:
488 Reply_Guard
mon (this, TAO_INVOKE_FAILURE
);
489 // We have received a message with a request to change the
490 // addressing mode. First let us read the mode that the
491 // server/agent asks for.
492 CORBA::Short addr_mode
= 0;
494 if (cdr
.read_short (addr_mode
) == 0)
496 // Could not demarshal the addressing disposition, raise an local
498 throw ::CORBA::MARSHAL (0, CORBA::COMPLETED_MAYBE
);
501 // Now set this addressing mode in the profile, so that
502 // the next invocation need not go through this.
503 this->resolver_
.profile ()->addressing_mode (addr_mode
);
505 mon
.set_status (TAO_INVOKE_RESTART
);
507 // Now restart the invocation
508 return TAO_INVOKE_RESTART
;
511 return TAO_INVOKE_SUCCESS
;
515 Synch_Twoway_Invocation::location_forward (TAO_InputCDR
&inp_stream
)
517 Reply_Guard
mon (this, TAO_INVOKE_FAILURE
);
519 if (TAO_debug_level
> 3)
521 TAOLIB_DEBUG ((LM_DEBUG
,
522 ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::")
523 ACE_TEXT ("location_forward being handled\n")));
526 CORBA::Object_var fwd
;
528 if (!(inp_stream
>> fwd
))
530 throw ::CORBA::MARSHAL (
531 CORBA::SystemException::_tao_minor_code (
532 TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE
,
534 CORBA::COMPLETED_NO
);
537 this->forwarded_reference (fwd
.in ());
539 mon
.set_status (TAO_INVOKE_RESTART
);
541 return TAO_INVOKE_RESTART
;
545 Synch_Twoway_Invocation::handle_user_exception (TAO_InputCDR
&cdr
)
547 Reply_Guard
mon (this,
550 if (TAO_debug_level
> 3)
551 TAOLIB_DEBUG ((LM_DEBUG
,
552 ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::")
553 ACE_TEXT ("handle_user_exception\n")));
555 // Pull the exception from the stream.
556 CORBA::String_var buf
;
558 if (!(cdr
>> buf
.inout ()))
560 // Could not demarshal the exception id, raise an local
562 throw ::CORBA::MARSHAL (0, CORBA::COMPLETED_MAYBE
);
565 CORBA::Exception
*exception
= this->details_
.corba_exception (buf
.in ());
567 exception
->_tao_decode (cdr
);
569 if (TAO_debug_level
> 5)
571 TAOLIB_DEBUG ((LM_DEBUG
,
572 ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::")
573 ACE_TEXT ("handle_user_exception - ")
574 ACE_TEXT ("raising exception %C\n"),
578 mon
.set_status (TAO_INVOKE_USER_EXCEPTION
);
580 // We must manage the memory allocated
581 // by the call above to alloc().
582 std::unique_ptr
<CORBA::Exception
> safety (exception
);
584 exception
->_raise ();
586 return TAO_INVOKE_USER_EXCEPTION
;
590 Synch_Twoway_Invocation::handle_system_exception (TAO_InputCDR
&cdr
)
592 Reply_Guard
mon (this, TAO_INVOKE_FAILURE
);
594 if (TAO_debug_level
> 3)
595 TAOLIB_DEBUG ((LM_DEBUG
,
596 ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::")
597 ACE_TEXT ("handle_system_exception\n")));
599 CORBA::String_var type_id
;
601 if (!(cdr
>> type_id
.inout ()))
603 // Could not demarshal the exception id, raise an local
605 throw ::CORBA::MARSHAL (0, CORBA::COMPLETED_MAYBE
);
608 CORBA::ULong minor
= 0;
609 CORBA::ULong completion
= 0;
611 if (!(cdr
>> minor
) || !(cdr
>> completion
))
613 throw ::CORBA::MARSHAL (0, CORBA::COMPLETED_MAYBE
);
616 bool retry_on_exception
= false;
617 bool do_forward
= false;
619 const TAO_ORB_Parameters
*orb_params
= this->stub ()->orb_core ()->orb_params ();
621 if (this->retry_state_
&&
622 this->retry_state_
->forward_on_exception_limit_used () &&
623 (CORBA::CompletionStatus
) completion
== CORBA::COMPLETED_NO
)
625 if (this->retry_state_
->forward_on_exception_increment (excep_for_type (type_id
.in ())))
627 retry_on_exception
= true;
628 this->retry_state_
->sleep_at_starting_profile (*this->stub ());
633 int const foe_kind
= orb_params
->forward_once_exception();
634 int const ex_id
= excep_for_type (type_id
.in ());
636 // this logic is a little confusing but prior to Jul 24 2009, TRANSIENT,
637 // OBJ_ADAPTER, NO_RESPONSE, and COMM_FAILURE were always retried if possible.
638 // Later, the ForwardOnceOn* were added, which reverts to default behavior
640 if ((CORBA::CompletionStatus
) completion
!= CORBA::COMPLETED_YES
)
644 case TAO::FOE_TRANSIENT
:
645 case TAO::FOE_COMM_FAILURE
:
646 retry_on_exception
= (foe_kind
& ex_id
) == 0;
648 case TAO::FOE_OBJ_ADAPTER
:
649 case TAO::FOE_NO_RESPONSE
:
650 retry_on_exception
= true;
652 case TAO::FOE_OBJECT_NOT_EXIST
:
653 retry_on_exception
= orb_params
->forward_invocation_on_object_not_exist ();
658 if (!retry_on_exception
)
660 do_forward
= !this->stub ()->forwarded_on_exception () &&
661 ((foe_kind
& ex_id
) == ex_id
);
666 if (retry_on_exception
|| do_forward
)
668 // If we are here then possibly we'll need a restart.
669 mon
.set_status (TAO_INVOKE_RESTART
);
671 if (TAO_debug_level
> 4)
672 TAOLIB_DEBUG ((LM_DEBUG
,
673 ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::")
674 ACE_TEXT ("handle_system_exception, profile forwarding ")
675 ACE_TEXT ("on exception %C \n"),
679 this->stub ()->forwarded_on_exception (true);
681 // Start the special case for FTCORBA.
683 * There has been a unanimous view that this is not the
684 * right way to do things. But a need to be compliant is
685 * forcing us into this.
687 Invocation_Status
const s
=
688 this->stub ()->orb_core ()->service_raise_transient_failure (
689 this->details_
.request_service_context ().service_info (),
690 this->resolver_
.profile ());
692 if (s
== TAO_INVOKE_RESTART
)
695 // Attempt profile retry.
697 * @note A location forwarding loop may occur where a client
698 * is bounced from the original target to the forwarded
699 * target and back if the application is not equipped to
700 * handle retries of previously called targets. TAO may
701 * be able to help in this case but it ultimately ends
702 * up being an application issue.
704 if (completion
!= CORBA::COMPLETED_MAYBE
&&
705 this->resolver_
.stub ()->next_profile_retry ())
707 return TAO_INVOKE_RESTART
;
710 // Fall through and raise an exception.
711 mon
.set_status (TAO_INVOKE_FAILURE
);
714 CORBA::SystemException
*ex
= TAO::create_system_exception (type_id
.in ());
718 // @@ We should raise a CORBA::NO_MEMORY, but we ran out
719 // of memory already. We need a pre-allocated, TSS,
720 // CORBA::NO_MEMORY instance
726 // Without this, the call to create_system_exception() above
727 // causes a memory leak. On platforms without native exceptions,
728 // the CORBA::Environment class manages the memory.
729 std::unique_ptr
<CORBA::SystemException
> safety (ex
);
732 ex
->completed (CORBA::CompletionStatus (completion
));
734 if (TAO_debug_level
> 4)
735 TAOLIB_DEBUG ((LM_DEBUG
,
736 ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::")
737 ACE_TEXT ("handle_system_exception, about to raise\n")));
739 mon
.set_status (TAO_INVOKE_SYSTEM_EXCEPTION
);
741 // Raise the exception.
744 return TAO_INVOKE_SYSTEM_EXCEPTION
;
747 // =========================================================================
749 Synch_Oneway_Invocation::Synch_Oneway_Invocation (
750 CORBA::Object_ptr otarget
,
751 Profile_Transport_Resolver
&r
,
752 TAO_Operation_Details
&d
)
753 : Synch_Twoway_Invocation (otarget
, r
, d
, false)
758 Synch_Oneway_Invocation::remote_oneway (ACE_Time_Value
*max_wait_time
)
760 TAO::ORB_Countdown_Time
countdown (max_wait_time
);
762 CORBA::Octet
const response_flags
= this->details_
.response_flags ();
764 Invocation_Status s
= TAO_INVOKE_FAILURE
;
766 if (response_flags
== CORBA::Octet (Messaging::SYNC_WITH_SERVER
) ||
767 response_flags
== CORBA::Octet (Messaging::SYNC_WITH_TARGET
))
769 s
= Synch_Twoway_Invocation::remote_twoway (max_wait_time
);
774 #if TAO_HAS_INTERCEPTORS == 1
775 s
= this->send_request_interception ();
777 if (s
!= TAO_INVOKE_SUCCESS
)
782 #endif /*TAO_HAS_INTERCEPTORS */
783 TAO_Transport
* const transport
= this->resolver_
.transport ();
787 if (this->retry_state_
&&
788 this->retry_state_
->forward_on_exception_increment(FOE_TRANSIENT
))
790 if (TAO_debug_level
> 0)
791 TAOLIB_DEBUG ((LM_INFO
,
792 ACE_TEXT ("TAO (%P|%t) - Synch_Oneway_Invocation::")
793 ACE_TEXT ("remote_oneway retrying on TRANSIENT ")
794 ACE_TEXT ("exception\n")));
795 this->retry_state_
->next_profile_retry (*this->stub ());
796 return TAO_INVOKE_RESTART
;
800 // Way back, we failed to find a profile we could connect to.
801 // We've come this far only so we reach the interception points
802 // in case they can fix things. Time to bail....
803 throw CORBA::TRANSIENT (CORBA::OMGVMCID
| 2, CORBA::COMPLETED_NO
);
809 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX
, ace_mon
, transport
->output_cdr_lock (),
812 TAO_OutputCDR
&cdr
= transport
->out_stream ();
815 CDR_Byte_Order_Guard
cdr_guard (cdr
, this->_tao_byte_order ());
817 cdr
.message_attributes (this->details_
.request_id (),
818 this->resolver_
.stub (),
819 TAO_Message_Semantics (TAO_Message_Semantics::
823 this->write_header (cdr
);
825 this->marshal_data (cdr
);
829 if (transport
->is_connected ())
831 // We have a connected transport so we can send the message
832 s
= this->send_message (cdr
,
833 TAO_Message_Semantics (TAO_Message_Semantics::
837 if (transport
->wait_strategy ()->non_blocking () == 0 &&
838 transport
->orb_core ()->client_factory ()->use_cleanup_options ())
840 if (!transport
->wait_strategy ()->is_registered())
842 ACE_Event_Handler
* const eh
=
843 transport
->event_handler_i ();
845 ACE_Reactor
* const r
=
846 transport
->orb_core ()->reactor ();
848 if (r
->register_handler (eh
, ACE_Event_Handler::READ_MASK
) == -1)
850 if (TAO_debug_level
> 0)
851 TAOLIB_ERROR ((LM_ERROR
,
852 ACE_TEXT ("TAO (%P|%t) - Synch_Oneway_Invocation::")
853 ACE_TEXT ("remote_oneway transport[%d] ")
854 ACE_TEXT ("registration withreactor ")
855 ACE_TEXT ("returned an error\n"),
860 // Only set this flag when registration succeeds
861 transport
->wait_strategy ()->is_registered (true);
869 if (TAO_debug_level
> 4)
870 TAOLIB_DEBUG ((LM_DEBUG
,
871 ACE_TEXT ("TAO (%P|%t) - Synch_Oneway_Invocation::")
872 ACE_TEXT ("remote_oneway, queueing message\n")));
874 if (transport
->format_queue_message (cdr
,
876 this->resolver_
.stub()) != 0)
878 s
= TAO_INVOKE_FAILURE
;
881 } // CDR_Byte_Order_Guard
884 #if TAO_HAS_INTERCEPTORS == 1
885 s
= this->receive_other_interception ();
887 catch ( ::CORBA::Exception
& ex
)
889 PortableInterceptor::ReplyStatus
const status
=
890 this->handle_any_exception (&ex
);
892 if (status
== PortableInterceptor::LOCATION_FORWARD
||
893 status
== PortableInterceptor::TRANSPORT_RETRY
)
894 s
= TAO_INVOKE_RESTART
;
895 else if (status
== PortableInterceptor::SYSTEM_EXCEPTION
896 || status
== PortableInterceptor::USER_EXCEPTION
)
901 // Notify interceptors of non-CORBA exception, and propagate
902 // that exception to the caller.
904 PortableInterceptor::ReplyStatus
const st
=
905 this->handle_all_exception ();
907 if (st
== PortableInterceptor::LOCATION_FORWARD
||
908 st
== PortableInterceptor::TRANSPORT_RETRY
)
909 s
= TAO_INVOKE_RESTART
;
913 #endif /* TAO_HAS_INTERCEPTORS */
919 TAO_END_VERSIONED_NAMESPACE_DECL