Merge pull request #2216 from jwillemsen/jwi-cxxversionchecks
[ACE_TAO.git] / TAO / tao / CSD_Framework / CSD_FW_Server_Request_Wrapper.cpp
blob30d76194aa1797931bf230fc0dc29a48488b9b57
1 // -*- C++ -*-
2 #include "tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.h"
3 #include "tao/debug.h"
4 #include "tao/ORB_Constants.h"
5 #include "tao/ORB_Core.h"
6 #include "tao/Transport.h"
7 #include "tao/CDR.h"
9 #if !defined (__ACE_INLINE__)
10 # include "tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.inl"
11 #endif /* ! __ACE_INLINE__ */
13 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
15 TAO::CSD::FW_Server_Request_Wrapper::~FW_Server_Request_Wrapper()
17 // Only delete the request if we cloned it.
18 if (this->is_clone_)
20 // The TAO_Tagged_Profile type_id_ may have been duplicated.
21 if (this->request_->profile_.type_id_ != 0)
22 CORBA::string_free (
23 const_cast<char*> (this->request_->profile_.type_id_));
25 // Since this TAO_ServerRequest object is a clone, it
26 // "owns" the input and output CDR objects held by the
27 // incoming_ and outgoing_ data members, respectfully.
28 // Thus, for the clone case, the TAO_ServerRequest dtor
29 // needs to release (aka, delete) the CDR objects.
30 delete this->request_->incoming_;
32 // Get the start message block that reference to the data allocated
33 // on the heap.
34 if (this->request_->outgoing_ != 0)
36 char* buffer = this->request_->outgoing_->begin ()->base ();
37 delete [] buffer;
38 delete this->request_->outgoing_;
40 if (this->request_->operation_details_ != 0)
42 char* opname =
43 const_cast<char*> (this->request_->operation_details_->opname_);
44 delete [] opname;
46 if (this->request_->operation_details_->num_args_ > 0)
48 for (CORBA::ULong i = 0;
49 i < this->request_->operation_details_->num_args_; i++)
51 delete this->request_->operation_details_->args_[i];
54 delete [] this->request_->operation_details_->args_;
57 delete this->request_->operation_details_;
60 if (this->request_->transport_ != 0)
61 this->request_->transport_->remove_reference ();
63 delete this->request_;
68 // Assumes that the servant argument is not a NULL pointer.
69 void
70 TAO::CSD::FW_Server_Request_Wrapper::dispatch (
71 PortableServer::Servant servant,
72 TAO::Portable_Server::Servant_Upcall *servant_upcall)
74 try
76 servant->_dispatch(*this->request_, servant_upcall);
78 // Only CORBA exceptions are caught here.
79 catch (const ::CORBA::Exception& ex)
81 if (this->request_->collocated())
83 // For collocated requests, we re-throw the exception.
84 throw;
86 else if (!this->request_->sync_with_server() &&
87 this->request_->response_expected() &&
88 !this->request_->deferred_reply())
90 // The request is a remote request that is expecting a reply.
91 this->request_->tao_send_reply_exception(ex);
93 else if (TAO_debug_level > 0)
95 // It is unfortunate that an exception (probably a system
96 // exception) was thrown by the dispatch code (even by the
97 // user) when the client was not expecting a response.
98 // However, in this case, we cannot close the connection
99 // down, since it really isn't the client's fault.
101 TAOLIB_ERROR ((LM_ERROR,
102 ACE_TEXT ("(%P|%t) exception thrown ")
103 ACE_TEXT ("but client is not waiting a response\n")));
105 ex._tao_print_exception ("FW_Server_Request_Wrapper::dispatch ()");
108 catch (...)
110 // @@ TODO some c++ exception or another, but what do we do with
111 // it?
112 // We are supposed to map it into a CORBA::UNKNOWN exception.
113 // BTW, this cannot be detected if using the <env> mapping. If
114 // we have native exceptions but no support for them in the ORB
115 // we should still be able to catch it. If we don't have native
116 // exceptions it couldn't have been raised in the first place!
117 CORBA::UNKNOWN exception (CORBA::SystemException::_tao_minor_code
118 (TAO_UNHANDLED_SERVER_CXX_EXCEPTION, 0),
119 CORBA::COMPLETED_MAYBE);
121 if (this->request_->collocated())
123 // For collocated requests, we re-throw the exception.
124 throw;
126 else if (!this->request_->sync_with_server() &&
127 this->request_->response_expected() &&
128 !this->request_->deferred_reply())
130 // The request is a remote request that is expecting a reply.
131 this->request_->tao_send_reply_exception(exception);
133 else if (TAO_debug_level > 0)
135 // It is unfortunate that an exception (probably a system
136 // exception) was thrown by the dispatch code (even by the
137 // user) when the client was not expecting a response.
138 // However, in this case, we cannot close the connection
139 // down, since it really isn't the client's fault.
141 TAOLIB_ERROR ((LM_ERROR,
142 ACE_TEXT ("(%P|%t) exception thrown ")
143 ACE_TEXT ("but client is not waiting a response\n")));
145 exception._tao_print_exception (
146 "FW_Server_Request_Wrapper::dispatch ()");
153 TAO_ServerRequest*
154 TAO::CSD::FW_Server_Request_Wrapper::clone (TAO_ServerRequest*& request)
156 // TBD-CSD: Ultimately add an argument for an allocator.
157 TAO_ServerRequest* clone_obj = 0;
158 ACE_NEW_RETURN (clone_obj,
159 TAO_ServerRequest (),
162 // TYPE: TAO_GIOP_Message_Base*
163 // ACTION: Assuming that a shallow-copy is ok here.
164 clone_obj->mesg_base_ = request->mesg_base_;
166 // TYPE: const char*
167 // ACTION: Method performs deep-copy of string contents.
168 clone_obj->operation (CORBA::string_dup (request->operation ()),
169 request->operation_length (),
172 // TYPE: CORBA::Object_var
173 // ACTION: Assignment performs reference-counted copy of object ref.
174 clone_obj->forward_location_ = request->forward_location_;
176 // TYPE: bool
177 // ACTION: Primitive data type assignment
178 clone_obj->is_forwarded_ = request->is_forwarded_;
180 // TYPE: TAO_InputCDR*
181 // ACTION: This *must* be "cloned".
182 if (request->incoming_ != 0)
184 clone_obj->incoming_ = this->clone (request->incoming_);
187 // TYPE: TAO_OutputCDR*
188 // ACTION: This *must* be "cloned".
189 if (request->outgoing_ != 0)
191 clone_obj->outgoing_ = this->create_new_output_cdr ();
194 // TYPE: TAO_Transport*
195 // ACTION: Assuming that a shallow-copy is ok here.
196 clone_obj->transport_ = request->transport_;
197 if (clone_obj->transport_ != 0)
198 clone_obj->transport_->add_reference ();
200 // TYPE: CORBA::Boolean
201 // ACTION: Primitive data type assignment.
202 clone_obj->response_expected_ = request->response_expected_;
204 // TYPE: CORBA::Boolean
205 // ACTION: Primitive data type assignment.
206 clone_obj->deferred_reply_ = request->deferred_reply_;
208 // TYPE: CORBA::Boolean
209 // ACTION: Primitive data type assignment.
210 clone_obj->sync_with_server_ = request->sync_with_server_;
212 // TYPE: CORBA::Boolean
213 // ACTION: Primitive data type assignment.
214 clone_obj->is_dsi_ = request->is_dsi_;
216 // TYPE: CORBA::ULong
217 // ACTION: Primitive data type assignment.
218 clone_obj->reply_status_ = request->reply_status_;
220 // TYPE: TAO_ORB_Core*
221 // ACTION: Assuming that a shallow-copy is ok here.
222 clone_obj->orb_core_ = request->orb_core_;
224 // TYPE: TAO_Service_Context
225 // ACTION: No copy/assignment operator, so adding/using a clone operation.
226 this->clone (request->request_service_context_, clone_obj->request_service_context_);
228 // TYPE: TAO_Service_Context
229 // ACTION: No copy/assignment operator, so adding/using a clone operation.
230 this->clone (request->reply_service_context_, clone_obj->reply_service_context_);
232 // TYPE: CORBA::ULong
233 // ACTION: Primitive data type assignment.
234 clone_obj->request_id_ = request->request_id_;
236 // TYPE: TAO_Tagged_Profile
237 // ACTION: No copy/assignment operator, so adding/using a clone operation.
238 this->clone (request->profile_, clone_obj->profile_);
240 // TYPE: CORBA::OctetSeq_var
241 // ACTION: Assignment performs reference-counted copy of sequence.
242 clone_obj->requesting_principal_ = request->requesting_principal_;
244 // TYPE: ptrdiff_t
245 // ACTION: Primitive data type assignment (unsigned integral type).
246 clone_obj->dsi_nvlist_align_ = request->dsi_nvlist_align_;
248 // TYPE: TAO_Operation_Details const * const
249 // ACTION: Need to clone this.
250 if (request->operation_details_ != 0)
252 ACE_ASSERT (request->incoming_ == 0);
253 if (this->clone (request->operation_details_,
254 clone_obj->operation_details_,
255 clone_obj->incoming_) == false)
257 return 0;
261 // TYPE: CORBA::Boolean
262 // ACTION: Primitive data type assignment.
263 clone_obj->argument_flag_ = request->argument_flag_;
265 #if TAO_HAS_INTERCEPTORS == 1
266 // TYPE: size_t
267 // ACTION: Primitive data type assignment.
268 clone_obj->interceptor_count_ = request->interceptor_count_;
270 // TYPE: TAO::PICurrent_Impl
271 // ACTION: Copy/assignment operator disabled on purpose.
272 // Just leave this alone for a clone.
274 // clone_obj->rs_pi_current_
276 // TYPE: CORBA::OctetSeq_var
277 // ACTION: Assignment performs reference-counted copy of sequence.
278 // Assuming that this is ok.
279 // Just leave this alone for a clone.
281 //clone_obj->result_seq_ = request->result_seq_;
282 #endif /* TAO_HAS_INTERCEPTORS == 1 */
284 if (clone_obj->transport_ != 0)
286 clone_obj->transport_->assign_translators(clone_obj->incoming_,
287 clone_obj->outgoing_);
289 return clone_obj;
293 TAO_InputCDR*
294 TAO::CSD::FW_Server_Request_Wrapper::clone (TAO_InputCDR*& from)
296 TAO_InputCDR* clone_ptr = 0;
297 ACE_NEW_RETURN (clone_ptr,
298 TAO_InputCDR(*from),
300 return clone_ptr;
304 bool
305 TAO::CSD::FW_Server_Request_Wrapper::clone (TAO_Operation_Details const *& from,
306 TAO_Operation_Details const *& to,
307 TAO_InputCDR*& cdr)
309 TAO_Operation_Details *& from_non_const
310 = const_cast <TAO_Operation_Details *&>(from);
312 char* cloned_op_name = 0;
313 ACE_NEW_RETURN (cloned_op_name,
314 char[from_non_const->opname_len_ + 1],
315 false);
316 ACE_OS::strncpy(cloned_op_name, from_non_const->opname_, from_non_const->opname_len_);
317 cloned_op_name[from_non_const->opname_len_] = '\0';
319 // See if we can clone arguments. If we can, the user compiled the
320 // idl with the clonable arguments option, great. If not, then
321 // use the marshaling technique to copy the arguments
322 TAO::Argument** cloned_args = 0;
323 CORBA::ULong num_cloned_args = 0;
324 if (from->num_args_ > 0)
326 TAO::Argument* retval = from->args_[0]->clone();
327 if (retval != 0)
329 ACE_NEW_RETURN (cloned_args,
330 TAO::Argument*[from->num_args_],
331 false);
332 cloned_args[0] = retval;
333 for (CORBA::ULong i = 1; i < from->num_args_; i++)
335 cloned_args[i] = from->args_[i]->clone();
337 num_cloned_args = from->num_args_;
339 else
341 static constexpr size_t mb_size = 2048;
342 ACE_NEW_RETURN (cdr,
343 TAO_InputCDR (mb_size),
344 false);
346 // To avoid duplicating and copying the data block, allow the
347 // TAO_OutputCDR to share the data block of TAO_InputCDR's message block.
348 ACE_Message_Block* mb = const_cast<ACE_Message_Block*> (cdr->start ());
349 TAO_OutputCDR outcdr (mb);
351 if (! from_non_const->marshal_args (outcdr))
353 TAOLIB_ERROR ((LM_ERROR,
354 ACE_TEXT("(%P|%T) TAO::CSD::FW_Server_Request_Wrapper::")
355 ACE_TEXT("clone TAO_Operation_Details failed\n")));
356 return false;
359 // The TAO_OutputCDR made a new message block around the data block
360 // held by the message block owned by the TAO_InputCDR. We need to
361 // make sure that the results of marshaling are propagated back to the
362 // message block in the TAO_InputCDR.
363 const ACE_Message_Block* begin = outcdr.begin ();
364 if (begin == outcdr.current ())
366 // A chain was not made, so we can just adjust the read and write
367 // pointers
368 mb->rd_ptr (begin->rd_ptr ());
369 mb->wr_ptr (begin->wr_ptr ());
371 else
373 // A costly, but necessary, copying of data blocks. This shouldn't
374 // happen that often assuming that the size of the message block
375 // allocated during the allocation of TAO_InputCDR is "big enough"
376 // for most operation parameters.
377 cdr->reset (begin, outcdr.byte_order ());
382 // CSD-TBD: Eventually need to use allocators.
384 // CSD-TBD: Assert that this->ex_data_ and this->ex_count_ are both == 0
385 TAO_Operation_Details* to_non_const = 0;
386 ACE_NEW_RETURN (to_non_const,
387 TAO_Operation_Details(cloned_op_name,
388 from_non_const->opname_len_,
389 cloned_args,
390 num_cloned_args,
393 false);
396 // DATA MEMBER: const char *opname_;
397 // DATA MEMBER: CORBA::ULong opname_len_;
398 // DATA MEMBER: CORBA::Boolean argument_flag_;
399 // DATA MEMBER: TAO::Argument **args_;
400 // DATA MEMBER: CORBA::ULong num_args_;
401 // DATA MEMBER: TAO::Exception_Data *ex_data_;
402 // DATA MEMBER: CORBA::ULong ex_count_;
404 // ACTION: None - handled in ctor
407 // DATA MEMBER: CORBA::ULong request_id_;
408 // DATA MEMBER: CORBA::Octet response_flags_;
409 // DATA MEMBER: TAO_Target_Specification::TAO_Target_Address addressing_mode_;
410 // DATA MEMBER: TAO_Service_Context request_service_info_;
411 // DATA MEMBER: TAO_Service_Context reply_service_info_;
413 // ACTION: Use assignment op to copy from "this" object to the clone.
415 to_non_const->request_id_ = from->request_id_;
416 to_non_const->response_flags_ = from->response_flags_;
417 to_non_const->addressing_mode_ = from->addressing_mode_;
419 // DATA MEMBER: TAO_Service_Context request_service_info_;
420 // DATA MEMBER: TAO_Service_Context reply_service_info_;
422 // ACTION: Use the TAO_Service_Context clone() method.
424 this->clone (from_non_const->request_service_info_, to_non_const->request_service_info_);
425 this->clone (from_non_const->reply_service_info_, to_non_const->reply_service_info_);
427 to = to_non_const;
429 return true;
433 void
434 TAO::CSD::FW_Server_Request_Wrapper::clone (TAO_Tagged_Profile& from,
435 TAO_Tagged_Profile& to)
437 to.orb_core_ = from.orb_core_;
438 to.discriminator_ = from.discriminator_;
439 to.object_key_extracted_ = from.object_key_extracted_;
440 to.object_key_ = from.object_key_;
441 to.profile_ = from.profile_;
442 to.profile_index_ = from.profile_index_;
443 to.type_id_ = from.type_id_ == 0 ? 0 :
444 CORBA::string_dup (from.type_id_);
448 void
449 TAO::CSD::FW_Server_Request_Wrapper::clone (TAO_Service_Context& from,
450 TAO_Service_Context& to)
452 to.service_context_ = from.service_context_;
455 TAO_OutputCDR*
456 TAO::CSD::FW_Server_Request_Wrapper::create_new_output_cdr ()
458 TAO_OutputCDR* cdr = 0;
460 // A buffer that we will use to initialise the CDR stream
461 char* repbuf = 0;
462 ACE_NEW_RETURN (repbuf,
463 char[ACE_CDR::DEFAULT_BUFSIZE],
466 TAO_GIOP_Message_Version giop_version;
467 this->request_->outgoing_->get_version (giop_version);
469 // Initialze an output CDR on the stack
470 // NOTE: Don't jump to a conclusion as to why we are using the
471 // input_cdr and hence the global pool here. These pools will move
472 // to the lanes anyway at some point of time. Further, it would have
473 // been awesome to have this in TSS. But for some reason the cloning
474 // that happens when the ORB gets flow controlled while writing a
475 // reply is messing things up. We crash horribly. Doing this adds a
476 // lock, we need to set things like this -- put stuff in TSS here
477 // and transfer to global memory when we get flow controlled. We
478 // need to work on the message block to get it right!
479 ACE_NEW_RETURN (cdr,
480 TAO_OutputCDR (repbuf,
481 ACE_CDR::DEFAULT_BUFSIZE,
482 TAO_ENCAP_BYTE_ORDER,
483 this->request_->orb_core_->input_cdr_buffer_allocator (),
484 this->request_->orb_core_->input_cdr_dblock_allocator (),
485 this->request_->orb_core_->input_cdr_msgblock_allocator (),
486 this->request_->orb_core_->orb_params ()->cdr_memcpy_tradeoff (),
487 giop_version.major,
488 giop_version.minor),
491 return cdr;
494 TAO_END_VERSIONED_NAMESPACE_DECL