summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TAO/orbsvcs/orbsvcs/LB_LeastLoaded.inl17
-rw-r--r--TAO/orbsvcs/orbsvcs/LB_LoadAlert.inl15
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.cpp387
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.h65
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.inl17
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlert.cpp35
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlert.h90
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlert.inl15
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlertInfo.cpp36
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlertInfo.h67
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlertMap.cpp27
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlertMap.h44
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadListMap.cpp26
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadListMap.h43
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadManager.cpp736
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadManager.h171
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_MemberLocator.cpp4
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Random.cpp2
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Random.h7
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RoundRobin.cpp67
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RoundRobin.h94
21 files changed, 1557 insertions, 408 deletions
diff --git a/TAO/orbsvcs/orbsvcs/LB_LeastLoaded.inl b/TAO/orbsvcs/orbsvcs/LB_LeastLoaded.inl
index d2d3dc420cd..cb650c93ba0 100644
--- a/TAO/orbsvcs/orbsvcs/LB_LeastLoaded.inl
+++ b/TAO/orbsvcs/orbsvcs/LB_LeastLoaded.inl
@@ -2,19 +2,6 @@
//
// $Id$
-ACE_INLINE CORBA::Float
-TAO_LB_LeastLoaded::raw_load (CORBA::Float load)
-{
- return this->dampened_load (load + this->per_balance_load_);
-}
-
-
-ACE_INLINE CORBA::Float
-TAO_LB_LeastLoaded::raw_load (CORBA::Float load)
-{
- return this->dampened_load (load + this->per_balance_load_);
-}
-
ACE_INLINE CORBA::Float
TAO_LB_LeastLoaded::effective_load (CORBA::Float previous_load,
@@ -29,8 +16,8 @@ TAO_LB_LeastLoaded::effective_load (CORBA::Float previous_load,
ACE_ASSERT (this->tolerance_ != 0);
- // Compute th effective load.
- result = raw_load / this->tolerance_;
+ // Compute the effective load.
+ result /= this->tolerance_;
return result;
}
diff --git a/TAO/orbsvcs/orbsvcs/LB_LoadAlert.inl b/TAO/orbsvcs/orbsvcs/LB_LoadAlert.inl
new file mode 100644
index 00000000000..2099eae3096
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LB_LoadAlert.inl
@@ -0,0 +1,15 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_INLINE CORBA::Boolean
+TAO_LB_LoadAlert::alerted (void) const
+{
+ return this->alerted_;
+}
+
+ACE_INLINE CORBA::Object_ptr
+TAO_LB_LoadAlert::forward (void)
+{
+ return CORBA::Object::_duplicate (this->forward_.in ());
+}
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.cpp
index 6ff77419e3a..28a2b745f27 100644
--- a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.cpp
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.cpp
@@ -1,6 +1,7 @@
// -*- C++ -*-
#include "LB_LeastLoaded.h"
+#include "LB_LoadMap.h"
#include "orbsvcs/PortableGroup/PG_conf.h"
#include "tao/debug.h"
@@ -20,30 +21,34 @@ TAO_LB_LeastLoaded::TAO_LB_LeastLoaded (CORBA::Float critical_threshold,
CORBA::Float dampening,
CORBA::Float per_balance_load)
: load_map_ (0),
- lock_ (),
- critical_threshold_ (0),
- reject_threshold_ (0),
- tolerance_ (1),
- dampening_ (0),
- per_balance_load_ (0)
+ lock_ (0),
+ critical_threshold_ (critical_threshold),
+ reject_threshold_ (reject_threshold),
+ tolerance_ (tolerance == 0 ? 1 : tolerance),
+ dampening_ (dampening),
+ per_balance_load_ (per_balance_load)
{
// A load map that retains previous load values at a given location
- // is only needed if dampening is enabled, i.e. non-zero.
+ // and lock are only needed if dampening is enabled, i.e. non-zero.
if (this->dampening_ != 0)
- ACE_NEW (this->load_map_,
- LoadMap (TAO_PG_MAX_LOCATIONS));
+ {
+ ACE_NEW (this->load_map_, TAO_LB_LoadMap (TAO_PG_MAX_LOCATIONS));
+
+ ACE_NEW (this->lock_, TAO_SYNCH_MUTEX);
+ }
}
TAO_LB_LeastLoaded::~TAO_LB_LeastLoaded (void)
{
delete this->load_map_;
+ delete this->lock_;
}
char *
TAO_LB_LeastLoaded::name (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
ACE_THROW_SPEC ((CORBA::SystemException))
{
- return CORBA::string_dup ("TAO_LB_LeastLoaded");
+ return CORBA::string_dup ("LeastLoaded");
}
CosLoadBalancing::Properties *
@@ -74,14 +79,35 @@ TAO_LB_LeastLoaded::push_loads (
if (loads.length () == 0)
ACE_THROW (CORBA::BAD_PARAM ());
+ CosLoadBalancing::Load load; // Unused
+
+ this->push_loads (the_location,
+ loads,
+ load
+ ACE_ENV_ARG_PARAMETER);
+}
+
+void
+TAO_LB_LeastLoaded::push_loads (
+ const PortableGroup::Location & the_location,
+ const CosLoadBalancing::LoadList & loads,
+ CosLoadBalancing::Load & load
+ ACE_ENV_ARG_DECL)
+{
+ if (loads.length () == 0)
+ ACE_THROW (CORBA::BAD_PARAM ());
+
+ // Only the first load is used by this load balancing strategy.
const CosLoadBalancing::Load & new_load = loads[0];
if (this->load_map_ != 0)
{
- TAO_LB_LoadMap::ENTRY * load;
- if (this->load_map_->find (the_location, load) == 0)
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, *this->lock_);
+
+ TAO_LB_LoadMap::ENTRY * entry;
+ if (this->load_map_->find (the_location, entry) == 0)
{
- CosLoadBalancing::Load & previous_load = load->int_id_;
+ CosLoadBalancing::Load & previous_load = entry->int_id_;
if (previous_load.id != new_load.id)
ACE_THROW (CORBA::BAD_PARAM ()); // Somebody switched
@@ -89,13 +115,15 @@ TAO_LB_LeastLoaded::push_loads (
previous_load.value =
this->effective_load (previous_load.value, new_load.value);
+
+ load = previous_load;
}
else
{
const CosLoadBalancing::Load eff_load =
{
new_load.id,
- this->effective_load (0, new_load.value);
+ this->effective_load (0, new_load.value)
};
if (this->load_map_->bind (the_location, eff_load) != 0)
@@ -107,10 +135,17 @@ TAO_LB_LeastLoaded::push_loads (
ACE_THROW (CORBA::INTERNAL ());
}
+
+ load = eff_load;
}
}
+ else
+ {
+ load.id = new_load.id;
+ load.value = this->effective_load (0, new_load.value);
+ }
}
-
+
CORBA::Object_ptr
TAO_LB_LeastLoaded::next_member (
PortableGroup::ObjectGroup_ptr object_group,
@@ -138,7 +173,10 @@ TAO_LB_LeastLoaded::next_member (
PortableGroup::Location location;
CORBA::Boolean found_location =
- this->get_location (locations.in (), location);
+ this->get_location (object_group,
+ load_manager,
+ locations.in (),
+ location);
if (found_location)
{
@@ -154,89 +192,9 @@ TAO_LB_LeastLoaded::next_member (
}
}
-void
-TAO_LB_LeastLoaded::analyze_loads (
- PortableGroup::ObjectGroup_ptr object_group,
- CosLoadBalancing::LoadManager_ptr load_manager
- ACE_ENV_ARG_DECL)
- ACE_THROW_SPEC ((CORBA::SystemException))
-{
- int send_load_advisory = 0;
-
- {
- ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
-
-
- TAO_LB_Location_Map::iterator begin =
- location_map.begin ();
-
- TAO_LB_Location_Map::iterator end =
- location_map.end ();
-
- float s = 0;
- CORBA::ULong n = 0;
- TAO_LB_Location_Map::iterator i = begin;
- for ( ; i != end; ++i)
- {
- s += (*i)->int_id_.load_list[0].value; // @@ Hard coded to
- // get things
- // going.
- n++;
- }
-
- float avg = (n == 0 ? s : s / n);
- float cl = proxy->current_load ();
-
- if (avg == 0)
- return;
-
- float relative_load = cl / avg;
-
- // @@ Ossama: Make the 1.5 factor adjustable, it is how much
- // dispersion we tolerate before starting to send advisories.
- if (relative_load > 1 + 1.5F / n)
- {
- proxy->has_high_load_ = 1;
- send_load_advisory = 2; // 2 == Send high load advisory
- }
-
- if (send_load_advisory == 1 && relative_load < 1 + 0.9F / n)
- {
- proxy->has_high_load_ = 0;
- send_load_advisory = 1; // 1 == Send nominal load advisory
- }
- }
-
- // @@ Ossama: no debug messages in production code, my fault....
- // ACE_DEBUG ((LM_DEBUG, "Load[%x] %f %f %f\n",
- // proxy, cl, avg, relative_load));
-
- // @@ Ossama: Make the 1.5 factor adjustable, it is how much
- // dispersion we tolerate before starting to send advisories.
- if (send_load_advisory == 2)
- {
- proxy->control_->high_load_advisory (ACE_ENV_SINGLE_ARG_PARAMETER);
- ACE_CHECK;
-
- return; // We may not throw an exception, so explicitly return.
- }
-
- // @@ Ossama: notice that we wait until the load is signifcantly
- // lower before sending the nominal load advisory, it does not
- // matter that much because the replicas automatically restart after
- // rejecting one client....
- // @@ Ossama: make the 0.9 factor adjustable, at least at
- // construction time...
- if (send_load_advisory == 1)
- {
- proxy->control_->nominal_load_advisory (ACE_ENV_SINGLE_ARG_PARAMETE);
- ACE_CHECK;
- }
-
-}
-
CORBA::Boolean
TAO_LB_LeastLoaded::get_location (
+ PortableGroup::ObjectGroup_ptr object_group,
const CosLoadBalancing::LoadManager_ptr load_manager,
const PortableGroup::Locations & locations,
PortableGroup::Location & location)
@@ -247,196 +205,59 @@ TAO_LB_LeastLoaded::get_location (
const CORBA::ULong len = locations.length ();
- {
- ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
- guard,
- this->lock_,
- 0);
-
- for (CORBA::ULong i = 0; i < len; ++i)
- {
- const PortableGroup::Location & loc = locations[i];
-
- // Retrieve the load list for the location from the
- // LoadManager and push it to this Strategy's load processor.
- CosLoadBalancing::LoadList_var current_loads =
- load_manager->get_loads (loc
- ACE_ENV_ARG_PARAMETER);
- ACE_TRY_CHECK;
-
- this->push_loads (loc,
- current_loads.in ()
- ACE_ENV_ARG_PARAMETER);
- ACE_TRY_CHECK;
-
- // WRONG!!! THIS IS LEAST LOADED, NOT MINIMUM DISPERSION!
- LoadMap::ENTRY * entry;
- if (this->load_map_.find (locations[i], entry) == 0
- && (i == 0 || entry.value < min_load))
- {
- min_load = entry->value;
- location_index = i;
- found_location = 1;
- }
- }
- }
-
- if (found_location)
- location = locations[location_index];
-
- return found_location;
-}
-
-CORBA::Object_ptr
-TAO_LB_LeastLoaded::replica (
- TAO_LB_ObjectGroup_Map_Entry *entry
- ACE_ENV_ARG_DECL)
- ACE_THROW_SPEC ((CORBA::SystemException))
-{
- for ( ; ; )
+ for (CORBA::ULong i = 0; i < len; ++i)
{
- ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
- guard,
- entry->lock,
- CORBA::Object::_nil ());
-
- if (entry->replica_infos.is_empty ())
- // @@ What do we do if the set is empty?
- ACE_THROW_RETURN (CORBA::OBJECT_NOT_EXIST (),
- CORBA::Object::_nil ());
-
- TAO_LB_ReplicaInfo_Set::iterator begin = entry->replica_infos.begin ();
- TAO_LB_ReplicaInfo_Set::iterator end = entry->replica_infos.end ();
-
- TAO_LB_ReplicaInfo_Set::iterator i = begin;
- TAO_LB_ReplicaInfo *replica_info = (*i);
-
- LoadBalancing::LoadList *d =
- replica_info->location_entry->load_list.ptr ();
-
- for (++i ; i != end; ++i)
+ const PortableGroup::Location & loc = locations[i];
+
+ // Retrieve the load list for the location from the LoadManager
+ // and push it to this Strategy's load processor.
+ CosLoadBalancing::LoadList_var current_loads =
+ load_manager->get_loads (loc
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CosLoadBalancing::Load load;
+ this->push_loads (loc,
+ current_loads.in (),
+ load
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ if (load.value < this->reject_threshold_
+ && (i == 0 || load.value < min_load))
{
- LoadBalancing::LoadList *load =
- (*i)->location_entry->load_list.ptr ();
-
- // @@ Hardcode one load and don't bother checking the
- // LoadId, for now. (just to get things going)
- if ((*d)[CORBA::ULong (0)].value > (*load)[CORBA::ULong (0)].value)
- {
- replica_info = *i;
- d = (*i)->location_entry->load_list.ptr ();
- }
+ min_load = load.value;
+ location_index = i;
+ found_location = 1;
+ }
+ else if (load.value > this->critical_threshold_)
+ {
+ // The location is overloaded. Perform load shedding by
+ // informing the LoadAlert object associated with the member
+ // at that location it should redirect client requests back
+ // to the LoadManager.
+ //
+ // AMI is used to improve member selection times and overall
+ // throughput since the LoadAlert object need not be alerted
+ // synchronously. In particular, the load alert can and
+ // should be performed in parallel to the member selection.
+ load_manager->enable_alert (object_group,
+ loc
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ else if (load.value <= this->critical_threshold_)
+ {
+ // The location is not overloaded
+ load_manager->disable_alert (object_group,
+ loc
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
}
-
- // Before returning an object reference to the client
- // validate it first.
- CORBA::Object_ptr object = replica_info->replica.in ();
-
- {
- ACE_Reverse_Lock<TAO_SYNCH_MUTEX> reverse_lock (entry->lock);
-
- ACE_GUARD_RETURN (ACE_Reverse_Lock<TAO_SYNCH_MUTEX>,
- reverse_guard,
- reverse_lock,
- CORBA::Object::_nil ());
-
- // @@ Ossama: we should setup a timeout policy here...
- ACE_TRY
- {
- CORBA::Boolean non_existent =
- object->_non_existent (ACE_ENV_SINGLE_ARG_PARAMETER);
- ACE_TRY_CHECK;
- if (!non_existent)
- {
- return CORBA::Object::_duplicate (object);
- }
- }
- ACE_CATCHANY
- {
- // @@ HACK! Do the right thing!
- return CORBA::Object::_duplicate (object);
- }
- ACE_ENDTRY;
- }
}
-}
-
-void
-TAO_LB_LeastLoaded::analyze_loads (
- TAO_LB_Location_Map &location_map
- ACE_ENV_ARG_DECL)
-{
- int send_load_advisory = 0;
-
- {
- ACE_MT (ACE_GUARD (TAO_SYNCH_MUTEX,
- guard,
- this->lock_));
-
-
- TAO_LB_Location_Map::iterator begin =
- location_map.begin ();
-
- TAO_LB_Location_Map::iterator end =
- location_map.end ();
-
- float s = 0;
- CORBA::ULong n = 0;
- TAO_LB_Location_Map::iterator i = begin;
- for ( ; i != end; ++i)
- {
- s += (*i)->int_id_.load_list[0].value; // @@ Hard coded to
- // get things
- // going.
- n++;
- }
-
- float avg = (n == 0 ? s : s / n);
- float cl = proxy->current_load ();
-
- if (avg == 0)
- return;
-
- float relative_load = cl / avg;
-
- // @@ Ossama: Make the 1.5 factor adjustable, it is how much
- // dispersion we tolerate before starting to send advisories.
- if (relative_load > 1 + 1.5F / n)
- {
- proxy->has_high_load_ = 1;
- send_load_advisory = 2; // 2 == Send high load advisory
- }
-
- if (send_load_advisory == 1 && relative_load < 1 + 0.9F / n)
- {
- proxy->has_high_load_ = 0;
- send_load_advisory = 1; // 1 == Send nominal load advisory
- }
- }
-
- // @@ Ossama: no debug messages in production code, my fault....
- // ACE_DEBUG ((LM_DEBUG, "Load[%x] %f %f %f\n",
- // proxy, cl, avg, relative_load));
-
- // @@ Ossama: Make the 1.5 factor adjustable, it is how much
- // dispersion we tolerate before starting to send advisories.
- if (send_load_advisory == 2)
- {
- proxy->control_->high_load_advisory (ACE_ENV_SINGLE_ARG_PARAMETER);
- ACE_CHECK;
- return; // We may not throw an exception, so explicitly return.
- }
+ if (found_location)
+ location = locations[location_index];
- // @@ Ossama: notice that we wait until the load is signifcantly
- // lower before sending the nominal load advisory, it does not
- // matter that much because the replicas automatically restart after
- // rejecting one client....
- // @@ Ossama: make the 0.9 factor adjustable, at least at
- // construction time...
- if (send_load_advisory == 1)
- {
- proxy->control_->nominal_load_advisory (ACE_ENV_SINGLE_ARG_PARAMETER);
- ACE_CHECK;
- }
+ return found_location;
}
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.h b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.h
index fd74cd698d3..25c2ae91240 100644
--- a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.h
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.h
@@ -22,10 +22,24 @@
# pragma once
# endif /* ACE_LACKS_PRAGMA_ONCE */
-#include "orbsvcs/CosLoadBalancingS.h"
+#include "orbsvcs/CosLoadBalancingC.h"
#include "ace/Synch.h"
+namespace TAO_LB
+{
+ /**
+ * @name Default LeastLoaded strategy parameters.
+ *
+ * Defaults defined by the Load Balancing specification.
+ */
+ const CORBA::Float LL_DEFAULT_CRITICAL_THRESHOLD = 0;
+ const CORBA::Float LL_DEFAULT_REJECT_THRESHOLD = 0;
+ const CORBA::Float LL_DEFAULT_TOLERANCE = 1;
+ const CORBA::Float LL_DEFAULT_DAMPENING = 0;
+ const CORBA::Float LL_DEFAULT_PER_BALANCE_LOAD = 0;
+}
+
/**
* @class TAO_LB_LeastLoaded
*
@@ -34,16 +48,21 @@
* This load balancing strategy is designed to select an object group
* member residing at a location with the smallest load.
*/
-class TAO_LoadBalancing_Export TAO_LB_LeastLoaded
- : public virtual POA_CosLoadBalancing::Strategy
+class TAO_LB_LeastLoaded
+ : public virtual CosLoadBalancing::Strategy,
+ public virtual CORBA::LocalObject
{
public:
- typedef TAO_LB_LoadMap LoadMap;
/// Constructor.
- TAO_LB_LeastLoaded (void);
-
- /// Destructor
+ TAO_LB_LeastLoaded (
+ CORBA::Float critical_threshold = TAO_LB::LL_DEFAULT_CRITICAL_THRESHOLD,
+ CORBA::Float reject_threshold = TAO_LB::LL_DEFAULT_REJECT_THRESHOLD,
+ CORBA::Float tolerance = TAO_LB::LL_DEFAULT_TOLERANCE,
+ CORBA::Float dampening = TAO_LB::LL_DEFAULT_DAMPENING,
+ CORBA::Float per_balance_load = TAO_LB::LL_DEFAULT_PER_BALANCE_LOAD);
+
+ /// Destructor.
~TAO_LB_LeastLoaded (void);
/**
@@ -73,42 +92,42 @@ public:
PortableGroup::ObjectGroupNotFound,
PortableGroup::MemberNotFound));
- virtual void analyze_loads (
- PortableGroup::ObjectGroup_ptr object_group,
- CosLoadBalancing::LoadManager_ptr load_manager
- ACE_ENV_ARG_DECL_WITH_DEFAULTS)
- ACE_THROW_SPEC ((CORBA::SystemException));
+// virtual void analyze_loads (
+// PortableGroup::ObjectGroup_ptr object_group,
+// CosLoadBalancing::LoadManager_ptr load_manager
+// ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+// ACE_THROW_SPEC ((CORBA::SystemException));
//@}
protected:
/// Retrieve the least loaded location from the given list of
/// locations.
- CORBA::Boolean get_location (const PortableGroup::Locations & locations,
+ CORBA::Boolean get_location (PortableGroup::ObjectGroup_ptr object_group,
+ CosLoadBalancing::LoadManager_ptr load_manager,
+ const PortableGroup::Locations & locations,
PortableGroup::Location & location);
-
/// Return the effective load.
CORBA::Float effective_load (CORBA::Float previous_load,
CORBA::Float new_load);
- ///
- void push_load (
+ /// Push the new load into this Strategy's load processor, and
+ /// return the corresponding effective load.
+ void push_loads (
const PortableGroup::Location & the_location,
- const CosLoadBalancing::Load & new_load
+ const CosLoadBalancing::LoadList & loads,
CosLoadBalancing::Load & effective_load
- ACE_ENV_ARG_DECL)
- ACE_THROW_SPEC ((CORBA::SystemException));
-
+ ACE_ENV_ARG_DECL);
private:
- /// Container that maps location to load list.
- LoadMap load_map_;
+ /// Table that maps location to load list.
+ TAO_LB_LoadMap * load_map_;
/// Lock used to ensure atomic access to state retained by this
/// class.
- TAO_SYNCH_MUTEX lock_;
+ TAO_SYNCH_MUTEX * lock_;
CORBA::Float critical_threshold_;
CORBA::Float reject_threshold_;
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.inl b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.inl
index d2d3dc420cd..cb650c93ba0 100644
--- a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.inl
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.inl
@@ -2,19 +2,6 @@
//
// $Id$
-ACE_INLINE CORBA::Float
-TAO_LB_LeastLoaded::raw_load (CORBA::Float load)
-{
- return this->dampened_load (load + this->per_balance_load_);
-}
-
-
-ACE_INLINE CORBA::Float
-TAO_LB_LeastLoaded::raw_load (CORBA::Float load)
-{
- return this->dampened_load (load + this->per_balance_load_);
-}
-
ACE_INLINE CORBA::Float
TAO_LB_LeastLoaded::effective_load (CORBA::Float previous_load,
@@ -29,8 +16,8 @@ TAO_LB_LeastLoaded::effective_load (CORBA::Float previous_load,
ACE_ASSERT (this->tolerance_ != 0);
- // Compute th effective load.
- result = raw_load / this->tolerance_;
+ // Compute the effective load.
+ result /= this->tolerance_;
return result;
}
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlert.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlert.cpp
new file mode 100644
index 00000000000..c46a044c271
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlert.cpp
@@ -0,0 +1,35 @@
+#include "LB_LoadAlert.h"
+
+
+ACE_RCSID (LoadBalancer,
+ LB_LoadAlert,
+ "$Id$")
+
+#if !defined (__ACE_INLINE__)
+# include "LB_LoadAlert.inl"
+#endif /* __ACE_INLINE__ */
+
+TAO_LB_LoadAlert::TAO_LB_LoadAlert (void)
+ : alerted_ (0),
+ forward_ ()
+{
+}
+
+TAO_LB_LoadAlert::~TAO_LB_LoadAlert (void)
+{
+}
+
+void
+TAO_LB_LoadAlert::enable_alert (CORBA::Object /* object_group */
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->alerted_ = 1;
+}
+
+void
+TAO_LB_LoadAlert::disable_alert (ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->alerted_ = 0;
+}
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlert.h b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlert.h
new file mode 100644
index 00000000000..0f8001ec47d
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlert.h
@@ -0,0 +1,90 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file LB_LoadAlert.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_LB_LOAD_ALERT_H
+#define TAO_LB_LOAD_ALERT_H
+
+#include "ace/pre.h"
+
+#include "orbsvcs/CosLoadBalancingS.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroupC.h"
+
+
+class TAO_LoadBalancing_Export TAO_LB_LoadAlert
+ : public virtual POA_CosLoadBalancing::LoadAlert,
+ public virtual PortableServer::RefCountServantBase
+{
+public:
+
+ /// Constructor.
+ TAO_LB_LoadAlert (void);
+
+ /**
+ * @name CosLoadBalancing::LoadAlert Methods
+ *
+ * Methods required by the CosLoadBalancing::LoadAlert interface.
+ */
+ //@{
+
+ /// Forward requests back to the load manager via the object group
+ /// reference.
+ virtual void enable_alert (CORBA::Object object_group
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /// Stop forwarding requests, and begin accepting them again.
+ virtual void disable_alert (ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ //@}
+
+ /// Has this LoadAlert servant been alerted of a high load condition
+ /// by the LoadManager.
+ CORBA::Boolean alerted (void) const;
+
+ CORBA::Object_ptr forward (void);
+
+protected:
+
+ /// Destructor.
+ /**
+ * Protected destructor to enforce correct memory management via
+ * reference counting.
+ */
+ ~TAO_LB_LoadAlert (void);
+
+private:
+
+ /// Has this LoadAlert servant been alerted of a high load condition
+ /// by the LoadManager?
+ CORBA::Boolean alerted_;
+
+ /// Reference to the object which clients will be forwarded to if an
+ /// "alert" condition exists.
+ CORBA::Object_var forward_;
+
+};
+
+
+#if defined (__ACE_INLINE__)
+# include "LB_LoadAlert.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+
+#endif /* TAO_LB_LOAD_ALERT_H */
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlert.inl b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlert.inl
new file mode 100644
index 00000000000..2099eae3096
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlert.inl
@@ -0,0 +1,15 @@
+// -*- C++ -*-
+//
+// $Id$
+
+ACE_INLINE CORBA::Boolean
+TAO_LB_LoadAlert::alerted (void) const
+{
+ return this->alerted_;
+}
+
+ACE_INLINE CORBA::Object_ptr
+TAO_LB_LoadAlert::forward (void)
+{
+ return CORBA::Object::_duplicate (this->forward_.in ());
+}
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlertInfo.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlertInfo.cpp
new file mode 100644
index 00000000000..48dc8296aa8
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlertInfo.cpp
@@ -0,0 +1,36 @@
+#include "LB_LoadAlertInfo.h"
+#include "orbsvcs/PortableGroup/PG_Operators.h"
+
+ACE_RCSID (LoadBalancing,
+ LB_LoadAlertInfo,
+ "$Id$")
+
+TAO_LB_LoadAlertInfo::TAO_LB_LoadAlertInfo (void)
+ : load_alert (),
+ location (),
+ alerted (0)
+{
+}
+
+int
+TAO_LB_LoadAlertInfo::operator== (const TAO_LB_LoadAlertInfo & rhs)
+{
+ // For the purposes of the LoadAlert info set, only the location is
+ // important.
+ return this->location == rhs.location;
+}
+
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+
+template class ACE_Node<TAO_LB_LoadAlertInfo>;
+template class ACE_Unbounded_Set<TAO_LB_LoadAlertInfo>;
+template class ACE_Unbounded_Set_Iterator<TAO_LB_LoadAlertInfo>;
+
+#elif defined(ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+
+#pragma instantiate ACE_Node<TAO_LB_LoadAlertInfo>
+#pragma instantiate ACE_Unbounded_Set<TAO_LB_LoadAlertInfo>
+#pragma instantiate ACE_Unbounded_Set_Iterator<TAO_LB_LoadAlertInfo>
+
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlertInfo.h b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlertInfo.h
new file mode 100644
index 00000000000..93a7ae4b9f6
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlertInfo.h
@@ -0,0 +1,67 @@
+// -*- C++ -*-
+
+//=======================================================================
+/**
+ * @file LB_LoadAlertInfo.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=======================================================================
+
+
+#ifndef TAO_LB_LOAD_ALERT_INFO_H
+#define TAO_LB_LOAD_ALERT_INFO_H
+
+#include "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/CosLoadBalancingC.h"
+
+
+/**
+ * @class TAO_LB_LoadAlertInfo
+ *
+ * @brief Structure that contains all LoadAlert-specific information.
+ *
+ * Structure that contains all LoadAlert-specific information.
+ */
+struct TAO_LB_LoadAlertInfo
+{
+ /// Constructor.
+ TAO_LB_LoadAlertInfo (void);
+
+ /// Reference to the LoadAlert object.
+ CosLoadBalancing::LoadAlert_var load_alert;
+
+ /// The location at which the member resides.
+ PortableGroup::Location location;
+
+ /// True if the LoadAlert object has been alerted about a given load
+ /// condition. False otherwise.
+ CORBA::Boolean alerted;
+
+ /// Equality operator.
+ /**
+ * For the purposes of the LoadAlert info set, only the location is
+ * important. In particular, if a LoadAlert object already resides
+ * at the given location for a particular object group, this
+ * equality operator will return true.
+ */
+ int operator== (const TAO_LB_LoadAlertInfo & rhs);
+
+};
+
+
+typedef ACE_Unbounded_Set<TAO_LB_LoadAlertInfo> TAO_LB_LoadAlertInfoSet;
+
+
+#include "ace/post.h"
+
+#endif /* TAO_LB_LOAD_ALERT_INFO_H */
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlertMap.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlertMap.cpp
new file mode 100644
index 00000000000..878de1e4d2f
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlertMap.cpp
@@ -0,0 +1,27 @@
+// -*- C++ -*-
+
+#include "LB_LoadAlertMap.h"
+
+
+ACE_RCSID (LoadBalancing,
+ LB_LoadAlertMap,
+ "$Id$")
+
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+
+template class ACE_Hash_Map_Entry<ACE_UINT32, TAO_LB_LoadAlertInfoSet>;
+template class ACE_Hash_Map_Manager_Ex<ACE_UINT32, TAO_LB_LoadAlertInfoSet, ACE_Hash<ACE_UINT32>, ACE_Equal_To<ACE_UINT32>, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Iterator_Base_Ex<ACE_UINT32, TAO_LB_LoadAlertInfoSet, ACE_Hash<ACE_UINT32>, ACE_Equal_To<ACE_UINT32>, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Iterator_Ex<ACE_UINT32, TAO_LB_LoadAlertInfoSet, ACE_Hash<ACE_UINT32>, ACE_Equal_To<ACE_UINT32>, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Reverse_Iterator_Ex<ACE_UINT32, TAO_LB_LoadAlertInfoSet, ACE_Hash<ACE_UINT32>, ACE_Equal_To<ACE_UINT32>, ACE_Null_Mutex>;
+
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+
+#pragma instantiate ACE_Hash_Map_Entry<ACE_UINT32, TAO_LB_LoadAlertInfoSet>
+#pragma instantiate ACE_Hash_Map_Manager_Ex<ACE_UINT32, TAO_LB_LoadAlertInfoSet, ACE_Hash<ACE_UINT32>, ACE_Equal_To<ACE_UINT32>, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<ACE_UINT32, TAO_LB_LoadAlertInfoSet, ACE_Hash<ACE_UINT32>, ACE_Equal_To<ACE_UINT32>, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Iterator_Ex<ACE_UINT32, TAO_LB_LoadAlertInfoSet, ACE_Hash<ACE_UINT32>, ACE_Equal_To<ACE_UINT32>, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<ACE_UINT32, TAO_LB_LoadAlertInfoSet, ACE_Hash<ACE_UINT32>, ACE_Equal_To<ACE_UINT32>, ACE_Null_Mutex>
+
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlertMap.h b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlertMap.h
new file mode 100644
index 00000000000..79e2e6bac53
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAlertMap.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+
+//=======================================================================
+/**
+ * @file LB_LoadAlertMap.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=======================================================================
+
+
+#ifndef TAO_LB_LOAD_ALERT_MAP_H
+#define TAO_LB_LOAD_ALERT_MAP_H
+
+#include "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "LB_LoadAlertInfo.h"
+
+#include "tao/PortableServer/Key_Adapters.h"
+#include "tao/PortableServer/PortableServerC.h"
+
+#include "ace/Hash_Map_Manager_T.h"
+
+
+/// LoadAlertInfo hash map typedef.
+typedef ACE_Hash_Map_Manager_Ex<
+ ACE_UINT32,
+ TAO_LB_LoadAlertInfoSet,
+ ACE_Hash<ACE_UINT32>,
+ ACE_Equal_To<ACE_UINT32>,
+ ACE_Null_Mutex> TAO_LB_LoadAlertMap;
+
+
+#include "ace/post.h"
+
+#endif /* TAO_LB_LOAD_ALERT_MAP_H */
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadListMap.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadListMap.cpp
new file mode 100644
index 00000000000..75ed8e3a833
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadListMap.cpp
@@ -0,0 +1,26 @@
+// -*- C++ -*-
+
+#include "LB_LoadListMap.h"
+
+ACE_RCSID (LoadBalancing,
+ LB_LoadListMap,
+ "$Id$")
+
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+
+template class ACE_Hash_Map_Entry<PortableGroup::Location, CosLoadBalancing::LoadList>;
+template class ACE_Hash_Map_Manager_Ex<PortableGroup::Location, CosLoadBalancing::LoadList, TAO_PG_Location_Hash, TAO_PG_Location_Equal_To, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Iterator_Base_Ex<PortableGroup::Location, CosLoadBalancing::LoadList, TAO_PG_Location_Hash, TAO_PG_Location_Equal_To, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Iterator_Ex<PortableGroup::Location, CosLoadBalancing::LoadList, TAO_PG_Location_Hash, TAO_PG_Location_Equal_To, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Reverse_Iterator_Ex<PortableGroup::Location, CosLoadBalancing::LoadList, TAO_PG_Location_Hash, TAO_PG_Location_Equal_To, ACE_Null_Mutex>;
+
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+
+#pragma instantiate ACE_Hash_Map_Entry<PortableGroup::Location, CosLoadBalancing::LoadList>
+#pragma instantiate ACE_Hash_Map_Manager_Ex<PortableGroup::Location, CosLoadBalancing::LoadList, TAO_PG_Location_Hash, TAO_PG_Location_Equal_To, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<PortableGroup::Location, CosLoadBalancing::LoadList, TAO_PG_Location_Hash, TAO_PG_Location_Equal_To, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Iterator_Ex<PortableGroup::Location, CosLoadBalancing::LoadList, TAO_PG_Location_Hash, TAO_PG_Location_Equal_To, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<PortableGroup::Location, CosLoadBalancing::LoadList, TAO_PG_Location_Hash, TAO_PG_Location_Equal_To, ACE_Null_Mutex>
+
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadListMap.h b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadListMap.h
new file mode 100644
index 00000000000..7382bcda92d
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadListMap.h
@@ -0,0 +1,43 @@
+// -*- C++ -*-
+
+//=======================================================================
+/**
+ * @file LB_LoadListMap.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=======================================================================
+
+
+#ifndef TAO_LB_LOAD_LIST_MAP_H
+#define TAO_LB_LOAD_LIST_MAP_H
+
+#include "ace/pre.h"
+
+#include "orbsvcs/CosLoadBalancingC.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroupC.h"
+
+#include "orbsvcs/PortableGroup/PG_Location_Hash.h"
+#include "orbsvcs/PortableGroup/PG_Location_Equal_To.h"
+
+#include "ace/Hash_Map_Manager_T.h"
+
+
+/// LoadList hash map.
+typedef ACE_Hash_Map_Manager_Ex<
+ PortableGroup::Location,
+ CosLoadBalancing::LoadList,
+ TAO_PG_Location_Hash,
+ TAO_PG_Location_Equal_To,
+ ACE_Null_Mutex> TAO_LB_LoadListMap;
+
+#include "ace/post.h"
+
+#endif /* TAO_LB_LOAD_LIST_MAP_H */
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadManager.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadManager.cpp
index 568d2834c52..c0f95b2023c 100644
--- a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadManager.cpp
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadManager.cpp
@@ -1,14 +1,17 @@
#include "LB_LoadManager.h"
#include "LB_MemberLocator.h"
+#include "LB_LoadAlert_Handler.h"
+#include "LB_RoundRobin.h"
+#include "LB_Random.h"
+#include "LB_LeastLoaded.h"
#include "LB_conf.h"
#include "orbsvcs/PortableGroup/PG_Property_Utils.h"
#include "orbsvcs/PortableGroup/PG_conf.h"
-#include "tao/ORB_Core.h"
-
-//#include "ace/Auto_Ptr.h"
+#include "tao/Messaging/Messaging.h"
+#include "tao/debug.h"
ACE_RCSID (LoadBalancing,
LB_LoadManager,
@@ -18,36 +21,404 @@ ACE_RCSID (LoadBalancing,
TAO_LB_LoadManager::TAO_LB_LoadManager (void)
: reactor_ (0),
poa_ (),
+ monitor_lock_ (),
+ load_lock_ (),
+ load_alert_lock_ (),
lock_ (),
monitor_map_ (TAO_PG_MAX_LOCATIONS),
+ load_map_ (TAO_PG_MAX_LOCATIONS),
+ load_alert_map_ (TAO_PG_MAX_OBJECT_GROUPS),
object_group_manager_ (),
property_manager_ (object_group_manager_),
generic_factory_ (object_group_manager_, property_manager_),
pull_handler_ (),
timer_id_ (-1),
- lm_ref_ ()
+ lm_ref_ (),
+ round_robin_ (0),
+ random_ (0),
+ least_loaded_ (0),
+ built_in_balancing_strategy_name_ (1),
+ custom_balancing_strategy_name_ (1)
{
this->pull_handler_.initialize (&this->monitor_map_, this);
+
+ // @note "this->init()" is not called here (in the constructor)
+ // since it may thrown in an exception. Throwing an exception
+ // in a constructor in an emulated exception environment is
+ // problematic since native exception semantics cannot be
+ // reproduced in such a case. As such, init() must be called
+ // by whatever code instantiates this LoadManager.
}
TAO_LB_LoadManager::~TAO_LB_LoadManager (void)
{
+ delete this->round_robin_;
+ delete this->random_;
+ delete this->least_loaded_;
}
void
TAO_LB_LoadManager::push_loads (
- const PortableGroup::Location & /* the_location */,
- const CosLoadBalancing::LoadList & /* loads */
+ const PortableGroup::Location & the_location,
+ const CosLoadBalancing::LoadList & loads
ACE_ENV_ARG_DECL)
ACE_THROW_SPEC ((CORBA::SystemException))
{
-#if 0
- // Only the first load is used by this load balancing strategy.
if (loads.length () == 0)
ACE_THROW (CORBA::BAD_PARAM ());
-#endif /* 0 */
- ACE_THROW (CORBA::NO_IMPLEMENT ());
+ ACE_GUARD (TAO_SYNCH_MUTEX,
+ guard,
+ this->load_lock_);
+
+ if (this->load_map_.rebind (the_location, loads) == -1)
+ ACE_THROW (CORBA::INTERNAL ());
+}
+
+CosLoadBalancing::LoadList *
+TAO_LB_LoadManager::get_loads (const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ CosLoadBalancing::LocationNotFound))
+{
+ CosLoadBalancing::LoadList * tmp;
+ ACE_NEW_THROW_EX (tmp,
+ CosLoadBalancing::LoadList,
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO_DEFAULT_MINOR_CODE,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (0);
+
+ CosLoadBalancing::LoadList_var loads = tmp;
+
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->load_lock_,
+ 0);
+
+ if (this->load_map_.find (the_location, *tmp) == 0)
+ return loads._retn ();
+ else
+ ACE_THROW_RETURN (CosLoadBalancing::LocationNotFound (), 0);
+}
+
+void
+TAO_LB_LoadManager::enable_alert (PortableGroup::ObjectGroup_ptr object_group,
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((PortableGroup::ObjectGroupNotFound,
+ CosLoadBalancing::LoadAlertNotFound))
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->load_alert_lock_);
+
+ // TAO's PortableGroup library only uses the lower 32 bits of the
+ // ObjectGroupId, so this cast is safe.
+ ACE_UINT32 group_id =
+ ACE_static_cast (ACE_UINT32,
+ this->get_object_group_id (object_group
+ ACE_ENV_ARG_PARAMETER));
+ ACE_CHECK;
+
+ TAO_LB_LoadAlertMap::ENTRY * entry;
+ if (this->load_alert_map_.find (group_id, entry) == 0)
+ {
+ // A LoadAlert list for the given ObjectGroup exists. Find the
+ // reference to the LoadAlert object residing at the given
+ // location.
+ TAO_LB_LoadAlertInfoSet & alert_set = entry->int_id_;
+
+ TAO_LB_LoadAlertInfoSet::iterator end =
+ alert_set.end ();
+
+ for (TAO_LB_LoadAlertInfoSet::iterator i = alert_set.begin ();
+ i != end;
+ ++i)
+ {
+ if ((*i).location == the_location)
+ {
+ // Duplicate before releasing the LoadAlertMap lock to
+ // prevent a race condition from occuring. The
+ // LoadAlertInfoSet may be altered prior to invoking an
+ // operation on the LoadAlert object.
+ CosLoadBalancing::LoadAlert_var load_alert =
+ CosLoadBalancing::LoadAlert::_duplicate (
+ (*i).load_alert.in ());
+
+ // The alert condition will be enabled.
+ // @note There is a subtle problem here. If the below
+ // remote invocation fails, this variable will be
+ // incorrectly to "true."
+ (*i).alerted = 1;
+
+ // Release the lock prior to making the below remote
+ // invocation.
+ ACE_Reverse_Lock<TAO_SYNCH_MUTEX> reverse_lock (
+ this->load_alert_lock_);
+ ACE_GUARD (ACE_Reverse_Lock<TAO_SYNCH_MUTEX>,
+ reverse_guard,
+ reverse_lock);
+
+ // Use AMI to make the following operation
+ // "non-blocking," allowing the caller to continue
+ // without being forced to wait for a response.
+ load_alert->sendc_enable_alert (this->load_alert_handler_.in (),
+ object_group
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ return;
+ }
+ }
+
+ ACE_THROW (CosLoadBalancing::LoadAlertNotFound ());
+ }
+ else
+ {
+ ACE_THROW (PortableGroup::ObjectGroupNotFound ());
+ }
+}
+
+void
+TAO_LB_LoadManager::disable_alert (PortableGroup::ObjectGroup_ptr object_group,
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((PortableGroup::ObjectGroupNotFound,
+ CosLoadBalancing::LoadAlertNotFound))
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->load_alert_lock_);
+
+ // TAO's PortableGroup library only uses the lower 32 bits of the
+ // ObjectGroupId, so this cast is safe.
+ ACE_UINT32 group_id =
+ ACE_static_cast (ACE_UINT32,
+ this->get_object_group_id (object_group
+ ACE_ENV_ARG_PARAMETER));
+ ACE_CHECK;
+
+ TAO_LB_LoadAlertMap::ENTRY * entry;
+ if (this->load_alert_map_.find (group_id, entry) == 0)
+ {
+ // A LoadAlert list for the given ObjectGroup exists. Find the
+ // reference to the LoadAlert object residing at the given
+ // location.
+ TAO_LB_LoadAlertInfoSet & alert_set = entry->int_id_;
+
+ TAO_LB_LoadAlertInfoSet::iterator end =
+ alert_set.end ();
+
+ for (TAO_LB_LoadAlertInfoSet::iterator i = alert_set.begin ();
+ i != end;
+ ++i)
+ {
+ // Only perform a remote invocation if the LoadAlert object
+ // was previously alerted.
+ if ((*i).location == the_location && (*i).alerted)
+ {
+ // Duplicate before releasing the LoadAlertMap lock to
+ // prevent a race condition on the iterator from
+ // occuring. The LoadAlertInfoSet may be altered prior
+ // to invoking an operation on the LoadAlert object.
+ CosLoadBalancing::LoadAlert_var load_alert =
+ CosLoadBalancing::LoadAlert::_duplicate (
+ (*i).load_alert.in ());
+
+ // @note There is a subtle problem here. If the below
+ // remote invocation fails, this variable will be
+ // incorrectly to "false."
+ (*i).alerted = 0; // The alert condition will be disabled.
+
+ // Release the lock prior to making the below remote
+ // invocation.
+ ACE_Reverse_Lock<TAO_SYNCH_MUTEX> reverse_lock (
+ this->load_alert_lock_);
+ ACE_GUARD (ACE_Reverse_Lock<TAO_SYNCH_MUTEX>,
+ reverse_guard,
+ reverse_lock);
+
+ // Use AMI to make the following operation
+ // "non-blocking," allowing the caller to continue
+ // without being forced to wait for a response.
+ load_alert->sendc_disable_alert (this->load_alert_handler_.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ return;
+ }
+ }
+
+ ACE_THROW (CosLoadBalancing::LoadAlertNotFound ());
+ }
+ else
+ {
+ ACE_THROW (PortableGroup::ObjectGroupNotFound ());
+ }
+}
+
+void
+TAO_LB_LoadManager::register_load_alert (
+ PortableGroup::ObjectGroup_ptr object_group,
+ const PortableGroup::Location & the_location,
+ CosLoadBalancing::LoadAlert_ptr load_alert
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound,
+ CosLoadBalancing::LoadAlertAlreadyPresent,
+ CosLoadBalancing::LoadAlertNotAdded))
+{
+ if (CORBA::is_nil (load_alert))
+ ACE_THROW (CORBA::BAD_PARAM ());
+
+ // @todo Verify that a member of the given object group actually
+ // exists at "the_location." It doesn't make much sense to
+ // register a LoadAlert object for a non-existent member.
+
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->load_alert_lock_);
+
+ // TAO's PortableGroup library only uses the lower 32 bits of the
+ // ObjectGroupId, so this cast is safe.
+ ACE_UINT32 group_id =
+ ACE_static_cast (ACE_UINT32,
+ this->get_object_group_id (object_group
+ ACE_ENV_ARG_PARAMETER));
+ ACE_CHECK;
+
+ TAO_LB_LoadAlertMap::ENTRY * entry;
+ if (this->load_alert_map_.find (group_id, entry) == 0)
+ {
+ // A LoadAlert list for the given ObjectGroup exists. Verify
+ // that no LoadAlert object for the member residing at the given
+ // location exists.
+
+ TAO_LB_LoadAlertInfoSet & alert_set = entry->int_id_;
+
+ TAO_LB_LoadAlertInfoSet::iterator end =
+ alert_set.end ();
+
+ for (TAO_LB_LoadAlertInfoSet::iterator i = alert_set.begin ();
+ i != end;
+ ++i)
+ {
+ if ((*i).location == the_location)
+ ACE_THROW (CosLoadBalancing::LoadAlertAlreadyPresent ());
+ }
+
+ TAO_LB_LoadAlertInfo load_alert_info;
+ load_alert_info.load_alert =
+ CosLoadBalancing::LoadAlert::_duplicate (load_alert);
+ load_alert_info.location = the_location;
+
+ if (alert_set.insert_tail (load_alert_info) != 0)
+ ACE_THROW (CosLoadBalancing::LoadAlertNotAdded ());
+ }
+ else
+ {
+ // No LoadAlert list exists for the given ObjectGroup. Create
+ // one and insert its initial member.
+
+ TAO_LB_LoadAlertInfo load_alert_info;
+ load_alert_info.load_alert =
+ CosLoadBalancing::LoadAlert::_duplicate (load_alert);
+ load_alert_info.location = the_location;
+
+ TAO_LB_LoadAlertInfoSet alert_set;
+ if (alert_set.insert_tail (load_alert_info) != 0
+ || this->load_alert_map_.bind (group_id, alert_set) != 0)
+ ACE_THROW (CosLoadBalancing::LoadAlertNotAdded ());
+ }
+}
+
+CosLoadBalancing::LoadAlert_ptr
+TAO_LB_LoadManager::get_load_alert (
+ PortableGroup::ObjectGroup_ptr object_group,
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound,
+ CosLoadBalancing::LoadAlertNotFound))
+{
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->load_alert_lock_,
+ CosLoadBalancing::LoadAlert::_nil ());
+
+ // TAO's PortableGroup library only uses the lower 32 bits of the
+ // ObjectGroupId, so this cast is safe.
+ ACE_UINT32 group_id =
+ ACE_static_cast (ACE_UINT32,
+ this->get_object_group_id (object_group
+ ACE_ENV_ARG_PARAMETER));
+ ACE_CHECK_RETURN (CosLoadBalancing::LoadAlert::_nil ());
+
+ TAO_LB_LoadAlertMap::ENTRY * entry;
+ if (this->load_alert_map_.find (group_id, entry) == 0)
+ {
+ // A LoadAlert list for the given ObjectGroup exists. Find the
+ // LoadAlert object for the member residing at the given
+ // location.
+
+ TAO_LB_LoadAlertInfoSet & alert_set = entry->int_id_;
+
+ TAO_LB_LoadAlertInfoSet::iterator end =
+ alert_set.end ();
+
+ for (TAO_LB_LoadAlertInfoSet::iterator i = alert_set.begin ();
+ i != end;
+ ++i)
+ {
+ if ((*i).location == the_location)
+ return
+ CosLoadBalancing::LoadAlert::_duplicate ((*i).load_alert.in ());
+ }
+
+ ACE_THROW_RETURN (CosLoadBalancing::LoadAlertNotFound (),
+ CosLoadBalancing::LoadAlert::_nil ());
+ }
+ else
+ ACE_THROW_RETURN (PortableGroup::ObjectGroupNotFound (),
+ CosLoadBalancing::LoadAlert::_nil ());
+}
+
+void
+TAO_LB_LoadManager::remove_load_alert (
+ PortableGroup::ObjectGroup_ptr object_group,
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound,
+ CosLoadBalancing::LoadAlertNotFound))
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->load_alert_lock_);
+
+ // TAO's PortableGroup library only uses the lower 32 bits of the
+ // ObjectGroupId, so this cast is safe.
+ ACE_UINT32 group_id =
+ ACE_static_cast (ACE_UINT32,
+ this->get_object_group_id (object_group
+ ACE_ENV_ARG_PARAMETER));
+ ACE_CHECK;
+
+ TAO_LB_LoadAlertMap::ENTRY * entry;
+ if (this->load_alert_map_.find (group_id, entry) == 0)
+ {
+ // A LoadAlert list for the given ObjectGroup exists. Find the
+ // LoadAlert object for the member residing at the given
+ // location.
+
+ TAO_LB_LoadAlertInfoSet & alert_set = entry->int_id_;
+
+ TAO_LB_LoadAlertInfo alert_info;
+ alert_info.location = the_location;
+ // No need to set the LoadAlert member. It isn't used in
+ // comparisons.
+
+ if (alert_set.remove (alert_info) != 0)
+ ACE_THROW (CosLoadBalancing::LoadAlertNotFound ());
+ }
+ else
+ ACE_THROW (PortableGroup::ObjectGroupNotFound ());
+
}
void
@@ -66,7 +437,7 @@ TAO_LB_LoadManager::register_load_monitor (
ACE_GUARD (TAO_SYNCH_MUTEX,
guard,
- this->lock_);
+ this->monitor_lock_);
int result = this->monitor_map_.bind (the_location, the_monitor);
@@ -116,7 +487,7 @@ TAO_LB_LoadManager::get_load_monitor (
{
ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
guard,
- this->lock_,
+ this->monitor_lock_,
CosLoadBalancing::LoadMonitor::_nil ());
TAO_LB_MonitorMap::ENTRY * entry;
@@ -139,7 +510,7 @@ TAO_LB_LoadManager::remove_load_monitor (
{
ACE_GUARD (TAO_SYNCH_MUTEX,
guard,
- this->lock_);
+ this->monitor_lock_);
if (this->monitor_map_.unbind (the_location) != 0)
ACE_THROW (CosLoadBalancing::LocationNotFound ());
@@ -171,6 +542,10 @@ TAO_LB_LoadManager::set_default_properties (
PortableGroup::InvalidProperty,
PortableGroup::UnsupportedProperty))
{
+ this->check_strategy_prop (props
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
this->property_manager_.set_default_properties (props
ACE_ENV_ARG_PARAMETER);
}
@@ -187,7 +562,7 @@ TAO_LB_LoadManager::get_default_properties (
void
TAO_LB_LoadManager::remove_default_properties (
- const PortableGroup::Properties &props
+ const PortableGroup::Properties & props
ACE_ENV_ARG_DECL)
ACE_THROW_SPEC ((CORBA::SystemException,
PortableGroup::InvalidProperty,
@@ -200,12 +575,16 @@ TAO_LB_LoadManager::remove_default_properties (
void
TAO_LB_LoadManager::set_type_properties (
const char *type_id,
- const PortableGroup::Properties &overrides
+ const PortableGroup::Properties & overrides
ACE_ENV_ARG_DECL)
ACE_THROW_SPEC ((CORBA::SystemException,
PortableGroup::InvalidProperty,
PortableGroup::UnsupportedProperty))
{
+ this->check_strategy_prop (overrides
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
this->property_manager_.set_type_properties (type_id,
overrides
ACE_ENV_ARG_PARAMETER);
@@ -225,7 +604,7 @@ TAO_LB_LoadManager::get_type_properties (
void
TAO_LB_LoadManager::remove_type_properties (
const char *type_id,
- const PortableGroup::Properties &props
+ const PortableGroup::Properties & props
ACE_ENV_ARG_DECL)
ACE_THROW_SPEC ((CORBA::SystemException,
PortableGroup::InvalidProperty,
@@ -239,13 +618,17 @@ TAO_LB_LoadManager::remove_type_properties (
void
TAO_LB_LoadManager::set_properties_dynamically (
PortableGroup::ObjectGroup_ptr object_group,
- const PortableGroup::Properties &overrides
+ const PortableGroup::Properties & overrides
ACE_ENV_ARG_DECL)
ACE_THROW_SPEC ((CORBA::SystemException,
PortableGroup::ObjectGroupNotFound,
PortableGroup::InvalidProperty,
PortableGroup::UnsupportedProperty))
{
+ this->check_strategy_prop (overrides
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
this->property_manager_.set_properties_dynamically (object_group,
overrides
ACE_ENV_ARG_PARAMETER);
@@ -266,9 +649,9 @@ TAO_LB_LoadManager::get_properties (
PortableGroup::ObjectGroup_ptr
TAO_LB_LoadManager::create_member (
PortableGroup::ObjectGroup_ptr object_group,
- const PortableGroup::Location &the_location,
- const char *type_id,
- const PortableGroup::Criteria &the_criteria
+ const PortableGroup::Location & the_location,
+ const char * type_id,
+ const PortableGroup::Criteria & the_criteria
ACE_ENV_ARG_DECL)
ACE_THROW_SPEC ((CORBA::SystemException,
PortableGroup::ObjectGroupNotFound,
@@ -289,7 +672,7 @@ TAO_LB_LoadManager::create_member (
PortableGroup::ObjectGroup_ptr
TAO_LB_LoadManager::add_member (
PortableGroup::ObjectGroup_ptr object_group,
- const PortableGroup::Location &the_location,
+ const PortableGroup::Location & the_location,
CORBA::Object_ptr member
ACE_ENV_ARG_DECL)
ACE_THROW_SPEC ((CORBA::SystemException,
@@ -307,7 +690,7 @@ TAO_LB_LoadManager::add_member (
PortableGroup::ObjectGroup_ptr
TAO_LB_LoadManager::remove_member (
PortableGroup::ObjectGroup_ptr object_group,
- const PortableGroup::Location &the_location
+ const PortableGroup::Location & the_location
ACE_ENV_ARG_DECL)
ACE_THROW_SPEC ((CORBA::SystemException,
PortableGroup::ObjectGroupNotFound,
@@ -358,7 +741,7 @@ TAO_LB_LoadManager::get_object_group_ref (
CORBA::Object_ptr
TAO_LB_LoadManager::get_member_ref (
PortableGroup::ObjectGroup_ptr object_group,
- const PortableGroup::Location &the_location
+ const PortableGroup::Location & the_location
ACE_ENV_ARG_DECL)
ACE_THROW_SPEC ((CORBA::SystemException,
PortableGroup::ObjectGroupNotFound,
@@ -463,8 +846,8 @@ TAO_LB_LoadManager::delete_object (
}
CORBA::Object_ptr
-TAO_LB_LoadManager::member (const PortableServer::ObjectId & oid
- ACE_ENV_ARG_DECL)
+TAO_LB_LoadManager::next_member (const PortableServer::ObjectId & oid
+ ACE_ENV_ARG_DECL)
{
// Pass the cached loads to the balancing strategy so that the
// strategy may choose which member to forward requests to next.
@@ -481,30 +864,38 @@ TAO_LB_LoadManager::member (const PortableServer::ObjectId & oid
ACE_ENV_ARG_PARAMETER);
ACE_CHECK_RETURN (CORBA::Object::_nil ());
- // @todo Cache this property name. No need to create it each time
- // this method is called.
- PortableGroup::Name balancing_strategy_name (1);
- balancing_strategy_name.length (1);
- balancing_strategy_name[0].id =
- CORBA::string_dup ("org.omg.CosLoadBalancing.Strategy");
-
+ // Prefer custom load balancing strategies over built-in ones.
PortableGroup::Value value;
CosLoadBalancing::Strategy_var balancing_strategy;
- if (TAO_PG::get_property_value (balancing_strategy_name,
- properties.in (),
- value)
- && (value >>= balancing_strategy.inout ())
- && !CORBA::is_nil (balancing_strategy.in ()))
+ const char * built_in; // Name of built-in Strategy
+ if ((TAO_PG::get_property_value (this->custom_balancing_strategy_name_,
+ properties.in (),
+ value)
+ && (value >>= balancing_strategy.inout ())
+ && !CORBA::is_nil (balancing_strategy.in ())))
{
- // @todo Cache this ObjectGroupManager reference.
- PortableGroup::ObjectGroupManager_var group_manager =
- this->object_group_manager_._this (ACE_ENV_SINGLE_ARG_PARAMETER);
- ACE_CHECK_RETURN (CORBA::Object::_nil ());
-
return balancing_strategy->next_member (object_group.in (),
this->lm_ref_.in ()
ACE_ENV_ARG_PARAMETER);
}
+ else if (TAO_PG::get_property_value (this->built_in_balancing_strategy_name_,
+ properties.in (),
+ value)
+ && (value >>= built_in))
+ {
+ balancing_strategy = this->built_in_strategy (built_in);
+ if (!CORBA::is_nil (balancing_strategy.in ()))
+ {
+ return balancing_strategy->next_member (object_group.in (),
+ this->lm_ref_.in ()
+ ACE_ENV_ARG_PARAMETER);
+ }
+ else
+ {
+ ACE_THROW_RETURN (CORBA::INTERNAL (),
+ CORBA::Object::_nil ());
+ }
+ }
else
{
ACE_THROW_RETURN (CORBA::OBJECT_NOT_EXIST (),
@@ -514,10 +905,13 @@ TAO_LB_LoadManager::member (const PortableServer::ObjectId & oid
void
TAO_LB_LoadManager::init (
- CORBA::ORB_ptr orb,
+ ACE_Reactor * reactor,
PortableServer::POA_ptr root_poa
ACE_ENV_ARG_DECL)
{
+ ACE_ASSERT (reactor != 0);
+ ACE_ASSERT (!CORBA::is_nil (root_poa));
+
ACE_GUARD (TAO_SYNCH_MUTEX,
guard,
this->lock_);
@@ -615,7 +1009,7 @@ TAO_LB_LoadManager::init (
poa_manager->activate (ACE_ENV_SINGLE_ARG_PARAMETER);
ACE_CHECK;
- this->reactor_ = orb->orb_core ()->reactor ();
+ this->reactor_ = reactor;
}
if (CORBA::is_nil (this->lm_ref_.in ()))
@@ -623,4 +1017,258 @@ TAO_LB_LoadManager::init (
this->lm_ref_ = this->_this (ACE_ENV_SINGLE_ARG_PARAMETER);
ACE_CHECK;
}
+
+ if (CORBA::is_nil (this->load_alert_handler_.in ()))
+ {
+ TAO_LB_LoadAlert_Handler * handler;
+ ACE_NEW_THROW_EX (handler,
+ TAO_LB_LoadAlert_Handler,
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO_DEFAULT_MINOR_CODE,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK;
+
+ PortableServer::ServantBase_var safe_handler = handler;
+
+ this->load_alert_handler_ =
+ handler->_this (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+
+ this->built_in_balancing_strategy_name_.length (1);
+ this->built_in_balancing_strategy_name_[0].id =
+ CORBA::string_dup ("org.omg.CosLoadBalancing.Strategy");
+
+ this->custom_balancing_strategy_name_.length (1);
+ this->custom_balancing_strategy_name_[0].id =
+ CORBA::string_dup ("org.omg.CosLoadBalancing.CustomStrategy");
+}
+
+ACE_INLINE CosLoadBalancing::Strategy_ptr
+TAO_LB_LoadManager::built_in_strategy (const char * strategy)
+{
+ ACE_ASSERT (strategy != 0);
+
+ CosLoadBalancing::Strategy_ptr s;
+
+ // @todo We should probably shove this code into a factory.
+
+ if (ACE_OS::strcmp ("RoundRobin", strategy) == 0)
+ {
+ // Double-checked locking
+ if (this->round_robin_ == 0)
+ {
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->lock_,
+ 0);
+
+ if (this->round_robin_ == 0)
+ {
+ ACE_NEW_RETURN (this->round_robin_,
+ TAO_LB_RoundRobin,
+ CosLoadBalancing::Strategy::_nil ());
+ }
+ }
+
+ s = this->round_robin_;
+ }
+
+ else if (ACE_OS::strcmp ("Random", strategy) == 0)
+ {
+ // Double-checked locking
+ if (this->random_ == 0)
+ {
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->lock_,
+ 0);
+
+ if (this->random_ == 0)
+ {
+ ACE_NEW_RETURN (this->random_,
+ TAO_LB_Random,
+ CosLoadBalancing::Strategy::_nil ());
+ }
+ }
+
+ s = this->random_;
+ }
+
+ else if (ACE_OS::strcmp ("LeastLoaded", strategy) == 0)
+ {
+ // Double-checked locking
+ if (this->least_loaded_ == 0)
+ {
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->lock_,
+ 0);
+
+ if (this->least_loaded_ == 0)
+ {
+ // Use default "LeastLoaded" properties.
+ ACE_NEW_RETURN (this->least_loaded_,
+ TAO_LB_LeastLoaded,
+ CosLoadBalancing::Strategy::_nil ());
+ }
+ }
+
+ s = this->least_loaded_;
+ }
+
+ else
+ {
+ if (TAO_debug_level > 0)
+ ACE_ERROR ((LM_ERROR,
+ "ERROR: TAO_LB_LoadManager::next_member - "
+ "Unknown/unexpected built-in Strategy:\n"
+ " \"%s\"\n",
+ strategy));
+
+ // This should never occur!
+ return CosLoadBalancing::Strategy::_nil ();
+ }
+
+ ACE_ASSERT (!CORBA::is_nil (s));
+
+ return CosLoadBalancing::Strategy::_duplicate (s);
+}
+
+void
+TAO_LB_LoadManager::check_strategy_prop (
+ const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL)
+{
+ const CORBA::ULong len = props.length ();
+ for (CORBA::ULong i; i < len; ++i)
+ {
+ const PortableGroup::Property & property = props[i];
+ if (ACE_OS::strcmp (property.nam[0].id.in (),
+ "org.omg.CosLoadBalancing.CustomStrategy") == 0)
+ {
+ CosLoadBalancing::CustomStrategy_var strategy;
+ if (!(property.val >>= strategy.inout ())
+ || CORBA::is_nil (strategy.in ()))
+ ACE_THROW (PortableGroup::InvalidProperty (property.nam,
+ property.val));
+ }
+
+ else if (ACE_OS::strcmp (property.nam[0].id.in (),
+ "org.omg.CosLoadBalancing.Strategy") == 0)
+ {
+ CosLoadBalancing::StrategyInfo * info;
+ if (property.val >>= info)
+ {
+ if (ACE_OS::strcmp (info->name.in (), "LeastLoaded") == 0)
+ {
+ this->init_least_loaded (info->props
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+ }
+ else
+ ACE_THROW (PortableGroup::InvalidProperty (property.nam,
+ property.val));
+ }
+
+ }
+}
+
+void
+TAO_LB_LoadManager::init_least_loaded (const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL)
+{
+ // Double-checked locking
+ if (this->least_loaded_ == 0)
+ {
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
+
+ if (this->least_loaded_ == 0)
+ {
+ CORBA::Float critical_threshold =
+ TAO_LB::LL_DEFAULT_CRITICAL_THRESHOLD;
+ CORBA::Float reject_threshold = TAO_LB::LL_DEFAULT_REJECT_THRESHOLD;
+ CORBA::Float tolerance = TAO_LB::LL_DEFAULT_TOLERANCE;
+ CORBA::Float dampening = TAO_LB::LL_DEFAULT_DAMPENING;
+ CORBA::Float per_balance_load = TAO_LB::LL_DEFAULT_PER_BALANCE_LOAD;
+
+ const CORBA::ULong len = props.length ();
+ for (CORBA::ULong i; i < len; ++i)
+ {
+ const PortableGroup::Property & property = props[i];
+ if (ACE_OS::strcmp (property.nam[0].id.in (),
+ "org.omg.CosLoadBalancing.Strategy.LeastLoaded.CriticalThreshold") == 0)
+ {
+ this->extract_float_property (property,
+ critical_threshold
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+
+ else if (ACE_OS::strcmp (property.nam[0].id.in (),
+ "org.omg.CosLoadBalancing.Strategy.LeastLoaded.RejectThreshold") == 0)
+ {
+ this->extract_float_property (property,
+ reject_threshold
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+
+ else if (ACE_OS::strcmp (property.nam[0].id.in (),
+ "org.omg.CosLoadBalancing.Strategy.LeastLoaded.Tolerance") == 0)
+ {
+ this->extract_float_property (property,
+ tolerance
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+
+ else if (ACE_OS::strcmp (property.nam[0].id.in (),
+ "org.omg.CosLoadBalancing.Strategy.LeastLoaded.Dampening") == 0)
+ {
+ this->extract_float_property (property,
+ dampening
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+
+ else if (ACE_OS::strcmp (property.nam[0].id.in (),
+ "org.omg.CosLoadBalancing.Strategy.LeastLoaded.PerBalanceLoad") == 0)
+ {
+ this->extract_float_property (property,
+ per_balance_load
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+ }
+
+ // Use default "LeastLoaded" properties.
+ ACE_NEW_THROW_EX (this->least_loaded_,
+ TAO_LB_LeastLoaded (critical_threshold,
+ reject_threshold,
+ tolerance,
+ dampening,
+ per_balance_load),
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO_DEFAULT_MINOR_CODE,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK;
+ }
+ }
+}
+
+void
+TAO_LB_LoadManager::extract_float_property (
+ const PortableGroup::Property & property,
+ CORBA::Float & value
+ ACE_ENV_ARG_DECL)
+{
+ if (!(property.val >>= value))
+ ACE_THROW (PortableGroup::InvalidProperty (property.nam,
+ property.val));
}
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadManager.h b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadManager.h
index fedce5dd7b8..464476de890 100644
--- a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadManager.h
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadManager.h
@@ -23,7 +23,9 @@
#endif /* ACE_LACKS_PRAGMA_ONCE */
+#include "LB_LoadAlertMap.h"
#include "LB_MonitorMap.h"
+#include "LB_LoadListMap.h"
#include "LB_Pull_Handler.h"
#include "orbsvcs/PortableGroupC.h"
@@ -34,20 +36,20 @@
/// Forward declarations
-class TAO_LB_Balancing_Strategy;
+class TAO_LB_RoundRobin;
+class TAO_LB_Random;
+class TAO_LB_LeastLoaded;
class TAO_LoadBalancing_Export TAO_LB_LoadManager
- : public virtual POA_CosLoadBalancing::LoadManager
+ : public virtual POA_CosLoadBalancing::LoadManager,
+ public virtual PortableServer::RefCountServantBase
{
public:
/// Constructor.
TAO_LB_LoadManager (void);
- /// Destructor.
- ~TAO_LB_LoadManager (void);
-
/**
* @name CosLoadBalancing::LoadManager Methods
*
@@ -55,12 +57,65 @@ public:
*/
//@{
- // For the PUSH load monitoring style.
+ /// For the PUSH load monitoring style.
virtual void push_loads (const PortableGroup::Location & the_location,
const CosLoadBalancing::LoadList & loads
ACE_ENV_ARG_DECL_WITH_DEFAULTS)
ACE_THROW_SPEC ((CORBA::SystemException));
+ /// Return the raw loads at the given location.
+ virtual CosLoadBalancing::LoadList * get_loads (
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ CosLoadBalancing::LocationNotFound));
+
+ /// Inform member at given location of load alert condition.
+ virtual void enable_alert (PortableGroup::ObjectGroup_ptr object_group,
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((PortableGroup::ObjectGroupNotFound,
+ CosLoadBalancing::LoadAlertNotFound));
+
+ /// Inform member at given location that load alert condition has
+ /// passed.
+ virtual void disable_alert (PortableGroup::ObjectGroup_ptr object_group,
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((PortableGroup::ObjectGroupNotFound,
+ CosLoadBalancing::LoadAlertNotFound));
+
+ /// Register a LoadAlert object for the member at the given
+ /// location.
+ virtual void register_load_alert (
+ PortableGroup::ObjectGroup_ptr object_group,
+ const PortableGroup::Location & the_location,
+ CosLoadBalancing::LoadAlert_ptr load_alert
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound,
+ CosLoadBalancing::LoadAlertAlreadyPresent,
+ CosLoadBalancing::LoadAlertNotAdded));
+
+ /// Retrieve the LoadAlert object for the member at the given
+ /// location.
+ virtual CosLoadBalancing::LoadAlert_ptr get_load_alert (
+ PortableGroup::ObjectGroup_ptr object_group,
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound,
+ CosLoadBalancing::LoadAlertNotFound));
+
+ /// Remove (de-register) the LoadAlert object for the member at the
+ /// given location.
+ virtual void remove_load_alert (PortableGroup::ObjectGroup_ptr object_group,
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound,
+ CosLoadBalancing::LoadAlertNotFound));
+
/// Register a load monitor with the load balancer.
virtual void register_load_monitor (
CosLoadBalancing::LoadMonitor_ptr load_monitor,
@@ -302,30 +357,29 @@ public:
/**
* Select the next member of the object group corresponding to the
* given ObjectId. The object group's load balancing strategy
- * will be queried that member.
+ * will be queried for that member.
*/
- CORBA::Object_ptr member (const PortableServer::ObjectId & oid
- ACE_ENV_ARG_DECL);
+ CORBA::Object_ptr next_member (const PortableServer::ObjectId & oid
+ ACE_ENV_ARG_DECL);
public:
- /// Return a reference to the replica to which the current client
- /// request will be forwarded.
- /**
- * The load balancer does the right thing and figures which object
- * group the replica should be chosen from.
- */
- CORBA::Object_ptr replica (const PortableServer::ObjectId &oid
- ACE_ENV_ARG_DECL);
-
-
/// Initialize the load balancer. This will cause a child POA to be
/// created with the appropriate policies to support ServantLocators
- /// (i.e. for the ReplicaLocator).
- void init (CORBA::ORB_ptr orb,
+ /// (i.e. for the MemberLocator).
+ void init (ACE_Reactor * reactor,
PortableServer::POA_ptr root_poa
ACE_ENV_ARG_DECL);
+protected:
+
+ /// Destructor.
+ /**
+ * Destructor is protected to enforce correct memory management
+ * through reference counting.
+ */
+ ~TAO_LB_LoadManager (void);
+
private:
/// Extract the value of the InitialNumberReplicas property from
@@ -347,6 +401,34 @@ private:
const PortableGroup::Criteria & the_criteria,
PortableGroup::FactoryInfos & factory_infos) const;
+ /// Return a reference to the built-in load balancing strategy named
+ /// "strategy."
+ CosLoadBalancing::Strategy_ptr built_in_strategy (const char * strategy);
+
+ /// Check validity of Strategy or CustomStrategy property.
+ /**
+ * If a "LeastLoaded" Strategy is found in the property list, the
+ * LeastLoaded Strategy implementation will be initialized with the
+ * provided LeastLoaded-specific properties.
+ */
+ void check_strategy_prop (const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL);
+
+ /// Initialize the built-in LeastLoaded Strategy with the given
+ /// LeastLoaded properties.
+ void init_least_loaded (const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL);
+
+ /// Utility method to extract a CORBA::Float value from the given
+ /// property.
+ /**
+ * @note This method is really only used when initializing the
+ * LeastLoaded built-in Strategy.
+ */
+ void extract_float_property (const PortableGroup::Property & property,
+ CORBA::Float & value
+ ACE_ENV_ARG_DECL);
+
private:
/// Reactor used when pulling loads from registered load monitors.
@@ -355,13 +437,29 @@ private:
/// The POA that dispatches requests to the ReplicaLocator.
PortableServer::POA_var poa_;
- /// Mutex that provides synchronization.
+ /// Mutex that provides synchronization for the LoadMonitor map.
+ TAO_SYNCH_MUTEX monitor_lock_;
+
+ /// Mutex that provides synchronization for the LoadMap table.
+ TAO_SYNCH_MUTEX load_lock_;
+
+ /// Mutex that provides synchronization for the LoadAlert table.
+ TAO_SYNCH_MUTEX load_alert_lock_;
+
+ /// Mutex that provides synchronization for the LoadManager's
+ /// state.
TAO_SYNCH_MUTEX lock_;
/// Table that maps PortableGroup::Location to load monitor at that
/// location.
TAO_LB_MonitorMap monitor_map_;
+ /// Table that maps location to load list.
+ TAO_LB_LoadListMap load_map_;
+
+ /// Table that maps object group and location to LoadAlert object.
+ TAO_LB_LoadAlertMap load_alert_map_;
+
/// The ObjectGroupManager that implements the functionality
/// necessary for application-controlled object group membership.
TAO_PG_ObjectGroupManager object_group_manager_;
@@ -384,6 +482,35 @@ private:
/// Cached object reference that points to this servant.
CosLoadBalancing::LoadManager_var lm_ref_;
+ /// Cached object reference that points to the AMI handler for all
+ /// LoadAlert objects.
+ CosLoadBalancing::AMI_LoadAlertHandler_var load_alert_handler_;
+
+ /**
+ * @name Built-in load balancing strategy implementations
+ *
+ * "Built-in" load balancing strategies defined by the load
+ * balancing specification.
+ */
+ //@{
+ /// The "RoundRobin" load balancing strategy.
+ TAO_LB_RoundRobin * round_robin_;
+
+ /// The "Random" load balancing strategy.
+ TAO_LB_Random * random_;
+
+ /// The "LeastLoaded" load balancing strategy.
+ TAO_LB_LeastLoaded * least_loaded_;
+ //@}
+
+ /// Cached instance of the Property name
+ /// "org.omg.CosLoadBalancing.Strategy".
+ PortableGroup::Name built_in_balancing_strategy_name_;
+
+ /// Cached instance of the Property name
+ /// "org.omg.CosLoadBalancing.CustomStrategy".
+ PortableGroup::Name custom_balancing_strategy_name_;
+
};
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_MemberLocator.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_MemberLocator.cpp
index 1c189bf7f2c..7012d1ab668 100644
--- a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_MemberLocator.cpp
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_MemberLocator.cpp
@@ -23,8 +23,8 @@ TAO_LB_MemberLocator::preinvoke (
PortableServer::ForwardRequest))
{
CORBA::Object_var member =
- this->load_manager_->member (oid
- ACE_ENV_ARG_PARAMETER);
+ this->load_manager_->next_member (oid
+ ACE_ENV_ARG_PARAMETER);
ACE_CHECK_RETURN (0);
// ACE_DEBUG ((LM_DEBUG,
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Random.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Random.cpp
index 38a018f12c7..0831b8ce4f4 100644
--- a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Random.cpp
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Random.cpp
@@ -16,7 +16,7 @@ char *
TAO_LB_Random::name (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
ACE_THROW_SPEC ((CORBA::SystemException))
{
- return CORBA::string_dup ("TAO_LB_Random");
+ return CORBA::string_dup ("Random");
}
CosLoadBalancing::Properties *
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Random.h b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Random.h
index 5518bdb1e76..277f8fa9103 100644
--- a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Random.h
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Random.h
@@ -20,7 +20,7 @@
# pragma once
# endif /* ACE_LACKS_PRAGMA_ONCE */
-#include "orbsvcs/CosLoadBalancingS.h"
+#include "orbsvcs/CosLoadBalancingC.h"
/**
* @class TAO_LB_Random
@@ -30,8 +30,9 @@
* This load balancing strategy is designed to select an object group
* member residing at a random location.
*/
-class TAO_LoadBalancing_Export TAO_LB_Random
- : public virtual POA_CosLoadBalancing::Strategy
+class TAO_LB_Random
+ : public virtual CosLoadBalancing::Strategy,
+ public virtual CORBA::LocalObject
{
public:
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RoundRobin.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RoundRobin.cpp
new file mode 100644
index 00000000000..15dfeb2bdf3
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RoundRobin.cpp
@@ -0,0 +1,67 @@
+// -*- C++ -*-
+
+#include "LB_RoundRobin.h"
+#include "orbsvcs/PortableGroup/PG_conf.h"
+#include "tao/debug.h"
+
+
+ACE_RCSID (LoadBalancing,
+ LB_RoundRobin,
+ "$Id$")
+
+
+TAO_LB_RoundRobin::TAO_LB_RoundRobin (void)
+ // : lock_ (),
+{
+}
+
+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))
+{
+ CosLoadBalancing::Properties * props = 0;
+ ACE_NEW_THROW_EX (props,
+ CosLoadBalancing::Properties,
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO_DEFAULT_MINOR_CODE,
+ 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 ());
+}
+
+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))
+{
+ ACE_THROW_RETURN (CORBA::NO_IMPLEMENT (), CORBA::Object::_nil ());
+}
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RoundRobin.h b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RoundRobin.h
new file mode 100644
index 00000000000..5cf5579fbd7
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RoundRobin.h
@@ -0,0 +1,94 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file LB_RoundRobin.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef LB_ROUND_ROBIN_H
+#define LB_ROUND_ROBIN_H
+
+#include "ace/pre.h"
+
+#include "LB_LoadMap.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/CosLoadBalancingC.h"
+
+#include "ace/Synch.h"
+
+/**
+ * @class TAO_LB_RoundRobin_Strategy
+ *
+ * @brief "Round Robin" load balancing strategy
+ *
+ * This load balancing strategy is designed to select an object group
+ * member residing at the next location.
+ */
+class TAO_LB_RoundRobin
+ : public virtual CosLoadBalancing::Strategy,
+ public virtual CORBA::LocalObject
+{
+public:
+
+ /// Constructor.
+ TAO_LB_RoundRobin (void);
+
+ /// Destructor
+ ~TAO_LB_RoundRobin (void);
+
+ /**
+ * @name CosLoadBalancing::Strategy methods
+ *
+ * Methods required by the CosLoadBalancing::Strategy interface.
+ */
+ //@{
+ virtual char * name (ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual CosLoadBalancing::Properties * get_properties (
+ ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual void push_loads (
+ const PortableGroup::Location & the_location,
+ const CosLoadBalancing::LoadList & loads
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ CosLoadBalancing::StrategyNotAdaptive));
+
+ virtual CORBA::Object_ptr next_member (
+ PortableGroup::ObjectGroup_ptr object_group,
+ CosLoadBalancing::LoadManager_ptr load_manager
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound,
+ PortableGroup::MemberNotFound));
+
+protected:
+
+ /// Retrieve the least loaded location from the given list of
+ /// locations.
+// CORBA::Boolean get_location (const PortableGroup::Locations & locations,
+// PortableGroup::Location & location);
+
+private:
+
+ /// Lock used to ensure atomic access to state retained by this
+ /// class.
+// TAO_SYNCH_MUTEX lock_;
+
+};
+
+#include "ace/post.h"
+
+#endif /* LB_ROUND_ROBIN_H */