Public Member Functions | Protected Member Functions | Protected Attributes | Private Types | Private Member Functions | Private Attributes

TAO_AMH_Response_Handler Class Reference

Class representing an Asynchronous-Method-Handling (AMH) ResponseHandler (RH) object. More...

#include <AMH_Response_Handler.h>

Inheritance diagram for TAO_AMH_Response_Handler:
Inheritance graph
[legend]
Collaboration diagram for TAO_AMH_Response_Handler:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 TAO_AMH_Response_Handler ()
 Constructor.
virtual ~TAO_AMH_Response_Handler (void)
 Destructor.
virtual void init (TAO_ServerRequest &server_request, TAO_AMH_BUFFER_ALLOCATOR *allocator)
Mutators for refcount

virtual void _remove_ref (void)
 Decrement the reference count.

Protected Member Functions

void _tao_rh_init_reply (void)
void _tao_rh_send_reply (void)
 Sends the marshalled reply back to the client.
void _tao_rh_send_exception (const CORBA::Exception &ex)
 Send back an exception to the client.
void _tao_rh_send_location_forward (CORBA::Object_ptr fwd, CORBA::Boolean is_perm)
 Send back a location forward exception to the client.

Protected Attributes

TAO_OutputCDR _tao_out
 The outgoing CDR stream.
GIOP::ReplyStatusType reply_status_
 Reply status (will be NO_EXCEPTION in the majority of the.

Private Types

enum  RH_Reply_Status { TAO_RS_UNINITIALIZED, TAO_RS_INITIALIZED, TAO_RS_SENDING, TAO_RS_SENT }

Private Member Functions

 TAO_AMH_Response_Handler (const TAO_AMH_Response_Handler &)
TAO_AMH_Response_Handleroperator= (const TAO_AMH_Response_Handler &)

Private Attributes

TAO_GIOP_Message_Basemesg_base_
 Pointer to the original message-base.
CORBA::ULong request_id_
 Copy of the request-id of the original Server-Request.
CORBA::Boolean response_expected_
TAO_Transporttransport_
TAO_ORB_Coreorb_core_
TAO_Service_Context reply_service_context_
 The reply service context.
CORBA::Boolean argument_flag_
RH_Reply_Status rh_reply_status_
TAO_SYNCH_MUTEX mutex_
 Mutex to ensure the AMH-RH method call is thread-safe.
TAO_AMH_BUFFER_ALLOCATORallocator_

Detailed Description

Class representing an Asynchronous-Method-Handling (AMH) ResponseHandler (RH) object.

Class encapsulates state required to send a response back to the client independent of the thread that originally created the state on the activation-record. Thus the required state (copied from TAO_Server_Request) is 'stored' on the heap.

One RH is created for every client request and the RH can be used only once i.e., the asynchronous method can be called only once. This class also encapsulates various initialisation and response-sending functionality that is common to all RHs (generated by the IDL compiler). Thus the IDL-compiler has to generate less code which in turn reduces the overall code size for an application.

Definition at line 66 of file AMH_Response_Handler.h.


Member Enumeration Documentation

Various states the ResponseHandler can be in.

These states represent various states the RH can be in and the states are used not only in implementing the 'once-only semantics of RHs, but in making sure well the call thread-safe as well.

Enumerator:
TAO_RS_UNINITIALIZED 
TAO_RS_INITIALIZED 
TAO_RS_SENDING 
TAO_RS_SENT 

Definition at line 169 of file AMH_Response_Handler.h.

    {
      TAO_RS_UNINITIALIZED,
      TAO_RS_INITIALIZED,
      TAO_RS_SENDING,
      TAO_RS_SENT
    };


Constructor & Destructor Documentation

TAO_AMH_Response_Handler::TAO_AMH_Response_Handler (  ) 
TAO_AMH_Response_Handler::~TAO_AMH_Response_Handler ( void   )  [virtual]

Destructor.

Releases the transport and in case of an error, sends the appropriate exception back to the client

Definition at line 32 of file AMH_Response_Handler.cpp.

{
  this->transport_->remove_reference ();

  // Since we are destroying the object we put a huge lock around the
  // whole destruction process (just paranoid).
  {
    ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->mutex_);

    if (this->response_expected_ == 0) //oneway ?
      {
        return;
      }

    // If the ResponseHandler is being destroyed before a reply has
    // been sent to the client, we send a system exception
    // CORBA::NO_RESPONSE, with minor code to indicate the problem.
    if (this->rh_reply_status_ == TAO_RS_SENT)
      {
        return;
      }
  }

  // If sending the exception to the client fails, then we just give
  // up, release the transport and return.
  try
    {
      CORBA::NO_RESPONSE ex (CORBA::SystemException::_tao_minor_code
                             (TAO_AMH_REPLY_LOCATION_CODE,
                              EFAULT),
                             CORBA::COMPLETED_NO);
      this->_tao_rh_send_exception (ex);
    }
  catch (...)
    {
    }
}

TAO_AMH_Response_Handler::TAO_AMH_Response_Handler ( const TAO_AMH_Response_Handler  )  [private]

Member Function Documentation

void TAO_AMH_Response_Handler::_remove_ref ( void   )  [virtual]

Decrement the reference count.

Reimplemented from CORBA::Object.

Definition at line 297 of file AMH_Response_Handler.cpp.

{
  if (this->refcount_.decrement () > 0)
    return;

  if (this->allocator_)
    {
      TAO::TAO_Buffer_Allocator<TAO_AMH_Response_Handler, TAO_AMH_BUFFER_ALLOCATOR> allocator (this->allocator_);

      allocator.release (this);
    }
  else
    {
      delete this;
    }
}

void TAO_AMH_Response_Handler::_tao_rh_init_reply ( void   )  [protected]

Sets up the various parameters in anticipation of returning a reply to the client. return/OUT/INOUT arguments are marshalled into the Output stream after this method has been called.

Definition at line 89 of file AMH_Response_Handler.cpp.

{
  {
    ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->mutex_);
    if (this->rh_reply_status_ != TAO_RS_UNINITIALIZED)
      {
        // Looks like someone is trying to call an AMH method
        // more than once
        //
        // We assume that the servant has already processed the
        // request and is now trying to send back the reply.  Hence we
        // say that the operation has completed but let the server
        // anyway that it is not doing something right.
        throw ::CORBA::BAD_INV_ORDER
                          (CORBA::SystemException::_tao_minor_code
                                  (TAO_AMH_REPLY_LOCATION_CODE,
                                   EEXIST),
                           CORBA::COMPLETED_YES);
      }
  }

  // Construct our reply generator.
  TAO_Pluggable_Reply_Params_Base reply_params;
  reply_params.request_id_ = this->request_id_;
  reply_params.service_context_notowned (&(this->reply_service_context_.service_info ()));
  reply_params.argument_flag_ = this->argument_flag_;
  reply_params.reply_status (this->reply_status_);

  {
    ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->mutex_);

    this->mesg_base_->generate_reply_header (this->_tao_out, reply_params);

    // We are done initialising the reply
    this->rh_reply_status_ = TAO_RS_INITIALIZED;
  }

}

void TAO_AMH_Response_Handler::_tao_rh_send_exception ( const CORBA::Exception ex  )  [protected]

Send back an exception to the client.

Definition at line 173 of file AMH_Response_Handler.cpp.

{
  {
    ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->mutex_);
    if (this->rh_reply_status_ != TAO_RS_UNINITIALIZED)
      {
        throw ::CORBA::BAD_INV_ORDER (
          CORBA::SystemException::_tao_minor_code (
            TAO_AMH_REPLY_LOCATION_CODE,
            ENOTSUP),
          CORBA::COMPLETED_YES);
      }
    this->rh_reply_status_ = TAO_RS_SENDING;
  }

  TAO_Pluggable_Reply_Params_Base reply_params;
  reply_params.request_id_ = this->request_id_;
  reply_params.svc_ctx_.length (0);
  reply_params.service_context_notowned (&this->reply_service_context_.service_info ());
  reply_params.argument_flag_ = true;
  // @@ It appears as if there should be a more efficient way to do
  //    this: the caller already knows this because it is part of the
  //    ExceptionHolder information.
  if (CORBA::SystemException::_downcast (&ex))
    {
      reply_params.reply_status (GIOP::SYSTEM_EXCEPTION);
    }
  else
    {
      reply_params.reply_status (GIOP::USER_EXCEPTION);
    }

  if (this->mesg_base_->generate_exception_reply (this->_tao_out,
                                                  reply_params,
                                                  ex) == -1)
    {
      throw ::CORBA::INTERNAL ();
    }

  // Send the Exception
  if (this->transport_->send_message (this->_tao_out,
                                      0,
                                      TAO_REPLY) == -1)
    {
      if (TAO_debug_level > 0)
        ACE_ERROR ((LM_ERROR,
                    ACE_TEXT ("TAO: (%P|%t|%N|%l):  ")
                    ACE_TEXT ("TAO_AMH_Response_Handler:")
                    ACE_TEXT (" could not send exception reply\n")));
    }

  {
    ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->mutex_);
    this->rh_reply_status_ = TAO_RS_SENT;
  }
}

void TAO_AMH_Response_Handler::_tao_rh_send_location_forward ( CORBA::Object_ptr  fwd,
CORBA::Boolean  is_perm 
) [protected]

Send back a location forward exception to the client.

Definition at line 231 of file AMH_Response_Handler.cpp.

{
  {
    ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->mutex_);
    if (this->rh_reply_status_ != TAO_RS_UNINITIALIZED)
      {
        throw ::CORBA::BAD_INV_ORDER (
          CORBA::SystemException::_tao_minor_code (
            TAO_AMH_REPLY_LOCATION_CODE,
            ENOTSUP),
          CORBA::COMPLETED_YES);
      }
    this->rh_reply_status_ = TAO_RS_SENDING;
  }


  TAO_Pluggable_Reply_Params_Base reply_params;
  reply_params.request_id_ = this->request_id_;
  reply_params.svc_ctx_.length (0);
  reply_params.service_context_notowned
    (&this->reply_service_context_.service_info ());
  reply_params.argument_flag_ = true;
  if (is_perm)
    {
      reply_params.reply_status (GIOP::LOCATION_FORWARD_PERM);
    }
  else
    {
      reply_params.reply_status (GIOP::LOCATION_FORWARD);
    }

  if (this->mesg_base_->generate_reply_header (this->_tao_out,
                                               reply_params) == -1)
    {
      throw ::CORBA::INTERNAL ();
    }

  if (!(this->_tao_out << fwd))
    {
      if (TAO_debug_level > 0)
        ACE_ERROR ((LM_ERROR,
                    ACE_TEXT ("TAO (%P|%t) ERROR: Unable to marshal ")
                    ACE_TEXT ("forward reference.\n")));
      return;
    }

  // Send the Exception
  if (this->transport_->send_message (this->_tao_out,
                                      0,
                                      TAO_REPLY) == -1)
    {
      if (TAO_debug_level > 0)
        ACE_ERROR ((LM_ERROR,
                    ACE_TEXT ("TAO: (%P|%t|%N|%l):  ")
                    ACE_TEXT ("TAO_AMH_Response_Handler: could not send ")
                    ACE_TEXT ("location forward reply\n")));
    }

  {
    ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->mutex_);
    this->rh_reply_status_ = TAO_RS_SENT;
  }
}

void TAO_AMH_Response_Handler::_tao_rh_send_reply ( void   )  [protected]

Sends the marshalled reply back to the client.

Definition at line 129 of file AMH_Response_Handler.cpp.

{
  {
    ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->mutex_);

    // If the reply has not been initialised, raise an exception to the
    // server-app saying it is not doing something right.
    if (this->rh_reply_status_ != TAO_RS_INITIALIZED)
      {
        throw ::CORBA::BAD_INV_ORDER (
                          CORBA::SystemException::_tao_minor_code (
                                                  TAO_AMH_REPLY_LOCATION_CODE,
                                                  ENOTSUP),
                          CORBA::COMPLETED_YES);
      }
    this->rh_reply_status_ = TAO_RS_SENDING;
  }

  // Send the message.
  int result = this->transport_->send_message (this->_tao_out,
                                               0,
                                               TAO_REPLY);

  if (result == -1)
    {
      if (TAO_debug_level > 0)
        {
          // No exception but some kind of error, yet a response
          // is required.
          ACE_ERROR ((
                      LM_ERROR,
                      ACE_TEXT ("TAO: (%P|%t) %p: cannot send NO_EXCEPTION reply\n"),
                      ACE_TEXT ("TAO_AMH_Response_Handler::_tao_rh_send_reply")
                      ));
        }
    }

  {
    ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->mutex_);
    this->rh_reply_status_ = TAO_RS_SENT;
  }
}

void TAO_AMH_Response_Handler::init ( TAO_ServerRequest server_request,
TAO_AMH_BUFFER_ALLOCATOR allocator 
) [virtual]

Stores necessary information from a TAO_Server_Request onto the heap

Definition at line 71 of file AMH_Response_Handler.cpp.

{
  mesg_base_ = server_request.mesg_base_;
  request_id_ = server_request.request_id_;
  response_expected_  = server_request.response_expected_;
  transport_ = server_request.transport ();
  orb_core_ = server_request.orb_core ();
  allocator_ = allocator;

  TAO_GIOP_Message_Version v;
  server_request.outgoing()->get_version(v);
  this->_tao_out.set_version(v.major, v.minor);
  this->transport_->assign_translators (0, &this->_tao_out);
  this->transport_->add_reference ();
}

TAO_AMH_Response_Handler& TAO_AMH_Response_Handler::operator= ( const TAO_AMH_Response_Handler  )  [private]

Member Data Documentation

The outgoing CDR stream.

The IDL-generated ResponseHandler implementations used this field to marshal the response. Making it a field instead of a public accessor makes the code in the generated ResponseHandler implementation a lot more readable.

Definition at line 123 of file AMH_Response_Handler.h.

Allocator used to allocate this object. If zero then we are allocated from the heap

Definition at line 190 of file AMH_Response_Handler.h.

Alwyas set to true (we always have something to return to the client

Definition at line 160 of file AMH_Response_Handler.h.

Pointer to the original message-base.

Definition at line 135 of file AMH_Response_Handler.h.

TAO_SYNCH_MUTEX TAO_AMH_Response_Handler::mutex_ [private]

Mutex to ensure the AMH-RH method call is thread-safe.

Definition at line 186 of file AMH_Response_Handler.h.

A pointer to the ORB Core for the context where the request was created.

Reimplemented from CORBA::Object.

Reimplemented in TAO_AMH_DSI_Response_Handler.

Definition at line 148 of file AMH_Response_Handler.h.

The reply service context.

Definition at line 151 of file AMH_Response_Handler.h.

GIOP::ReplyStatusType TAO_AMH_Response_Handler::reply_status_ [protected]

Reply status (will be NO_EXCEPTION in the majority of the.

Definition at line 126 of file AMH_Response_Handler.h.

Copy of the request-id of the original Server-Request.

Definition at line 138 of file AMH_Response_Handler.h.

Definition at line 140 of file AMH_Response_Handler.h.

Definition at line 176 of file AMH_Response_Handler.h.

Handle to transport through which the reply will be sent Copy of transport in original Server_Request

Definition at line 144 of file AMH_Response_Handler.h.


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