summaryrefslogtreecommitdiff
path: root/TAO/examples/Load_Balancing_persistent/Load_Balancer_i.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/examples/Load_Balancing_persistent/Load_Balancer_i.cpp')
-rw-r--r--TAO/examples/Load_Balancing_persistent/Load_Balancer_i.cpp1013
1 files changed, 1013 insertions, 0 deletions
diff --git a/TAO/examples/Load_Balancing_persistent/Load_Balancer_i.cpp b/TAO/examples/Load_Balancing_persistent/Load_Balancer_i.cpp
new file mode 100644
index 00000000000..f5d171a3b4f
--- /dev/null
+++ b/TAO/examples/Load_Balancing_persistent/Load_Balancer_i.cpp
@@ -0,0 +1,1013 @@
+// $Id$
+#include "Load_Balancer_i.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Hash_Map_Manager_T.h"
+
+const char *rr_name_bind = "RR_Group";
+// Name binding for the location of the Round Robin info in the mem pool
+
+const char *random_name_bind = "Random_Group";
+// Name binding for the location of the Random info in the mem pool
+
+const char *flags_name_bind = "FLAGS";
+// Name binding for the location of the flags info in the mem pool
+
+const char *dll_name_bind = "DLL_LIST";
+// Name binding for the DLL_LIst in the me_pool;
+
+const char *server_id_name_bind = "server_id";
+// Some cookie that is used for appending names
+
+Object_Group_Factory_i::Object_Group_Factory_i (CORBA::ORB_ptr orb,
+ PortableServer::POA_ptr poa)
+ :orb_ (orb),
+ poa_ (PortableServer::POA::_duplicate (poa)),
+ random_groups_ (0),
+ rr_groups_ (0),
+ flags_ (0)
+{
+ ACE_MMAP_Memory_Pool::OPTIONS options (ACE_DEFAULT_BASE_ADDR);
+ ACE_NEW (this->mem_pool_,
+ ALLOCATOR ("Mem_Pool",
+ "Mem_Pool",
+ &options));
+}
+
+Object_Group_Factory_i::~Object_Group_Factory_i (void)
+{
+ delete this->mem_pool_;
+}
+
+PortableServer::POA_ptr
+Object_Group_Factory_i::_default_POA (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return PortableServer::POA::_duplicate (this->poa_.in ());
+}
+
+
+Load_Balancer::Object_Group_ptr
+Object_Group_Factory_i::make_round_robin (const char * id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::duplicate_group))
+{
+
+ if (this->mem_pool_->find (rr_name_bind,
+ (void *&)this->rr_groups_) == -1)
+ {
+ void *hash_map = this->mem_pool_->malloc (sizeof (HASH_MAP));
+ ACE_NEW_THROW_EX (this->rr_groups_,
+ (hash_map) HASH_MAP (this->mem_pool_),
+ CORBA::NO_MEMORY ());
+ ACE_CHECK_RETURN (Load_Balancer::Object_Group::_nil ());
+
+ // Bind it in the mem pool with a name
+ if (this->mem_pool_->bind (rr_name_bind,
+ (void *)this->rr_groups_) != 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind \n"),
+ 0);
+ }
+ }
+
+ return this->make_group (0,
+ id
+ ACE_ENV_ARG_PARAMETER);
+}
+
+void
+Object_Group_Factory_i::unbind_round_robin (const char * id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::no_such_group))
+{
+ if (this->rr_groups_ == 0)
+ {
+ if (this->mem_pool_->find (rr_name_bind,
+ (void *&)this->rr_groups_) == -1)
+ ACE_THROW (Load_Balancer::no_such_group ());
+ }
+
+ char *int_id = 0;
+
+ // Throw an exception if not found in the HASH MAP
+ if (this->rr_groups_->find (const_cast<char *> (id),
+ this->mem_pool_) < 0)
+ ACE_THROW (Load_Balancer::no_such_group ());
+
+ // Unbind the entry
+ this->rr_groups_->unbind (const_cast<char *> (id),
+ int_id,
+ this->mem_pool_);
+
+ // Free the memory from the pool
+ this->mem_pool_->free (int_id - (ACE_OS::strlen (id) + 1));
+
+ // Change the FLAGS variable
+ if (this->flags_ == 0)
+ {
+ if (this->mem_pool_->find (flags_name_bind,
+ (void *&)this->flags_) == -1)
+ return;
+ }
+
+ // Bump down the flags value
+ --this->flags_;
+
+}
+
+Load_Balancer::Object_Group_ptr
+Object_Group_Factory_i::make_random (const char * id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::duplicate_group))
+{
+
+ if (this->mem_pool_->find (random_name_bind, (void * &)this->random_groups_) == -1)
+ {
+ void *hash_map = this->mem_pool_->malloc (sizeof (HASH_MAP));
+
+ ACE_NEW_THROW_EX (this->random_groups_,
+ (hash_map) HASH_MAP (this->mem_pool_),
+ CORBA::NO_MEMORY ());
+ ACE_CHECK_RETURN (Load_Balancer::Object_Group::_nil ());
+
+ // Bind it in the mem pool with a name
+ if (this->mem_pool_->bind (random_name_bind,
+ (void *)this->random_groups_) != 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind \n"),
+ 0);
+ }
+ }
+
+ return this->make_group (1,
+ id
+ ACE_ENV_ARG_PARAMETER);
+}
+
+
+void
+Object_Group_Factory_i::unbind_random (const char * id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::no_such_group))
+{
+ if (this->random_groups_ == 0)
+ {
+ if (this->mem_pool_->find (random_name_bind,
+ (void *&)this->random_groups_) == -1)
+ ACE_THROW (Load_Balancer::no_such_group ());
+ }
+
+ char *int_id = 0;
+
+ // Throw an exception if not found in the HASH MAP
+ if (this->random_groups_->find (const_cast<char *> (id),
+ this->mem_pool_) < 0)
+ ACE_THROW (Load_Balancer::no_such_group ());
+
+ // Unbind the entry
+ this->random_groups_->unbind (const_cast<char *> (id),
+ int_id,
+ this->mem_pool_);
+
+ // Free the memory from the pool
+ this->mem_pool_->free (int_id - (ACE_OS::strlen (id) + 1));
+
+ // Change the FLAGS variable
+ if (this->flags_ == 0)
+ {
+ if (this->mem_pool_->find (flags_name_bind,
+ (void *&)this->flags_) == -1)
+ return;
+ }
+
+ // Bump down the flags value
+ this->flags_ -= 2;
+}
+
+Load_Balancer::Object_Group_ptr
+Object_Group_Factory_i::make_group (int random,
+ const char * id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::duplicate_group))
+{
+ // Store our result here for return.
+ Load_Balancer::Object_Group_var group;
+
+ // Create an appropriate servant.
+ Object_Group_i *group_servant = 0;
+
+ // Check to make sure we don't already have a group with the same
+ // <id>.
+
+ if (random)
+ {
+ if (this->random_groups_->find (const_cast<char *> (id),
+ this->mem_pool_) == 0)
+ ACE_THROW_RETURN (Load_Balancer::duplicate_group (),
+ Load_Balancer::Object_Group::_nil ());
+ }
+ else
+ {
+ if (this->rr_groups_->find (const_cast<char *> (id),
+ this->mem_pool_) == 0)
+ ACE_THROW_RETURN (Load_Balancer::duplicate_group (),
+ Load_Balancer::Object_Group::_nil ());
+ }
+
+
+
+ // As we are sure that it is not in the list go ahead and insert it
+ if (random)
+ ACE_NEW_THROW_EX (group_servant,
+ Random_Object_Group (id,
+ this->poa_.in ()),
+ CORBA::NO_MEMORY ());
+ else
+ ACE_NEW_THROW_EX (group_servant,
+ RR_Object_Group (id,
+ this->poa_.in ()),
+ CORBA::NO_MEMORY ());
+ ACE_CHECK_RETURN (group._retn ());
+
+ // Register with the poa, begin using ref. counting.
+ group = group_servant->_this (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (group._retn ());
+
+ group_servant->_remove_ref (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (Load_Balancer::Object_Group::_nil ());
+
+ CORBA::String_var ior =
+ this->orb_->object_to_string (group.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (Load_Balancer::Object_Group::_nil ());
+
+
+ // Calculate and allocate the memory we need to store this name to
+ // object binding.
+ size_t id_len = ACE_OS::strlen (id) + 1;
+ size_t kind_len = ACE_OS::strlen (ior.in ()) + 1;
+
+ char *ptr = (char *) this->mem_pool_->malloc (id_len + kind_len);
+
+ if (ptr == 0)
+ ACE_THROW_RETURN (CORBA::NO_MEMORY (),
+ Load_Balancer::Object_Group::_nil ());
+
+ char * id_ptr = ptr;
+ char * ior_ptr = ptr + id_len;
+
+ ACE_OS::strcpy (id_ptr, id);
+ ACE_OS::strcpy (ior_ptr, ior.in ());
+
+ // Store the results here
+ CORBA::Long result = 0;
+
+ // Make an entry in appropriate map of groups.
+ if (random)
+ {
+ result = this->random_groups_->bind (id_ptr,
+ ior_ptr,
+ this->mem_pool_);
+ }
+ else
+ {
+ result = this->rr_groups_->bind (id_ptr,
+ ior_ptr,
+ this->mem_pool_);
+ }
+
+
+
+ // Update the value of flags_
+ this->update_flags (random
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (Load_Balancer::Object_Group::_nil ());
+
+ if (result == -1)
+ {
+ // For some reason the bind failed. Free our
+ // dynamically allocated memory.
+ this->mem_pool_->free ((void *) ptr);
+ ACE_THROW_RETURN (Load_Balancer::duplicate_group (),
+ Load_Balancer::Object_Group::_nil ());
+
+ }
+
+ // Return.
+ ACE_DEBUG ((LM_DEBUG, "Successfully created new group: %s\n", id));
+
+ return group._retn ();
+}
+
+
+Load_Balancer::Object_Group_ptr
+Object_Group_Factory_i::resolve (const char * id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::no_such_group))
+{
+
+
+
+#if defined (DOORS_MEASURE_STATS)
+ // Time the calls
+ // Record the entry time.
+ ACE_hrtime_t latency_base = ACE_OS::gethrtime ();
+
+#endif /*DOORS_MEASURE_STATS*/
+
+ // It could be that the Load balancing service could have failed
+ // before the Client tries to invoke this call.. In such a case the
+ // Service should look in to the MMAP file and read in the info
+ // before it can resolve the ID sent by the client.. So we check
+ // whether the class holds the pointer.. If not we look in to the
+ // MMAP file for the relevant info..
+ if (!this->rr_groups_)
+ {
+ if (this->mem_pool_->find (rr_name_bind,
+ (void *&)this->rr_groups_) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%N|%l) The factory does not have any references ")
+ ACE_TEXT ("to the group that you have sought \n\n")),
+ 0);
+ }
+ }
+
+ if (!this->random_groups_)
+ {
+ if (this->mem_pool_->find (random_name_bind,
+ (void *&)this->random_groups_) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%N|%l) The factory does not have any references ")
+ ACE_TEXT ("to the group that you have sought \n\n")),
+ 0);
+
+ }
+ }
+
+ if (!this->flags_)
+ {
+ this->mem_pool_->find (flags_name_bind,
+ (void *&)this->flags_);
+ this->update_objects (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (Load_Balancer::Object_Group::_nil ());
+ }
+
+ char *ior = 0;
+
+ if (rr_groups_->find (const_cast<char *> (id),
+ ior,
+ this->mem_pool_) == -1
+ && random_groups_->find (const_cast<char *> (id),
+ ior,
+ this->mem_pool_) == -1)
+ ACE_THROW_RETURN (Load_Balancer::no_such_group (),
+ 0);
+
+ CORBA::Object_var objref =
+ this->orb_->string_to_object (ior
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (Load_Balancer::Object_Group::_nil ());
+
+ Load_Balancer::Object_Group_ptr
+ object_group = Load_Balancer::Object_Group::_narrow (objref.in ()
+ ACE_ENV_ARG_PARAMETER);
+
+ ACE_CHECK_RETURN (Load_Balancer::Object_Group::_nil ());
+
+
+#if defined (DOORS_MEASURE_STATS)
+ // Grab timestamp again.
+ ACE_hrtime_t now = ACE_OS::gethrtime ();
+
+ this->throughput_.sample (0,
+ now - latency_base);
+
+ ACE_UINT32 gsf = ACE_High_Res_Timer::global_scale_factor ();
+ ACE_OS::printf ("*=*=*=*=Aggregated result *=*=*=*=*= \n");
+ this->throughput_.dump_results ("Aggregated", gsf);
+
+#endif /*DOORS_MEASURE_STATS*/
+
+ return object_group;
+}
+
+Load_Balancer::Group_List *
+Object_Group_Factory_i::list_groups (int random
+ ACE_ENV_ARG_DECL)
+{
+ Load_Balancer::Group_List * list;
+
+ // Figure out the length of the list.
+ CORBA::ULong len;
+ if (random)
+ len = random_groups_->current_size ();
+ else
+ len = rr_groups_->current_size ();
+
+ // Allocate the list of <len> length.
+ ACE_NEW_THROW_EX (list,
+ Load_Balancer::Group_List (len),
+ CORBA::NO_MEMORY ());
+ ACE_CHECK_RETURN (list);
+ list->length (len);
+
+ // Create an iterator for group structure to populate the list.
+ HASH_MAP::ITERATOR *group_iter;
+ HASH_MAP::ITERATOR random_iter (*(this->random_groups_));
+ HASH_MAP::ITERATOR rr_iter (*(this->rr_groups_));
+ if (random)
+ group_iter = &random_iter;
+ else
+ group_iter = &rr_iter;
+
+ // Iterate over groups and populate the list.
+ HASH_MAP::ENTRY *hash_entry = 0;
+ for (CORBA::ULong i = 0; i < len; i++)
+ {
+ group_iter->next (hash_entry);
+ group_iter->advance ();
+
+ (*list)[i] = ACE_OS::strdup (hash_entry->ext_id_);
+ }
+
+ return list;
+}
+
+Load_Balancer::Group_List *
+Object_Group_Factory_i::round_robin_groups (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return list_groups (0 ACE_ENV_ARG_PARAMETER);
+}
+
+Load_Balancer::Group_List *
+Object_Group_Factory_i::random_groups (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return list_groups (1 ACE_ENV_ARG_PARAMETER);
+}
+
+
+void
+Object_Group_Factory_i::update_flags (int random
+ ACE_ENV_ARG_DECL)
+{
+ //First check whether we have memory for flags_
+ if (!this->flags_)
+ {
+ if (this->mem_pool_->find (flags_name_bind,
+ (void *&) this->flags_) == -1)
+ {
+ void *value =
+ this->mem_pool_->malloc (sizeof (CORBA::Short));
+ ACE_NEW_THROW_EX (this->flags_,
+ (value) CORBA::Short (0),
+ CORBA::NO_MEMORY ());
+ ACE_CHECK;
+
+ // Initialize the variable
+ this->mem_pool_->bind (flags_name_bind,
+ (void *)this->flags_);
+ }
+ }
+
+ CORBA::Short val = *(this->flags_);
+ switch (val)
+ {
+ case 0:
+ if (random)
+ *(this->flags_) = 2;
+ else
+ *(this->flags_) = 1;
+ break;
+ case 1:
+ if (random)
+ *(this->flags_) = 3;
+ break;
+ case 2:
+ if (!random)
+ *(this->flags_) = 3;
+ break;
+
+ }
+}
+
+void
+Object_Group_Factory_i::update_objects (ACE_ENV_SINGLE_ARG_DECL)
+{
+ // Create an appropriate servant.
+ Object_Group_i * group_servant = 0;
+ Object_Group_i *group_servant_rep = 0;
+
+ // Check the value of of flags_ & do the instantiation and
+ // registration
+
+ switch (*(this->flags_))
+ {
+ case 1:
+ ACE_NEW_THROW_EX (group_servant,
+ RR_Object_Group ("Round Robin group",
+ this->poa_.in ()),
+ CORBA::NO_MEMORY ());
+ group_servant->_this ();
+ break;
+
+ case 2:
+ ACE_NEW_THROW_EX (group_servant,
+ Random_Object_Group ("Random group",
+ this->poa_.in ()),
+ CORBA::NO_MEMORY ());
+ group_servant->_this ();
+ break;
+ case 3:
+ ACE_NEW_THROW_EX (group_servant_rep,
+ Random_Object_Group ("Random group",
+ this->poa_.in ()),
+ CORBA::NO_MEMORY ());
+ group_servant_rep->_this ();
+
+ ACE_NEW_THROW_EX (group_servant,
+ RR_Object_Group ("Round Robin group",
+ this->poa_.in ()),
+ CORBA::NO_MEMORY ());
+ group_servant->_this ();
+ break;
+ }
+
+}
+
+
+Object_Group_i::Object_Group_i (const char * id,
+ PortableServer::POA_ptr poa)
+ :poa_ (PortableServer::POA::_duplicate (poa)),
+ member_id_list_ (0),
+ members_ (0),
+ id_ (id),
+ allocator_ (0)
+{
+
+ if (!this->allocator_)
+ {
+ ACE_MMAP_Memory_Pool::OPTIONS options (ACE_DEFAULT_BASE_ADDR);
+ ACE_NEW (this->allocator_,
+ ALLOCATOR ("Mem_Pool",
+ "Mem_Pool",
+ &options));
+ }
+}
+
+
+Object_Group_i::~Object_Group_i (void)
+{
+ // Need to delete all the items from the member_id_list, to avoid
+ // memory leaks.
+ Object_Group_i::ITERATOR iter (*member_id_list_);
+
+ do
+ {
+ delete (iter.next ());
+ } while (iter.advance ());
+
+ delete this->allocator_;
+}
+
+
+PortableServer::POA_ptr
+Object_Group_i::_default_POA (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return PortableServer::POA::_duplicate (this->poa_.in ());
+}
+
+
+char *
+Object_Group_i::id (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return CORBA::string_dup (id_.c_str ());
+}
+
+void
+Object_Group_i::bind (const Load_Balancer::Member & member
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::duplicate_member))
+{
+
+ if (this->members_ == 0)
+ {
+ ACE_CString id = this->id (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+
+ id += server_id_name_bind;
+
+ if (this->allocator_->find (id.c_str (), (void *&)this->members_) == -1)
+ {
+ void *hash_map = this->allocator_->malloc (sizeof (HASH_MAP));
+ ACE_NEW_THROW_EX (this->members_,
+ (hash_map) HASH_MAP (this->allocator_),
+ CORBA::NO_MEMORY ());
+ ACE_CHECK;
+
+ // Bind it in the mem pool with a name
+ if (this->allocator_->bind (id.c_str (),
+ (void *)this->members_) != 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "Unable to bind \n"));
+
+ }
+ }
+ }
+
+ // Check whether the element already exists..
+ if (this->members_->find (const_cast<char *> ((const char *) member.id),
+ this->allocator_) == 0)
+ ACE_THROW (Load_Balancer::duplicate_member ());
+
+ size_t id_len = ACE_OS::strlen (member.id) + 1;
+ size_t ref_len = ACE_OS::strlen (member.obj) + 1;
+
+ char *mem_alloc = (char *)this->allocator_->malloc (id_len + ref_len);
+
+ if (mem_alloc == 0)
+ ACE_THROW (CORBA::NO_MEMORY ());
+
+ char **id_ptr = (char **)this->allocator_->malloc (sizeof (char *));
+ *id_ptr = mem_alloc;
+ char *ior_ptr = mem_alloc + id_len;
+
+ ACE_OS::strcpy (*id_ptr, member.id);
+ ACE_OS::strcpy (ior_ptr, member.obj);
+
+
+ // Insert new member into <members_> and check for duplicates/failures.
+ int result = this->members_->trybind (*id_ptr,
+ ior_ptr);
+
+ if (result == 1)
+ ACE_THROW (Load_Balancer::duplicate_member ());
+ else if (result == -1)
+ ACE_THROW (CORBA::INTERNAL ());
+
+ // Search the list first from the mem mapp pool and then Insert new
+ // member's id into <member_id_list_>.
+
+ ACE_CString id = dll_name_bind;
+ id += this->id (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+
+
+ if (this->allocator_->find (id.c_str (),
+ (void *&)this->member_id_list_)
+ == -1)
+ {
+ void *dll_list = this->allocator_->malloc (sizeof (LIST));
+ ACE_NEW_THROW_EX (this->member_id_list_,
+ (dll_list) LIST (this->allocator_),
+ CORBA::NO_MEMORY ());
+ ACE_CHECK;
+
+ // Bind it in the mem pool with a name
+ if (this->allocator_->bind (id.c_str (),
+ (void *)this->member_id_list_) != 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "Unable to bind \n"));
+ return;
+ }
+ }
+
+ if (member_id_list_->insert_tail (id_ptr) == 0)
+ ACE_THROW (CORBA::NO_MEMORY ());
+
+ // Theoretically, we should deal with memory failures more
+ // thoroughly. But, practically, the whole system is going to be
+ // hosed anyways ...
+}
+
+void
+Object_Group_i::unbind (const char * id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::no_such_member))
+{
+ // Check whether the this->member_ is NULL
+ if (this->members_ == 0)
+ {
+ ACE_CString id = this->id (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+
+ id += server_id_name_bind;
+
+ if (this->allocator_->find (id.c_str (),
+ (void *&)this->members_) == -1)
+ {
+ ACE_THROW (Load_Balancer::no_such_member ());
+ }
+ }
+ // Check to make sure we have it.
+ if (this->members_->find (const_cast<char *> (id),
+ this->allocator_) == -1)
+ ACE_THROW (Load_Balancer::no_such_member ());
+
+ // Remove all entries for this member.
+ this->members_->unbind (const_cast<char *> (id),
+ this->allocator_);
+
+ if (this->member_id_list_ == 0)
+ {
+ ACE_CString id = dll_name_bind;
+ id += this->id (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+
+ if (this->allocator_->find (id.c_str (),
+ (void *&)this->member_id_list_)
+ == -1)
+ ACE_THROW (Load_Balancer::no_such_member ());
+
+ }
+
+
+
+ Object_Group_i::ITERATOR iter (*(this->member_id_list_));
+
+ while (ACE_OS::strcmp (id,*(iter.next ())))
+ iter.advance ();
+
+ this->allocator_->free ((void *) iter.next ());
+
+ iter.remove ();
+}
+
+char *
+Object_Group_i::resolve_with_id (const char * id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::no_such_member))
+{
+ CORBA::String_var ior;
+
+
+ if (this->members_->find (const_cast<char *> (id),
+ ior.out (), this->allocator_) == -1)
+ ACE_THROW_RETURN (Load_Balancer::no_such_member (),
+ 0);
+
+ char *retn_ptr = CORBA::string_dup (ior.in ());
+
+ return retn_ptr;
+
+}
+
+Load_Balancer::Member_ID_List *
+Object_Group_i::members (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ Load_Balancer::Member_ID_List * list = 0;
+
+ this->read_from_memory (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // Figure out the length of the list.
+ CORBA::ULong len = this->members_->current_size ();
+
+ // Allocate the list of <len> length.
+ ACE_NEW_THROW_EX (list,
+ Load_Balancer::Member_ID_List (len),
+ CORBA::NO_MEMORY ());
+ ACE_CHECK_RETURN (list);
+ list->length (len);
+
+ // Create an iterator for <member_id_list_> to populate the list.
+ Object_Group_i::ITERATOR id_iter (*this->member_id_list_);
+
+ char **item = 0;
+ // Iterate over groups and populate the list.
+ for (CORBA::ULong i = 0; i < len; i++)
+ {
+ this->member_id_list_->get (item);
+ (*list)[i] = *(id_iter.next ());
+ id_iter.advance ();
+ }
+
+ return list;
+}
+
+void
+Object_Group_i::destroy (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ // Deregister with POA.
+ PortableServer::POA_var poa =
+ this->_default_POA (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+
+ PortableServer::ObjectId_var id =
+ poa->servant_to_id (this
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ poa->deactivate_object (id.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+void
+Object_Group_i::read_from_memory (ACE_ENV_SINGLE_ARG_DECL)
+{
+ // Sanity check needs to be done in all the places
+ ACE_CString id = this->id (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+
+ if (!this->members_)
+ {
+ id += server_id_name_bind;
+
+ if (this->allocator_->find (id.c_str (),
+ (void *&)this->members_) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "Unable to find tha HASH MAP in the MMAP file \n"));
+ }
+ }
+
+
+ if (!this->member_id_list_)
+ {
+ id = dll_name_bind;
+ id += this->id (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+
+ if (this->allocator_->find (id.c_str (),
+ (void *&)this->member_id_list_) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "Unable to find tha HASH MAP in the MMAP file \n"));
+ }
+ }
+
+}
+
+
+Random_Object_Group::Random_Object_Group (const char *id,
+ PortableServer::POA_ptr poa)
+ : Object_Group_i (id, poa)
+{
+ // Seed the random number generator.
+ ACE_OS::srand (ACE_OS::time ());
+}
+
+char *
+Random_Object_Group::resolve (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::no_such_member))
+{
+
+ this->read_from_memory (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ size_t group_size = this->members_->current_size ();
+ if (group_size == 0)
+ ACE_THROW_RETURN (Load_Balancer::no_such_member (),
+ 0);
+
+ // Generate random number in the range [0, group_size - 1]
+ size_t member = ACE_OS::rand() % group_size;
+
+ // Get the id of the member to return to the client.
+ char **id = 0;
+ this->member_id_list_->get (id, member);
+ ACE_DEBUG ((LM_DEBUG, "In Random Group resolved to: %s\n",
+ *id));
+
+ // Return the object reference corresponding to the found id to the
+ // client.
+ char *objref = 0;
+ this->members_->find (*id,
+ objref,
+ this->allocator_);
+ char *string_ptr = CORBA::string_dup (objref);
+ return string_ptr;
+}
+
+RR_Object_Group::RR_Object_Group (const char *id,
+ PortableServer::POA_ptr poa)
+ : Object_Group_i (id, poa),
+ next_ (0)
+{
+}
+
+char *
+RR_Object_Group::resolve (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::no_such_member))
+{
+ char *objref = 0;
+
+ this->read_from_memory (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ size_t group_size = this->members_->current_size ();
+ if (group_size == 0)
+ ACE_THROW_RETURN (Load_Balancer::no_such_member (),
+ 0);
+
+ // Get the id of the member to return to the client.
+ char **id = 0;
+ this->member_id_list_->get (id, next_);
+ ACE_DEBUG ((LM_DEBUG,
+ "In RR Group resolved to: %s\n", *id));
+
+ // Adjust <next_> for the next invocation.
+ next_ = (next_ + 1) % group_size;
+
+
+ // Return the object reference corresponding to the found id to the client.
+ if (this->members_->find (*id,
+ objref,
+ this->allocator_) == -1)
+ ACE_THROW_RETURN (CORBA::INTERNAL (),
+ 0);
+
+ char *retn_ptr = CORBA::string_dup (objref);
+
+ return retn_ptr;
+}
+
+void
+RR_Object_Group::unbind (const char *id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::no_such_member))
+{
+
+ if (this->members_ == 0)
+ {
+ ACE_CString id = this->id (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+
+ id += server_id_name_bind;
+
+ if (this->allocator_->find (id.c_str (),
+ (void *&)this->members_) == -1)
+ {
+ ACE_THROW (Load_Balancer::no_such_member ());
+ }
+ }
+
+ // Check to make sure we have it.
+ if (this->members_->find (const_cast<char *> (id),
+ this->allocator_) == -1)
+ ACE_THROW (Load_Balancer::no_such_member ());
+
+ // Remove all entries for this member.
+ this->members_->unbind (const_cast<char *> (id),
+ this->allocator_);
+
+ // As we remove the id from the <member_id_list>, we note the
+ // position of the id in the list.
+ if (this->member_id_list_ == 0)
+ {
+ ACE_CString id = dll_name_bind;
+ id += this->id (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+
+ if (this->allocator_->find (id.c_str (),
+ (void *&)this->member_id_list_)
+ == -1)
+ ACE_THROW (Load_Balancer::no_such_member ());
+
+ }
+
+ size_t position = 0;
+ Object_Group_i::ITERATOR iter (*member_id_list_);
+ while (ACE_OS::strcmp (id ,*(iter.next ())))
+ {
+ iter.advance ();
+ position++;
+ }
+ this->allocator_->free (iter.next ());
+ iter.remove ();
+
+ size_t curr_size = this->members_->current_size ();
+
+ // Update <next_> if necessary to reflect the deletion.
+ if (position < next_)
+ this->next_--;
+ else if (curr_size == 0)
+ this->next_ = 0;
+ else if (position == next_)
+ this->next_ = next_ % (this->members_->current_size ());
+}
+