diff options
Diffstat (limited to 'TAO/tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.cpp')
-rw-r--r-- | TAO/tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.cpp | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/TAO/tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.cpp b/TAO/tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.cpp new file mode 100644 index 00000000000..24684bf7866 --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.cpp @@ -0,0 +1,474 @@ +// $Id$ +#include "tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.h" +#include "tao/debug.h" +#include "tao/ORB_Constants.h" +#include "tao/ORB_Core.h" +#include "tao/Transport.h" +#include "tao/CDR.h" + + +ACE_RCSID (CSD_Framework, + FW_Server_Request_Wrapper, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.inl" +#endif /* ! __ACE_INLINE__ */ + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO::CSD::FW_Server_Request_Wrapper::~FW_Server_Request_Wrapper() +{ + // Only delete the request if we cloned it. + if (this->is_clone_) + { + // The TAO_Tagged_Profile type_id_ may have been duplicated. + if (this->request_->profile_.type_id_ != 0) + CORBA::string_free ( + const_cast<char*> (this->request_->profile_.type_id_)); + + // Since this TAO_ServerRequest object is a clone, it + // "owns" the input and output CDR objects held by the + // incoming_ and outgoing_ data members, respectfully. + // Thus, for the clone case, the TAO_ServerRequest dtor + // needs to release (aka, delete) the CDR objects. + delete this->request_->incoming_; + + // Get the start message block that reference to the data allocated + // on the heap. + if (this->request_->outgoing_ != 0) + { + char* buffer = this->request_->outgoing_->begin ()->base (); + delete [] buffer; + delete this->request_->outgoing_; + } + if (this->request_->operation_details_ != 0) + { + char* opname = (char*)this->request_->operation_details_->opname_; + delete [] opname; + delete this->request_->operation_details_; + } + + if (this->request_->transport_ != 0) + this->request_->transport_->remove_reference (); + + delete this->request_; + } +} + + +// Assumes that the servant argument is not a NULL pointer. +void +TAO::CSD::FW_Server_Request_Wrapper::dispatch + (PortableServer::Servant servant + ACE_ENV_ARG_DECL) +{ + ACE_TRY + { + servant->_dispatch(*this->request_, 0 ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + // Only CORBA exceptions are caught here. + ACE_CATCHANY + { + if (this->request_->collocated()) + { + // For collocated requests, we re-throw the exception. + ACE_RE_THROW; + } + else if (!this->request_->sync_with_server() && + this->request_->response_expected() && + !this->request_->deferred_reply()) + { + // The request is a remote request that is expecting a reply. + this->request_->tao_send_reply_exception(ACE_ANY_EXCEPTION); + } + else if (TAO_debug_level > 0) + { + // It is unfortunate that an exception (probably a system + // exception) was thrown by the dispatch code (even by the + // user) when the client was not expecting a response. + // However, in this case, we cannot close the connection + // down, since it really isn't the client's fault. + + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) exception thrown ") + ACE_TEXT ("but client is not waiting a response\n"))); + + ACE_PRINT_EXCEPTION ( + ACE_ANY_EXCEPTION, + "FW_Server_Request_Wrapper::dispatch ()"); + } + } +#if defined (TAO_HAS_EXCEPTIONS) + ACE_CATCHALL + { + // @@ TODO some c++ exception or another, but what do we do with + // it? + // We are supposed to map it into a CORBA::UNKNOWN exception. + // BTW, this cannot be detected if using the <env> mapping. If + // we have native exceptions but no support for them in the ORB + // we should still be able to catch it. If we don't have native + // exceptions it couldn't have been raised in the first place! + CORBA::UNKNOWN exception (CORBA::SystemException::_tao_minor_code + (TAO_UNHANDLED_SERVER_CXX_EXCEPTION, 0), + CORBA::COMPLETED_MAYBE); + + if (this->request_->collocated()) + { + // For collocated requests, we re-throw the exception. + ACE_RE_THROW; + } + else if (!this->request_->sync_with_server() && + this->request_->response_expected() && + !this->request_->deferred_reply()) + { + // The request is a remote request that is expecting a reply. + this->request_->tao_send_reply_exception(exception); + } + else if (TAO_debug_level > 0) + { + // It is unfortunate that an exception (probably a system + // exception) was thrown by the dispatch code (even by the + // user) when the client was not expecting a response. + // However, in this case, we cannot close the connection + // down, since it really isn't the client's fault. + + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) exception thrown ") + ACE_TEXT ("but client is not waiting a response\n"))); + + ACE_PRINT_EXCEPTION ( + exception, + "FW_Server_Request_Wrapper::dispatch ()"); + } + } +#endif /* TAO_HAS_EXCEPTIONS */ + + ACE_ENDTRY; +} + + +TAO_ServerRequest* +TAO::CSD::FW_Server_Request_Wrapper::clone (TAO_ServerRequest*& request) +{ + // TBD-CSD: Ultimately add an argument for an allocator. + TAO_ServerRequest* clone_obj; + ACE_NEW_RETURN (clone_obj, + TAO_ServerRequest (), + 0); + + if (clone_obj == 0) + { + return 0; + } + + // TYPE: TAO_Pluggable_Messaging* + // ACTION: Assuming that a shallow-copy is ok here. + clone_obj->mesg_base_ = request->mesg_base_; + + // TYPE: const char* + // ACTION: Method performs deep-copy of string contents. + clone_obj->operation (CORBA::string_dup (request->operation ()), + request->operation_length (), + 1); + + // TYPE: CORBA::Object_var + // ACTION: Assignment performs reference-counted copy of object ref. + clone_obj->forward_location_ = request->forward_location_; + + // TYPE: TAO_InputCDR* + // ACTION: This *must* be "cloned". + if (request->incoming_ != 0) + { + clone_obj->incoming_ = this->clone (request->incoming_); + } + + // TYPE: TAO_OutputCDR* + // ACTION: This *must* be "cloned". + if (request->outgoing_ != 0) + { + clone_obj->outgoing_ = this->create_new_output_cdr (); + } + + // TYPE: TAO_Transport* + // ACTION: Assuming that a shallow-copy is ok here. + clone_obj->transport_ = request->transport_; + if (clone_obj->transport_ != 0) + clone_obj->transport_->add_reference (); + + // TYPE: CORBA::Boolean + // ACTION: Primitive data type assignment. + clone_obj->response_expected_ = request->response_expected_; + + // TYPE: CORBA::Boolean + // ACTION: Primitive data type assignment. + clone_obj->deferred_reply_ = request->deferred_reply_; + + // TYPE: CORBA::Boolean + // ACTION: Primitive data type assignment. + clone_obj->sync_with_server_ = request->sync_with_server_; + + // TYPE: CORBA::Boolean + // ACTION: Primitive data type assignment. + clone_obj->is_dsi_ = request->is_dsi_; + + // TYPE: CORBA::ULong + // ACTION: Primitive data type assignment. + clone_obj->exception_type_ = request->exception_type_; + + // TYPE: TAO_ORB_Core* + // ACTION: Assuming that a shallow-copy is ok here. + clone_obj->orb_core_ = request->orb_core_; + + // TYPE: TAO_Service_Context + // ACTION: No copy/assignment operator, so adding/using a clone operation. + this->clone (request->request_service_context_, clone_obj->request_service_context_); + + // TYPE: TAO_Service_Context + // ACTION: No copy/assignment operator, so adding/using a clone operation. + this->clone (request->reply_service_context_, clone_obj->reply_service_context_); + + // TYPE: CORBA::ULong + // ACTION: Primitive data type assignment. + clone_obj->request_id_ = request->request_id_; + + // TYPE: TAO_Tagged_Profile + // ACTION: No copy/assignment operator, so adding/using a clone operation. + this->clone (request->profile_, clone_obj->profile_); + + // TYPE: CORBA::OctetSeq_var + // ACTION: Assignment performs reference-counted copy of sequence. + clone_obj->requesting_principal_ = request->requesting_principal_; + + // TYPE: ptrdiff_t + // ACTION: Primitive data type assignment (unsigned integral type). + clone_obj->dsi_nvlist_align_ = request->dsi_nvlist_align_; + + // TYPE: TAO_Operation_Details const * const + // ACTION: Need to clone this. + if (request->operation_details_ != 0) + { + ACE_ASSERT (request->incoming_ == 0); + if (this->clone (request->operation_details_, + clone_obj->operation_details_, + clone_obj->incoming_) == false) + { + return 0; + } + } + + // TYPE: CORBA::Boolean + // ACTION: Primitive data type assignment. + clone_obj->argument_flag_ = request->argument_flag_; + + //#if TAO_HAS_INTERCEPTORS == 1 + // TYPE: size_t + // ACTION: Primitive data type assignment. + // Just leave this alone for a clone. + // + //clone_obj->interceptor_count_ = request->interceptor_count_; + + // TYPE: TAO::PICurrent_Impl + // ACTION: Copy/assignment operator disabled on purpose. + // Just leave this alone for a clone. + // + // clone_obj->rs_pi_current_ + + // TYPE: CORBA::OctetSeq_var + // ACTION: Assignment performs reference-counted copy of sequence. + // Assuming that this is ok. + // Just leave this alone for a clone. + // + //clone_obj->result_seq_ = request->result_seq_; + //#endif /* TAO_HAS_INTERCEPTORS == 1 */ + + if (clone_obj->transport_ != 0) + { + clone_obj->transport_->assign_translators(clone_obj->incoming_, + clone_obj->outgoing_); + } + return clone_obj; +} + + +TAO_InputCDR* +TAO::CSD::FW_Server_Request_Wrapper::clone (TAO_InputCDR*& from) +{ + TAO_InputCDR* clone_ptr = 0; + ACE_NEW_RETURN (clone_ptr, + TAO_InputCDR(*from), + 0); + return clone_ptr; +} + + +bool +TAO::CSD::FW_Server_Request_Wrapper::clone (TAO_Operation_Details const *& from, + TAO_Operation_Details const *& to, + TAO_InputCDR*& cdr) +{ + TAO_Operation_Details *& from_non_const + = const_cast <TAO_Operation_Details *&>(from); + + char* cloned_op_name; + ACE_NEW_RETURN (cloned_op_name, + char[from_non_const->opname_len_ + 1], + false); + ACE_OS::strncpy(cloned_op_name, from_non_const->opname_, from_non_const->opname_len_); + cloned_op_name[from_non_const->opname_len_] = '\0'; + + static const size_t mb_size = 2048; + ACE_NEW_RETURN (cdr, + TAO_InputCDR (mb_size), + false); + + // To avoid duplicating and copying the data block, allow the + // TAO_OutputCDR to share the data block of TAO_InputCDR's message block. + ACE_Message_Block* mb = const_cast<ACE_Message_Block*> (cdr->start ()); + TAO_OutputCDR outcdr (mb); + + if (! from_non_const->marshal_args (outcdr)) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT("(%P|%T) TAO::CSD::FW_Server_Request_Wrapper::") + ACE_TEXT("clone TAO_Operation_Details failed\n"))); + return false; + } + + // The TAO_OutputCDR made a new message block around the data block + // held by the message block owned by the TAO_InputCDR. We need to + // make sure that the results of marshaling are propagated back to the + // message block in the TAO_InputCDR. + const ACE_Message_Block* begin = outcdr.begin (); + if (begin == outcdr.current ()) + { + // A chain was not made, so we can just adjust the read and write + // pointers + mb->rd_ptr (begin->rd_ptr ()); + mb->wr_ptr (begin->wr_ptr ()); + } + else + { + // A costly, but necessary, copying of data blocks. This shouldn't + // happen that often assuming that the size of the message block + // allocated during the allocation of TAO_InputCDR is "big enough" + // for most operation parameters. + cdr->reset (begin, outcdr.byte_order ()); + } + + // CSD-TBD: Eventually need to use allocators. + + // CSD-TBD: Assert that this->ex_data_ and this->ex_count_ are both == 0 + TAO_Operation_Details* to_non_const; + ACE_NEW_RETURN (to_non_const, + TAO_Operation_Details(cloned_op_name, + from_non_const->opname_len_, + from_non_const->argument_flag_, + 0, + 0, + 0, + 0), + false); + + + // DATA MEMBER: const char *opname_; + // DATA MEMBER: CORBA::ULong opname_len_; + // DATA MEMBER: CORBA::Boolean argument_flag_; + // DATA MEMBER: TAO::Argument **args_; + // DATA MEMBER: CORBA::ULong num_args_; + // DATA MEMBER: TAO::Exception_Data *ex_data_; + // DATA MEMBER: CORBA::ULong ex_count_; + // + // ACTION: None - handled in ctor + // + + // DATA MEMBER: CORBA::ULong request_id_; + // DATA MEMBER: CORBA::Octet response_flags_; + // DATA MEMBER: TAO_Target_Specification::TAO_Target_Address addressing_mode_; + // DATA MEMBER: TAO_Service_Context request_service_info_; + // DATA MEMBER: TAO_Service_Context reply_service_info_; + // + // ACTION: Use assignment op to copy from "this" object to the clone. + // + to_non_const->request_id_ = from->request_id_; + to_non_const->response_flags_ = from->response_flags_; + to_non_const->addressing_mode_ = from->addressing_mode_; + + // DATA MEMBER: TAO_Service_Context request_service_info_; + // DATA MEMBER: TAO_Service_Context reply_service_info_; + // + // ACTION: Use the TAO_Service_Context clone() method. + // + this->clone (from_non_const->request_service_info_, to_non_const->request_service_info_); + this->clone (from_non_const->reply_service_info_, to_non_const->reply_service_info_); + + to = to_non_const; + + return true; +} + + +void +TAO::CSD::FW_Server_Request_Wrapper::clone (TAO_Tagged_Profile& from, + TAO_Tagged_Profile& to) +{ + to.orb_core_ = from.orb_core_; + to.discriminator_ = from.discriminator_; + to.object_key_extracted_ = from.object_key_extracted_; + to.object_key_ = from.object_key_; + to.profile_ = from.profile_; + to.profile_index_ = from.profile_index_; + to.type_id_ = from.type_id_ == 0 ? 0 : + CORBA::string_dup (from.type_id_); +} + + +void +TAO::CSD::FW_Server_Request_Wrapper::clone (TAO_Service_Context& from, + TAO_Service_Context& to) +{ + to.service_context_ = from.service_context_; +} + +TAO_OutputCDR* +TAO::CSD::FW_Server_Request_Wrapper::create_new_output_cdr () +{ + TAO_OutputCDR* cdr = 0; + + // A buffer that we will use to initialise the CDR stream + char* repbuf; + ACE_NEW_RETURN (repbuf, + char[ACE_CDR::DEFAULT_BUFSIZE], + 0); + + ACE_CDR::Octet major; + ACE_CDR::Octet minor; + this->request_->outgoing_->get_version (major, minor); + + // Initialze an output CDR on the stack + // NOTE: Don't jump to a conclusion as to why we are using the + // input_cdr and hence the global pool here. These pools will move + // to the lanes anyway at some point of time. Further, it would have + // been awesome to have this in TSS. But for some reason the cloning + // that happens when the ORB gets flow controlled while writing a + // reply is messing things up. We crash horribly. Doing this adds a + // lock, we need to set things like this -- put stuff in TSS here + // and transfer to global memory when we get flow controlled. We + // need to work on the message block to get it right! + ACE_NEW_RETURN (cdr, + TAO_OutputCDR (repbuf, + ACE_CDR::DEFAULT_BUFSIZE, + TAO_ENCAP_BYTE_ORDER, + this->request_->orb_core_->input_cdr_buffer_allocator (), + this->request_->orb_core_->input_cdr_dblock_allocator (), + this->request_->orb_core_->input_cdr_msgblock_allocator (), + this->request_->orb_core_->orb_params ()->cdr_memcpy_tradeoff (), + major, + minor), + 0); + + return cdr; +} + +TAO_END_VERSIONED_NAMESPACE_DECL |