diff options
Diffstat (limited to 'trunk/TAO/tao/Messaging/Asynch_Invocation.cpp')
-rw-r--r-- | trunk/TAO/tao/Messaging/Asynch_Invocation.cpp | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/trunk/TAO/tao/Messaging/Asynch_Invocation.cpp b/trunk/TAO/tao/Messaging/Asynch_Invocation.cpp new file mode 100644 index 00000000000..7296456a0ad --- /dev/null +++ b/trunk/TAO/tao/Messaging/Asynch_Invocation.cpp @@ -0,0 +1,196 @@ +//$Id$ + +#include "tao/Messaging/Asynch_Invocation.h" +#include "tao/Messaging/Asynch_Reply_Dispatcher.h" + +#include "tao/Profile_Transport_Resolver.h" +#include "tao/Invocation_Utils.h" +#include "tao/operation_details.h" +#include "tao/Bind_Dispatcher_Guard.h" +#include "tao/Transport.h" +#include "tao/Muxed_TMS.h" +#include "tao/Pluggable_Messaging.h" +#include "tao/ORB_Constants.h" + +#if TAO_HAS_INTERCEPTORS == 1 +# include "tao/PortableInterceptorC.h" +#endif /*TAO_HAS_INTERCEPTORS */ + +ACE_RCSID (Messaging, + Asynch_Invocation, + "$Id$") + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace TAO +{ + Asynch_Remote_Invocation::Asynch_Remote_Invocation ( + CORBA::Object_ptr otarget, + Profile_Transport_Resolver &resolver, + TAO_Operation_Details &detail, + TAO_Asynch_Reply_Dispatcher_Base *rd, + bool response_expected) + : Synch_Twoway_Invocation (otarget, + resolver, + detail, + response_expected) + , safe_rd_ (rd) + { + } + + Invocation_Status + Asynch_Remote_Invocation::remote_invocation (ACE_Time_Value *max_wait_time + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::Exception)) + { + TAO_Target_Specification tspec; + this->init_target_spec (tspec ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (TAO_INVOKE_FAILURE); + + TAO_OutputCDR &cdr = + this->resolver_.transport ()->messaging_object ()->out_stream (); + + Invocation_Status s = TAO_INVOKE_FAILURE; + +#if TAO_HAS_INTERCEPTORS == 1 + s = + this->send_request_interception (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (TAO_INVOKE_FAILURE); + + if (s != TAO_INVOKE_SUCCESS) + return s; +#endif /*TAO_HAS_INTERCEPTORS */ + + // We have started the interception flow. We need to call the + // ending interception flow if things go wrong. The purpose of the + // try block is to take care of the cases when things go wrong. + ACE_TRY + { + // Oneway semantics. See comments for below send_message() + // call. + cdr.message_attributes (this->details_.request_id (), + this->resolver_.stub (), + TAO_Transport::TAO_ONEWAY_REQUEST, + max_wait_time); + + this->write_header (tspec, + cdr + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->marshal_data (cdr + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // Register a reply dispatcher for this invocation. Use the + // preallocated reply dispatcher. + TAO_Bind_Dispatcher_Guard dispatch_guard ( + this->details_.request_id (), + this->safe_rd_.get (), + this->resolver_.transport ()->tms ()); + + // Now that we have bound the reply dispatcher to the map, just + // loose ownership of the reply dispatcher. + this->safe_rd_.release (); + + if (dispatch_guard.status () != 0) + { + // @@ What is the right way to handle this error? Do we need + // to call the interceptors in this case? + ACE_THROW_RETURN (CORBA::INTERNAL (TAO::VMCID, + CORBA::COMPLETED_NO), + TAO_INVOKE_FAILURE); + } + + // Do not unbind during destruction. We need the entry to be + // there in the map since the reply dispatcher depends on + // that. This is also a trigger to loose the ownership of the + // reply dispatcher. + dispatch_guard.status (TAO_Bind_Dispatcher_Guard::NO_UNBIND); + + // Send it as a oneway request. It will make all the required + // paraphernalia within the ORB to fire, like buffering if + // send blocks etc. + s = + this->send_message (cdr, + TAO_Transport::TAO_ONEWAY_REQUEST, + max_wait_time + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + +#if TAO_HAS_INTERCEPTORS == 1 + // NOTE: We don't need to do the auto_ptr <> trick. We got here + // in the first place since the message was sent properly, + // which implies a reply would be available. Therefore the + // reply dispatcher should be available for another thread to + // collect and dispatch the reply. In MT cases, things are + // more hairy. Just imagine what happens when another thread + // is collecting the reply when we are happily invoking + // interceptors? + + // Nothing great on here. If we get a restart during send or a + // proper send, we are supposed to call receiver_other () + // interception point. So we do that here + Invocation_Status tmp = + this->receive_other_interception (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + // We got an error during the interception. + if (s == TAO_INVOKE_SUCCESS && tmp != TAO_INVOKE_SUCCESS) + s = tmp; +#endif /*TAO_HAS_INTERCEPTORS */ + + // If an error occurred just return. At this point all the + // endpoint interception would have been invoked. The callee + // would take care of the rest. + if (s != TAO_INVOKE_SUCCESS) + return s; + + // NOTE: Not sure how things are handles with exclusive muxed + // strategy. + if (this->resolver_.transport ()->idle_after_send ()) + (void) this->resolver_.transport_released (); + + } + ACE_CATCHANY + { +#if TAO_HAS_INTERCEPTORS == 1 + PortableInterceptor::ReplyStatus const status = + this->handle_any_exception (&ACE_ANY_EXCEPTION + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (status == PortableInterceptor::LOCATION_FORWARD || + status == PortableInterceptor::TRANSPORT_RETRY) + s = TAO_INVOKE_RESTART; + else if (status == PortableInterceptor::SYSTEM_EXCEPTION + || status == PortableInterceptor::USER_EXCEPTION) +#endif /*TAO_HAS_INTERCEPTORS*/ + ACE_RE_THROW; + } +# if defined (ACE_HAS_EXCEPTIONS) \ + && defined (ACE_HAS_BROKEN_UNEXPECTED_EXCEPTIONS) + ACE_CATCHALL + { +#if TAO_HAS_INTERCEPTORS == 1 + PortableInterceptor::ReplyStatus st = + this->handle_all_exception (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (st == PortableInterceptor::LOCATION_FORWARD || + st == PortableInterceptor::TRANSPORT_RETRY) + s = TAO_INVOKE_RESTART; + else +#endif /*TAO_HAS_INTERCEPTORS == 1*/ + ACE_RE_THROW; + } +# endif /* ACE_HAS_EXCEPTIONS && + ACE_HAS_BROKEN_UNEXPECTED_EXCEPTION*/ + ACE_ENDTRY; + ACE_CHECK_RETURN (TAO_INVOKE_FAILURE); + + return s; + } +} + +TAO_END_VERSIONED_NAMESPACE_DECL |