Public Member Functions | Private Member Functions | Private Attributes

TAO::CSD::FW_Server_Request_Wrapper Class Reference

Wrapper around a TAO_Server_Request that will be cloned at the proper time. More...

#include <CSD_FW_Server_Request_Wrapper.h>

Collaboration diagram for TAO::CSD::FW_Server_Request_Wrapper:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 FW_Server_Request_Wrapper (TAO_ServerRequest &server_request)
 Constructor.
 ~FW_Server_Request_Wrapper ()
 Destructor.
void clone ()
 Perform the clone operation.
void dispatch (PortableServer::Servant servant)
 Dispatch the request to the servant.
void cancel ()
 Cancel the request.

Private Member Functions

TAO_ServerRequestclone (TAO_ServerRequest *&from)
TAO_InputCDRclone (TAO_InputCDR *&from)
 Clone an input cdr stream.
bool clone (TAO_Operation_Details const *&from, TAO_Operation_Details const *&to, TAO_InputCDR *&cdr)
void clone (TAO_Tagged_Profile &from, TAO_Tagged_Profile &to)
 Clone the TAO_Tagged_Profile object.
void clone (TAO_Service_Context &from, TAO_Service_Context &to)
 Clone the TAO_Service_Context object.
TAO_OutputCDRcreate_new_output_cdr ()

Private Attributes

bool is_clone_
TAO_ServerRequestrequest_
 Pointer to the underlying TAO_ServerRequest object.

Detailed Description

Wrapper around a TAO_Server_Request that will be cloned at the proper time.

This CSD Framework class is used to provide an interface to a TAO_ServerRequest object such that it can be used for CSD strategies that need to clone TAO_Server_Requests (ie, so that they may be placed on a queue to be dispatched by another thread).

There are several purposes for this class, with the main thing being that the TAO_ServerRequest object is not used directly by the CSD Strategies since it is, after all, an internal TAO class that was never meant to be exposed. Future changes to TAO's internal design may cause disruption in the TAO_ServerRequest class. These changes would only need to be accounted for here in this FW_Server_Request_Wrapper class' implementation, and all CSD Strategies will work again. It's a maintenance issue.

Note:
: The CSD namespace is inside of TAO namespace in current implementation. This can be changed but, at least for now, it's already been delivered to some customs, we leave it as-is. If it needs to change, we will make this change.

Definition at line 60 of file CSD_FW_Server_Request_Wrapper.h.


Constructor & Destructor Documentation

TAO::CSD::FW_Server_Request_Wrapper::FW_Server_Request_Wrapper ( TAO_ServerRequest server_request  ) 

Constructor.

Definition at line 11 of file CSD_FW_Server_Request_Wrapper.inl.

  : is_clone_(false),
    request_(&server_request)
{
}

TAO::CSD::FW_Server_Request_Wrapper::~FW_Server_Request_Wrapper (  ) 

Destructor.

Definition at line 20 of file CSD_FW_Server_Request_Wrapper.cpp.

{
  // 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 =
            const_cast<char*> (this->request_->operation_details_->opname_);
          delete [] opname;

          if (this->request_->operation_details_->num_args_ > 0)
            {
              for (CORBA::ULong i = 0;
                   i < this->request_->operation_details_->num_args_; i++)
                {
                  delete this->request_->operation_details_->args_[i];
                }

              delete [] this->request_->operation_details_->args_;
            }

          delete this->request_->operation_details_;
        }

      if (this->request_->transport_ != 0)
        this->request_->transport_->remove_reference ();

      delete this->request_;
    }
}


Member Function Documentation

void TAO::CSD::FW_Server_Request_Wrapper::cancel ( void   ) 

Cancel the request.

Definition at line 35 of file CSD_FW_Server_Request_Wrapper.inl.

{
  // We only need to handle remote requests that are expecting a reply.
  if (!this->request_->collocated()       &&
      !this->request_->sync_with_server() &&
      this->request_->response_expected() &&
      !this->request_->deferred_reply())
    {
          CORBA::NO_IMPLEMENT ex;
          this->request_->tao_send_reply_exception(ex);
    }
}

TAO_ServerRequest * TAO::CSD::FW_Server_Request_Wrapper::clone ( TAO_ServerRequest *&  from  )  [private]

Create a deep copy of the request_ object. The other clone methods are used to support the TAO_ServerRequest clone.

Definition at line 158 of file CSD_FW_Server_Request_Wrapper.cpp.

{
  // TBD-CSD: Ultimately add an argument for an allocator.
  TAO_ServerRequest* clone_obj = 0;
  ACE_NEW_RETURN (clone_obj,
                  TAO_ServerRequest (),
                  0);

  // TYPE: TAO_GIOP_Message_Base*
  // 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: bool
  // ACTION: Primitive data type assignment
  clone_obj->is_forwarded_ = request->is_forwarded_;

  // 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->reply_status_ = request->reply_status_;

  // 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;
}

void TAO::CSD::FW_Server_Request_Wrapper::clone ( TAO_Service_Context from,
TAO_Service_Context to 
) [private]

Clone the TAO_Service_Context object.

Definition at line 455 of file CSD_FW_Server_Request_Wrapper.cpp.

void TAO::CSD::FW_Server_Request_Wrapper::clone ( TAO_Tagged_Profile from,
TAO_Tagged_Profile to 
) [private]
bool TAO::CSD::FW_Server_Request_Wrapper::clone ( TAO_Operation_Details const *&  from,
TAO_Operation_Details const *&  to,
TAO_InputCDR *&  cdr 
) [private]

Create a deep copy of a TAO_Operation_Details object and marshall the arguments into a TAO_InputCDR stream. The cloned TAO_Operation_Details object is created without any arguments. This would help the skeleton code to determine whether the arguments are in the operation_details_ object or should be demarshalled from the incoming_ stream in the request_ object.

Definition at line 311 of file CSD_FW_Server_Request_Wrapper.cpp.

{
  TAO_Operation_Details *& from_non_const
    = const_cast <TAO_Operation_Details *&>(from);

  char* cloned_op_name = 0;
  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';

  // See if we can clone arguments.  If we can, the user compiled the
  // idl with the clonable arguments option, great.  If not, then
  // use the marshaling technique to copy the arguments
  TAO::Argument** cloned_args = 0;
  CORBA::ULong num_cloned_args = 0;
  if (from->num_args_ > 0)
    {
      TAO::Argument* retval = from->args_[0]->clone();
      if (retval != 0)
        {
          ACE_NEW_RETURN (cloned_args,
                          TAO::Argument*[from->num_args_],
                          false);
          cloned_args[0] = retval;
          for (CORBA::ULong i = 1; i < from->num_args_; i++)
            {
              cloned_args[i] = from->args_[i]->clone();
            }
          num_cloned_args = from->num_args_;
        }
      else
        {
          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 = 0;
  ACE_NEW_RETURN (to_non_const,
                  TAO_Operation_Details(cloned_op_name,
                                        from_non_const->opname_len_,
                                        cloned_args,
                                        num_cloned_args,
                                        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;
}

TAO_InputCDR * TAO::CSD::FW_Server_Request_Wrapper::clone ( TAO_InputCDR *&  from  )  [private]

Clone an input cdr stream.

Definition at line 300 of file CSD_FW_Server_Request_Wrapper.cpp.

{
  TAO_InputCDR* clone_ptr = 0;
  ACE_NEW_RETURN (clone_ptr,
                  TAO_InputCDR(*from),
                  0);
  return clone_ptr;
}

void TAO::CSD::FW_Server_Request_Wrapper::clone ( void   ) 

Perform the clone operation.

Definition at line 20 of file CSD_FW_Server_Request_Wrapper.inl.

{
  // Only clone the TAO_Server_Request object if we have not performed the
  // clone already.  This really should only be called once, but this code
  // makes sure that we do not introduce a leak.
  if (!this->is_clone_)
    {
      this->request_ = this->clone (this->request_);
      this->is_clone_ = true;
    }
}

TAO_OutputCDR * TAO::CSD::FW_Server_Request_Wrapper::create_new_output_cdr (  )  [private]

Create a TAO_OutputCDR stream initialized with a heap allocated buffer.

Definition at line 462 of file CSD_FW_Server_Request_Wrapper.cpp.

{
  TAO_OutputCDR* cdr = 0;

  // A buffer that we will use to initialise the CDR stream
  char* repbuf = 0;
  ACE_NEW_RETURN (repbuf,
                 char[ACE_CDR::DEFAULT_BUFSIZE],
                 0);

  TAO_GIOP_Message_Version giop_version;
  this->request_->outgoing_->get_version (giop_version);

  // 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 (),
                                 giop_version.major,
                                 giop_version.minor),
                  0);

  return cdr;
}

void TAO::CSD::FW_Server_Request_Wrapper::dispatch ( PortableServer::Servant  servant  ) 

Dispatch the request to the servant.

Definition at line 76 of file CSD_FW_Server_Request_Wrapper.cpp.

{
  try
    {
      servant->_dispatch(*this->request_, 0);
    }
  // Only CORBA exceptions are caught here.
  catch (const ::CORBA::Exception& ex)
    {
      if (this->request_->collocated())
        {
          // For collocated requests, we re-throw the exception.
          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(ex);
        }
      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")));

          ex._tao_print_exception ("FW_Server_Request_Wrapper::dispatch ()");
        }
     }
  catch (...)
    {
      // @@ 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.
          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")));

          exception._tao_print_exception (
            "FW_Server_Request_Wrapper::dispatch ()");
        }
     }

}


Member Data Documentation

bool TAO::CSD::FW_Server_Request_Wrapper::is_clone_ [private]

A flag that indicates that the TAO_ServerRequest object is already cloned.

Definition at line 111 of file CSD_FW_Server_Request_Wrapper.h.

TAO_ServerRequest* TAO::CSD::FW_Server_Request_Wrapper::request_ [private]

Pointer to the underlying TAO_ServerRequest object.

Definition at line 114 of file CSD_FW_Server_Request_Wrapper.h.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines