summaryrefslogtreecommitdiff
path: root/TAO/examples/Load_Balancing/Load_Balancer_i.cpp
diff options
context:
space:
mode:
authormarina <marina@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-08-21 22:37:09 +0000
committermarina <marina@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-08-21 22:37:09 +0000
commit43d163312698c50fd9ffef208fc0b8654a82e31b (patch)
treef39257e3a4c9fea9f0bd846c9531730130cf401a /TAO/examples/Load_Balancing/Load_Balancer_i.cpp
parent88c6c81859c4e6439a374a6ae55ad28fd891f72b (diff)
downloadATCD-43d163312698c50fd9ffef208fc0b8654a82e31b.tar.gz
ChangeLogTag:Sat Aug 21 17:18:07 1999 Marina Spivak <marina@cs.wustl.edu>
Diffstat (limited to 'TAO/examples/Load_Balancing/Load_Balancer_i.cpp')
-rw-r--r--TAO/examples/Load_Balancing/Load_Balancer_i.cpp419
1 files changed, 419 insertions, 0 deletions
diff --git a/TAO/examples/Load_Balancing/Load_Balancer_i.cpp b/TAO/examples/Load_Balancing/Load_Balancer_i.cpp
new file mode 100644
index 00000000000..90411209419
--- /dev/null
+++ b/TAO/examples/Load_Balancing/Load_Balancer_i.cpp
@@ -0,0 +1,419 @@
+// $Id$
+// ============================================================================
+//
+// = FILENAME
+// Load_Balancer_i.cpp
+//
+// = AUTHOR
+// Marina Spivak <marina@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "Load_Balancer_i.h"
+#include "ace/Auto_Ptr.h"
+
+Object_Group_Factory_i::Object_Group_Factory_i (void)
+{
+}
+
+Object_Group_Factory_i::~Object_Group_Factory_i (void)
+{
+}
+
+Load_Balancer::Object_Group_ptr
+Object_Group_Factory_i::make_round_robin (const char * id,
+ CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::duplicate_group))
+{
+ return make_group (0,
+ id,
+ ACE_TRY_ENV);
+}
+
+Load_Balancer::Object_Group_ptr
+Object_Group_Factory_i::make_random (const char * id,
+ CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::duplicate_group))
+{
+ return make_group (1,
+ id,
+ ACE_TRY_ENV);
+}
+
+Load_Balancer::Object_Group_ptr
+Object_Group_Factory_i::make_group (int random,
+ const char * id,
+ CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::duplicate_group))
+{
+ ACE_CString group_id (id);
+
+ // Check to make sure we don't already have a group with the same
+ // <id>.
+ if (rr_groups_.find (group_id) == 0
+ || random_groups_.find (group_id) == 0)
+ ACE_THROW_RETURN (Load_Balancer::duplicate_group,
+ Load_Balancer::Object_Group::_nil ());
+ else
+ {
+ // Store our result here for return.
+ Load_Balancer::Object_Group_var group;
+
+ // Create an appropriate servant.
+ Object_Group_i * group_servant;
+ if (random)
+ ACE_NEW_THROW_EX (group_servant,
+ Random_Object_Group (id),
+ CORBA::NO_MEMORY ());
+ else
+ ACE_NEW_THROW_EX (group_servant,
+ RR_Object_Group (id),
+ CORBA::NO_MEMORY ());
+ ACE_CHECK_RETURN (group._retn ());
+
+ // Temporarily put the servant into the auto_ptr.
+ ACE_Auto_Basic_Ptr<Object_Group_i> temp (group_servant);
+
+ // Register with the poa, begin using ref. counting.
+ group = group_servant->_this (ACE_TRY_ENV);
+ ACE_CHECK_RETURN (group._retn ());
+
+ group_servant->_remove_ref (ACE_TRY_ENV);
+ ACE_CHECK_RETURN (Load_Balancer::Object_Group::_nil ());
+ temp.release ();
+
+ // Make an entry in appropriate map of groups.
+ if (random)
+ {
+ if (random_groups_.bind (group_id, group) == -1)
+ ACE_THROW_RETURN (CORBA::INTERNAL (),
+ Load_Balancer::Object_Group::_nil ());
+ }
+ else
+ if (rr_groups_.bind (group_id, group) == -1)
+ ACE_THROW_RETURN (CORBA::INTERNAL (),
+ 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,
+ CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::no_such_group))
+{
+ ACE_CString group_id (id);
+ Load_Balancer::Object_Group_var group;
+
+ if (rr_groups_.find (group_id, group) == -1
+ && random_groups_.find (group_id, group) == -1)
+ ACE_THROW_RETURN (Load_Balancer::no_such_group,
+ Load_Balancer::Object_Group::_nil ());
+ else
+ return group._retn ();
+}
+
+Load_Balancer::Group_List *
+Object_Group_Factory_i::list_groups (int random,
+ CORBA::Environment &ACE_TRY_ENV)
+{
+ 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.
+ Object_Group_Factory_i::HASH_MAP::ITERATOR *group_iter;
+
+ if (random)
+ (*group_iter) = Object_Group_Factory_i::HASH_MAP::ITERATOR (random_groups_);
+ else
+ (*group_iter) = Object_Group_Factory_i::HASH_MAP::ITERATOR (rr_groups_);
+
+ // Iterate over groups and populate the list.
+ Object_Group_Factory_i::HASH_MAP::ENTRY *hash_entry;
+ for (CORBA::ULong i = 0; i < len; i++)
+ {
+ group_iter->next (hash_entry);
+ group_iter->advance ();
+
+ (*list)[i] = hash_entry->ext_id_.c_str ();
+ }
+
+ return list;
+}
+
+Load_Balancer::Group_List *
+Object_Group_Factory_i::round_robin_groups (CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return list_groups (0, ACE_TRY_ENV);
+}
+
+Load_Balancer::Group_List *
+Object_Group_Factory_i::random_groups (CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return list_groups (1, ACE_TRY_ENV);
+}
+
+Object_Group_i::Object_Group_i (const char * id)
+ : id_ (id)
+{
+}
+
+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 ());
+}
+
+char *
+Object_Group_i::id (CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return CORBA::string_dup (id_.c_str ());
+}
+
+void
+Object_Group_i::bind (const Load_Balancer::Member & member,
+ CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::duplicate_member))
+{
+ ACE_CString member_id (member.id);
+ CORBA::Object_var obj = CORBA::Object::_duplicate (member.obj.in ());
+
+ // Insert new member into <members_> and check for duplicates/failures.
+ int result = members_.trybind (member_id, obj);
+ if (result == 1)
+ ACE_THROW (Load_Balancer::duplicate_member);
+ else if (result == -1)
+ ACE_THROW (CORBA::INTERNAL ());
+
+ // Insert new member's id into <member_id_list_>.
+ ACE_CString *new_id;
+ ACE_NEW_THROW_EX (new_id,
+ ACE_CString (member.id),
+ CORBA::NO_MEMORY ());
+ ACE_CHECK;
+ if (member_id_list_.insert_tail (new_id) == 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,
+ CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::no_such_member))
+{
+ ACE_CString member_id (id);
+
+ // Code below works iff list and hash map states are consistent,
+ // which is the case unless the system experienced major problems,
+ // e.g., ran out of memory ...
+
+ // Check to make sure we have it.
+ if (members_.find (member_id) == -1)
+ ACE_THROW (Load_Balancer::no_such_member);
+
+ // Remove all entries for this member.
+ members_.unbind (member_id);
+
+ Object_Group_i::ITERATOR iter (member_id_list_);
+ while (member_id != *(iter.next ()))
+ iter.advance ();
+ delete (iter.next ());
+ iter.remove ();
+}
+
+CORBA::Object_ptr
+Object_Group_i::resolve_with_id (const char * id,
+ CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::no_such_member))
+{
+ CORBA::Object_var obj;
+ ACE_CString member_id (id);
+
+ if (members_.find (member_id, obj) == -1)
+ ACE_THROW_RETURN (Load_Balancer::no_such_member,
+ obj._retn ());
+
+ return obj._retn ();
+}
+
+Load_Balancer::Member_ID_List *
+Object_Group_i::members (CORBA::Environment &ACE_TRY_ENV)
+{
+ Load_Balancer::Member_ID_List * list;
+
+ // Figure out the length of the list.
+ CORBA::ULong len = 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 (member_id_list_);
+
+ // Iterate over groups and populate the list.
+ for (CORBA::ULong i = 0; i < len; i++)
+ {
+ (*list)[i] = id_iter.next ()->c_str ();
+ id_iter.advance ();
+ }
+
+ return list;
+}
+
+void
+Object_Group_i::destroy (CORBA::Environment &ACE_TRY_ENV)
+{
+ // Deregister with POA.
+ PortableServer::POA_var poa =
+ this->_default_POA (ACE_TRY_ENV);
+ ACE_CHECK;
+
+ PortableServer::ObjectId_var id =
+ poa->servant_to_id (this,
+ ACE_TRY_ENV);
+ ACE_CHECK;
+
+ poa->deactivate_object (id.in (),
+ ACE_TRY_ENV);
+ ACE_CHECK;
+}
+
+Random_Object_Group::Random_Object_Group (const char *id)
+ : Object_Group_i (id)
+{
+ // Seed the random number generator.
+ ACE_OS::srand (ACE_OS::time ());
+}
+
+CORBA::Object_ptr
+Random_Object_Group::resolve (CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::no_such_member))
+{
+ CORBA::Object_var obj;
+
+ size_t group_size = members_.current_size ();
+ if (group_size == 0)
+ ACE_THROW_RETURN (Load_Balancer::no_such_member,
+ obj._retn ());
+
+ // 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.
+ ACE_CString *id;
+ member_id_list_.get (id, member);
+ ACE_DEBUG ((LM_DEBUG, "In Random Group resolved to: %s\n",
+ id->c_str()));
+
+ // Return the object reference corresponding to the found id to the client.
+ members_.find (*id, obj);
+ return obj._retn ();
+}
+
+RR_Object_Group::RR_Object_Group (const char *id)
+ : Object_Group_i (id),
+ next_ (0)
+{
+}
+
+CORBA::Object_ptr
+RR_Object_Group::resolve (CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::no_such_member))
+{
+ CORBA::Object_var obj;
+
+ size_t group_size = members_.current_size ();
+ if (group_size == 0)
+ ACE_THROW_RETURN (Load_Balancer::no_such_member,
+ obj._retn ());
+
+ // Get the id of the member to return to the client.
+ ACE_CString *id;
+ member_id_list_.get (id, next_);
+ ACE_DEBUG ((LM_DEBUG, "In RR Group resolved to: %s\n", id->c_str ()));
+
+ // Adjust <next_> for the next invocation.
+ next_ = (next_ + 1) % group_size;
+
+ // Return the object reference corresponding to the found id to the client.
+ if (members_.find (*id, obj) == -1)
+ ACE_THROW_RETURN (CORBA::INTERNAL (),
+ CORBA::Object::_nil ());
+
+ return obj._retn ();
+}
+
+void
+RR_Object_Group::unbind (const char *id,
+ CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ Load_Balancer::no_such_member))
+{
+ ACE_CString member_id (id);
+
+ // Check to make sure we have it.
+ if (members_.find (member_id) == -1)
+ ACE_THROW (Load_Balancer::no_such_member);
+
+ // Remove all entries for this member.
+ members_.unbind (member_id);
+
+ // As we remove the id from the <member_id_list>, we note the
+ // position of the id in the list.
+ size_t position = 0;
+ Object_Group_i::ITERATOR iter (member_id_list_);
+ while (member_id != *(iter.next ()))
+ {
+ iter.advance ();
+ position++;
+ }
+ delete (iter.next ());
+ iter.remove ();
+
+ // Update <next_> if necessary to reflect the deletion.
+ if (position < next_)
+ next_--;
+
+ else if (position == next_)
+ next_ = next_ % (members_.current_size ());
+}