TAO_Server_Request.cpp

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

Generated on Thu Nov 9 11:54:23 2006 for TAO by doxygen 1.3.6