s/Uint/UInt/g
[ACE_TAO.git] / TAO / tao / LocateRequest_Invocation.cpp
blob55fba32925560659fe258d44faa9e88b2a121e76
1 // -*- C++ -*-
2 #include "tao/LocateRequest_Invocation.h"
3 #include "tao/Profile_Transport_Resolver.h"
4 #include "tao/operation_details.h"
5 #include "tao/Stub.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
19 namespace TAO
21 /**
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
34 public:
35 First_Request_Guard (TAO_Transport &transport);
37 ~First_Request_Guard ();
39 private:
40 /// The transport that we guard.
41 TAO_Transport &transport_;
43 /// Original value of first_request from transport.
44 bool is_first_;
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,
64 resolver,
65 detail)
69 Invocation_Status
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 ()));
77 if (!rd_p)
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 (),
87 rd.get (),
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;
116 countdown.update ();
118 s = this->send_message (cdr, TAO_Message_Semantics (), max_wait_time);
121 if (s != TAO_INVOKE_SUCCESS)
122 return s;
124 countdown.update ();
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 ();
142 return s;
145 Invocation_Status
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:
156 break;
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