diff options
author | jai <jai@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2004-01-30 23:07:42 +0000 |
---|---|---|
committer | jai <jai@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2004-01-30 23:07:42 +0000 |
commit | 74fec246bba6803e0295f48e2a70d4d7e255adfb (patch) | |
tree | 3e9c1ceeb1f7b9e11ed587a300be3b70c76e1ade | |
parent | cdd0661aaa60b46ee748fe9b68ac3d632bb86d00 (diff) | |
download | ATCD-74fec246bba6803e0295f48e2a70d4d7e255adfb.tar.gz |
Fri Jan 30 16:43:43 2004 Jaiganesh B <jai@dre.vanderbilt.edu>
-rw-r--r-- | TAO/ChangeLog | 20 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.cpp | 434 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.h | 187 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.inl | 23 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.cpp | 620 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.h | 204 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.inl | 22 |
7 files changed, 1507 insertions, 3 deletions
diff --git a/TAO/ChangeLog b/TAO/ChangeLog index f6c94079ca6..958b281a294 100644 --- a/TAO/ChangeLog +++ b/TAO/ChangeLog @@ -1,7 +1,21 @@ +Fri Jan 30 16:43:43 2004 Jaiganesh B <jai@dre.vanderbilt.edu> + + * orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.h: + * orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.cpp: + * orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.inl: + * orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.h: + * orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.cpp: + * orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.inl: + * orbsvcs/orbsvcs/Makefile.CosLoadBalancing: + + Integrated two new adaptive load balancing strategies + with the TAO Load Balancing Service - Cygnus. + + Thu Jan 29 18:14:20 2004 Jeff Parsons <j.parsons@vanderbilt.edu> * TAO_IDL/util/utl_global.cpp: - + When executing validate_included_idl_files() on a non-windows platform, the system function realpath() is called. Denny Kolb <kolb@g2ss.com> has submitted a version for use on LynxOS, @@ -10,7 +24,7 @@ Thu Jan 29 18:14:20 2004 Jeff Parsons <j.parsons@vanderbilt.edu> Thu Jan 29 15:33:16 2004 Jeff Parsons <j.parsons@vanderbilt.edu> * tao/TypeCodeFactory/TypeCodeFactory_i.cpp: - + Added missing parenthesis is a block of code compiled only when ACE_SWAP_ON_WRITE is defined. This closes [BUGID:1732]. Thanks to Mouna Seri <seri@crhc.uiuc.edu> for making the @@ -75,7 +89,7 @@ Thu Jan 29 14:10:27 2004 Balachandran Natarajan <bala@dre.vanderbilt.edu> Thanks to Duane Binder<duane.binder@veritas.com> for providing patches to fix some of the messages printed out using - ACE_Log_Msg. + ACE_Log_Msg. Thu Jan 29 14:03:42 2004 Chad Elliott <elliott_c@ociweb.com> diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.cpp new file mode 100644 index 00000000000..9cdd42917f6 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.cpp @@ -0,0 +1,434 @@ +#include "LB_LoadAverage.h" +#include "LB_LoadMap.h" +#include "LB_Random.h" + +#include "orbsvcs/PortableGroup/PG_conf.h" + +#include "tao/debug.h" +#include "tao/ORB_Constants.h" +#include "ace/Null_Mutex.h" + +ACE_RCSID (LoadBalancing, + LB_LoadAverage, + "$Id$") + +#if !defined (__ACE_INLINE__) +#include "LB_LoadAverage.inl" +#endif /* defined INLINE */ + + +TAO_LB_LoadAverage::TAO_LB_LoadAverage (PortableServer::POA_ptr poa) + : poa_ (PortableServer::POA::_duplicate (poa)), + load_map_ (0), + lock_ (0), + properties_ (), + tolerance_ (TAO_LB::LA_DEFAULT_TOLERANCE), + dampening_ (TAO_LB::LA_DEFAULT_DAMPENING), + per_balance_load_ (TAO_LB::LA_DEFAULT_DAMPENING) +{ + // A load map that retains previous load values at a given location + // and lock are only needed if dampening is enabled, i.e. non-zero. + if (this->dampening_ != 0) + { + ACE_NEW (this->load_map_, TAO_LB_LoadMap (TAO_PG_MAX_LOCATIONS)); + + ACE_NEW (this->lock_, TAO_SYNCH_MUTEX); + } + + // Initialize the random load balancing strategy. + TAO_LB_Random::init (); +} + +TAO_LB_LoadAverage::~TAO_LB_LoadAverage (void) +{ + delete this->load_map_; + delete this->lock_; +} + +char * +TAO_LB_LoadAverage::name (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return CORBA::string_dup ("LoadAverage"); +} + +CosLoadBalancing::Properties * +TAO_LB_LoadAverage::get_properties (ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + CosLoadBalancing::Properties * props = 0; + ACE_NEW_THROW_EX (props, + CosLoadBalancing::Properties (this->properties_), + CORBA::NO_MEMORY ( + CORBA::SystemException::_tao_minor_code ( + TAO_DEFAULT_MINOR_CODE, + ENOMEM), + CORBA::COMPLETED_NO)); + ACE_CHECK_RETURN (0); + + return props; +} + +void +TAO_LB_LoadAverage::push_loads ( + const PortableGroup::Location & the_location, + const CosLoadBalancing::LoadList & loads + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + // Only the first load is used by this load balancing strategy. + 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_LoadAverage::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) + { + 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 = entry->int_id_; + + if (previous_load.id != new_load.id) + ACE_THROW (CORBA::BAD_PARAM ()); // Somebody switched + // LoadIds on us! + + 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) + }; + + if (this->load_map_->bind (the_location, eff_load) != 0) + { + if (TAO_debug_level > 0) + ACE_ERROR ((LM_ERROR, + "ERROR: TAO_LB_LoadAverage - " + "Unable to push loads\n")); + + ACE_THROW (CORBA::INTERNAL ()); + } + + load = eff_load; + } + } + else + { + load.id = new_load.id; + load.value = this->effective_load (0, new_load.value); + } +} + +CosLoadBalancing::LoadList * +TAO_LB_LoadAverage::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); + + CosLoadBalancing::LoadList_var loads = + load_manager->get_loads (the_location + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + + this->push_loads (the_location, + loads.in (), + loads[0] + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + + return loads._retn (); +} + + +CORBA::Object_ptr +TAO_LB_LoadAverage::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 ()); + + PortableGroup::Locations_var locations = + load_manager->locations_of_members (object_group + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + + if (locations->length () == 0) + ACE_THROW_RETURN (CORBA::TRANSIENT (), + CORBA::Object::_nil ()); + + // @note The Random load balancing strategy is used since it is + // very lightweight and stateless. + + return TAO_LB_Random::_tao_next_member (object_group, + load_manager, + locations.in () + ACE_ENV_ARG_PARAMETER); +} + +void +TAO_LB_LoadAverage::analyze_loads ( + PortableGroup::ObjectGroup_ptr object_group, + CosLoadBalancing::LoadManager_ptr load_manager + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + if (CORBA::is_nil (load_manager)) + ACE_THROW (CORBA::BAD_PARAM ()); + + PortableGroup::Locations_var locations = + load_manager->locations_of_members (object_group + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + if (locations->length () == 0) + ACE_THROW (CORBA::TRANSIENT ()); + + const CORBA::ULong len = locations->length (); + + CosLoadBalancing::Load total_load; + CosLoadBalancing::Load avg_load; + + CosLoadBalancing::LoadList tmp (len); + tmp.length (1); + + // Iterate through the entire location list to determine + // the average load of all the locations + for (CORBA::ULong i = 0; i < len; ++i) + { + ACE_TRY + { + 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; + + total_load.value = total_load.value + load.value; + + tmp[i] = load; + + /* + ACE_DEBUG ((LM_DEBUG, + "TOTAL == %f\n", + total_load.value)); + */ + + } + ACE_CATCH (CosLoadBalancing::LocationNotFound, ex) + { + // no location found + // + } + ACE_ENDTRY; + ACE_CHECK; + } + + avg_load.value = total_load.value / len; + + // Iterate through the entire location list to determine + // the location where the load has to be shed. + for (CORBA::ULong i = 0; i < len; ++i) + { + ACE_TRY + { + 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 present_load; + this->push_loads (loc, + current_loads.in (), + present_load + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + */ + + /* + ACE_DEBUG ((LM_DEBUG, + "EFFECTIVE_LOAD == %f\n" + "AVERAGE == %f\n", + tmp[i].value, + avg_load.value)); + */ + + if (tmp[i].value <= avg_load.value) + { + load_manager->disable_alert (loc + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + else + { + /* + ACE_DEBUG ((LM_DEBUG, + "%P --- ALERTING LOCATION %u\n", + i)); + */ + load_manager->enable_alert (loc + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + } + ACE_CATCH (CosLoadBalancing::LocationNotFound, ex) + { + // no location found + // + } + ACE_ENDTRY; + ACE_CHECK; + } + +} + +PortableServer::POA_ptr +TAO_LB_LoadAverage::_default_POA (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) +{ + return PortableServer::POA::_duplicate (this->poa_.in ()); +} + +CORBA::Boolean +TAO_LB_LoadAverage::get_location ( + CosLoadBalancing::LoadManager_ptr load_manager /* the manager */, + const PortableGroup::Locations & locations /* locations */, + PortableGroup::Location & location /* the location */ + ACE_ENV_ARG_DECL_NOT_USED) +{ + CORBA::Boolean found_location = 0; + return found_location; +} + +void +TAO_LB_LoadAverage::init (const PortableGroup::Properties & props + ACE_ENV_ARG_DECL) +{ + CORBA::Float tolerance = TAO_LB::LA_DEFAULT_TOLERANCE; + CORBA::Float dampening = TAO_LB::LA_DEFAULT_DAMPENING; + CORBA::Float per_balance_load = TAO_LB::LA_DEFAULT_PER_BALANCE_LOAD; + + const CORBA::ULong len = props.length (); + for (CORBA::ULong i = 0; i < len; ++i) + { + const PortableGroup::Property & property = props[i]; + if (ACE_OS::strcmp (property.nam[0].id.in (), + "org.omg.CosLoadBalancing.Strategy.LoadAverage.Tolerance") == 0) + { + this->extract_float_property (property, + tolerance + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + // Valid tolerance values are greater than or equal to one. + if (tolerance < 1) + ACE_THROW (PortableGroup::InvalidProperty (property.nam, + property.val)); + } + + else if (ACE_OS::strcmp (property.nam[0].id.in (), + "org.omg.CosLoadBalancing.Strategy.LoadAverage.Dampening") == 0) + { + this->extract_float_property (property, + dampening + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + // Dampening range is [0,1). + if (dampening < 0 || dampening >= 1) + ACE_THROW (PortableGroup::InvalidProperty (property.nam, + property.val)); + } + + else if (ACE_OS::strcmp (property.nam[0].id.in (), + "org.omg.CosLoadBalancing.Strategy.LoadAverage.PerBalanceLoad") == 0) + { + this->extract_float_property (property, + per_balance_load + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + } + } + + this->properties_ = props; + + this->tolerance_ = tolerance; + this->dampening_ = dampening; + this->per_balance_load_ = per_balance_load; + + /* + ACE_DEBUG ((LM_DEBUG, + "--------------------------------\n" + "tolerance = %f\n" + "dampening = %f\n" + "per_balance_load = %f\n" + "--------------------------------\n", + tolerance, + dampening, + per_balance_load)); + */ +} + +void +TAO_LB_LoadAverage::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_LoadAverage.h b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.h new file mode 100644 index 00000000000..2fc3410e981 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.h @@ -0,0 +1,187 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file LB_LoadAverage.h + * + * $Id$ + * + * @author Jaiganesh Balasubramanian <jai@dre.vanderbilt.edu> + * @author Ossama Othman <jai@dre.vanderbilt.edu> + */ +//============================================================================= + + +#ifndef LB_LOAD_AVERAGE_H +#define LB_LOAD_AVERAGE_H + +#include /**/ "ace/pre.h" + +#include "LB_LoadMap.h" + +# if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +# endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "orbsvcs/CosLoadBalancingS.h" + +#include "ace/Synch_Traits.h" +#include "ace/Thread_Mutex.h" + +namespace TAO_LB +{ + /** + * @name Default LoadAverage strategy parameters. + * + * Defaults defined by the Load Balancing specification. + */ + //@{ + const CORBA::Float LA_DEFAULT_TOLERANCE = 1; + const CORBA::Float LA_DEFAULT_DAMPENING = 0; + const CORBA::Float LA_DEFAULT_PER_BALANCE_LOAD = 0; + //@} + +} + +/** + * @class TAO_LB_LoadAverage + * + * @brief "Least loaded" load balancing strategy + * + * This load balancing strategy is designed to select an object group + * member residing at a location with the smallest load. + */ +class TAO_LB_LoadAverage + : public virtual POA_CosLoadBalancing::Strategy, + public virtual PortableServer::RefCountServantBase +{ +public: + + /// Constructor. + TAO_LB_LoadAverage (PortableServer::POA_ptr poa); + + /** + * @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)); + + virtual CosLoadBalancing::LoadList * get_loads ( + CosLoadBalancing::LoadManager_ptr load_manager, + const PortableGroup::Location & the_location + ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC ((CORBA::SystemException, + CosLoadBalancing::LocationNotFound)); + + 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)); + + 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)); + //@} + + /// Returns the default POA for this servant. + virtual PortableServer::POA_ptr _default_POA ( + ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS + ); + + /// Initialize the LoadAverage instance with the given properties. + void init (const PortableGroup::Properties & props + ACE_ENV_ARG_DECL); + +protected: + + /// Destructor. + ~TAO_LB_LoadAverage (void); + + /// Retrieve the least loaded location from the given list of + /// locations. + CORBA::Boolean get_location (CosLoadBalancing::LoadManager_ptr load_manager, + const PortableGroup::Locations & locations, + PortableGroup::Location & location + ACE_ENV_ARG_DECL); + + /// Return the effective load. + CORBA::Float effective_load (CORBA::Float previous_load, + CORBA::Float new_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::LoadList & loads, + CosLoadBalancing::Load & effective_load + ACE_ENV_ARG_DECL); + + /// Utility method to extract a CORBA::Float value from the given + /// property. + void extract_float_property (const PortableGroup::Property & property, + CORBA::Float & value + ACE_ENV_ARG_DECL); + +private: + + /// This servant's default POA. + PortableServer::POA_var poa_; + + /// 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_; + + /// Cached set of properties used when initializing this strategy. + CosLoadBalancing::Properties properties_; + + /** + * @name LoadAverage Property Values + * + * Cached LoadAverage load balancing strategy property values. + */ + //@{ + + /// + CORBA::Float tolerance_; + + /// + CORBA::Float dampening_; + + /// + CORBA::Float per_balance_load_; + + //@} + + CosLoadBalancing::LoadList current_loads_; + +}; + + +#if defined (__ACE_INLINE__) +#include "LB_LoadAverage.inl" +#endif /* defined INLINE */ + +#include /**/ "ace/post.h" + +#endif /* LB_LOAD_AVERAGE_H */ diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.inl b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.inl new file mode 100644 index 00000000000..807367ef5c1 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.inl @@ -0,0 +1,23 @@ +// -*- C++ -*- +// +// $Id$ + + +ACE_INLINE CORBA::Float +TAO_LB_LoadAverage::effective_load (CORBA::Float previous_load, + CORBA::Float new_load) +{ + // Apply per-balance load. (Recompute raw load) + previous_load += this->per_balance_load_; + + // Apply dampening. (Recompute new raw load) + CORBA::Float result = + this->dampening_ * previous_load + (1 - this->dampening_) * new_load; + + ACE_ASSERT (this->tolerance_ != 0); + + // Compute the effective load. + result /= this->tolerance_; + + return result; +} diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.cpp new file mode 100644 index 00000000000..b03702b45e3 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.cpp @@ -0,0 +1,620 @@ +#include "LB_LoadMinimum.h" +#include "ace/OS_NS_sys_time.h" +#include "LB_LoadMap.h" +#include "LB_Random.h" + +#include "orbsvcs/PortableGroup/PG_conf.h" + +#include "tao/debug.h" +#include "tao/ORB_Constants.h" +#include "ace/Null_Mutex.h" + +ACE_RCSID (LoadBalancing, + LB_LoadMinimum, + "$Id$") + +#if !defined (__ACE_INLINE__) +#include "LB_LoadMinimum.inl" +#endif /* defined INLINE */ + + +TAO_LB_LoadMinimum::TAO_LB_LoadMinimum (PortableServer::POA_ptr poa) + : poa_ (PortableServer::POA::_duplicate (poa)), + load_map_ (0), + lock_ (0), + properties_ (), + tolerance_ (TAO_LB::LM_DEFAULT_TOLERANCE), + dampening_ (TAO_LB::LM_DEFAULT_DAMPENING), + per_balance_load_ (TAO_LB::LM_DEFAULT_DAMPENING) +{ + // A load map that retains previous load values at a given location + // and lock are only needed if dampening is enabled, i.e. non-zero. + if (this->dampening_ != 0) + { + ACE_NEW (this->load_map_, TAO_LB_LoadMap (TAO_PG_MAX_LOCATIONS)); + + ACE_NEW (this->lock_, TAO_SYNCH_MUTEX); + } + + // Initialize the random load balancing strategy. + TAO_LB_Random::init (); +} + +TAO_LB_LoadMinimum::~TAO_LB_LoadMinimum (void) +{ + delete this->load_map_; + delete this->lock_; +} + +char * +TAO_LB_LoadMinimum::name (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return CORBA::string_dup ("LoadMinimum"); +} + +CosLoadBalancing::Properties * +TAO_LB_LoadMinimum::get_properties (ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + CosLoadBalancing::Properties * props = 0; + ACE_NEW_THROW_EX (props, + CosLoadBalancing::Properties (this->properties_), + CORBA::NO_MEMORY ( + CORBA::SystemException::_tao_minor_code ( + TAO_DEFAULT_MINOR_CODE, + ENOMEM), + CORBA::COMPLETED_NO)); + ACE_CHECK_RETURN (0); + + return props; +} + +void +TAO_LB_LoadMinimum::push_loads ( + const PortableGroup::Location & the_location, + const CosLoadBalancing::LoadList & loads + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + // Only the first load is used by this load balancing strategy. + 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_LoadMinimum::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) + { + 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 = entry->int_id_; + + if (previous_load.id != new_load.id) + ACE_THROW (CORBA::BAD_PARAM ()); // Somebody switched + // LoadIds on us! + + 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) + }; + + if (this->load_map_->bind (the_location, eff_load) != 0) + { + if (TAO_debug_level > 0) + ACE_ERROR ((LM_ERROR, + "ERROR: TAO_LB_LoadMinimum - " + "Unable to push loads\n")); + + ACE_THROW (CORBA::INTERNAL ()); + } + + load = eff_load; + } + } + else + { + load.id = new_load.id; + load.value = this->effective_load (0, new_load.value); + } +} + +CosLoadBalancing::LoadList * +TAO_LB_LoadMinimum::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); + + CosLoadBalancing::LoadList_var loads = + load_manager->get_loads (the_location + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + + this->push_loads (the_location, + loads.in (), + loads[0] + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + + return loads._retn (); +} + + +CORBA::Object_ptr +TAO_LB_LoadMinimum::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 ()); + + PortableGroup::Locations_var locations = + load_manager->locations_of_members (object_group + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + + if (locations->length () == 0) + ACE_THROW_RETURN (CORBA::TRANSIENT (), + CORBA::Object::_nil ()); + + // @@ RACE CONDITION. OBJECT GROUP MEMBERSHIP MAY CHANGE AFTER + // RETRIEVING LOCATIONS! HOW DO WE HANDLE THAT? + + PortableGroup::Location location; + CORBA::Boolean found_location = + this->get_location (load_manager, + locations.in (), + location + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + + if (found_location) + { +// ACE_DEBUG ((LM_DEBUG, +// "RETURNING REFERENCE FOR LOCATION \"%s\"\n", +// location[0].id.in ())); + + return load_manager->get_member_ref (object_group, + location + ACE_ENV_ARG_PARAMETER); + } + else + { + // No loads have been reported for any of the locations the + // object group members reside at. If no loads have been + // reported to the LoadManager, adaptive load balancing + // decisions cannot be made. Fall back on a non-adaptive + // strategy, such as the Random load balancing strategy, + // instead. + // + // @note The Random load balancing strategy is used since it is + // very lightweight and stateless. + + return TAO_LB_Random::_tao_next_member (object_group, + load_manager, + locations.in () + ACE_ENV_ARG_PARAMETER); + } +} + +void +TAO_LB_LoadMinimum::analyze_loads ( + PortableGroup::ObjectGroup_ptr object_group, + CosLoadBalancing::LoadManager_ptr load_manager + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + if (CORBA::is_nil (load_manager)) + ACE_THROW (CORBA::BAD_PARAM ()); + + PortableGroup::Locations_var locations = + load_manager->locations_of_members (object_group + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + if (locations->length () == 0) + ACE_THROW (CORBA::TRANSIENT ()); + + const CORBA::ULong len = locations->length (); + + CosLoadBalancing::Load total_load; + CosLoadBalancing::Load avg_load; + + CosLoadBalancing::LoadList tmp (len); + tmp.length (1); + + // Iterate through the entire location list to determine + // the average load of all the locations + for (CORBA::ULong i = 0; i < len; ++i) + { + ACE_TRY + { + 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; + + total_load.value = total_load.value + load.value; + tmp[i] = load; + + /* + ACE_DEBUG ((LM_DEBUG, + "TOTAL == %f\n", + total_load.value)); + */ + + } + ACE_CATCH (CosLoadBalancing::LocationNotFound, ex) + { + // no location found + // + } + ACE_ENDTRY; + ACE_CHECK; + } + + avg_load.value = total_load.value / len; + + // Iterate through the entire location list to determine + // the location where the load has to be shed. + for (CORBA::ULong i = 0; i < len; ++i) + { + ACE_TRY + { + 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 present_load; + this->push_loads (loc, + current_loads.in (), + present_load + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + */ + + /* + ACE_DEBUG ((LM_DEBUG, + "EFFECTIVE_LOAD == %f\n" + "AVERAGE == %f\n", + tmp[i].value, + avg_load.value)); + */ + + if (tmp[i].value <= avg_load.value) + { + load_manager->disable_alert (loc + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + else + { + + /* + ACE_DEBUG ((LM_DEBUG, + "%P --- ALERTING LOCATION %u\n", + i)); + */ + load_manager->enable_alert (loc + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + } + ACE_CATCH (CosLoadBalancing::LocationNotFound, ex) + { + // no location found + // + } + ACE_ENDTRY; + ACE_CHECK; + } + +} + +PortableServer::POA_ptr +TAO_LB_LoadMinimum::_default_POA (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) +{ + return PortableServer::POA::_duplicate (this->poa_.in ()); +} + +CORBA::Boolean +TAO_LB_LoadMinimum::get_location ( + CosLoadBalancing::LoadManager_ptr load_manager, + const PortableGroup::Locations & locations, + PortableGroup::Location & location + ACE_ENV_ARG_DECL) +{ + CORBA::Float min_load = FLT_MAX; // Start out with the largest + // positive value. + + CORBA::ULong location_index = 0; + CORBA::Boolean found_location = 0; + CORBA::Boolean found_load = 0; + + const CORBA::ULong len = locations.length (); + + // Iterate through the entire location list to find the least loaded + // of them. + for (CORBA::ULong i = 0; i < len; ++i) + { + ACE_TRY + { + 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; + + found_load = 1; + + CosLoadBalancing::Load load; + this->push_loads (loc, + current_loads.in (), + load + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (load.value < min_load) + { +// ACE_DEBUG ((LM_DEBUG, +// "**** LOAD == %f\n", +// load.value)); + + if (i > 0 && load.value != 0) + { + /* + percent difference = + (min_load - load.value) / load.value + == (min_load / load.value) - 1 + + The latter form is used to avoid a potential + arithmetic overflow problem, such as when + (min_load - load.value) > FLT_MAX, assuming that + either load.value is negative and min_load is + positive, or vice versa. + */ + const CORBA::Float percent_diff = + (min_load / load.value) - 1; + + /* + A "thundering herd" phenomenon may occur when + location loads are basically the same (e.g. only + differ by a very small amount), where one object + group member ends up receiving the majority of + requests from different clients. In order to + prevent a single object group member from + receiving such request bursts, one of two equally + loaded locations is chosen at random. Thanks to + Carlos, Marina and Jody at ATD for coming up with + this solution to this form of the thundering herd + problem. + + See the documentation for + TAO_LB::LL_DEFAULT_LOAD_PERCENT_DIFF_CUTOFF in + LB_LoadMinimum.h for additional information. + */ + if (percent_diff <= TAO_LB::LM_DEFAULT_LOAD_PERCENT_DIFF_CUTOFF) + { + // Prevent integer arithmetic overflow. + const CORBA::Float NUM_MEMBERS = 2; + + // n == 0: Use previously selected location. + // n == 1: Use current location. + const CORBA::ULong n = + ACE_static_cast (CORBA::ULong, + NUM_MEMBERS * ACE_OS::rand () + / (RAND_MAX + 1.0)); + + ACE_ASSERT (n == 0 || n == 1); + + if (n == 1) + { + min_load = load.value; + location_index = i; + found_location = 1; + +// ACE_DEBUG ((LM_DEBUG, +// "** NEW MIN_LOAD == %f\n", +// min_load)); + } + +// if (n == 0) +// ACE_DEBUG ((LM_DEBUG, "^^^^^ PREVIOUS LOCATION\n")); +// else +// ACE_DEBUG ((LM_DEBUG, "^^^^^ CURRENT LOCATION\n")); + + } + else + { + min_load = load.value; + location_index = i; + found_location = 1; + +// ACE_DEBUG ((LM_DEBUG, +// "***** NEW MIN_LOAD == %f\n", +// min_load)); + } + } + else + { + min_load = load.value; + location_index = i; + found_location = 1; + +// ACE_DEBUG ((LM_DEBUG, +// "NEW MIN_LOAD == %f\n", +// min_load)); + } + } + + // ACE_DEBUG ((LM_DEBUG, "NEW MIN_LOAD == %f\n", min_load)); + } + ACE_CATCH (CosLoadBalancing::LocationNotFound, ex) + { + // No load available for the requested location. Try the + // next location. + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + } + +// ACE_DEBUG ((LM_DEBUG, +// "FOUND_LOAD == %u\n" +// "FOUND_LOCATION == %u\n", +// found_load, +// found_location)); + + // If no loads were found, return without an exception to allow this + // strategy to select a member using an alternative method + // (e.g. random selection). + if (found_load) + { + if (found_location) + location = locations[location_index]; +// ACE_DEBUG ((LM_DEBUG, "LOCATION ID == %s\n", location[0].id.in ())); + } + + //ACE_DEBUG ((LM_DEBUG, "LOCATED = %u\n", location_index)); + + return found_location; +} + +void +TAO_LB_LoadMinimum::init (const PortableGroup::Properties & props + ACE_ENV_ARG_DECL) +{ + CORBA::Float tolerance = TAO_LB::LM_DEFAULT_TOLERANCE; + CORBA::Float dampening = TAO_LB::LM_DEFAULT_DAMPENING; + CORBA::Float per_balance_load = TAO_LB::LM_DEFAULT_PER_BALANCE_LOAD; + + const CORBA::ULong len = props.length (); + for (CORBA::ULong i = 0; i < len; ++i) + { + const PortableGroup::Property & property = props[i]; + if (ACE_OS::strcmp (property.nam[0].id.in (), + "org.omg.CosLoadBalancing.Strategy.LoadMinimum.Tolerance") == 0) + { + this->extract_float_property (property, + tolerance + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + // Valid tolerance values are greater than or equal to one. + if (tolerance < 1) + ACE_THROW (PortableGroup::InvalidProperty (property.nam, + property.val)); + } + + else if (ACE_OS::strcmp (property.nam[0].id.in (), + "org.omg.CosLoadBalancing.Strategy.LoadMinimum.Dampening") == 0) + { + this->extract_float_property (property, + dampening + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + // Dampening range is [0,1). + if (dampening < 0 || dampening >= 1) + ACE_THROW (PortableGroup::InvalidProperty (property.nam, + property.val)); + } + + else if (ACE_OS::strcmp (property.nam[0].id.in (), + "org.omg.CosLoadBalancing.Strategy.LoadMinimum.PerBalanceLoad") == 0) + { + this->extract_float_property (property, + per_balance_load + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + } + } + + this->properties_ = props; + + this->tolerance_ = tolerance; + this->dampening_ = dampening; + this->per_balance_load_ = per_balance_load; + + /* + ACE_DEBUG ((LM_DEBUG, + "--------------------------------\n" + "tolerance = %f\n" + "dampening = %f\n" + "per_balance_load = %f\n" + "--------------------------------\n", + tolerance, + dampening, + per_balance_load)); + */ +} + +void +TAO_LB_LoadMinimum::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_LoadMinimum.h b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.h new file mode 100644 index 00000000000..bf96ad0e870 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.h @@ -0,0 +1,204 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file LB_LoadMinimum.h + * + * $Id$ + * + * @author Jaiganesh Balasubramanian <jai@dre.vanderbilt.edu> + * Ossama Othman <ossama@uci.edu> + */ +//============================================================================= + + +#ifndef LB_LOAD_MINIMUM_H +#define LB_LOAD_MINIMUM_H + +#include /**/ "ace/pre.h" + +#include "LB_LoadMap.h" + +# if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +# endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "orbsvcs/CosLoadBalancingS.h" + +#include "ace/Synch_Traits.h" +#include "ace/Thread_Mutex.h" + +namespace TAO_LB +{ + /** + * @name Default LoadMinimum strategy parameters. + * + * Defaults defined by the Load Balancing specification. + */ + //@{ + const CORBA::Float LM_DEFAULT_TOLERANCE = 1; + const CORBA::Float LM_DEFAULT_DAMPENING = 0; + const CORBA::Float LM_DEFAULT_PER_BALANCE_LOAD = 0; + //@} + + /** + * @name TAO-specific LoadMinimum strategy parameters. + * + * Parameters internal to TAO's LoadMinimum strategy + * implementation. + */ + //@{ + /// Percentage difference between two load values that determines + /// whether the loads are considered equivalent. + /** + * If the percent difference between two loads, i.e.: + * (Old Load - New Load) / New Load + * is less than or equal to this value, the two loads will be + * considered equivalent. In such a case, an object group member + * residing at the location corresponding to one of the two loads + * will be selected at random. + */ + const CORBA::Float LM_DEFAULT_LOAD_PERCENT_DIFF_CUTOFF = 0.01f; // 1% + //@} +} + +/** + * @class TAO_LB_LoadMinimum + * + * @brief "Least loaded" load balancing strategy + * + * This load balancing strategy is designed to select an object group + * member residing at a location with the smallest load. + */ +class TAO_LB_LoadMinimum + : public virtual POA_CosLoadBalancing::Strategy, + public virtual PortableServer::RefCountServantBase +{ +public: + + /// Constructor. + TAO_LB_LoadMinimum (PortableServer::POA_ptr poa); + + /** + * @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)); + + virtual CosLoadBalancing::LoadList * get_loads ( + CosLoadBalancing::LoadManager_ptr load_manager, + const PortableGroup::Location & the_location + ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC ((CORBA::SystemException, + CosLoadBalancing::LocationNotFound)); + + 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)); + + 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)); + //@} + + /// Returns the default POA for this servant. + virtual PortableServer::POA_ptr _default_POA ( + ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS + ); + + /// Initialize the LoadMinimum instance with the given properties. + void init (const PortableGroup::Properties & props + ACE_ENV_ARG_DECL); + +protected: + + /// Destructor. + ~TAO_LB_LoadMinimum (void); + + /// Retrieve the least loaded location from the given list of + /// locations. + CORBA::Boolean get_location (CosLoadBalancing::LoadManager_ptr load_manager, + const PortableGroup::Locations & locations, + PortableGroup::Location & location + ACE_ENV_ARG_DECL); + + /// Return the effective load. + CORBA::Float effective_load (CORBA::Float previous_load, + CORBA::Float new_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::LoadList & loads, + CosLoadBalancing::Load & effective_load + ACE_ENV_ARG_DECL); + + /// Utility method to extract a CORBA::Float value from the given + /// property. + void extract_float_property (const PortableGroup::Property & property, + CORBA::Float & value + ACE_ENV_ARG_DECL); + +private: + + /// This servant's default POA. + PortableServer::POA_var poa_; + + /// 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_; + + /// Cached set of properties used when initializing this strategy. + CosLoadBalancing::Properties properties_; + + /** + * @name LoadMinimum Property Values + * + * Cached LoadMinimum load balancing strategy property values. + */ + //@{ + + /// + CORBA::Float tolerance_; + + /// + CORBA::Float dampening_; + + /// + CORBA::Float per_balance_load_; + + //@} + +}; + + +#if defined (__ACE_INLINE__) +#include "LB_LoadMinimum.inl" +#endif /* defined INLINE */ + +#include /**/ "ace/post.h" + +#endif /* LB_LOAD_MINIMUM_H */ diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.inl b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.inl new file mode 100644 index 00000000000..4f096fa4040 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.inl @@ -0,0 +1,22 @@ +// -*- C++ -*- +// +// $Id$ + +ACE_INLINE CORBA::Float +TAO_LB_LoadMinimum::effective_load (CORBA::Float previous_load, + CORBA::Float new_load) +{ + // Apply per-balance load. (Recompute raw load) + previous_load += this->per_balance_load_; + + // Apply dampening. (Recompute new raw load) + CORBA::Float result = + this->dampening_ * previous_load + (1 - this->dampening_) * new_load; + + ACE_ASSERT (this->tolerance_ != 0); + + // Compute the effective load. + result /= this->tolerance_; + + return result; +} |