summaryrefslogtreecommitdiff
path: root/TAO/orbsvcs/orbsvcs/FaultTolerance/FT_Service_Callbacks.cpp
blob: e46044243e76ef663890ee80bd2233454654adbe (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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
// $Id$

#include "orbsvcs/FaultTolerance/FT_Service_Callbacks.h"
#include "orbsvcs/FaultTolerance/FT_ClientPolicy_i.h"

#include "ace/OS_NS_sys_time.h"

#include "tao/MProfile.h"
#include "tao/Profile.h"
#include "tao/Tagged_Components.h"
#include "tao/Stub.h"
#include "tao/Invocation_Utils.h"
#include "tao/ORB_Core.h"
#include "tao/Client_Strategy_Factory.h"
#include "tao/CDR.h"
#include "tao/SystemException.h"

ACE_RCSID (FaultTolerance,
           FT_Service_Callbacks,
           "$Id$")


TAO_BEGIN_VERSIONED_NAMESPACE_DECL

TAO_FT_Service_Callbacks::TAO_FT_Service_Callbacks (TAO_ORB_Core *orb_core)

  : orb_core_ (orb_core),
    profile_lock_ (0)
{
  this->profile_lock_ =
    this->orb_core_->client_factory ()->create_profile_lock ();
}

TAO_FT_Service_Callbacks::~TAO_FT_Service_Callbacks (void)
{
  // Delete the memeory for the lock
  delete this->profile_lock_;
}

CORBA::Boolean
TAO_FT_Service_Callbacks::select_profile (const TAO_MProfile &mprofile,
    TAO_Profile *&pfile)
{
  CORBA::ULong const sz = mprofile.size ();

  // Iterate through the list in a circular fashion. Stop one before
  // the list instead of trying the same thing again.
  for (CORBA::ULong i = 0;
       i != sz;
       ++i)
    {
      const TAO_Profile *curr_pfile = mprofile.get_profile (i);

      IOP::TaggedComponent tagged_component;
      tagged_component.tag = IOP::TAG_FT_PRIMARY;

      // Get the tagged component from the  profile
      const TAO_Tagged_Components &pfile_tagged =
        curr_pfile->tagged_components ();

      // Search for the TaggedComponent that we want
      if (pfile_tagged.get_component (tagged_component) == 1)
      {
        // We have found a primary IOR
        pfile = const_cast<TAO_Profile *>(curr_pfile);
        return true;
      }
    }

  return false;
}

CORBA::Boolean
TAO_FT_Service_Callbacks::object_is_nil (CORBA::Object_ptr obj)
{
  // Get the count
  CORBA::ULong count = obj->_stubobj ()->base_profiles ().profile_count ();

  // If the profile count is zero then return true
  if (count == 0)
    return true;
  else
    {
      // else if each of the profile is nil
      for (CORBA::ULong cnt = 0;
           cnt < count;
           cnt++)
        {
          TAO_Profile *pfile =
            obj->_stubobj ()->base_profiles ().get_profile (cnt);

          if (pfile != 0)
            return false;
        }
    }

  // If it reaches here then it should be nill
  return true;

}

TAO_Service_Callbacks::Profile_Equivalence
TAO_FT_Service_Callbacks::is_profile_equivalent (const TAO_Profile *this_p,
                                                 const TAO_Profile *that_p)
{
  const TAO_Tagged_Components &this_comp =
    this_p->tagged_components ();

  const TAO_Tagged_Components &that_comp =
    that_p->tagged_components ();

  IOP::TaggedComponent this_tc, that_tc;
  this_tc.tag = that_tc.tag = IOP::TAG_FT_GROUP;

  if (this_comp.get_component (this_tc) == 1)
    {
      if (that_comp.get_component (that_tc) == 1)
        {
          TAO_InputCDR this_cdr (reinterpret_cast<const char*> (this_tc.component_data.get_buffer ()),
                             this_tc.component_data.length ());

          TAO_InputCDR that_cdr (reinterpret_cast<const char*> (that_tc.component_data.get_buffer ()),
                             that_tc.component_data.length ());

          CORBA::Boolean this_byte_order;
          CORBA::Boolean that_byte_order;

          if (this_cdr >> ACE_InputCDR::to_boolean (this_byte_order) == 0 ||
              that_cdr >> ACE_InputCDR::to_boolean (that_byte_order) == 0)
            {
              // Have tags but full of garbage - not equivalent
              return TAO_Service_Callbacks::NOT_EQUIVALENT;
            }

          this_cdr.reset_byte_order (static_cast<int> (this_byte_order));
          that_cdr.reset_byte_order (static_cast<int> (that_byte_order));


          FT::TagFTGroupTaggedComponent this_group_component;
          FT::TagFTGroupTaggedComponent that_group_component;

          this_cdr >> this_group_component;
          that_cdr >> that_group_component;

          // check if domain id and group id are the same
          if ((ACE_OS::strcmp (this_group_component.group_domain_id,
                               that_group_component.group_domain_id) == 0) &&
              (this_group_component.object_group_id ==
               that_group_component.object_group_id))
             {
               // Both have matching tags - true
               return TAO_Service_Callbacks::EQUIVALENT;
             }
        }

      return TAO_Service_Callbacks::NOT_EQUIVALENT;
    }
  else
    {
      if (that_comp.get_component (that_tc) == 1)
        {
          return TAO_Service_Callbacks::NOT_EQUIVALENT;
        }
    }

  return TAO_Service_Callbacks::DONT_KNOW;
}

CORBA::ULong
TAO_FT_Service_Callbacks::hash_ft (TAO_Profile *p, CORBA::ULong max)
{
  // At this point we assume that all the checks for other things
  // within the profiles have been satisfied
  TAO_Tagged_Components &this_comp =
    p->tagged_components ();

  IOP::TaggedComponent tc;
  tc.tag = IOP::TAG_FT_GROUP;

  if (this_comp.get_component (tc) == 0)
    return 0;

  // extract the group component
  TAO_InputCDR cdr (reinterpret_cast<const char*> (tc.component_data.get_buffer ()),
                    tc.component_data.length ());

  CORBA::Boolean byte_order;
  if ((cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
  {
    return 0;
  }

  cdr.reset_byte_order (static_cast<int> (byte_order));

  FT::TagFTGroupTaggedComponent group_component;

  cdr >> group_component;

  return (CORBA::ULong) group_component.object_group_id % max;
}

CORBA::Boolean
TAO_FT_Service_Callbacks::is_permanent_forward_condition (const CORBA::Object_ptr obj,
                                                          const TAO_Service_Context &service_context) const
{
  // do as much as possible outside of lock
  IOP::ServiceContext sc;
  sc.context_id = IOP::FT_GROUP_VERSION;

  if (service_context.get_context (sc) == 0)
      return false; /* false */

  IOP::TaggedComponent tc;
  tc.tag = IOP::TAG_FT_GROUP;

  const TAO_Stub * stub = obj->_stubobj ();
  // check for forward_profiles, branching to speed up operation on base_profiles
  if (stub->forward_profiles ())
    {
      // set lock, as forward_profiles might be deleted concurrently
      ACE_MT (ACE_GUARD_RETURN (ACE_Lock,
                                guard,
                                *stub->profile_lock (),
                                0));

      // even now, the forward profiles might have been deleted in the meanwhile
      const TAO_MProfile &mprofile = stub->forward_profiles()
          ? *(stub->forward_profiles())
          : stub->base_profiles();

      if (mprofile.profile_count() == 0)
        // releasing lock
        return false;

      // assuming group-attributes are set for all profiles, check
      // only the first profile
      const TAO_Tagged_Components &tagged_components =
              mprofile.get_profile (0)->tagged_components ();

      if (tagged_components.get_component (tc) == 0)
        // releasing lock
        return false; /* false */

      return true; /* true */

      // releasing lock
    }
  else /* operate on constant basic_profiles */
    {
      const TAO_MProfile &mprofile = stub->base_profiles();

      if (mprofile.profile_count() == 0)
        return false;

      // assuming group-attributes are set for all profiles, check only the first profile
      const TAO_Tagged_Components &tagged_components =
              mprofile.get_profile (0)->tagged_components ();

      if (tagged_components.get_component (tc) == 0)
        return false; /* false */

      return true; /* true */
    }
}


TAO::Invocation_Status
TAO_FT_Service_Callbacks::raise_comm_failure (
    IOP::ServiceContextList &context_list,
    TAO_Profile *profile)
{
  if (this->restart_policy_check (context_list,
                                  profile))
    return TAO::TAO_INVOKE_RESTART;

  // As the right tags are not found close the connection and throw an
  // exception
  throw CORBA::COMM_FAILURE (
    CORBA::SystemException::_tao_minor_code (
      TAO_INVOCATION_RECV_REQUEST_MINOR_CODE,
      errno),
    CORBA::COMPLETED_MAYBE);
}

TAO::Invocation_Status
TAO_FT_Service_Callbacks::raise_transient_failure (
    IOP::ServiceContextList &service,
    TAO_Profile *profile)
{
  if (this->restart_policy_check (service,
                                  profile))
    return TAO::TAO_INVOKE_RESTART;

  // Unlike COMM_FAILURE do not raise an exception since the
  // completion status is not known and no assumption can be made.
  return TAO::TAO_INVOKE_SYSTEM_EXCEPTION;
}

CORBA::Boolean
TAO_FT_Service_Callbacks::restart_policy_check (
    IOP::ServiceContextList &service_list,
    const TAO_Profile *profile)
{
  // Check whether the IOP::FT_REQUEST exists within the service
  // context list and FT::FT_GROUP exists within the profile that we
  // have
  IOP::TaggedComponent tagged_component;
  tagged_component.tag = IOP::TAG_FT_GROUP;

  if (profile->tagged_components ().get_component (tagged_component)
      == 1)
    {
      // Look for the FT_REQUEST context id
      for (CORBA::ULong i = 0;
           i < service_list.length ();
           i++)
        {
          if (service_list[i].context_id == IOP::FT_REQUEST)
            {
              // This would be a heck of a lot easier if we had the invocation
              // here rather than just the contexts, but lemons -> lemonade I guess.
              TAO_InputCDR cdr (reinterpret_cast <const char*> (service_list[i].context_data.get_buffer ()),
                                service_list[i].context_data.length ());
              CORBA::Boolean byte_order;
              if ((cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
                return 0;
              cdr.reset_byte_order (static_cast <int> (byte_order));
              FT::FTRequestServiceContext ftsrc;
              if ((cdr >> ftsrc) == 0)
                return 0;

              return (ftsrc.expiration_time > now ());
            }
        }
    }

  // Failure
  return 0;
}

TimeBase::TimeT
TAO_FT_Service_Callbacks::now (void)
{
  // Grab the localtime on the machine where this is running
  ACE_Time_Value time_val = ACE_OS::gettimeofday ();
  TimeBase::TimeT sec_part  = ((TimeBase::TimeT)time_val.sec ()) * 10000000;
  TimeBase::TimeT usec_part = ((TimeBase::TimeT)time_val.usec ()) * 10;

  // Add the offset to convert from posix time.
  return (sec_part + usec_part + ACE_UINT64_LITERAL (0x1B21DD213814000));
}

TAO_END_VERSIONED_NAMESPACE_DECL