Merge pull request #2301 from sonndinh/remove-dup-reactor-functions
[ACE_TAO.git] / TAO / tao / PI_Server / ServerRequestInfo.cpp
blob418c92be0b16546f8ab5c6e23b78a27bca9af6cc
1 // -*- C++ -*-
2 #include "tao/PI_Server/ServerRequestInfo.h"
4 #if (TAO_HAS_INTERCEPTORS == 1)
6 #include "tao/PortableServer/Root_POA.h"
7 #include "tao/PortableServer/Servant_Upcall.h"
8 #include "tao/PortableServer/Servant_Base.h"
10 #include "tao/TAO_Server_Request.h"
11 #include "tao/ORB_Core.h"
12 #include "tao/PolicyC.h"
13 #include "tao/AnyTypeCode/DynamicC.h"
14 #include "tao/ORB_Core.h"
15 #include "tao/Service_Context.h"
16 #include "tao/PI/RequestInfo_Util.h"
17 #include "tao/PI/PICurrent.h"
18 #include "tao/PI/PICurrent_Impl.h"
19 #include "tao/AnyTypeCode/ExceptionA.h"
21 #include "ace/OS_NS_string.h"
23 # if !defined (__ACE_INLINE__)
24 # include "tao/PI_Server/ServerRequestInfo.inl"
25 # endif /* !__ACE_INLINE__ */
27 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
29 CORBA::ULong
30 TAO::ServerRequestInfo::request_id ()
32 // The request ID returned by this method need not correspond to the
33 // GIOP request ID sent with the client request. The request ID
34 // must be unique across all outstanding requests. To avoid locking
35 // overhead, the address of the TAO_ServerRequest object is used as
36 // the request ID. This guarantees that the request ID is unique.
38 // For 64-bit platforms, only the lower 32 bits are used. Hopefully
39 // that will be enough to ensure uniqueness.
41 CORBA::ULong id = 0;
43 // Note that we reinterpret_cast to an "unsigned long" instead of
44 // CORBA::ULong since we need to first cast to an integer large
45 // enough to hold an address to avoid compile-time warnings on some
46 // 64-bit platforms.
48 if (sizeof (this) == 4) // 32 bit address
49 id = static_cast <CORBA::ULong> (
50 reinterpret_cast <ptrdiff_t>
51 (&(this->server_request_)));
53 else if (sizeof (this) == 8) // 64 bit address -- use lower 32 bits
54 id = static_cast <CORBA::ULong> (
55 reinterpret_cast <ptrdiff_t>
56 (&(this->server_request_)) & 0xFFFFFFFFu);
58 else
59 // @@ Rather than fallback on the GIOP request ID, we should use
60 // an atomically incremented variable specific to the ORB, or
61 // perhaps specific to the process.
62 id = this->server_request_.request_id (); // Fallback
64 return id;
67 char *
68 TAO::ServerRequestInfo::operation ()
70 return CORBA::string_dup (this->server_request_.operation ());
73 Dynamic::ParameterList *
74 TAO::ServerRequestInfo::arguments ()
76 if (!this->args_)
78 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
81 // Generate the argument list on demand.
82 Dynamic::ParameterList * const parameter_list =
83 TAO_RequestInfo_Util::make_parameter_list ();
85 Dynamic::ParameterList_var safe_parameter_list = parameter_list;
87 // Return value is always generated as first TAO::Argument in
88 // skeleton. It shouldn't be included in the parameter list.
89 // Skip it.
90 TAO::Argument * const * const begin = this->args_ + 1;
91 TAO::Argument * const * const end = this->args_ + this->nargs_;
93 ACE_ASSERT (end - begin >= 0);
95 parameter_list->length (static_cast<CORBA::ULong> (end - begin));
97 CORBA::ULong p = 0;
98 for (TAO::Argument * const * i = begin; i != end; ++i, ++p)
100 // Insert the operation parameters into the
101 // Dynamic::ParameterList.
102 Dynamic::Parameter& parameter = (*parameter_list)[p];
103 parameter.mode = (*i)->mode ();
104 // When we are in receive_request and have an out argument, then
105 // don't copy it, just let the any be empty with typecode tk_null
106 if ((this->server_request_.pi_reply_status () != -1) ||
107 (this->server_request_.pi_reply_status () == -1 &&
108 (*i)->mode () != CORBA::PARAM_OUT))
110 (*i)->interceptor_value (&parameter.argument);
114 return safe_parameter_list._retn ();
117 Dynamic::ExceptionList *
118 TAO::ServerRequestInfo::exceptions ()
120 if (!this->args_)
122 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
125 // Generate the exception list on demand.
126 Dynamic::ExceptionList * const exception_list =
127 TAO_RequestInfo_Util::make_exception_list ();
129 Dynamic::ExceptionList_var safe_exception_list = exception_list;
131 exception_list->length (this->nexceptions_);
133 CORBA::TypeCode_ptr const * const begin = this->exceptions_;
134 CORBA::TypeCode_ptr const * const end =
135 this->exceptions_ + this->nexceptions_;
137 CORBA::ULong e = 0;
138 for (CORBA::TypeCode_ptr const * i = begin; i != end; ++i, ++e)
140 CORBA::TypeCode_ptr tcp_object = *i;
141 (*exception_list)[e] = tcp_object;
144 return safe_exception_list._retn ();
147 Dynamic::ContextList *
148 TAO::ServerRequestInfo::contexts ()
150 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
153 Dynamic::RequestContext *
154 TAO::ServerRequestInfo::operation_context ()
156 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
159 CORBA::Any *
160 TAO::ServerRequestInfo::result ()
162 if (!this->args_)
164 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
167 // Generate the result on demand.
168 static CORBA::Boolean const tk_void_any = true;
170 CORBA::Any * result_any = TAO_RequestInfo_Util::make_any (tk_void_any);
172 CORBA::Any_var safe_result_any = result_any;
174 // Result is always first element in TAO::Argument array.
175 TAO::Argument * const r = this->args_[0];
177 r->interceptor_value (result_any);
179 return safe_result_any._retn ();
182 CORBA::Boolean
183 TAO::ServerRequestInfo::response_expected ()
185 return this->server_request_.response_expected ();
188 Messaging::SyncScope
189 TAO::ServerRequestInfo::sync_scope ()
191 if (this->server_request_.sync_with_server ())
193 return Messaging::SYNC_WITH_SERVER;
196 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
199 PortableInterceptor::ReplyStatus
200 TAO::ServerRequestInfo::reply_status ()
202 if (this->server_request_.pi_reply_status () == -1)
204 // A reply hasn't been received yet.
205 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
208 return this->server_request_.pi_reply_status ();
211 CORBA::Object_ptr
212 TAO::ServerRequestInfo::forward_reference ()
214 if (this->server_request_.pi_reply_status () != PortableInterceptor::LOCATION_FORWARD)
216 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
219 // TAO_ServerRequest::forward_location() already duplicates the
220 // object reference. There is no need to duplicate it here.
221 return this->server_request_.forward_location ();
224 CORBA::Any *
225 TAO::ServerRequestInfo::get_slot (PortableInterceptor::SlotId id)
227 // Retrieve the total number of assigned slots from the PICurrent.
228 // No TSS access is incurred.
229 CORBA::Object_ptr pi_current_obj =
230 this->server_request_.orb_core ()->pi_current ();
232 TAO::PICurrent *pi_current =
233 dynamic_cast <TAO::PICurrent*> (pi_current_obj);
235 if (!pi_current)
236 throw ::CORBA::INTERNAL ();
238 pi_current->check_validity (id);
240 // Retrieve the request scope PICurrent object.
241 TAO::PICurrent_Impl *rsc = this->server_request_.rs_pi_current ();
243 return rsc->get_slot (id);
246 IOP::ServiceContext *
247 TAO::ServerRequestInfo::get_request_service_context (IOP::ServiceId id)
249 TAO_Service_Context &service_context_list =
250 this->server_request_.request_service_context ();
252 return this->get_service_context_i (service_context_list, id);
255 IOP::ServiceContext *
256 TAO::ServerRequestInfo::get_reply_service_context (IOP::ServiceId id)
258 TAO_Service_Context & service_context_list =
259 this->server_request_.reply_service_context ();
261 return this->get_service_context_i (service_context_list, id);
264 IOP::ServiceContext *
265 TAO::ServerRequestInfo::get_service_context_i (
266 TAO_Service_Context & service_context_list,
267 IOP::ServiceId id)
269 IOP::ServiceContext_var service_context;
271 if (service_context_list.get_context (id, service_context.out ()) != 0)
273 // Found.
274 return service_context._retn ();
276 else
278 // Not found.
279 throw ::CORBA::BAD_PARAM (CORBA::OMGVMCID | 26, CORBA::COMPLETED_NO);
283 // Use at own risk. There is no way currently of extracting an
284 // exception from an Any. This method is in place just to be compliant
285 // with the spec.
286 CORBA::Any *
287 TAO::ServerRequestInfo::sending_exception ()
289 if (this->server_request_.pi_reply_status () != PortableInterceptor::SYSTEM_EXCEPTION
290 && this->server_request_.pi_reply_status () != PortableInterceptor::USER_EXCEPTION)
292 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
295 // The spec says that if it is a user exception which cannot be
296 // inserted then the UNKNOWN exception should be thrown with minor
297 // code 1.
298 CORBA::Any * temp {};
300 ACE_NEW_THROW_EX (temp,
301 CORBA::Any,
302 CORBA::NO_MEMORY (
303 CORBA::SystemException::_tao_minor_code (
304 TAO::VMCID,
305 ENOMEM),
306 CORBA::COMPLETED_NO));
308 CORBA::Any_var caught_exception_var = temp;
310 if (this->server_request_.caught_exception ())
312 (*temp) <<= *(this->server_request_.caught_exception ());
315 return caught_exception_var._retn ();
318 char *
319 TAO::ServerRequestInfo::server_id ()
321 if (this->servant_upcall_)
323 return CORBA::string_dup (this->server_request_.orb_core ()->server_id ());
326 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
329 char *
330 TAO::ServerRequestInfo::orb_id ()
332 if (this->servant_upcall_)
334 return CORBA::string_dup (this->server_request_.orb_core ()->orbid ());
337 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
340 PortableInterceptor::AdapterName *
341 TAO::ServerRequestInfo::adapter_name ()
343 // The adapter_name attribute defines a name for the object adapter
344 // that services requests for the invoked object. In the case of the
345 // POA, the adapter_name is the sequence of names from the root POA
346 // to the POA that services the request. The root POA is not named
347 // in this sequence.
348 if (this->servant_upcall_)
350 return this->servant_upcall_->poa ().adapter_name ();
353 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
356 PortableInterceptor::ObjectId *
357 TAO::ServerRequestInfo::object_id ()
359 if (this->servant_upcall_ != 0)
361 const PortableServer::ObjectId &id =
362 this->servant_upcall_->user_id ();
364 PortableInterceptor::ObjectId *tmp {};
366 ACE_NEW_THROW_EX (tmp,
367 PortableInterceptor::ObjectId,
368 CORBA::NO_MEMORY (
369 CORBA::SystemException::_tao_minor_code (
370 TAO::VMCID,
371 ENOMEM),
372 CORBA::COMPLETED_NO));
374 PortableInterceptor::ObjectId_var obj_id = tmp;
376 // @@ It would be nice to avoid this copy. However, we can't be
377 // sure if the octet sequence will out live the POA from
378 // which the object ID is ultimately obtained. In the event
379 // the octet sequence does out live the POA, a copy is indeed
380 // necessary. Do a copy to be on the safe side. In any
381 // case, this is still faster than the
382 // PortableServer::Current::object_id() method since no TSS
383 // access is involved.
384 CORBA::ULong const len = id.length ();
385 obj_id->length (len);
386 CORBA::Octet *buffer = obj_id->get_buffer ();
387 ACE_OS::memcpy (buffer, id.get_buffer (), len);
389 return obj_id._retn ();
392 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
395 CORBA::OctetSeq *
396 TAO::ServerRequestInfo::adapter_id ()
398 if (this->servant_upcall_)
400 return this->servant_upcall_->poa ().id ();
403 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
406 char *
407 TAO::ServerRequestInfo::target_most_derived_interface ()
409 if (this->servant_upcall_ == 0)
411 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
414 PortableServer::Servant const servant = this->servant_upcall_->servant ();
416 if (servant == 0)
418 throw ::CORBA::NO_RESOURCES (CORBA::OMGVMCID | 1, CORBA::COMPLETED_NO);
421 return CORBA::string_dup (servant->_interface_repository_id ());
424 CORBA::Policy_ptr
425 TAO::ServerRequestInfo::get_server_policy (CORBA::PolicyType type)
427 if (this->servant_upcall_ != 0)
429 CORBA::Policy_var policy =
430 this->servant_upcall_->poa ().get_policy (type);
432 if (!CORBA::is_nil (policy.in ()))
434 return policy._retn ();
436 else
438 // No policy matching the given PolicyType was found.
439 throw ::CORBA::INV_POLICY (CORBA::OMGVMCID | 3, CORBA::COMPLETED_NO);
443 // @@ Technically, we shouldn't be throwing this exception since
444 // this method should be valid in all server side request
445 // interception points.
446 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
449 void
450 TAO::ServerRequestInfo::set_slot (PortableInterceptor::SlotId id,
451 const CORBA::Any &data)
453 // Retrieve the total number of assigned slots from the PICurrent
454 // object. No TSS access is incurred.
455 CORBA::Object_ptr pi_current_obj =
456 this->server_request_.orb_core ()->pi_current ();
458 TAO::PICurrent *pi_current =
459 dynamic_cast <TAO::PICurrent*> (pi_current_obj);
461 if (!pi_current)
462 throw ::CORBA::INTERNAL ();
464 pi_current->check_validity (id);
466 // Retrieve the "request scope current" (RSC).
467 TAO::PICurrent_Impl * rsc = this->server_request_.rs_pi_current ();
469 rsc->set_slot (id, data);
472 CORBA::Boolean
473 TAO::ServerRequestInfo::target_is_a (const char * id)
475 if (this->servant_upcall_ == 0)
477 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
480 // Implemented in the generated skeleton.
481 PortableServer::Servant const servant = this->servant_upcall_->servant ();
483 if (servant == 0)
485 throw ::CORBA::NO_RESOURCES (CORBA::OMGVMCID | 1, CORBA::COMPLETED_NO);
488 return servant->_is_a (id);
491 void
492 TAO::ServerRequestInfo::add_reply_service_context (
493 const IOP::ServiceContext & service_context,
494 CORBA::Boolean replace)
496 // Get the service context from the list
497 TAO_Service_Context &service_context_list =
498 this->server_request_.reply_service_context ();
500 if (service_context_list.set_context (service_context, replace) == 0)
502 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 15, CORBA::COMPLETED_NO);
506 TAO_END_VERSIONED_NAMESPACE_DECL
508 #endif /* TAO_HAS_INTERCEPTORS == 1 */