00001 // -*- C++ -*- 00002 00003 // ========================================================================= 00004 /** 00005 * @file AMH_Response_Handler.h 00006 * 00007 * $Id: AMH_Response_Handler.h 81429 2008-04-24 18:49:54Z johnnyw $ 00008 * 00009 * @author Mayur Deshpande <mayur@ics.uci.edu> 00010 */ 00011 // ========================================================================= 00012 00013 #ifndef TAO_AMH_RESPONSE_HANDLER_H 00014 #define TAO_AMH_RESPONSE_HANDLER_H 00015 00016 #include "tao/Messaging/messaging_export.h" 00017 00018 #include "tao/Allocator.h" 00019 #include "tao/Service_Context.h" 00020 #include "tao/CDR.h" 00021 #include "tao/LocalObject.h" 00022 #include "tao/Buffer_Allocator_T.h" 00023 #include "tao/GIOPC.h" 00024 #include "ace/Synch_Traits.h" 00025 #include "ace/Thread_Mutex.h" 00026 #include "ace/Null_Mutex.h" 00027 #include "tao/Exception.h" 00028 00029 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00030 # pragma once 00031 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00032 00033 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00034 class ACE_Allocator; 00035 ACE_END_VERSIONED_NAMESPACE_DECL 00036 00037 TAO_BEGIN_VERSIONED_NAMESPACE_DECL 00038 00039 class TAO_Transport; 00040 class TAO_GIOP_Message_Base; 00041 class TAO_Output_CDR; 00042 class TAO_ORB_Core; 00043 class TAO_ServerRequest; 00044 00045 typedef ACE_Allocator TAO_AMH_BUFFER_ALLOCATOR; 00046 00047 /** 00048 * @class TAO_AMH_Response_Handler 00049 * 00050 * @brief Class representing an Asynchronous-Method-Handling (AMH) 00051 * ResponseHandler (RH) object. 00052 * 00053 * Class encapsulates state required to send a response back to the 00054 * client independent of the thread that originally created the state 00055 * on the activation-record. Thus the required state (copied from 00056 * TAO_Server_Request) is 'stored' on the heap. 00057 * 00058 * One RH is created for every client request and the RH can be used 00059 * only once i.e., the asynchronous method can be called only once. 00060 * This class also encapsulates various initialisation and 00061 * response-sending functionality that is common to all RHs (generated 00062 * by the IDL compiler). Thus the IDL-compiler has to generate less 00063 * code which in turn reduces the overall code size for an 00064 * application. 00065 */ 00066 class TAO_Messaging_Export TAO_AMH_Response_Handler 00067 // @@ Mayur, this is not the correct way to use 00068 // TAO_LocalRefCounted_Object. Application code is supposed to use 00069 // it when necessary. You're forcing applications to use a 00070 // reference counted version of their AMH_Response_Handler. This 00071 // isn't consistent with the specified semantics detailed in the 00072 // CCM spec. Please remove this and place it where appropriate in 00073 // your AMH tests and examples. 00074 : public ::CORBA::LocalObject 00075 { 00076 public: 00077 00078 /// Constructor 00079 TAO_AMH_Response_Handler (); 00080 00081 /// Destructor 00082 /** 00083 * Releases the transport and in case of an error, sends the appropriate 00084 * exception back to the client 00085 */ 00086 virtual ~TAO_AMH_Response_Handler (void); 00087 00088 /** 00089 * Stores necessary information from a TAO_Server_Request onto the heap 00090 */ 00091 virtual void init (TAO_ServerRequest &server_request, 00092 TAO_AMH_BUFFER_ALLOCATOR* allocator); 00093 00094 /// @name Mutators for refcount 00095 //@{ 00096 virtual void _remove_ref (void); 00097 //@} 00098 00099 protected: 00100 00101 /// Sets up the various parameters in anticipation of returning a reply 00102 /// to the client. return/OUT/INOUT arguments are marshalled into the 00103 /// Output stream after this method has been called. 00104 void _tao_rh_init_reply (void); 00105 00106 /// Sends the marshalled reply back to the client. 00107 void _tao_rh_send_reply (void); 00108 00109 /// Send back an exception to the client. 00110 void _tao_rh_send_exception (const CORBA::Exception &ex); 00111 00112 /// Send back a location forward exception to the client. 00113 void _tao_rh_send_location_forward (CORBA::Object_ptr fwd, 00114 CORBA::Boolean is_perm); 00115 00116 /// The outgoing CDR stream 00117 /** 00118 * The IDL-generated ResponseHandler implementations used this field 00119 * to marshal the response. 00120 * Making it a field instead of a public accessor makes the code in 00121 * the generated ResponseHandler implementation a lot more readable. 00122 */ 00123 TAO_OutputCDR _tao_out; 00124 00125 /// Reply status (will be NO_EXCEPTION in the majority of the 00126 GIOP::ReplyStatusType reply_status_; 00127 00128 private: 00129 00130 // Private and undefined, standard C++ idiom to prohibit copying. 00131 TAO_AMH_Response_Handler (const TAO_AMH_Response_Handler&); 00132 TAO_AMH_Response_Handler& operator= (const TAO_AMH_Response_Handler&); 00133 00134 /// Pointer to the original message-base 00135 TAO_GIOP_Message_Base *mesg_base_; 00136 00137 /// Copy of the request-id of the original Server-Request 00138 CORBA::ULong request_id_; 00139 00140 CORBA::Boolean response_expected_; 00141 00142 /// Handle to transport through which the reply will be sent 00143 /// Copy of transport in original Server_Request 00144 TAO_Transport *transport_; 00145 00146 /// A pointer to the ORB Core for the context where the request was 00147 /// created. 00148 TAO_ORB_Core * orb_core_; 00149 00150 /// The reply service context 00151 TAO_Service_Context reply_service_context_; 00152 00153 /// Alwyas set to true (we always have something to return to the 00154 /// client 00155 // @@ Mayur: I think not! This is used to generate padding in GIOP 00156 // 1.2 messages (where the payload must start on an 8-byte 00157 // boundary. But some replys have no payload (only header), in 00158 // those cases you cannot insert the padding. We need the 00159 // ResponseHandler to set this field correctly! 00160 CORBA::Boolean argument_flag_; 00161 00162 /** 00163 * Various states the ResponseHandler can be in. 00164 * 00165 * These states represent various states the RH can be in and 00166 * the states are used not only in implementing the 'once-only semantics of 00167 * RHs, but in making sure well the call thread-safe as well. 00168 */ 00169 enum RH_Reply_Status 00170 { 00171 TAO_RS_UNINITIALIZED, 00172 TAO_RS_INITIALIZED, 00173 TAO_RS_SENDING, 00174 TAO_RS_SENT 00175 }; 00176 RH_Reply_Status rh_reply_status_; 00177 00178 // I would use the "state pattern".. 00179 // Carlos, Isn't that an overkill? 00180 // @@ Mayur: it depends on what form of the "State Pattern" you 00181 // use. The more generic form, as described in GoF, uses a class 00182 // for each state, super-elegant but indeed a bit heavy handed. 00183 // The lighter-weight form (using a state variable 00184 00185 /// Mutex to ensure the AMH-RH method call is thread-safe. 00186 TAO_SYNCH_MUTEX mutex_; 00187 00188 /// Allocator used to allocate this object. If zero then we are allocated 00189 /// from the heap 00190 TAO_AMH_BUFFER_ALLOCATOR* allocator_; 00191 }; 00192 00193 namespace TAO 00194 { 00195 /** 00196 * @class ARH_Refcount_Functor 00197 * 00198 * @brief Functor for refcounting of TAO_AMH_Response_Handler 00199 * 00200 * This is used to safely handle the destruction of 00201 * TAO_AMH_Response_Handler objects which are created on the 00202 * heap. We cannot use auto_ptr <> since it calls delete on the 00203 * pointer, and calling delete on TAO_AMH_Response_Handler * 00204 * will not work. Hence this functor will be used with Auto_Functor 00205 * class to handle the memory safely. 00206 * 00207 * @todo Ideally, this class can be a generic class. But that 00208 * requires quite a bit of cleanup within TAO to be more useful. 00209 */ 00210 class TAO_Messaging_Export ARH_Refcount_Functor 00211 { 00212 public: 00213 void operator() (TAO_AMH_Response_Handler *arh) throw (); 00214 }; 00215 00216 } 00217 00218 TAO_END_VERSIONED_NAMESPACE_DECL 00219 00220 #endif /* TAO_AMH_RESPONSE_HANDLER_H */