summaryrefslogtreecommitdiff
path: root/TAO/tao/LocateRequest_Invocation_Adapter.cpp
blob: e7920ac5439d2523f93baddff19b0c68d21f2b7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// -*- C++ -*-
#include "tao/LocateRequest_Invocation_Adapter.h"
#include "tao/Profile_Transport_Resolver.h"
#include "tao/operation_details.h"
#include "tao/LocateRequest_Invocation.h"
#include "tao/Transport.h"
#include "tao/Transport_Mux_Strategy.h"
#include "tao/GIOP_Utils.h"
#include "tao/ORB_Core.h"
#include "tao/Stub.h"
#include "tao/SystemException.h"
#include "ace/Service_Config.h"

TAO_BEGIN_VERSIONED_NAMESPACE_DECL

namespace TAO
{
  LocateRequest_Invocation_Adapter::LocateRequest_Invocation_Adapter (
    CORBA::Object_ptr target)
    : target_ (target)
    , list_ (nullptr)
  {
  }

  void
  LocateRequest_Invocation_Adapter::invoke ()
  {
    CORBA::Object_var effective_target =
      CORBA::Object::_duplicate (this->target_);

    TAO_Stub * const stub =
      this->target_->_stubobj ();
    if (stub == nullptr)
      throw ::CORBA::INTERNAL (
                     CORBA::SystemException::_tao_minor_code (
                       0,
                         EINVAL),
                        CORBA::COMPLETED_NO);

    // The invocation has got to be within the context of the
    // corresponding ORB's configuration. Otherwise things like
    // timeout hooks, etc may not work as expected. Especially if
    // there are multiple ORB instances in the process, each with its
    // own, local configuration.
    ACE_Service_Config_Guard scg (stub->orb_core ()->configuration ());

    ACE_Time_Value tmp_wait_time;
    ACE_Time_Value *max_wait_time = nullptr;

    if (this->get_timeout (tmp_wait_time))
      max_wait_time = &tmp_wait_time;

    Invocation_Status s = TAO_INVOKE_START;

    while (s == TAO_INVOKE_START || s == TAO_INVOKE_RESTART)
      {
        Profile_Transport_Resolver resolver (effective_target.in (), stub, true);

        try
          {
            resolver.init_inconsistent_policies ();

            resolver.resolve (max_wait_time);

            if (!resolver.transport ())
              {
                // We failed to find a profile we could connect to.
                throw CORBA::TRANSIENT (CORBA::OMGVMCID | 2, CORBA::COMPLETED_NO);
              }

            // Dummy operation details that is used to instantiate the
            // LocateRequest class.
            TAO_Operation_Details op (nullptr, 0);

            op.request_id (resolver.transport ()->tms ()->request_id ());
            TAO::LocateRequest_Invocation synch (this->target_, resolver, op);

            s = synch.invoke (max_wait_time);
            if (s == TAO_INVOKE_RESTART &&
                (synch.reply_status () == GIOP::LOCATION_FORWARD ||
                 synch.reply_status () == GIOP::LOCATION_FORWARD_PERM))
              {
                CORBA::Boolean const is_permanent_forward =
                  (synch.reply_status () == GIOP::LOCATION_FORWARD_PERM);

                effective_target = synch.steal_forwarded_reference ();

                this->object_forwarded (effective_target,
                                        resolver.stub (),
                                        is_permanent_forward);
              }
          }
        catch (const ::CORBA::INV_POLICY&)
          {
            this->list_ = resolver.steal_inconsistent_policies ();
            throw;
          }
      }

    return;
  }

  CORBA::PolicyList *
  LocateRequest_Invocation_Adapter::get_inconsistent_policies ()
  {
    return this->list_._retn ();
  }

  bool
  LocateRequest_Invocation_Adapter::get_timeout (ACE_Time_Value &timeout)
  {
    bool has_timeout = false;
    this->target_->orb_core ()->call_timeout_hook (this->target_->_stubobj (),
                                                   has_timeout,
                                                   timeout);

    return has_timeout;
  }

  void
  LocateRequest_Invocation_Adapter::object_forwarded (
    CORBA::Object_var &effective_target,
    TAO_Stub *stub,
    CORBA::Boolean permanent_forward)
  {
    // The object pointer has to be changed to a TAO_Stub pointer
    // in order to obtain the profiles.
    TAO_Stub *stubobj = nullptr;

    bool nil_forward_ref = false;
    if (CORBA::is_nil (effective_target.in ()))
      nil_forward_ref = true;
    else
      {
        stubobj =
          effective_target->_stubobj ();

        if (stubobj && stubobj->base_profiles ().size () == 0)
          nil_forward_ref = true;
      }

    if (nil_forward_ref)
      throw ::CORBA::TRANSIENT (
        CORBA::SystemException::_tao_minor_code (
          TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE,
          0),
        CORBA::COMPLETED_NO);

    if (stubobj == nullptr)
      throw ::CORBA::INTERNAL (
        CORBA::SystemException::_tao_minor_code (
          TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE,
          EINVAL),
        CORBA::COMPLETED_NO);

    // Reset the profile in the stubs
    stub->add_forward_profiles (stubobj->base_profiles (), permanent_forward);

    if (stub->next_profile () == nullptr)
      throw ::CORBA::TRANSIENT (
        CORBA::SystemException::_tao_minor_code (
          TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE,
          0),
        CORBA::COMPLETED_NO);

    return;
  }

} // End namespace TAO

TAO_END_VERSIONED_NAMESPACE_DECL