summaryrefslogtreecommitdiff
path: root/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RoundRobin.cpp
blob: ab865f8020e6dd3aa3cf91a76dc95c63d124284a (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 "orbsvcs/LoadBalancing/LB_RoundRobin.h"

#include "orbsvcs/PortableGroup/PG_conf.h"

#include "tao/debug.h"
#include "tao/ORB_Constants.h"

ACE_RCSID (LoadBalancing,
           LB_RoundRobin,
           "$Id$")

TAO_BEGIN_VERSIONED_NAMESPACE_DECL

TAO_LB_RoundRobin::TAO_LB_RoundRobin (PortableServer::POA_ptr poa)
  : poa_ (PortableServer::POA::_duplicate (poa)),
    lock_ (),
    location_index_map_ (TAO_PG_MAX_OBJECT_GROUPS)
{
}

TAO_LB_RoundRobin::~TAO_LB_RoundRobin (void)
{
}

char *
TAO_LB_RoundRobin::name (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
  ACE_THROW_SPEC ((CORBA::SystemException))
{
  return CORBA::string_dup ("RoundRobin");
}

CosLoadBalancing::Properties *
TAO_LB_RoundRobin::get_properties (ACE_ENV_SINGLE_ARG_DECL)
  ACE_THROW_SPEC ((CORBA::SystemException))
{
  // There are no RoundRobin properties.  Return an empty property
  // list.

  CosLoadBalancing::Properties * props = 0;
  ACE_NEW_THROW_EX (props,
                    CosLoadBalancing::Properties,
                    CORBA::NO_MEMORY (
                      CORBA::SystemException::_tao_minor_code (
                        TAO::VMCID,
                        ENOMEM),
                      CORBA::COMPLETED_NO));
  ACE_CHECK_RETURN (props);

  return props;
}

void
TAO_LB_RoundRobin::push_loads (
    const PortableGroup::Location & /* the_location */,
    const CosLoadBalancing::LoadList & /* loads */
    ACE_ENV_ARG_DECL)
  ACE_THROW_SPEC ((CORBA::SystemException,
                   CosLoadBalancing::StrategyNotAdaptive))
{
  ACE_THROW (CosLoadBalancing::StrategyNotAdaptive ());
}

CosLoadBalancing::LoadList *
TAO_LB_RoundRobin::get_loads (CosLoadBalancing::LoadManager_ptr load_manager,
                              const PortableGroup::Location & the_location
                              ACE_ENV_ARG_DECL)
  ACE_THROW_SPEC ((CORBA::SystemException,
                   CosLoadBalancing::LocationNotFound))
{
  if (CORBA::is_nil (load_manager))
    ACE_THROW_RETURN (CORBA::BAD_PARAM (), 0);

  return load_manager->get_loads (the_location
                                  ACE_ENV_ARG_PARAMETER);
}

CORBA::Object_ptr
TAO_LB_RoundRobin::next_member (
    PortableGroup::ObjectGroup_ptr object_group,
    CosLoadBalancing::LoadManager_ptr load_manager
    ACE_ENV_ARG_DECL)
  ACE_THROW_SPEC ((CORBA::SystemException,
                   PortableGroup::ObjectGroupNotFound,
                   PortableGroup::MemberNotFound))
{
  if (CORBA::is_nil (load_manager))
    ACE_THROW_RETURN (CORBA::BAD_PARAM (), CORBA::Object::_nil ());

  const PortableGroup::ObjectGroupId id =
    load_manager->get_object_group_id (object_group
                                       ACE_ENV_ARG_PARAMETER);
  ACE_CHECK_RETURN (CORBA::Object::_nil ());

  ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
                    monitor,
                    this->lock_,
                    CORBA::Object::_nil ());

  // Since this is "built-in" strategy, the LoadManager is collocated.
  // There is no need to release the lock during the following
  // invocation.
  //
  // There is a race condition here.  The
  PortableGroup::Locations_var locations =
    load_manager->locations_of_members (object_group
                                        ACE_ENV_ARG_PARAMETER);
  ACE_CHECK_RETURN (CORBA::Object::_nil ());

  const CORBA::ULong len = locations->length ();

  if (len == 0)
    ACE_THROW_RETURN (CORBA::TRANSIENT (),
                      CORBA::Object::_nil ());

  TAO_LB_Location_Index_Map::ENTRY * entry;
  if (this->location_index_map_.find (id, entry) == 0)
    {
      CORBA::ULong & i = entry->int_id_;

      if (len <= i)
        i = 0;  // Reset, i.e. wrap around

      // No need to release the lock since the LoadManager is
      // collocated.
      CORBA::Object_var member =
        load_manager->get_member_ref (object_group,
                                      locations[i]
                                      ACE_ENV_ARG_PARAMETER);
      ACE_CHECK_RETURN (CORBA::Object::_nil ());

      // Increment index to point to next location.
      i++;

      return member._retn ();
    }

  // The first time through this method.  Set up for the next time
  // around, and return the object reference residing at the first
  // location in the "locations of members" sequence.

  // Note that it is safe to set the next_index below to 1 even if the
  // length of the sequence is 1 since the above code handles the
  // boundary case correctly by wrapping around.

  const CORBA::ULong index = 0;
  if (this->location_index_map_.bind (id, index + 1) != 0)
    ACE_THROW_RETURN (CORBA::INTERNAL (), CORBA::Object::_nil ());

  return load_manager->get_member_ref (object_group,
                                       locations[index]
                                       ACE_ENV_ARG_PARAMETER);
}

void
TAO_LB_RoundRobin::analyze_loads (
    PortableGroup::ObjectGroup_ptr /* object_group */,
    CosLoadBalancing::LoadManager_ptr /* load_manager */
    ACE_ENV_ARG_DECL_NOT_USED)
  ACE_THROW_SPEC ((CORBA::SystemException))
{
}

PortableServer::POA_ptr
TAO_LB_RoundRobin::_default_POA (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
{
  return PortableServer::POA::_duplicate (this->poa_.in ());
}

TAO_END_VERSIONED_NAMESPACE_DECL