1 #include "Load_Balancer_i.h"
3 #include "ace/Hash_Map_Manager_T.h"
5 const char *rr_name_bind
= "RR_Group";
6 // Name binding for the location of the Round Robin info in the mem pool
8 const char *random_name_bind
= "Random_Group";
9 // Name binding for the location of the Random info in the mem pool
11 const char *flags_name_bind
= "FLAGS";
12 // Name binding for the location of the flags info in the mem pool
14 const char *dll_name_bind
= "DLL_LIST";
15 // Name binding for the DLL_LIst in the me_pool;
17 const char *server_id_name_bind
= "server_id";
18 // Some cookie that is used for appending names
20 Object_Group_Factory_i::Object_Group_Factory_i (CORBA::ORB_ptr orb
,
21 PortableServer::POA_ptr poa
)
23 poa_ (PortableServer::POA::_duplicate (poa
)),
28 ACE_MMAP_Memory_Pool::OPTIONS
options (ACE_DEFAULT_BASE_ADDR
);
29 ACE_NEW (this->mem_pool_
,
30 ALLOCATOR ("Mem_Pool",
35 Object_Group_Factory_i::~Object_Group_Factory_i ()
37 delete this->mem_pool_
;
40 PortableServer::POA_ptr
41 Object_Group_Factory_i::_default_POA ()
43 return PortableServer::POA::_duplicate (this->poa_
.in ());
47 Load_Balancer::Object_Group_ptr
48 Object_Group_Factory_i::make_round_robin (const char * id
)
52 if (this->mem_pool_
->find (rr_name_bind
,
55 this->rr_groups_
= reinterpret_cast <HASH_MAP
*> (tmp_rr
);
59 void *hash_map
= this->mem_pool_
->malloc (sizeof (HASH_MAP
));
62 throw CORBA::NO_MEMORY ();
64 this->rr_groups_
= new (hash_map
) HASH_MAP (this->mem_pool_
);
66 // Bind it in the mem pool with a name
67 if (this->mem_pool_
->bind (rr_name_bind
,
68 (void *)this->rr_groups_
) != 0)
70 ACE_ERROR_RETURN ((LM_ERROR
,
76 return this->make_group (0,
81 Object_Group_Factory_i::unbind_round_robin (const char * id
)
83 if (this->rr_groups_
== 0)
87 if (this->mem_pool_
->find (rr_name_bind
,
89 throw Load_Balancer::no_such_group ();
91 this->rr_groups_
= reinterpret_cast <HASH_MAP
*> (tmp_rr
);
96 // Throw an exception if not found in the HASH MAP
97 if (this->rr_groups_
->find (const_cast<char *> (id
),
99 throw Load_Balancer::no_such_group ();
102 this->rr_groups_
->unbind (const_cast<char *> (id
),
106 // Free the memory from the pool
107 this->mem_pool_
->free (int_id
- (ACE_OS::strlen (id
) + 1));
109 // Change the FLAGS variable
110 if (this->flags_
== 0)
114 if (this->mem_pool_
->find (flags_name_bind
,
118 this->flags_
= reinterpret_cast <CORBA::Short
*> (tmp_flags
);
121 // Bump down the flags value
125 Load_Balancer::Object_Group_ptr
126 Object_Group_Factory_i::make_random (const char * id
)
128 void *tmp_random (0);
130 if (this->mem_pool_
->find (random_name_bind
, tmp_random
) == 0)
132 this->random_groups_
= reinterpret_cast <HASH_MAP
*> (tmp_random
);
136 void *hash_map
= this->mem_pool_
->malloc (sizeof (HASH_MAP
));
139 throw CORBA::NO_MEMORY ();
141 this->random_groups_
= new (hash_map
) HASH_MAP (this->mem_pool_
);
143 // Bind it in the mem pool with a name
144 if (this->mem_pool_
->bind (random_name_bind
,
145 (void *)this->random_groups_
) != 0)
147 ACE_ERROR_RETURN ((LM_ERROR
,
153 return this->make_group (1,
159 Object_Group_Factory_i::unbind_random (const char * id
)
161 if (this->random_groups_
== 0)
163 void *tmp_random (0);
165 if (this->mem_pool_
->find (random_name_bind
,
167 throw Load_Balancer::no_such_group ();
169 this->random_groups_
= reinterpret_cast <HASH_MAP
*> (tmp_random
);
174 // Throw an exception if not found in the HASH MAP
175 if (this->random_groups_
->find (const_cast<char *> (id
),
176 this->mem_pool_
) < 0)
177 throw Load_Balancer::no_such_group ();
180 this->random_groups_
->unbind (const_cast<char *> (id
),
184 // Free the memory from the pool
185 this->mem_pool_
->free (int_id
- (ACE_OS::strlen (id
) + 1));
187 // Change the FLAGS variable
188 if (this->flags_
== 0)
192 if (this->mem_pool_
->find (flags_name_bind
,
196 this->flags_
= reinterpret_cast <CORBA::Short
*> (tmp_flags
);
199 // Bump down the flags value
203 Load_Balancer::Object_Group_ptr
204 Object_Group_Factory_i::make_group (int random
,
207 // Store our result here for return.
208 Load_Balancer::Object_Group_var group
;
210 // Create an appropriate servant.
211 Object_Group_i
*group_servant
= 0;
213 // Check to make sure we don't already have a group with the same
218 if (this->random_groups_
->find (const_cast<char *> (id
),
219 this->mem_pool_
) == 0)
220 throw Load_Balancer::duplicate_group ();
224 if (this->rr_groups_
->find (const_cast<char *> (id
),
225 this->mem_pool_
) == 0)
226 throw Load_Balancer::duplicate_group ();
230 // As we are sure that it is not in the list go ahead and insert it
232 ACE_NEW_THROW_EX (group_servant
,
233 Random_Object_Group (id
,
235 CORBA::NO_MEMORY ());
237 ACE_NEW_THROW_EX (group_servant
,
240 CORBA::NO_MEMORY ());
242 // Register with the poa, begin using ref. counting.
243 group
= group_servant
->_this ();
245 group_servant
->_remove_ref ();
247 CORBA::String_var ior
=
248 this->orb_
->object_to_string (group
.in ());
251 // Calculate and allocate the memory we need to store this name to
253 size_t id_len
= ACE_OS::strlen (id
) + 1;
254 size_t kind_len
= ACE_OS::strlen (ior
.in ()) + 1;
256 char *ptr
= (char *) this->mem_pool_
->malloc (id_len
+ kind_len
);
259 throw CORBA::NO_MEMORY ();
262 char * ior_ptr
= ptr
+ id_len
;
264 ACE_OS::strcpy (id_ptr
, id
);
265 ACE_OS::strcpy (ior_ptr
, ior
.in ());
267 // Store the results here
268 CORBA::Long result
= 0;
270 // Make an entry in appropriate map of groups.
273 result
= this->random_groups_
->bind (id_ptr
,
279 result
= this->rr_groups_
->bind (id_ptr
,
285 // Update the value of flags_
286 this->update_flags (random
);
290 // For some reason the bind failed. Free our
291 // dynamically allocated memory.
292 this->mem_pool_
->free ((void *) ptr
);
293 throw Load_Balancer::duplicate_group ();
297 ACE_DEBUG ((LM_DEBUG
, "Successfully created new group: %s\n", id
));
299 return group
._retn ();
303 Load_Balancer::Object_Group_ptr
304 Object_Group_Factory_i::resolve (const char * id
)
306 #if defined (DOORS_MEASURE_STATS)
308 // Record the entry time.
309 ACE_hrtime_t latency_base
= ACE_OS::gethrtime ();
311 #endif /*DOORS_MEASURE_STATS*/
313 // It could be that the Load balancing service could have failed
314 // before the Client tries to invoke this call.. In such a case the
315 // Service should look in to the MMAP file and read in the info
316 // before it can resolve the ID sent by the client.. So we check
317 // whether the class holds the pointer.. If not we look in to the
318 // MMAP file for the relevant info..
319 if (!this->rr_groups_
)
323 if (this->mem_pool_
->find (rr_name_bind
,
326 this->rr_groups_
= reinterpret_cast <HASH_MAP
*> (tmp_rr
);
330 ACE_ERROR_RETURN ((LM_ERROR
,
331 ACE_TEXT ("(%N|%l) The factory does not have any references ")
332 ACE_TEXT ("to the group that you have sought \n\n")),
337 if (!this->random_groups_
)
339 void *tmp_random (0);
341 if (this->mem_pool_
->find (random_name_bind
,
344 this->random_groups_
= reinterpret_cast <HASH_MAP
*> (tmp_random
);
348 ACE_ERROR_RETURN ((LM_ERROR
,
349 ACE_TEXT ("(%N|%l) The factory does not have any references ")
350 ACE_TEXT ("to the group that you have sought \n\n")),
359 this->mem_pool_
->find (flags_name_bind
,
361 this->flags_
= reinterpret_cast <CORBA::Short
*> (tmp_flags
);
363 this->update_objects ();
368 if (rr_groups_
->find (const_cast<char *> (id
),
370 this->mem_pool_
) == -1
371 && random_groups_
->find (const_cast<char *> (id
),
373 this->mem_pool_
) == -1)
374 throw Load_Balancer::no_such_group ();
376 CORBA::Object_var objref
=
377 this->orb_
->string_to_object (ior
);
379 Load_Balancer::Object_Group_ptr
380 object_group
= Load_Balancer::Object_Group::_narrow (objref
.in ());
383 #if defined (DOORS_MEASURE_STATS)
384 // Grab timestamp again.
385 ACE_hrtime_t now
= ACE_OS::gethrtime ();
387 this->throughput_
.sample (0,
390 ACE_High_Res_Timer::global_scale_factor_type gsf
=
391 ACE_High_Res_Timer::global_scale_factor ();
392 ACE_OS::printf ("*=*=*=*=Aggregated result *=*=*=*=*=\n");
393 this->throughput_
.dump_results (ACE_TEXT("Aggregated"), gsf
);
395 #endif /*DOORS_MEASURE_STATS*/
400 Load_Balancer::Group_List
*
401 Object_Group_Factory_i::list_groups (int random
)
403 Load_Balancer::Group_List
* list
;
405 // Figure out the length of the list.
408 len
= random_groups_
->current_size ();
410 len
= rr_groups_
->current_size ();
412 // Allocate the list of <len> length.
413 ACE_NEW_THROW_EX (list
,
414 Load_Balancer::Group_List (len
),
415 CORBA::NO_MEMORY ());
418 // Create an iterator for group structure to populate the list.
419 HASH_MAP::ITERATOR
*group_iter
;
420 HASH_MAP::ITERATOR
random_iter (*(this->random_groups_
));
421 HASH_MAP::ITERATOR
rr_iter (*(this->rr_groups_
));
423 group_iter
= &random_iter
;
425 group_iter
= &rr_iter
;
427 // Iterate over groups and populate the list.
428 HASH_MAP::ENTRY
*hash_entry
= 0;
429 for (CORBA::ULong i
= 0; i
< len
; i
++)
431 group_iter
->next (hash_entry
);
432 group_iter
->advance ();
434 (*list
)[i
] = ACE_OS::strdup (hash_entry
->ext_id_
);
440 Load_Balancer::Group_List
*
441 Object_Group_Factory_i::round_robin_groups ()
443 return list_groups (0);
446 Load_Balancer::Group_List
*
447 Object_Group_Factory_i::random_groups ()
449 return list_groups (1);
454 Object_Group_Factory_i::update_flags (int random
)
456 //First check whether we have memory for flags_
461 if (this->mem_pool_
->find (flags_name_bind
,
464 this->flags_
= reinterpret_cast <CORBA::Short
*> (tmp_flags
);
469 this->mem_pool_
->malloc (sizeof (CORBA::Short
));
472 throw CORBA::NO_MEMORY ();
474 this->flags_
= new (value
) CORBA::Short (0);
476 // Initialize the variable
477 this->mem_pool_
->bind (flags_name_bind
,
478 (void *)this->flags_
);
482 CORBA::Short val
= *(this->flags_
);
503 Object_Group_Factory_i::update_objects ()
505 // Create an appropriate servant.
506 Object_Group_i
* group_servant
= 0;
507 Object_Group_i
*group_servant_rep
= 0;
509 // Check the value of of flags_ & do the instantiation and
512 switch (*(this->flags_
))
515 ACE_NEW_THROW_EX (group_servant
,
516 RR_Object_Group ("Round Robin group",
518 CORBA::NO_MEMORY ());
519 group_servant
->_this ();
523 ACE_NEW_THROW_EX (group_servant
,
524 Random_Object_Group ("Random group",
526 CORBA::NO_MEMORY ());
527 group_servant
->_this ();
530 ACE_NEW_THROW_EX (group_servant_rep
,
531 Random_Object_Group ("Random group",
533 CORBA::NO_MEMORY ());
534 group_servant_rep
->_this ();
536 ACE_NEW_THROW_EX (group_servant
,
537 RR_Object_Group ("Round Robin group",
539 CORBA::NO_MEMORY ());
540 group_servant
->_this ();
547 Object_Group_i::Object_Group_i (const char * id
,
548 PortableServer::POA_ptr poa
)
549 :poa_ (PortableServer::POA::_duplicate (poa
)),
555 if (!this->allocator_
)
557 ACE_MMAP_Memory_Pool::OPTIONS
options (ACE_DEFAULT_BASE_ADDR
);
558 ACE_NEW (this->allocator_
,
559 ALLOCATOR ("Mem_Pool",
566 Object_Group_i::~Object_Group_i ()
568 // Need to delete all the items from the member_id_list, to avoid
570 Object_Group_i::ITERATOR
iter (*member_id_list_
);
574 delete (iter
.next ());
575 } while (iter
.advance ());
577 delete this->allocator_
;
581 PortableServer::POA_ptr
582 Object_Group_i::_default_POA ()
584 return PortableServer::POA::_duplicate (this->poa_
.in ());
589 Object_Group_i::id ()
591 return CORBA::string_dup (id_
.c_str ());
595 Object_Group_i::bind (const Load_Balancer::Member
& member
)
597 if (this->members_
== 0)
599 ACE_CString id
= this->id ();
601 id
+= server_id_name_bind
;
603 void *tmp_members (0);
605 if (this->allocator_
->find (id
.c_str (), tmp_members
) == 0)
607 this->members_
= reinterpret_cast <HASH_MAP
*> (tmp_members
);
611 void *hash_map
= this->allocator_
->malloc (sizeof (HASH_MAP
));
614 throw CORBA::NO_MEMORY ();
616 this->members_
= new (hash_map
) HASH_MAP (this->allocator_
);
618 // Bind it in the mem pool with a name
619 if (this->allocator_
->bind (id
.c_str (),
620 (void *)this->members_
) != 0)
622 ACE_ERROR ((LM_ERROR
,
623 "Unable to bind\n"));
628 // Check whether the element already exists..
629 if (this->members_
->find (const_cast<char *> ((const char *) member
.id
),
630 this->allocator_
) == 0)
631 throw Load_Balancer::duplicate_member ();
633 size_t id_len
= ACE_OS::strlen (member
.id
) + 1;
634 size_t ref_len
= ACE_OS::strlen (member
.obj
) + 1;
636 char *mem_alloc
= (char *)this->allocator_
->malloc (id_len
+ ref_len
);
639 throw CORBA::NO_MEMORY ();
641 char **id_ptr
= (char **)this->allocator_
->malloc (sizeof (char *));
643 char *ior_ptr
= mem_alloc
+ id_len
;
645 ACE_OS::strcpy (*id_ptr
, member
.id
);
646 ACE_OS::strcpy (ior_ptr
, member
.obj
);
649 // Insert new member into <members_> and check for duplicates/failures.
650 int result
= this->members_
->trybind (*id_ptr
,
654 throw Load_Balancer::duplicate_member ();
655 else if (result
== -1)
656 throw CORBA::INTERNAL ();
658 // Search the list first from the mem mapp pool and then Insert new
659 // member's id into <member_id_list_>.
661 ACE_CString id
= dll_name_bind
;
665 void *tmp_id_list (0);
667 if (this->allocator_
->find (id
.c_str (),
671 this->member_id_list_
= reinterpret_cast <LIST
*> (tmp_id_list
);
675 void *dll_list
= this->allocator_
->malloc (sizeof (LIST
));
678 throw CORBA::NO_MEMORY ();
680 this->member_id_list_
= new (dll_list
) LIST (this->allocator_
);
682 // Bind it in the mem pool with a name
683 if (this->allocator_
->bind (id
.c_str (),
684 (void *)this->member_id_list_
) != 0)
686 ACE_ERROR ((LM_ERROR
,
687 "Unable to bind\n"));
692 if (member_id_list_
->insert_tail (id_ptr
) == 0)
693 throw CORBA::NO_MEMORY ();
695 // Theoretically, we should deal with memory failures more
696 // thoroughly. But, practically, the whole system is going to be
701 Object_Group_i::unbind (const char * id
)
703 // Check whether the this->member_ is NULL
704 if (this->members_
== 0)
706 ACE_CString id
= this->id ();
708 id
+= server_id_name_bind
;
710 void *tmp_members (0);
712 if (this->allocator_
->find (id
.c_str (),
715 throw Load_Balancer::no_such_member ();
718 this->members_
= reinterpret_cast <HASH_MAP
*> (tmp_members
);
720 // Check to make sure we have it.
721 if (this->members_
->find (const_cast<char *> (id
),
722 this->allocator_
) == -1)
723 throw Load_Balancer::no_such_member ();
725 // Remove all entries for this member.
726 this->members_
->unbind (const_cast<char *> (id
),
729 if (this->member_id_list_
== 0)
731 ACE_CString id
= dll_name_bind
;
734 void *tmp_id_list (0);
736 if (this->allocator_
->find (id
.c_str (),
739 throw Load_Balancer::no_such_member ();
741 this->member_id_list_
= reinterpret_cast <LIST
*> (tmp_id_list
);
745 Object_Group_i::ITERATOR
iter (*(this->member_id_list_
));
747 while (ACE_OS::strcmp (id
,*(iter
.next ())))
750 this->allocator_
->free ((void *) iter
.next ());
756 Object_Group_i::resolve_with_id (const char * id
)
758 CORBA::String_var ior
;
761 if (this->members_
->find (const_cast<char *> (id
),
762 ior
.out (), this->allocator_
) == -1)
763 throw Load_Balancer::no_such_member ();
765 char *retn_ptr
= CORBA::string_dup (ior
.in ());
770 Load_Balancer::Member_ID_List
*
771 Object_Group_i::members ()
773 Load_Balancer::Member_ID_List
* list
= 0;
775 this->read_from_memory ();
777 // Figure out the length of the list.
778 CORBA::ULong len
= this->members_
->current_size ();
780 // Allocate the list of <len> length.
781 ACE_NEW_THROW_EX (list
,
782 Load_Balancer::Member_ID_List (len
),
783 CORBA::NO_MEMORY ());
786 // Create an iterator for <member_id_list_> to populate the list.
787 Object_Group_i::ITERATOR
id_iter (*this->member_id_list_
);
790 // Iterate over groups and populate the list.
791 for (CORBA::ULong i
= 0; i
< len
; i
++)
793 this->member_id_list_
->get (item
);
794 (*list
)[i
] = *(id_iter
.next ());
802 Object_Group_i::destroy ()
804 // Deregister with POA.
805 PortableServer::POA_var poa
=
806 this->_default_POA ();
808 PortableServer::ObjectId_var id
=
809 poa
->servant_to_id (this);
811 poa
->deactivate_object (id
.in ());
815 Object_Group_i::read_from_memory ()
817 // Sanity check needs to be done in all the places
818 ACE_CString id
= this->id ();
822 id
+= server_id_name_bind
;
824 void *tmp_members (0);
826 if (this->allocator_
->find (id
.c_str (),
829 this->members_
= reinterpret_cast <HASH_MAP
*> (tmp_members
);
833 ACE_ERROR ((LM_ERROR
,
834 "Unable to find tha HASH MAP in the MMAP file\n"));
839 if (!this->member_id_list_
)
844 void *tmp_id_list (0);
846 if (this->allocator_
->find (id
.c_str (),
849 this->member_id_list_
= reinterpret_cast <LIST
*> (tmp_id_list
);
853 ACE_ERROR ((LM_ERROR
,
854 "Unable to find tha HASH MAP in the MMAP file\n"));
861 Random_Object_Group::Random_Object_Group (const char *id
,
862 PortableServer::POA_ptr poa
)
863 : Object_Group_i (id
, poa
)
865 // Seed the random number generator.
866 ACE_OS::srand (static_cast<u_int
> (ACE_OS::time ()));
870 Random_Object_Group::resolve ()
872 this->read_from_memory ();
874 size_t group_size
= this->members_
->current_size ();
876 throw Load_Balancer::no_such_member ();
878 // Generate random number in the range [0, group_size - 1]
879 size_t member
= ACE_OS::rand() % group_size
;
881 // Get the id of the member to return to the client.
883 this->member_id_list_
->get (id
, member
);
884 ACE_DEBUG ((LM_DEBUG
, "In Random Group resolved to: %s\n",
887 // Return the object reference corresponding to the found id to the
890 this->members_
->find (*id
,
893 char *string_ptr
= CORBA::string_dup (objref
);
897 RR_Object_Group::RR_Object_Group (const char *id
,
898 PortableServer::POA_ptr poa
)
899 : Object_Group_i (id
, poa
),
905 RR_Object_Group::resolve ()
909 this->read_from_memory ();
911 size_t group_size
= this->members_
->current_size ();
913 throw Load_Balancer::no_such_member ();
915 // Get the id of the member to return to the client.
917 this->member_id_list_
->get (id
, next_
);
918 ACE_DEBUG ((LM_DEBUG
,
919 "In RR Group resolved to: %s\n", *id
));
921 // Adjust <next_> for the next invocation.
922 next_
= (next_
+ 1) % group_size
;
925 // Return the object reference corresponding to the found id to the client.
926 if (this->members_
->find (*id
,
928 this->allocator_
) == -1)
929 throw CORBA::INTERNAL ();
931 char *retn_ptr
= CORBA::string_dup (objref
);
937 RR_Object_Group::unbind (const char *id
)
939 if (this->members_
== 0)
941 ACE_CString id
= this->id ();
943 id
+= server_id_name_bind
;
945 void *tmp_members (0);
947 if (this->allocator_
->find (id
.c_str (),
950 throw Load_Balancer::no_such_member ();
953 this->members_
= reinterpret_cast <HASH_MAP
*> (tmp_members
);
956 // Check to make sure we have it.
957 if (this->members_
->find (const_cast<char *> (id
),
958 this->allocator_
) == -1)
959 throw Load_Balancer::no_such_member ();
961 // Remove all entries for this member.
962 this->members_
->unbind (const_cast<char *> (id
),
965 // As we remove the id from the <member_id_list>, we note the
966 // position of the id in the list.
967 if (this->member_id_list_
== 0)
969 ACE_CString id
= dll_name_bind
;
972 void *tmp_id_list (0);
974 if (this->allocator_
->find (id
.c_str (),
977 throw Load_Balancer::no_such_member ();
979 this->member_id_list_
= reinterpret_cast <LIST
*> (tmp_id_list
);
983 Object_Group_i::ITERATOR
iter (*member_id_list_
);
984 while (ACE_OS::strcmp (id
,*(iter
.next ())))
989 this->allocator_
->free (iter
.next ());
992 size_t curr_size
= this->members_
->current_size ();
994 // Update <next_> if necessary to reflect the deletion.
995 if (position
< next_
)
997 else if (curr_size
== 0)
999 else if (position
== next_
)
1000 this->next_
= next_
% (this->members_
->current_size ());