2 #include "tao/Messaging/Asynch_Invocation.h"
3 #include "tao/Messaging/Asynch_Reply_Dispatcher.h"
5 #include "tao/Profile_Transport_Resolver.h"
6 #include "tao/Invocation_Utils.h"
7 #include "tao/operation_details.h"
8 #include "tao/Bind_Dispatcher_Guard.h"
9 #include "tao/Transport.h"
10 #include "tao/Muxed_TMS.h"
11 #include "tao/GIOP_Message_Base.h"
12 #include "tao/ORB_Constants.h"
14 #if TAO_HAS_INTERCEPTORS == 1
15 # include "tao/PortableInterceptorC.h"
16 #endif /*TAO_HAS_INTERCEPTORS */
18 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
22 Asynch_Remote_Invocation::Asynch_Remote_Invocation (
23 CORBA::Object_ptr otarget
,
24 Profile_Transport_Resolver
&resolver
,
25 TAO_Operation_Details
&detail
,
26 TAO_Asynch_Reply_Dispatcher_Base
*rd
,
27 bool response_expected
)
28 : Synch_Twoway_Invocation (otarget
,
37 Asynch_Remote_Invocation::remote_invocation (ACE_Time_Value
*max_wait_time
)
39 Invocation_Status s
= TAO_INVOKE_FAILURE
;
41 #if TAO_HAS_INTERCEPTORS == 1
42 s
= this->send_request_interception ();
44 if (s
!= TAO_INVOKE_SUCCESS
)
47 // We have started the interception flow. We need to call the
48 // ending interception flow if things go wrong. The purpose of the
49 // try block is to take care of the cases when things go wrong.
52 #endif /* TAO_HAS_INTERCEPTORS */
53 TAO_Transport
* const transport
= this->resolver_
.transport ();
57 // Way back, we failed to find a profile we could connect to.
58 // We've come this far only so we reach the interception points
59 // in case they can fix things. Time to bail....
60 throw CORBA::TRANSIENT (CORBA::OMGVMCID
| 2, CORBA::COMPLETED_NO
);
63 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX
, ace_mon
,
64 transport
->output_cdr_lock (), TAO_INVOKE_FAILURE
);
67 this->resolver_
.transport ()->out_stream ();
70 CDR_Byte_Order_Guard
cdr_guard (cdr
, this->_tao_byte_order ());
72 // Oneway semantics. See comments for below send_message()
74 cdr
.message_attributes (this->details_
.request_id (),
75 this->resolver_
.stub (),
76 TAO_Message_Semantics (TAO_Message_Semantics::TAO_ONEWAY_REQUEST
,
77 TAO_Message_Semantics::TAO_ASYNCH_CALLBACK
),
80 this->write_header (cdr
);
82 this->marshal_data (cdr
);
84 // Register a reply dispatcher for this invocation. Use the
85 // preallocated reply dispatcher.
86 TAO_Bind_Dispatcher_Guard
dispatch_guard (
87 this->details_
.request_id (),
88 this->safe_rd_
.get (),
91 // Now that we have bound the reply dispatcher to the map, just
92 // loose ownership of the reply dispatcher.
93 this->safe_rd_
.release ();
95 if (dispatch_guard
.status () != 0)
97 // @@ What is the right way to handle this error? Do we need
98 // to call the interceptors in this case?
99 throw ::CORBA::INTERNAL (TAO::VMCID
, CORBA::COMPLETED_NO
);
102 // Do not unbind during destruction. We need the entry to be
103 // there in the map since the reply dispatcher depends on
104 // that. This is also a trigger to loose the ownership of the
106 dispatch_guard
.status (TAO_Bind_Dispatcher_Guard::NO_UNBIND
);
108 // Send it as a oneway request. It will make all the required
109 // paraphernalia within the ORB to fire, like buffering if
111 s
= this->send_message (cdr
,
112 TAO_Message_Semantics (TAO_Message_Semantics::TAO_ONEWAY_REQUEST
,
113 TAO_Message_Semantics::TAO_ASYNCH_CALLBACK
),
115 } // CDR_Byte_Order_Guard
119 #if TAO_HAS_INTERCEPTORS == 1
120 // NOTE: We don't need to do the auto_ptr <> trick. We got here
121 // in the first place since the message was sent properly,
122 // which implies a reply would be available. Therefore the
123 // reply dispatcher should be available for another thread to
124 // collect and dispatch the reply. In MT cases, things are
125 // more hairy. Just imagine what happens when another thread
126 // is collecting the reply when we are happily invoking
129 // Nothing great on here. If we get a restart during send or a
130 // proper send, we are supposed to call receiver_other ()
131 // interception point. So we do that here
132 Invocation_Status
const tmp
= this->receive_other_interception ();
134 // We got an error during the interception.
135 if (s
== TAO_INVOKE_SUCCESS
&& tmp
!= TAO_INVOKE_SUCCESS
)
137 #endif /* TAO_HAS_INTERCEPTORS */
139 // If an error occurred just return. At this point all the
140 // endpoint interception would have been invoked. The callee
141 // would take care of the rest.
142 if (s
!= TAO_INVOKE_SUCCESS
)
145 // transport strategy takes care of idling transport or not
146 transport
->idle_after_send ();
147 // release transport from resolver in any case since we don't
148 // want the resolver to make the transport idle if the strategy
150 this->resolver_
.transport_released ();
152 #if TAO_HAS_INTERCEPTORS == 1
154 catch ( ::CORBA::Exception
& ex
)
156 PortableInterceptor::ReplyStatus
const status
=
157 this->handle_any_exception (&ex
);
159 if (status
== PortableInterceptor::LOCATION_FORWARD
||
160 status
== PortableInterceptor::TRANSPORT_RETRY
)
161 s
= TAO_INVOKE_RESTART
;
162 else if (status
== PortableInterceptor::SYSTEM_EXCEPTION
163 || status
== PortableInterceptor::USER_EXCEPTION
)
168 // Notify interceptors of non-CORBA exception, and propagate
169 // that exception to the caller.
171 PortableInterceptor::ReplyStatus
const st
=
172 this->handle_all_exception ();
174 if (st
== PortableInterceptor::LOCATION_FORWARD
||
175 st
== PortableInterceptor::TRANSPORT_RETRY
)
176 s
= TAO_INVOKE_RESTART
;
180 #endif /* TAO_HAS_INTERCEPTORS */
186 TAO_END_VERSIONED_NAMESPACE_DECL