diff options
Diffstat (limited to 'TAO/tao/LocateRequest_Invocation.cpp')
-rw-r--r-- | TAO/tao/LocateRequest_Invocation.cpp | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/TAO/tao/LocateRequest_Invocation.cpp b/TAO/tao/LocateRequest_Invocation.cpp new file mode 100644 index 00000000000..203bcd5f605 --- /dev/null +++ b/TAO/tao/LocateRequest_Invocation.cpp @@ -0,0 +1,192 @@ +#include "tao/LocateRequest_Invocation.h" +#include "tao/Profile_Transport_Resolver.h" +#include "tao/operation_details.h" +#include "tao/Stub.h" +#include "tao/Bind_Dispatcher_Guard.h" +#include "tao/Transport.h" +#include "tao/Synch_Reply_Dispatcher.h" +#include "tao/GIOP_Utils.h" +#include "tao/Profile.h" +#include "tao/ORB_Constants.h" + +#include "ace/Countdown_Time.h" + +ACE_RCSID (tao, + LocateRequest_Invocation, + "$Id$") + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace TAO +{ + LocateRequest_Invocation::LocateRequest_Invocation ( + CORBA::Object_ptr otarget, + Profile_Transport_Resolver &resolver, + TAO_Operation_Details &detail + ) + : Synch_Twoway_Invocation (otarget, + resolver, + detail) + { + } + + Invocation_Status + LocateRequest_Invocation::invoke (ACE_Time_Value *max_wait_time + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::Exception)) + { + ACE_Countdown_Time countdown (max_wait_time); + + TAO_Synch_Reply_Dispatcher rd (this->resolver_.stub ()->orb_core (), + this->details_.reply_service_info ()); + + // Register a reply dispatcher for this invocation. Use the + // preallocated reply dispatcher. + TAO_Bind_Dispatcher_Guard dispatch_guard (this->details_.request_id (), + &rd, + this->resolver_.transport ()->tms ()); + + if (dispatch_guard.status () != 0) + { + // @@ What is the right way to handle this error? Do we need + // to call the interceptors in this case? + this->resolver_.transport ()->close_connection (); + + ACE_THROW_RETURN (CORBA::INTERNAL (TAO::VMCID, + CORBA::COMPLETED_NO), + TAO_INVOKE_FAILURE); + } + + TAO_Target_Specification tspec; + this->init_target_spec (tspec ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (TAO_INVOKE_FAILURE); + + TAO_Transport *transport = + this->resolver_.transport (); + + TAO_OutputCDR &cdr = transport->out_stream (); + + int const retval = + transport->generate_locate_request (tspec, + this->details_, + cdr); + ACE_CHECK_RETURN (TAO_INVOKE_FAILURE); + + if (retval == -1) + return TAO_INVOKE_FAILURE; + + countdown.update (); + + Invocation_Status s = + this->send_message (cdr, + TAO_Transport::TAO_TWOWAY_REQUEST, + max_wait_time + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (TAO_INVOKE_FAILURE); + + if (s != TAO_INVOKE_SUCCESS) + return s; + + countdown.update (); + + // For some strategies one may want to release the transport + // back to cache. If the idling is successfull let the + // resolver about that. + if (this->resolver_.transport ()->idle_after_send ()) + this->resolver_.transport_released (); + + s = + this->wait_for_reply (max_wait_time, + rd, + dispatch_guard + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (TAO_INVOKE_FAILURE); + + s = this->check_reply (rd + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (TAO_INVOKE_FAILURE); + + // For some strategies one may want to release the transport + // back to cache after receiving the reply. If the idling is + // successfull let the resolver about that. + if (this->resolver_.transport ()->idle_after_reply ()) + this->resolver_.transport_released (); + + return s; + } + + Invocation_Status + LocateRequest_Invocation::check_reply (TAO_Synch_Reply_Dispatcher &rd + ACE_ENV_ARG_DECL) + { + TAO_InputCDR &cdr = + rd.reply_cdr (); + + // Set the translators + this->resolver_.transport ()->assign_translators (&cdr, 0); + + switch (rd.reply_status ()) + { + case TAO_GIOP_OBJECT_HERE: + break; + case TAO_GIOP_UNKNOWN_OBJECT: + ACE_THROW_RETURN (CORBA::OBJECT_NOT_EXIST (TAO::VMCID, + CORBA::COMPLETED_YES), + TAO_INVOKE_FAILURE); + case TAO_GIOP_OBJECT_FORWARD: + case TAO_GIOP_OBJECT_FORWARD_PERM: + return this->location_forward (cdr + ACE_ENV_ARG_PARAMETER); + + case TAO_GIOP_LOC_SYSTEM_EXCEPTION: + { + // Pull the exception from the stream. + CORBA::String_var buf; + + if ((cdr >> buf.inout ()) == 0) + { + // Could not demarshal the exception id, raise a local + // CORBA::MARSHAL exception. + ACE_THROW_RETURN (CORBA::MARSHAL (TAO::VMCID, + CORBA::COMPLETED_MAYBE), + TAO_INVOKE_SYSTEM_EXCEPTION); + } + + // This kind of exception shouldn't happen with locate requests, + // but if it does, we turn it into a CORBA::UNKNOWN exception. + ACE_THROW_RETURN (CORBA::UNKNOWN (TAO::VMCID, + CORBA::COMPLETED_YES), + TAO_INVOKE_SYSTEM_EXCEPTION); + } + case TAO_GIOP_LOC_NEEDS_ADDRESSING_MODE: + { + // We have received an exception with a request to change the + // addressing mode. First let us read the mode that the + // server/agent asks for. + CORBA::Short addr_mode = 0; + + if (cdr.read_short (addr_mode) == 0) + { + // Could not demarshal the addressing disposition, raise a local + // CORBA::MARSHAL exception. + ACE_THROW_RETURN (CORBA::MARSHAL (TAO::VMCID, + CORBA::COMPLETED_MAYBE), + TAO_INVOKE_SUCCESS); + } + + // Now set this addressing mode in the profile, so that + // the next invocation need not go through this. + this->resolver_.profile ()->addressing_mode (addr_mode + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (TAO_INVOKE_SUCCESS); + + // Restart the invocation. + return TAO_INVOKE_RESTART; + } + } + + return TAO_INVOKE_SUCCESS; + } +} + +TAO_END_VERSIONED_NAMESPACE_DECL |