2 #include "tao/LocateRequest_Invocation.h"
3 #include "tao/Profile_Transport_Resolver.h"
4 #include "tao/operation_details.h"
6 #include "tao/Bind_Dispatcher_Guard.h"
7 #include "tao/Transport.h"
8 #include "tao/Synch_Reply_Dispatcher.h"
9 #include "tao/GIOP_Utils.h"
10 #include "tao/Profile.h"
11 #include "tao/ORB_Constants.h"
12 #include "tao/SystemException.h"
13 #include "ace/Intrusive_Auto_Ptr.h"
15 #include "tao/ORB_Time_Policy.h"
17 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
22 * @class First_Request_Guard
24 * @brief Auto pointer like class for first_request flag in transport.
26 * Since codeset service context is only sent in the first request it might
27 * happen that after LocateRequest (which doesn't include service context)
28 * no codeset negotiation happens in subsequent calls. In this respect
29 * LocateRequest is not the first request and thus First_Request_Guard
30 * restores first_request in transport to its original state.
32 class First_Request_Guard
35 First_Request_Guard (TAO_Transport
&transport
);
37 ~First_Request_Guard ();
40 /// The transport that we guard.
41 TAO_Transport
&transport_
;
43 /// Original value of first_request from transport.
47 First_Request_Guard::First_Request_Guard (TAO_Transport
&transport
)
48 : transport_ (transport
)
50 this->is_first_
= this->transport_
.first_request ();
53 First_Request_Guard::~First_Request_Guard ()
55 this->transport_
.first_request_sent (this->is_first_
);
58 LocateRequest_Invocation::LocateRequest_Invocation (
59 CORBA::Object_ptr otarget
,
60 Profile_Transport_Resolver
&resolver
,
61 TAO_Operation_Details
&detail
63 : Synch_Twoway_Invocation (otarget
,
70 LocateRequest_Invocation::invoke (ACE_Time_Value
*max_wait_time
)
72 TAO::ORB_Countdown_Time
countdown (max_wait_time
);
74 TAO_Synch_Reply_Dispatcher
*rd_p
= nullptr;
75 ACE_NEW_NORETURN (rd_p
, TAO_Synch_Reply_Dispatcher (this->resolver_
.stub ()->orb_core (),
76 this->details_
.reply_service_info ()));
79 throw ::CORBA::NO_MEMORY ();
82 ACE_Intrusive_Auto_Ptr
<TAO_Synch_Reply_Dispatcher
> rd(rd_p
, false);
84 // Register a reply dispatcher for this invocation. Use the
85 // preallocated reply dispatcher.
86 TAO_Bind_Dispatcher_Guard
dispatch_guard (this->details_
.request_id (),
88 this->resolver_
.transport ()->tms ());
90 if (dispatch_guard
.status () != 0)
92 // @@ What is the right way to handle this error? Do we need
93 // to call the interceptors in this case?
94 this->resolver_
.transport ()->close_connection ();
96 throw ::CORBA::INTERNAL (TAO::VMCID
, CORBA::COMPLETED_NO
);
99 TAO_Transport
*transport
= this->resolver_
.transport ();
101 Invocation_Status s
= TAO_INVOKE_FAILURE
;
103 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX
, ace_mon
,
104 transport
->output_cdr_lock (), TAO_INVOKE_FAILURE
);
105 TAO_OutputCDR
&cdr
= transport
->out_stream ();
107 // This must restore first_request flag after message is sent.
108 First_Request_Guard
fr_quard (*transport
);
110 TAO_Target_Specification tspec
;
111 this->init_target_spec (tspec
, cdr
);
113 if (transport
->generate_locate_request (tspec
, this->details_
, cdr
) == -1)
114 return TAO_INVOKE_FAILURE
;
118 s
= this->send_message (cdr
, TAO_Message_Semantics (), max_wait_time
);
121 if (s
!= TAO_INVOKE_SUCCESS
)
126 // For some strategies one may want to release the transport
127 // back to cache. If the idling is successful let the
128 // resolver about that.
129 if (this->resolver_
.transport ()->idle_after_send ())
130 this->resolver_
.transport_released ();
132 s
= this->wait_for_reply (max_wait_time
, *rd
.get (), dispatch_guard
);
134 s
= this->check_reply (*rd
.get ());
136 // For some strategies one may want to release the transport
137 // back to cache after receiving the reply. If the idling is
138 // successful let the resolver about that.
139 if (this->resolver_
.transport ()->idle_after_reply ())
140 this->resolver_
.transport_released ();
146 LocateRequest_Invocation::check_reply (TAO_Synch_Reply_Dispatcher
&rd
)
148 TAO_InputCDR
&cdr
= rd
.reply_cdr ();
150 // Set the translators
151 this->resolver_
.transport ()->assign_translators (&cdr
, nullptr);
153 switch (rd
.locate_reply_status ())
155 case GIOP::OBJECT_HERE
:
157 case GIOP::UNKNOWN_OBJECT
:
158 throw ::CORBA::OBJECT_NOT_EXIST (TAO::VMCID
, CORBA::COMPLETED_YES
);
159 case GIOP::OBJECT_FORWARD
:
160 case GIOP::OBJECT_FORWARD_PERM
:
161 return this->location_forward (cdr
);
162 case GIOP::LOC_SYSTEM_EXCEPTION
:
164 // Pull the exception from the stream.
165 CORBA::String_var buf
;
167 if ((cdr
>> buf
.inout ()) == 0)
169 // Could not demarshal the exception id, raise a local
170 // CORBA::MARSHAL exception.
171 throw ::CORBA::MARSHAL (TAO::VMCID
, CORBA::COMPLETED_MAYBE
);
174 // This kind of exception shouldn't happen with locate requests,
175 // but if it does, we turn it into a CORBA::UNKNOWN exception.
176 throw ::CORBA::UNKNOWN (TAO::VMCID
, CORBA::COMPLETED_YES
);
178 case GIOP::LOC_NEEDS_ADDRESSING_MODE
:
180 // We have received an exception with a request to change the
181 // addressing mode. First let us read the mode that the
182 // server/agent asks for.
183 CORBA::Short addr_mode
= 0;
185 if (cdr
.read_short (addr_mode
) == 0)
187 // Could not demarshal the addressing disposition, raise a local
188 // CORBA::MARSHAL exception.
189 throw ::CORBA::MARSHAL (TAO::VMCID
, CORBA::COMPLETED_MAYBE
);
192 // Now set this addressing mode in the profile, so that
193 // the next invocation need not go through this.
194 this->resolver_
.profile ()->addressing_mode (addr_mode
);
196 // Restart the invocation.
197 return TAO_INVOKE_RESTART
;
201 return TAO_INVOKE_SUCCESS
;
205 TAO_END_VERSIONED_NAMESPACE_DECL