TAO_Server_Request.cpp

Go to the documentation of this file.
00001 // $Id: TAO_Server_Request.cpp 79267 2007-08-08 15:51:45Z mesnier_p $
00002 
00003 #include "tao/TAO_Server_Request.h"
00004 #include "tao/ORB_Core.h"
00005 #include "tao/Timeprobe.h"
00006 #include "tao/debug.h"
00007 #include "tao/Pluggable_Messaging.h"
00008 #include "tao/GIOP_Utils.h"
00009 #include "tao/Stub.h"
00010 #include "tao/operation_details.h"
00011 #include "tao/Transport.h"
00012 #include "tao/CDR.h"
00013 #include "tao/SystemException.h"
00014 
00015 #if TAO_HAS_INTERCEPTORS == 1
00016 #include "tao/PortableInterceptorC.h"
00017 #include "tao/ServerRequestInterceptor_Adapter.h"
00018 #endif
00019 
00020 #if !defined (__ACE_INLINE__)
00021 # include "tao/TAO_Server_Request.inl"
00022 #endif /* ! __ACE_INLINE__ */
00023 
00024 ACE_RCSID (tao,
00025            TAO_Server_Request,
00026            "$Id: TAO_Server_Request.cpp 79267 2007-08-08 15:51:45Z mesnier_p $")
00027 
00028 #if defined (ACE_ENABLE_TIMEPROBES)
00029 
00030 static const char * TAO_Server_Request_Timeprobe_Description[] =
00031 {
00032   "TAO_ServerRequest::TAO_ServerRequest - start",
00033   "TAO_ServerRequest::TAO_ServerRequest - end",
00034 };
00035 
00036 enum
00037   {
00038     // Timeprobe description table start key.
00039     TAO_SERVER_REQUEST_START = 400,
00040     TAO_SERVER_REQUEST_END
00041   };
00042 
00043 // Setup Timeprobes
00044 ACE_TIMEPROBE_EVENT_DESCRIPTIONS (TAO_Server_Request_Timeprobe_Description,
00045                                   TAO_SERVER_REQUEST_START);
00046 
00047 #endif /* ACE_ENABLE_TIMEPROBES */
00048 
00049 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00050 
00051 TAO_ServerRequest::TAO_ServerRequest (TAO_Pluggable_Messaging *mesg_base,
00052                                       TAO_InputCDR &input,
00053                                       TAO_OutputCDR &output,
00054                                       TAO_Transport *transport,
00055                                       TAO_ORB_Core *orb_core)
00056   : mesg_base_ (mesg_base),
00057     operation_ (0),
00058     operation_len_ (0),
00059     release_operation_ (false),
00060     incoming_ (&input),
00061     outgoing_ (&output),
00062     response_expected_ (false),
00063     deferred_reply_ (false),
00064     sync_with_server_ (false),
00065     is_dsi_ (false),
00066     // @@ We shouldn't be using GIOP specific types here. Need to be revisited.
00067     exception_type_ (TAO_GIOP_NO_EXCEPTION),
00068     orb_core_ (orb_core),
00069     request_id_ (0),
00070     profile_ (orb_core),
00071     requesting_principal_ (0),
00072     dsi_nvlist_align_ (0),
00073     operation_details_ (0),
00074     argument_flag_ (true)
00075 #if TAO_HAS_INTERCEPTORS == 1
00076     , interceptor_count_ (0)
00077     , rs_pi_current_ (0)
00078     , caught_exception_ (0)
00079     , reply_status_ (-1)
00080 #endif  /* TAO_HAS_INTERCEPTORS == 1 */
00081     , transport_(transport) //already duplicated in TAO_Transport::process_parsed_messages ()
00082 {
00083   ACE_FUNCTION_TIMEPROBE (TAO_SERVER_REQUEST_START);
00084   // No-op.
00085 }
00086 
00087 // This constructor is used, by the locate request code.
00088 TAO_ServerRequest::TAO_ServerRequest (TAO_Pluggable_Messaging *mesg_base,
00089                                       CORBA::ULong request_id,
00090                                       CORBA::Boolean response_expected,
00091                                       CORBA::Boolean deferred_reply,
00092                                       TAO::ObjectKey &object_key,
00093                                       const char *operation,
00094                                       TAO_OutputCDR &output,
00095                                       TAO_Transport *transport,
00096                                       TAO_ORB_Core *orb_core,
00097                                       int &parse_error)
00098   : mesg_base_ (mesg_base),
00099     operation_ (CORBA::string_dup (operation)),
00100     operation_len_ (operation == 0 ? 0 : ACE_OS::strlen (operation)),
00101     release_operation_ (true),
00102     incoming_ (0),
00103     outgoing_ (&output),
00104     response_expected_ (response_expected),
00105     deferred_reply_ (deferred_reply),
00106     sync_with_server_ (false),
00107     is_dsi_ (false),
00108     exception_type_ (TAO_GIOP_NO_EXCEPTION),
00109     orb_core_ (orb_core),
00110     request_id_ (request_id),
00111     profile_ (orb_core),
00112     requesting_principal_ (0),
00113     dsi_nvlist_align_ (0),
00114     operation_details_ (0),
00115     argument_flag_ (true)
00116 #if TAO_HAS_INTERCEPTORS == 1
00117   , interceptor_count_ (0)
00118   , rs_pi_current_ (0)
00119   , caught_exception_ (0)
00120   , reply_status_ (-1)
00121 #endif  /* TAO_HAS_INTERCEPTORS == 1 */
00122   , transport_(transport) //already duplicated in TAO_Transport::process_parsed_messages ()
00123 {
00124   this->profile_.object_key (object_key);
00125   parse_error = 0;
00126 }
00127 
00128 // Constructor used in Thru-POA collocation code.
00129 TAO_ServerRequest::TAO_ServerRequest (TAO_ORB_Core * orb_core,
00130                                       TAO_Operation_Details const & details,
00131                                       CORBA::Object_ptr target)
00132   : mesg_base_ (0),
00133     operation_ (details.opname ()),
00134     operation_len_ (details.opname_len ()),
00135     release_operation_ (false),
00136     incoming_ (0),
00137     outgoing_ (0),
00138     response_expected_ (details.response_flags () == TAO_TWOWAY_RESPONSE_FLAG
00139                         || details.response_flags () == static_cast<CORBA::Octet> (Messaging::SYNC_WITH_SERVER)
00140                         || details.response_flags () == static_cast<CORBA::Octet> (Messaging::SYNC_WITH_TARGET)),
00141     deferred_reply_ (false),
00142     sync_with_server_ (details.response_flags () == static_cast<CORBA::Octet> (Messaging::SYNC_WITH_SERVER)),
00143     is_dsi_ (false),
00144     exception_type_ (TAO_GIOP_NO_EXCEPTION),
00145     orb_core_ (orb_core),
00146     request_id_ (0),
00147     profile_ (orb_core),
00148     requesting_principal_ (0),
00149     dsi_nvlist_align_ (0),
00150     operation_details_ (&details),
00151     argument_flag_ (false)
00152 #if TAO_HAS_INTERCEPTORS == 1
00153   , interceptor_count_ (0)
00154   , rs_pi_current_ (0)
00155   , caught_exception_ (0)
00156   , reply_status_ (-1)
00157 #endif  /* TAO_HAS_INTERCEPTORS == 1 */
00158   , transport_ (0)
00159 {
00160   // Have to use a const_cast<>.  *sigh*
00161   this->profile_.object_key (
00162     const_cast<TAO::ObjectKey &> (target->_stubobj ()->object_key ()));
00163 
00164   // Shallow copy the request service context list. This way the operation
00165   // details and server request share the request context.
00166   IOP::ServiceContextList & dest_request_contexts =
00167     this->request_service_context_.service_info ();
00168 
00169   IOP::ServiceContextList & src_request_contexts =
00170     (const_cast <TAO_Operation_Details&> (details)).request_service_info ();
00171 
00172   dest_request_contexts.replace (src_request_contexts.maximum (),
00173                                  src_request_contexts.length (),
00174                                  src_request_contexts.get_buffer (),
00175                                  false /* Do not release. */);
00176 
00177   // Don't shallow copy the reply service context. It is probably empty,
00178   // when then during the request it is used, the buffer gets allocated and
00179   // then the operation details don't get the reply service context
00180 }
00181 
00182 TAO_ServerRequest::~TAO_ServerRequest (void)
00183 {
00184 #if TAO_HAS_INTERCEPTORS == 1
00185   if (this->rs_pi_current_)
00186     {
00187       TAO::ServerRequestInterceptor_Adapter *interceptor_adapter =
00188         this->orb_core_->serverrequestinterceptor_adapter ();
00189 
00190       if (interceptor_adapter)
00191         {
00192           interceptor_adapter->deallocate_pi_current (
00193             this->rs_pi_current_);
00194         }
00195     }
00196 #endif  /* TAO_HAS_INTERCEPTORS == 1 */
00197   if (this->release_operation_)
00198     CORBA::string_free (const_cast<char*> (this->operation_));
00199 }
00200 
00201 CORBA::ORB_ptr
00202 TAO_ServerRequest::orb (void)
00203 {
00204   return this->orb_core_->orb ();
00205 }
00206 
00207 TAO_Service_Context &
00208 TAO_ServerRequest::reply_service_context (void)
00209 {
00210   if (!operation_details_)
00211   {
00212     return this->reply_service_context_;
00213   }
00214   else
00215   {
00216     return const_cast <TAO_Operation_Details*> (
00217       this->operation_details_)->reply_service_context ();
00218   }
00219 }
00220 
00221 
00222 void
00223 TAO_ServerRequest::init_reply (void)
00224 {
00225   if (!this->outgoing_)
00226     return;  // Collocated
00227 
00228   // Construct our reply generator.
00229   TAO_Pluggable_Reply_Params_Base reply_params;
00230 
00231   // We put all the info that we have in to this <reply_params> and
00232   // call the <write_reply_header> in the
00233   // pluggable_messaging_interface. One point to be noted however is
00234   // that, it was the pluggable_messaging classes who created us and
00235   // delegated us to do work on its behalf. But we would be calling
00236   // back. As we don't have a LOCK or any such things we can call
00237   // pluggable_messaging guys again. We would be on the same thread of
00238   // invocation. So *theoretically* there should not be a problem.
00239   reply_params.request_id_ = this->request_id_;
00240   reply_params.is_dsi_ = this->is_dsi_;
00241   reply_params.dsi_nvlist_align_ = this->dsi_nvlist_align_;
00242 
00243   // Send back the reply service context.
00244   reply_params.service_context_notowned (&this->reply_service_info ());
00245 
00246   // Are we going to marshall any data with the reply?
00247   reply_params.argument_flag_ = this->argument_flag_;
00248 
00249   // Forward exception only.
00250   if (!CORBA::is_nil (this->forward_location_.in ()))
00251     {
00252       CORBA::Boolean const permanent_forward_condition =
00253         this->orb_core_->is_permanent_forward_condition (this->forward_location_.in (),
00254                                                          this->request_service_context ());
00255 
00256       reply_params.reply_status_
00257         = permanent_forward_condition
00258         ? TAO_PLUGGABLE_MESSAGE_LOCATION_FORWARD_PERM
00259         : TAO_PLUGGABLE_MESSAGE_LOCATION_FORWARD;
00260     }
00261   // Any exception at all.
00262   else if (this->exception_type_ == TAO_GIOP_NO_EXCEPTION)
00263     {
00264       reply_params.reply_status_ = TAO_PLUGGABLE_MESSAGE_NO_EXCEPTION;
00265     }
00266   else
00267     {
00268       reply_params.reply_status_ = this->exception_type_;
00269     }
00270 
00271 
00272   this->outgoing_->message_attributes (this->request_id_,
00273                                        0,
00274                                        TAO_Transport::TAO_REPLY,
00275                                        0);
00276 
00277   // Construct a REPLY header.
00278   this->mesg_base_->generate_reply_header (*this->outgoing_, reply_params);
00279 
00280   // Finish the GIOP Reply header, then marshal the exception.
00281   if (reply_params.reply_status_ == TAO_PLUGGABLE_MESSAGE_LOCATION_FORWARD ||
00282       reply_params.reply_status_ == TAO_PLUGGABLE_MESSAGE_LOCATION_FORWARD_PERM)
00283     {
00284       // Marshal the forward location pointer.
00285       CORBA::Object_ptr object_ptr = this->forward_location_.in ();
00286 
00287       if ((*this->outgoing_ << object_ptr) == 0)
00288         {
00289           ACE_DEBUG ((LM_DEBUG,
00290                       ACE_TEXT ("TAO (%P|%t) - ServerRequest::init_reply, ")
00291                       ACE_TEXT ("TAO_GIOP_ServerRequest::marshal - ")
00292                       ACE_TEXT ("marshal encoding forwarded objref failed\n")));
00293         }
00294     }
00295   this->transport_->assign_translators (0, this->outgoing_);
00296 }
00297 
00298 void
00299 TAO_ServerRequest::send_no_exception_reply (void)
00300 {
00301   // Construct our reply generator.
00302   TAO_Pluggable_Reply_Params_Base reply_params;
00303   reply_params.request_id_ = this->request_id_;
00304   reply_params.is_dsi_ = this->is_dsi_;
00305   reply_params.dsi_nvlist_align_ = this->dsi_nvlist_align_;
00306 
00307   // Change this to pass back the same thing we received, as well as
00308   // leave a comment why this is important!
00309   reply_params.svc_ctx_.length (0);
00310 
00311   // Send back the reply service context.
00312   reply_params.service_context_notowned (&this->reply_service_info ());
00313 
00314   reply_params.reply_status_ = TAO_GIOP_NO_EXCEPTION;
00315 
00316   // No data anyway.
00317   reply_params.argument_flag_ = false;
00318 
00319   this->outgoing_->message_attributes (this->request_id_,
00320                                        0,
00321                                        TAO_Transport::TAO_REPLY,
00322                                        0);
00323 
00324   // Construct a REPLY header.
00325   this->mesg_base_->generate_reply_header (*this->outgoing_, reply_params);
00326 
00327   this->outgoing_->more_fragments (false);
00328 
00329   // Send the message.
00330   int result = this->transport_->send_message (*this->outgoing_,
00331                                                0,
00332                                                TAO_Transport::TAO_REPLY);
00333 
00334   if (result == -1)
00335     {
00336       if (TAO_debug_level > 0)
00337         {
00338           // No exception but some kind of error, yet a response
00339           // is required.
00340           ACE_ERROR ((
00341                       LM_ERROR,
00342                       ACE_TEXT ("TAO (%P|%t) - ServerRequest::send_no_exception_reply, ")
00343                       ACE_TEXT ("cannot send NO_EXCEPTION reply\n")
00344                       ));
00345         }
00346     }
00347 }
00348 
00349 void
00350 TAO_ServerRequest::tao_send_reply (void)
00351 {
00352   if (this->collocated ())
00353     return;  // No transport in the collocated case.
00354 
00355   this->outgoing_->more_fragments (false);
00356 
00357   int result = this->transport_->send_message (*this->outgoing_,
00358                                                0,
00359                                                TAO_Transport::TAO_REPLY);
00360   if (result == -1)
00361     {
00362       if (TAO_debug_level > 0)
00363         {
00364           // No exception but some kind of error, yet a response
00365           // is required.
00366           ACE_ERROR ((LM_ERROR,
00367                       ACE_TEXT ("TAO (%P|%t) - ServerRequest::tao_send_reply, ")
00368                       ACE_TEXT ("cannot send reply\n")));
00369         }
00370     }
00371 }
00372 
00373 void
00374 TAO_ServerRequest::tao_send_reply_exception (const CORBA::Exception &ex)
00375 {
00376   if (this->response_expected_ && !this->collocated ())
00377     {
00378       // A copy of the reply parameters
00379       TAO_Pluggable_Reply_Params_Base reply_params;
00380 
00381       reply_params.request_id_ = this->request_id_;
00382       reply_params.svc_ctx_.length (0);
00383 
00384       // Send back the reply service context.
00385       reply_params.service_context_notowned (&this->reply_service_info ());
00386 
00387       // We are going to send some data
00388       reply_params.argument_flag_ = true;
00389 
00390       // Make a default reply status
00391       reply_params.reply_status_ = TAO_GIOP_USER_EXCEPTION;
00392 
00393       // Check whether we are able to downcast the exception
00394       if (CORBA::SystemException::_downcast (&ex) != 0)
00395         {
00396           reply_params.reply_status_ = TAO_GIOP_SYSTEM_EXCEPTION;
00397         }
00398 
00399       // Create a new output CDR stream
00400 #if defined(ACE_INITIALIZE_MEMORY_BEFORE_USE)
00401       // Only inititialize the buffer if we're compiling with a profiler.
00402       // Otherwise, there is no real need to do so, especially since
00403       // we can avoid the initialization overhead at runtime if we
00404       // are not compiling with memory profiler support.
00405       char repbuf[ACE_CDR::DEFAULT_BUFSIZE] = { 0 };
00406 #else
00407       char repbuf[ACE_CDR::DEFAULT_BUFSIZE];
00408 #endif /* ACE_INITIALIZE_MEMORY_BEFORE_USE */
00409       TAO_GIOP_Message_Version gv;
00410       if (this->outgoing_)
00411         this->outgoing_->get_version (gv);
00412 
00413       TAO_OutputCDR output (repbuf,
00414                             sizeof repbuf,
00415                             TAO_ENCAP_BYTE_ORDER,
00416                             this->orb_core_->output_cdr_buffer_allocator (),
00417                             this->orb_core_->output_cdr_dblock_allocator (),
00418                             this->orb_core_->output_cdr_msgblock_allocator (),
00419                             this->orb_core_->orb_params ()->cdr_memcpy_tradeoff (),
00420                             this->mesg_base_->fragmentation_strategy (),
00421                             gv.major,
00422                             gv.minor);
00423 
00424       this->transport_->assign_translators (0, &output);
00425       // Make the reply message
00426       if (this->mesg_base_->generate_exception_reply (*this->outgoing_,
00427                                                       reply_params,
00428                                                       ex) == -1)
00429         {
00430           ACE_ERROR ((LM_ERROR,
00431                       ACE_TEXT ("TAO (%P|%t) - ServerRequest::tao_send_reply_exception, ")
00432                       ACE_TEXT ("could not make exception reply\n")));
00433 
00434         }
00435 
00436       this->outgoing_->more_fragments (false);
00437 
00438       // Send the message
00439       if (this->transport_->send_message (*this->outgoing_,
00440                                           0,
00441                                           TAO_Transport::TAO_REPLY) == -1)
00442         {
00443           ACE_ERROR ((LM_ERROR,
00444                       ACE_TEXT ("TAO (%P|%t) - ServerRequest::tao_send_reply_exception, ")
00445                       ACE_TEXT ("could not send exception reply\n")));
00446         }
00447     }
00448   else if (TAO_debug_level > 0)
00449     {
00450       // It is unfortunate that an exception (probably a system
00451       // exception) was thrown by the upcall code (even by the
00452       // user) when the client was not expecting a response.
00453       // However, in this case, we cannot close the connection
00454       // down, since it really isn't the client's fault.
00455 
00456       ACE_ERROR ((LM_ERROR,
00457                   ACE_TEXT ("TAO (%P|%t) - ServerRequest::tao_send_reply_exception, ")
00458                   ACE_TEXT ("exception thrown ")
00459                   ACE_TEXT ("but client is not waiting a response\n")));
00460     }
00461 }
00462 
00463 #if TAO_HAS_INTERCEPTORS == 1
00464 void
00465 TAO_ServerRequest::send_cached_reply (CORBA::OctetSeq &s)
00466 {
00467 #if defined(ACE_HAS_PURIFY)
00468   // Only inititialize the buffer if we're compiling with Purify.
00469   // Otherwise, there is no real need to do so, especially since
00470   // we can avoid the initialization overhead at runtime if we
00471   // are not compiling with Purify support.
00472   char repbuf[ACE_CDR::DEFAULT_BUFSIZE] = { 0 };
00473 #else
00474   char repbuf[ACE_CDR::DEFAULT_BUFSIZE];
00475 #endif /* ACE_HAS_PURIFY */
00476   TAO_GIOP_Message_Version gv;
00477   if (this->outgoing_)
00478     this->outgoing_->get_version (gv);
00479   TAO_OutputCDR output (repbuf,
00480                         sizeof repbuf,
00481                         TAO_ENCAP_BYTE_ORDER,
00482                         this->orb_core_->output_cdr_buffer_allocator (),
00483                         this->orb_core_->output_cdr_dblock_allocator (),
00484                         this->orb_core_->output_cdr_msgblock_allocator (),
00485                         this->orb_core_->orb_params ()->cdr_memcpy_tradeoff (),
00486                         this->mesg_base_->fragmentation_strategy (),
00487                         gv.major,
00488                         gv.minor);
00489 
00490   this->transport_->assign_translators (0, &output);
00491 
00492   // A copy of the reply parameters
00493   TAO_Pluggable_Reply_Params_Base reply_params;
00494 
00495   reply_params.request_id_ = this->request_id_;
00496 
00497   reply_params.svc_ctx_.length (0);
00498 
00499   // Send back the empty reply service context.
00500   reply_params.service_context_notowned (&this->reply_service_info ());
00501 
00502   // We are going to send some data
00503   reply_params.argument_flag_ = true;
00504 
00505   // Make a default reply status
00506   reply_params.reply_status_ = TAO_GIOP_NO_EXCEPTION;
00507 
00508   this->outgoing_->message_attributes (this->request_id_,
00509                                        0,
00510                                        TAO_Transport::TAO_REPLY,
00511                                        0);
00512 
00513   // Make the reply message
00514   if (this->mesg_base_->generate_reply_header (*this->outgoing_,
00515                                                reply_params) == -1)
00516     {
00517       ACE_ERROR ((LM_ERROR,
00518                   ACE_TEXT ("TAO (%P|%t) - ServerRequest::send_cached_reply, ")
00519                   ACE_TEXT ("could not make cached reply\n")));
00520 
00521     }
00522 
00523   /// Append reply here....
00524   this->outgoing_->write_octet_array (
00525     s.get_buffer (),
00526     s.length ());
00527 
00528   if (!this->outgoing_->good_bit ())
00529     ACE_ERROR ((LM_ERROR,
00530                 ACE_TEXT ("TAO (%P|%t) - ServerRequest::send_cached_reply, ")
00531                 ACE_TEXT ("could not marshal reply\n")));
00532 
00533   this->outgoing_->more_fragments (false);
00534 
00535   // Send the message
00536   if (this->transport_->send_message (*this->outgoing_,
00537                                       0,
00538                                       TAO_Transport::TAO_REPLY) == -1)
00539     {
00540       ACE_ERROR ((LM_ERROR,
00541                   ACE_TEXT ("TAO (%P|%t) - ServerRequest::send_cached_reply, ")
00542                   ACE_TEXT ("could not send cached reply\n")));
00543     }
00544 }
00545 
00546 void
00547 TAO_ServerRequest::caught_exception (CORBA::Exception *exception)
00548 {
00549   if (CORBA::SystemException::_downcast (exception) != 0)
00550     this->reply_status_ = PortableInterceptor::SYSTEM_EXCEPTION;
00551   else if (CORBA::UserException::_downcast (exception) != 0)
00552     this->reply_status_ = PortableInterceptor::USER_EXCEPTION;
00553 
00554   this->caught_exception_ = exception;
00555 }
00556 
00557 TAO::PICurrent_Impl *
00558 TAO_ServerRequest::rs_pi_current (void)
00559 {
00560   if (!this->rs_pi_current_)
00561     {
00562       TAO::ServerRequestInterceptor_Adapter *interceptor_adapter =
00563         this->orb_core_->serverrequestinterceptor_adapter ();
00564 
00565       if (interceptor_adapter)
00566         {
00567           this->rs_pi_current_ = interceptor_adapter->allocate_pi_current ();
00568         }
00569     }
00570 
00571   return this->rs_pi_current_;
00572 }
00573 
00574 TAO_END_VERSIONED_NAMESPACE_DECL
00575 
00576 #endif /* TAO_HAS_INTERCEPTORS */

Generated on Sun Jan 27 13:07:37 2008 for TAO by doxygen 1.3.6