summaryrefslogtreecommitdiff
path: root/ACE/TAO/tao/LocateRequest_Invocation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/TAO/tao/LocateRequest_Invocation.cpp')
-rw-r--r--ACE/TAO/tao/LocateRequest_Invocation.cpp208
1 files changed, 208 insertions, 0 deletions
diff --git a/ACE/TAO/tao/LocateRequest_Invocation.cpp b/ACE/TAO/tao/LocateRequest_Invocation.cpp
new file mode 100644
index 00000000000..3d97edf6d61
--- /dev/null
+++ b/ACE/TAO/tao/LocateRequest_Invocation.cpp
@@ -0,0 +1,208 @@
+#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 "tao/SystemException.h"
+#include "ace/Intrusive_Auto_Ptr.h"
+
+#include "ace/Countdown_Time.h"
+
+ACE_RCSID (tao,
+ LocateRequest_Invocation,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace TAO
+{
+ /**
+ * @class First_Request_Guard
+ *
+ * @brief Auto pointer like class for first_request flag in transport.
+ *
+ * Since codeset service context is only sent in the first request it might
+ * happen that after LocateRequest (which doesn't include service context)
+ * no codeset negotiation happens in subsequent calls. In this respect
+ * LocateRequest is not the first request and thus First_Request_Guard
+ * restores first_request in transport to its original state.
+ */
+ class First_Request_Guard
+ {
+ public:
+ First_Request_Guard (TAO_Transport &transport);
+
+ ~First_Request_Guard (void);
+
+ private:
+ /// The transport that we guard.
+ TAO_Transport &transport_;
+
+ /// Original value of first_request from transport.
+ bool is_first_;
+ };
+
+ First_Request_Guard::First_Request_Guard (TAO_Transport &transport)
+ : transport_ (transport)
+ {
+ this->is_first_ = this->transport_.first_request ();
+ }
+
+ First_Request_Guard::~First_Request_Guard (void)
+ {
+ this->transport_.first_request_sent (this->is_first_);
+ }
+
+ 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_Countdown_Time countdown (max_wait_time);
+
+ TAO_Synch_Reply_Dispatcher *rd_p = 0;
+ ACE_NEW_NORETURN (rd_p, TAO_Synch_Reply_Dispatcher (this->resolver_.stub ()->orb_core (),
+ this->details_.reply_service_info ()));
+ if (!rd_p)
+ {
+ throw ::CORBA::NO_MEMORY ();
+ }
+
+ ACE_Intrusive_Auto_Ptr<TAO_Synch_Reply_Dispatcher> rd(rd_p, false);
+
+ // Register a reply dispatcher for this invocation. Use the
+ // preallocated reply dispatcher.
+ TAO_Bind_Dispatcher_Guard dispatch_guard (this->details_.request_id (),
+ rd.get (),
+ 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 ();
+
+ throw ::CORBA::INTERNAL (TAO::VMCID, CORBA::COMPLETED_NO);
+ }
+
+ TAO_Transport *transport = this->resolver_.transport ();
+
+ Invocation_Status s = TAO_INVOKE_FAILURE;
+ {
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ace_mon,
+ transport->output_cdr_lock (), TAO_INVOKE_FAILURE);
+ TAO_OutputCDR &cdr = transport->out_stream ();
+
+ // This must restore first_request flag after message is sent.
+ First_Request_Guard fr_quard (*transport);
+
+ TAO_Target_Specification tspec;
+ this->init_target_spec (tspec, cdr);
+
+ if (transport->generate_locate_request (tspec, this->details_, cdr) == -1)
+ return TAO_INVOKE_FAILURE;
+
+ countdown.update ();
+
+ s = this->send_message (cdr, TAO_TWOWAY_REQUEST, max_wait_time);
+ }
+
+ 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.get (), dispatch_guard);
+
+ s = this->check_reply (*rd.get ());
+
+ // 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)
+ {
+ TAO_InputCDR &cdr = rd.reply_cdr ();
+
+ // Set the translators
+ this->resolver_.transport ()->assign_translators (&cdr, 0);
+
+ switch (rd.locate_reply_status ())
+ {
+ case GIOP::OBJECT_HERE:
+ break;
+ case GIOP::UNKNOWN_OBJECT:
+ throw ::CORBA::OBJECT_NOT_EXIST (TAO::VMCID, CORBA::COMPLETED_YES);
+ case GIOP::OBJECT_FORWARD:
+ case GIOP::OBJECT_FORWARD_PERM:
+ return this->location_forward (cdr);
+ case 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.
+ throw ::CORBA::MARSHAL (TAO::VMCID, CORBA::COMPLETED_MAYBE);
+ }
+
+ // This kind of exception shouldn't happen with locate requests,
+ // but if it does, we turn it into a CORBA::UNKNOWN exception.
+ throw ::CORBA::UNKNOWN (TAO::VMCID, CORBA::COMPLETED_YES);
+ }
+ case 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.
+ throw ::CORBA::MARSHAL (TAO::VMCID, CORBA::COMPLETED_MAYBE);
+ }
+
+ // 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);
+
+ // Restart the invocation.
+ return TAO_INVOKE_RESTART;
+ }
+ }
+
+ return TAO_INVOKE_SUCCESS;
+ }
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL