diff options
Diffstat (limited to 'TAO/orbsvcs/orbsvcs/Naming/FaultTolerant')
25 files changed, 5220 insertions, 0 deletions
diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Location_Index_Map.h b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Location_Index_Map.h new file mode 100644 index 00000000000..fa1fe4e3cee --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Location_Index_Map.h @@ -0,0 +1,42 @@ +// -*- C++ -*- + +//======================================================================= +/** + * @file FT_Location_Index_Map.h + * + * $Id$ + * + * @author Kevin Stanley <stanleyk@ociweb.com> + */ +//======================================================================= + + +#ifndef TAO_FT_LOCATION_INDEX_MAP_H +#define TAO_FT_LOCATION_INDEX_MAP_H + +#include /**/ "ace/pre.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "orbsvcs/PortableGroupC.h" + +#include "ace/Functor.h" +#include "ace/Hash_Map_Manager_T.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +/// Location index map. +typedef ACE_Hash_Map_Manager_Ex< + PortableGroup::ObjectGroupId, + CORBA::ULong, + ACE_Hash<ACE_UINT64>, + ACE_Equal_To<ACE_UINT64>, + ACE_Null_Mutex> TAO_FT_Location_Index_Map; + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" + +#endif /* TAO_FT_LOCATION_INDEX_MAP_H */ diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Manager.cpp b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Manager.cpp new file mode 100644 index 00000000000..011f25b2190 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Manager.cpp @@ -0,0 +1,747 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file FT_Naming_Manager.cpp + * + * $Id$ + * + * @author Kevin Stanley <stanleyk@ociweb.com> + */ +//============================================================================= + +#include "orbsvcs/Naming/FaultTolerant/FT_Naming_Manager.h" +#include "orbsvcs/FT_NamingManagerC.h" +#include "orbsvcs/PortableGroup/PG_Property_Utils.h" +#include "orbsvcs/PortableGroup/PG_Property_Set.h" +#include "orbsvcs/PortableGroup/PG_Object_Group.h" +#include "orbsvcs/PortableGroup/PG_conf.h" +#include "orbsvcs/PortableGroup/PG_Utils.h" + +#include "tao/debug.h" +#include "tao/ORB_Constants.h" + +#include "ace/SString.h" +#include "ace/OS_NS_sys_time.h" +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_string.h" + +// Use this macro at the beginning of CORBA methods +// to aid in debugging. +#define METHOD_ENTRY(name) \ + if (TAO_debug_level > 6) \ + { \ + ACE_DEBUG (( LM_DEBUG, \ + "Enter %s\n", #name \ + )); \ + } + +// Use this macro to return from CORBA methods +// to aid in debugging. Note that you can specify +// the return value after the macro, for example: +// METHOD_RETURN(Plugh::plover) xyzzy; is equivalent +// to return xyzzy; +// METHOD_RETURN(Plugh::troll); is equivalent to +// return; +// WARNING: THIS GENERATES TWO STATEMENTS!!! THE FOLLOWING +// will not do what you want it to: +// if (cave_is_closing) METHOD_RETURN(Plugh::pirate) aarrggh; +// Moral: Always use braces. +#define METHOD_RETURN(name) \ + if (TAO_debug_level > 6) \ + { \ + ACE_DEBUG (( LM_DEBUG, \ + "Leave %s\n", #name \ + )); \ + } \ + return /* value goes here */ + + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_FT_Naming_Manager::TAO_FT_Naming_Manager (void) + : factory_registry_ ("NamingManager::FactoryRegistry"), + group_factory_ (), + built_in_balancing_strategy_name_ (1), + object_group_property_name_ (1) + +{ + // The name for the property which contains the load balancing strategy value + this->built_in_balancing_strategy_name_.length (1); + this->built_in_balancing_strategy_name_[0].id = + FT_Naming::TAO_FT_LOAD_BALANCING_STRATEGY; + + // The name for the property which contains the object group name + this->object_group_property_name_.length (1); + this->object_group_property_name_[0].id = + FT_Naming::TAO_FT_OBJECT_GROUP_NAME; +} + +TAO_FT_Naming_Manager::~TAO_FT_Naming_Manager (void) +{ + this->object_group_property_name_.length (0); + this->built_in_balancing_strategy_name_.length (0); +} + + +CORBA::Object_ptr +TAO_FT_Naming_Manager::create_object_group ( + const char * group_name, + FT_Naming::LoadBalancingStrategyValue lb_strategy, + const ::PortableGroup::Criteria & the_criteria) +{ + // The when creating the object group, it starts as a generic + // CORBA Object. It will become the type of the first added + // member. + const char * type_id = ACE_TEXT ("IDL:omg.org:CORBA/Object:1.0"); + + // Add the group name to the criteria and create the object + TAO::PG_Property_Set property_set (the_criteria); + PortableGroup::Value value; + value <<= group_name; + property_set.set_property (FT_Naming::TAO_FT_OBJECT_GROUP_NAME, value); + + // Add the load balancing strategy to the properties + value <<= lb_strategy; + property_set.set_property (FT_Naming::TAO_FT_LOAD_BALANCING_STRATEGY, value); + + PortableGroup::Criteria new_criteria; + property_set.export_properties (new_criteria); + PortableGroup::GenericFactory::FactoryCreationId_var fcid; + + return this->create_object (group_name, type_id, new_criteria, fcid.out()); +} + +void +TAO_FT_Naming_Manager::delete_object_group (const char * group_name) +{ + // Find the object group with the specified name and delete the object + PortableGroup::ObjectGroup_var group = + this->get_object_group_ref_from_name (group_name); + + if (!CORBA::is_nil (group.in())) + { + PortableGroup::ObjectGroupId group_id = + this->get_object_group_id (group); + + // Delete the object group from the factory + this->group_factory_.delete_group (group_id); + } + else + { + throw PortableGroup::ObjectGroupNotFound (); + } + +} + +PortableGroup::ObjectGroup_ptr +TAO_FT_Naming_Manager::get_object_group_ref_from_name (const char * group_name) +{ + TAO::PG_Object_Group* group; + if (this->group_factory_.find_group_with_name (group_name, group)) + { + return group->reference (); + } + else + { + throw PortableGroup::ObjectGroupNotFound (); + } +} + +::FT_Naming::GroupNames * +TAO_FT_Naming_Manager::groups (::FT_Naming::LoadBalancingStrategyValue target_strategy) +{ + PortableGroup::ObjectGroups_var all_groups = this->group_factory_.all_groups (); + int num_groups = all_groups->length (); + + FT_Naming::GroupNames* group_names; + ACE_NEW_THROW_EX ( + group_names, + FT_Naming::GroupNames (num_groups), + CORBA::NO_MEMORY()); + + int matching_groups = 0; + for (int i = 0; i < num_groups; ++i) + { + PortableGroup::ObjectGroup_var obj_group = (all_groups.in ())[i].in (); + + // Extract the group's Load Balancing property + PortableGroup::Name lb_strat_property_name (1); + lb_strat_property_name.length (1); + lb_strat_property_name[0].id = CORBA::string_dup (::FT_Naming::TAO_FT_LOAD_BALANCING_STRATEGY); + PortableGroup::Properties_var props = this->get_properties (obj_group); + PortableGroup::Value value; + TAO_PG::get_property_value (lb_strat_property_name, props.in (), value); + ::FT_Naming::LoadBalancingStrategyValue lb_strategy_val; + value >>= lb_strategy_val; + + if (lb_strategy_val == target_strategy) + { // Groups load balancing strategy matches the target + // Increment the count of matching groups + ++matching_groups; + char* name; + + // Get the group name and add it to the list to return. + if (this->group_name (obj_group.in (), name)) + { // Group does have a name + group_names->length (matching_groups); + (*group_names)[matching_groups-1] = name; + } + else + { + { // Group has no name + (*group_names)[i] = CORBA::string_dup ("<unnamed group>"); + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("%T %n (%P|%t) - FT_Naming_Manager::groups: no name ") + ACE_TEXT ("property set on group.\n") + )); + } + } + } + } + // Set the length to the actual num added + group_names->length (matching_groups); + return group_names; +} + +void +TAO_FT_Naming_Manager::set_load_balancing_strategy ( + const char * group_name, + ::FT_Naming::LoadBalancingStrategyValue lb_strategy) +{ + CORBA::Object_var group = this->get_object_group_ref_from_name (group_name); + + TAO::PG_Property_Set property_set; + PortableGroup::Value value; + // Add the load balancing strategy to the properties + value <<= lb_strategy; + property_set.set_property (FT_Naming::TAO_FT_LOAD_BALANCING_STRATEGY, value); + PortableGroup::Properties properties; + property_set.export_properties (properties); + this->set_properties_dynamically (group, properties); +} + + +bool +TAO_FT_Naming_Manager::group_name (PortableGroup::ObjectGroup_ptr group, + char*& name) +{ + if (CORBA::is_nil (group)) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("%T %n (%P|%t) - FT_Naming_Manager::group_name: ") + ACE_TEXT ("cannot get name for a null object.\n") + )); + return false; + } + + TAO::PG_Object_Group* pg_group; + if (this->group_factory_.find_group (group, pg_group)) + { // Found the object group in the factory + const char* grp_name = pg_group->get_name (); + if (grp_name != 0) + { // Valid group name defined + name = CORBA::string_dup (grp_name); + return true; + } + else + { // The group has no name + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("TAO_FT_Naming_Manager::group_name - ") + ACE_TEXT ("object group does not have a name")), + false); + } + } + else + { // The factory does not know about the group + return false; + } +} + +void +TAO_FT_Naming_Manager::set_default_properties ( + const PortableGroup::Properties & props) +{ + + this->properties_support_.set_default_properties (props); + //@@ validate properties? +} + +PortableGroup::Properties * +TAO_FT_Naming_Manager::get_default_properties () +{ + return this->properties_support_.get_default_properties (); +} + +void +TAO_FT_Naming_Manager::remove_default_properties ( + const PortableGroup::Properties & props) +{ + this->properties_support_.remove_default_properties (props); +} + +void +TAO_FT_Naming_Manager::set_type_properties ( + const char *type_id, + const PortableGroup::Properties & overrides) +{ + this->properties_support_.set_type_properties ( + type_id, + overrides); +} + +PortableGroup::Properties * +TAO_FT_Naming_Manager::get_type_properties ( + const char *type_id) +{ + return this->properties_support_.get_type_properties (type_id); +} + +void +TAO_FT_Naming_Manager::remove_type_properties ( + const char *type_id, + const PortableGroup::Properties & props) +{ + this->properties_support_.remove_type_properties ( + type_id, + props); +} + +void +TAO_FT_Naming_Manager::set_properties_dynamically ( + PortableGroup::ObjectGroup_ptr object_group, + const PortableGroup::Properties & overrides) +{ + + TAO::PG_Object_Group * group = 0; + if (this->group_factory_.find_group (object_group, group)) + { + group->set_properties_dynamically (overrides); + } + else + { + throw PortableGroup::ObjectGroupNotFound (); + } +} + +PortableGroup::Properties * +TAO_FT_Naming_Manager::get_properties ( + PortableGroup::ObjectGroup_ptr object_group) +{ + PortableGroup::Properties_var result; + ACE_NEW_THROW_EX (result, PortableGroup::Properties(), CORBA::NO_MEMORY ()); + + TAO::PG_Object_Group * group = 0; + if (this->group_factory_.find_group (object_group, group)) + { + group->get_properties (result); + } + else + { + throw PortableGroup::ObjectGroupNotFound (); + } + return result._retn(); +} + +PortableGroup::ObjectGroup_ptr +TAO_FT_Naming_Manager::create_member ( + PortableGroup::ObjectGroup_ptr object_group, + const PortableGroup::Location & the_location, + const char * type_id, + const PortableGroup::Criteria & the_criteria) +{ + PortableGroup::ObjectGroup_var result = PortableGroup::ObjectGroup::_nil(); + TAO::PG_Object_Group * group = 0; + if (this->group_factory_.find_group (object_group, group)) + { + group->create_member (the_location, type_id, the_criteria); + result = group->reference (); + } + else + { + if (TAO_debug_level > 0) + { + ACE_ERROR ( (LM_ERROR, + ACE_TEXT ("%T %n (%P|%t) - FT_Naming_Manager::create_member: ") + ACE_TEXT ("unknown group\n") + )); + } + throw PortableGroup::ObjectGroupNotFound (); + } + return result._retn(); +} + +PortableGroup::ObjectGroup_ptr +TAO_FT_Naming_Manager::add_member ( + PortableGroup::ObjectGroup_ptr object_group, + const PortableGroup::Location & the_location, + CORBA::Object_ptr member) +{ + METHOD_ENTRY (TAO::FT_Naming_Manager::add_member); + PortableGroup::ObjectGroup_var result = PortableGroup::ObjectGroup::_nil (); + + // Find the object group corresponding to this IOGR + TAO::PG_Object_Group * group = 0; + if (this->group_factory_.find_group (object_group, group)) + { + try { + + group->add_member (the_location, + member); + } + catch (...) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO_FT_Naming_Manager::add_member - ") + ACE_TEXT ("Issue with IOR of group or member.\n"))); + throw PortableGroup::ObjectNotAdded (); + } + + result = group->reference (); + + } + else + { + if (TAO_debug_level > 0) + { + ACE_ERROR ( (LM_ERROR, + ACE_TEXT ("%T %n (%P|%t) - FT_Naming_Manager::add_member ") + ACE_TEXT ("to unknown group\n") + )); + } + throw PortableGroup::ObjectGroupNotFound (); + } + METHOD_RETURN (TAO::FT_Naming_Manager::add_member) result._retn (); +} + + +PortableGroup::ObjectGroup_ptr +TAO_FT_Naming_Manager::remove_member ( + PortableGroup::ObjectGroup_ptr object_group, + const PortableGroup::Location & the_location) +{ + PortableGroup::ObjectGroup_var result = PortableGroup::ObjectGroup::_nil (); + + // Find the object group corresponding to this IOGR + TAO::PG_Object_Group * group = 0; + if (this->group_factory_.find_group (object_group, group)) + { + group->remove_member (the_location); + + group->minimum_populate (); + //@@ how about the case where the member was removed successfully, + // but for one reason or another we were unable to bring the group + // back up to minimum_number_of_replicas? + + result = group->reference (); + } + else + { + throw PortableGroup::ObjectGroupNotFound (); + } + return result._retn (); +} + + +PortableGroup::Locations * +TAO_FT_Naming_Manager::locations_of_members ( + PortableGroup::ObjectGroup_ptr object_group) +{ + PortableGroup::Locations_var result = 0; + + // Find the object group corresponding to this IOGR + TAO::PG_Object_Group * group = 0; + if (this->group_factory_.find_group (object_group, group)) + { + result = group->locations_of_members (); + } + else + { + if (TAO_debug_level > 0) + { + ACE_ERROR ( (LM_ERROR, + ACE_TEXT ("%T %n (%P|%t) - FT_Naming_Manager::") + ACE_TEXT ("locations_of_members: unknown group\n") + )); + } + throw PortableGroup::ObjectGroupNotFound (); + } + return result._retn (); +} + +PortableGroup::ObjectGroups * +TAO_FT_Naming_Manager::groups_at_location ( + const PortableGroup::Location & the_location) +{ + return this->group_factory_.groups_at_location (the_location); +} + +PortableGroup::ObjectGroupId +TAO_FT_Naming_Manager::get_object_group_id ( + PortableGroup::ObjectGroup_ptr object_group) +{ + PortableGroup::ObjectGroupId result = 0; + TAO::PG_Object_Group * group = 0; + if (this->group_factory_.find_group (object_group, group)) + { + group->get_object_group_id (); + result = group->get_object_group_id (); + } + else + { + if (TAO_debug_level > 0) + { + ACE_ERROR ( (LM_ERROR, + ACE_TEXT ("%T %n (%P|%t) - FT_Naming_Manager::") + ACE_TEXT ("get_object_group_id: unknown group\n") + )); + } + throw PortableGroup::ObjectGroupNotFound (); + } + return result; +} + +PortableGroup::ObjectGroup_ptr +TAO_FT_Naming_Manager::get_object_group_ref ( + PortableGroup::ObjectGroup_ptr object_group) +{ + PortableGroup::ObjectGroup_var result = PortableGroup::ObjectGroup::_nil (); + + // Find the object group corresponding to this IOGR + TAO::PG_Object_Group * group = 0; + if (this->group_factory_.find_group (object_group, group)) + { + result = group->reference (); + } + else + { + if (TAO_debug_level > 0) + { + ACE_ERROR ( (LM_ERROR, + ACE_TEXT ("%T %n (%P|%t) - FT_Naming_Manager::") + ACE_TEXT ("get_object_group_ref: unknown group\n") + )); + } + throw PortableGroup::ObjectGroupNotFound (); + } + return result._retn(); +} + +PortableGroup::ObjectGroup_ptr TAO_FT_Naming_Manager::get_object_group_ref_from_id ( + PortableGroup::ObjectGroupId group_id) +{ + PortableGroup::ObjectGroup_var result = PortableGroup::ObjectGroup::_nil (); + + // Find the object group corresponding to this IOGR + TAO::PG_Object_Group * group = 0; + if (this->group_factory_.find_group (group_id, group)) + { + result = group->reference (); + } + else + { + if (TAO_debug_level > 0) + { + ACE_ERROR ( (LM_ERROR, + ACE_TEXT ("%T %n (%P|%t) - FT_Naming_Manager::") + ACE_TEXT ("get_object_group_ref_from_id: unknown group\n") + )); + } + throw PortableGroup::ObjectGroupNotFound (); + } + return result._retn(); +} + +CORBA::Object_ptr +TAO_FT_Naming_Manager::get_member_ref ( + PortableGroup::ObjectGroup_ptr object_group, + const PortableGroup::Location & the_location) +{ + CORBA::Object_var result = CORBA::Object::_nil(); + + // Find the object group corresponding to this IOGR + TAO::PG_Object_Group * group = 0; + if (this->group_factory_.find_group (object_group, group)) + { + result = group->get_member_reference (the_location); + } + else + { + if (TAO_debug_level > 0) + { + ACE_ERROR ( (LM_ERROR, + ACE_TEXT ("%T %n (%P|%t) - FT_Naming_Manager::") + ACE_TEXT ("get_member_ref: unknown group\n") + )); + } + throw PortableGroup::ObjectGroupNotFound (); + } + return result._retn(); +} + +CORBA::Object_ptr +TAO_FT_Naming_Manager::create_object ( + const char * object_name, + const char * type_id, + const PortableGroup::Criteria & the_criteria, + PortableGroup::GenericFactory::FactoryCreationId_out + factory_creation_id) +{ + METHOD_ENTRY (TAO::FT_Naming_Manager::create_object); + + //////////////////////////////// + // find the properties for this + // type of object group + ACE_Auto_Ptr<TAO::PG_Property_Set> typeid_properties + (this->properties_support_.find_typeid_properties (type_id)); + + TAO::PG_Object_Group * group + = this->group_factory_.create_group ( + type_id, + the_criteria, + typeid_properties.get ()); + + // The group now owns the properties. + typeid_properties.release (); + + group->set_name (object_name); + + // Dont distribute the object group for its usage in the FT_Naming_Manager + group->distribute (0); + + group->initial_populate (); + //@@ on error we should remove the group from the Group_Factory + // doing this "right" will require a var-type pointer to the object group + // that knows about the factory, too. + + // Allocate a new FactoryCreationId for use as an "out" parameter. + PortableGroup::GenericFactory::FactoryCreationId_ptr factory_id_ptr = 0; + ACE_NEW_THROW_EX (factory_id_ptr, + PortableGroup::GenericFactory::FactoryCreationId, + CORBA::NO_MEMORY ( + CORBA::SystemException::_tao_minor_code ( + TAO::VMCID, + ENOMEM), + CORBA::COMPLETED_NO)); + PortableGroup::GenericFactory::FactoryCreationId_var factory_id = factory_id_ptr; + PortableGroup::ObjectGroupId group_id = group->get_object_group_id (); + factory_id <<= group_id; + factory_creation_id = factory_id._retn(); + + METHOD_RETURN (TAO::FT_Naming_Manager::create_object) group->reference (); +} + +void +TAO_FT_Naming_Manager::delete_object ( + const PortableGroup::GenericFactory::FactoryCreationId & + factory_creation_id) +{ + + PortableGroup::ObjectGroupId group_id = 0; + if (factory_creation_id >>= group_id) + { + this->group_factory_.delete_group ( + group_id); + } + else + { + throw PortableGroup::ObjectNotFound (); + } +} + +void +TAO_FT_Naming_Manager::initialize (CORBA::ORB_ptr orb, + PortableServer::POA_ptr naming_mgr_poa) +{ + ACE_GUARD (TAO_SYNCH_MUTEX, + guard, + this->lock_); + + // Initialize the components used to implement the PortableGroup interfaces + this->factory_registry_.init (orb); + PortableGroup::FactoryRegistry_var factory_ref = + factory_registry_.reference (); + this->group_factory_.init (orb, + naming_mgr_poa, + factory_ref.in ()); +} + +CORBA::Object_ptr +TAO_FT_Naming_Manager::next_member (PortableGroup::ObjectGroup_ptr object_group) +{ + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, + monitor, + this->lock_, + CORBA::Object::_nil () + ); + + ACE_Auto_Ptr<PortableGroup::Properties> props ( + this->get_properties (object_group)); + PortableGroup::Value value; + CORBA::Boolean found = + TAO_PG::get_property_value (built_in_balancing_strategy_name_, + *(props.get ()), + value); + + // If there is no TAO_FT_LOAD_BALANCING_STRATEGY property in the object group + // return failure + if (!found) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("%T %n (%P|%t) - TAO_FT_Naming_Manager::next_member: ") + ACE_TEXT ("object group has no TAO_FT_LOAD_BALANCING_STRATEGY ") + ACE_TEXT ("property.\n") + )); + + return CORBA::Object::_nil(); + } + + // Extract the load balancing strategy value + FT_Naming::LoadBalancingStrategyValue load_bal_strategy; + value >>= load_bal_strategy; + + PortableGroup::Location next_location; + + bool result = false; + + switch (load_bal_strategy) + { + case FT_Naming::ROUND_ROBIN: + result = this->round_robin_.next_location (object_group, this, next_location); + break; + default: + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("%T %n (%P|%t) - TAO_FT_Naming_Manager::next_location: ") + ACE_TEXT ("unsupported load balancing strategy requested.\n") + )); + + return CORBA::Object::_nil(); + break; + } + + if (result == true) + return this->get_member_ref (object_group, next_location); + else + return CORBA::Object::_nil(); +} + + +void +TAO_FT_Naming_Manager::preprocess_properties (PortableGroup::Properties &) +{ + // Nothing to do here for now. +} + +void +TAO_FT_Naming_Manager::set_object_group_storable_factory (TAO::Storable_Factory * factory) +{ + this->group_factory_.set_object_group_storable_factory (factory); +} + +void +TAO_FT_Naming_Manager::set_object_group_stale (const FT_Naming::ObjectGroupUpdate & group_info) +{ + this->group_factory_.set_object_group_stale (group_info); +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Manager.h b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Manager.h new file mode 100644 index 00000000000..97193b9d9fe --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Manager.h @@ -0,0 +1,351 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file FT_Naming_Manager.h + * + * $Id$ + * + * @author Kevin Stanley <stanleyk@ociweb.com> + */ +//============================================================================= + + +#ifndef TAO_FT_NAMING_MANAGER_H +#define TAO_FT_NAMING_MANAGER_H + +#include /**/ "ace/pre.h" + +#include "orbsvcs/Naming/FaultTolerant/ftnaming_export.h" + +#include "orbsvcs/FT_NamingManagerS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "orbsvcs/FT_NamingManagerC.h" + +#include "orbsvcs/PortableGroup/PG_FactoryRegistry.h" +#include "orbsvcs/PortableGroup/PG_Properties_Support.h" +#include "orbsvcs/Naming/FaultTolerant/FT_PG_Group_Factory.h" +#include "orbsvcs/Naming/FaultTolerant/FT_Round_Robin.h" + +#include "ace/Task.h" +#include "tao/Condition.h" + + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace TAO +{ + class Storable_Factory; +} + +namespace FT_Naming +{ + struct ObjectGroupUpdate; +} + +/** + * @class TAO_FT_Naming_Manager + * @brief Implements the NamingManager interface for the Fault + * tolerant naming service. + * + * This class implements the NamingManager interface in support + * of the load balancing features of the FaultTolerant Naming + * Service. Uses can create and manage object groups which can be + * bound in the Naming Service, which will provide the load balancing + * functionality. + */ +class TAO_FtNaming_Export TAO_FT_Naming_Manager + : public virtual POA_FT_Naming::NamingManager, + public ACE_Task_Base +{ +public: + + /// Constructor. + TAO_FT_Naming_Manager (void); + + /** + * @name FT::NamingManager Methods + * + * + */ + + /// Creates an object group with the specified name and load + /// balancing strategy. + /// @param[in] group_name The symbolic name of the group that can + /// be used to refer to the group in other operations. + /// @param[in] lb_strategy The strategy to be used by the Naming + /// Service when this object group is resolved. + ///@param[in] the_criteria Properties to be used by the object group. + virtual PortableGroup::ObjectGroup_ptr create_object_group ( + const char * group_name, + FT_Naming::LoadBalancingStrategyValue lb_strategy, + const ::PortableGroup::Criteria & the_criteria); + + /// Deletes the object group with the provided group_name. + virtual void delete_object_group ( + const char * group_name); + + /// Retreives a reference to a group with the specified name + virtual PortableGroup::ObjectGroup_ptr get_object_group_ref_from_name ( + const char * group_name); + + /// Provide a new load balancing strategy for the group with the provided + /// name. + virtual void set_load_balancing_strategy ( + const char * group_name, + FT_Naming::LoadBalancingStrategyValue lb_strategy); + + /// Retreive the names of the groups with the specified load balanacing + /// strategy that have been created in this Naming Manager. + virtual FT_Naming::GroupNames * groups ( + ::FT_Naming::LoadBalancingStrategyValue target_strategy); + + /** + * @name PortableGroup::PropertyManager Methods + * + * Methods required by the PortableGroup::PropertyManager interface. + */ + //@{ + + /// Set the default properties to be used by all object groups. + virtual void set_default_properties ( + const PortableGroup::Properties & props); + + /// Get the default properties used by all object groups. + virtual PortableGroup::Properties * get_default_properties (); + + /// Remove default properties. + virtual void remove_default_properties ( + const PortableGroup::Properties & props); + + /// Set properties associated with a given Replica type. These + /// properties override the default properties. + virtual void set_type_properties ( + const char * type_id, + const PortableGroup::Properties & overrides); + + /** + * Return the properties associated with a give Replica type. These + * properties include the type-specific properties in use, in + * addition to the default properties that were not overridden. + */ + virtual PortableGroup::Properties * get_type_properties ( + const char * type_id); + + /// Remove the given properties associated with the Replica type ID. + virtual void remove_type_properties ( + const char * type_id, + const PortableGroup::Properties & props); + + /** + * Dynamically set the properties associated with a given object + * group as the load balancer and replicas are being executed. + * These properties override the type-specific and default + * properties. + */ + virtual void set_properties_dynamically ( + PortableGroup::ObjectGroup_ptr object_group, + const PortableGroup::Properties & overrides); + + /** + * Return the properties currently in use by the given object + * group. These properties include those that were set dynamically, + * type-specific properties that weren't overridden, properties that + * were used when the Replica was created, and default properties + * that weren't overridden. + */ + virtual PortableGroup::Properties * get_properties ( + PortableGroup::ObjectGroup_ptr object_group); + + //@} + + /** + * @name PortableGroup::ObjectGroupManager methods + * + * Methods required by the PortableGroup::ObjectGroupManager + * interface. + */ + //@{ + + /// Create a member using the load balancer ObjectGroupManager, and + /// add the created object to the ObjectGroup. + virtual PortableGroup::ObjectGroup_ptr create_member ( + PortableGroup::ObjectGroup_ptr object_group, + const PortableGroup::Location & the_location, + const char * type_id, + const PortableGroup::Criteria & the_criteria); + + /// Add an existing object to the ObjectGroup. + /// @param[in] object_group A reference for the group to which the + /// specified member is to be added. + /// @param[in] the_location The symbolic value that specifies this + /// specific member. The location can be any string value. + /// @param[in] member The object reference for the member. The first + /// member's type is used to defined the object group type. All subsequence + /// members must have the same type. + virtual PortableGroup::ObjectGroup_ptr add_member ( + PortableGroup::ObjectGroup_ptr object_group, + const PortableGroup::Location & the_location, + CORBA::Object_ptr member); + + /** + * Remove an object at a specific location from the given + * ObjectGroup. Deletion of application created objects must be + * deleted by the application. Objects created by the + * infrastructure (load balancer) will be deleted by the + * infrastructure. + */ + virtual PortableGroup::ObjectGroup_ptr remove_member ( + PortableGroup::ObjectGroup_ptr object_group, + const PortableGroup::Location & the_location); + + /// Return the locations of the members in the given ObjectGroup. + virtual PortableGroup::Locations * locations_of_members ( + PortableGroup::ObjectGroup_ptr object_group); + + /// Return the locations of the members in the given ObjectGroup. + virtual PortableGroup::ObjectGroups * groups_at_location ( + const PortableGroup::Location & the_location); + + /// Return the ObjectGroupId for the given ObjectGroup. + virtual PortableGroup::ObjectGroupId get_object_group_id ( + PortableGroup::ObjectGroup_ptr object_group); + + /// TAO specific method + virtual PortableGroup::ObjectGroup_ptr get_object_group_ref_from_id ( + PortableGroup::ObjectGroupId group_id); + + /// Return the reference corresponding to the Replica of a given + /// ObjectGroup at the given location. + virtual CORBA::Object_ptr get_member_ref ( + PortableGroup::ObjectGroup_ptr object_group, + const PortableGroup::Location & loc); + + //@} + + /** + * @name PortableGroup::GenericFactory methods + * + * Methods required by the PortableGroup::GenericFactory interface. + */ + //@{ + + /** + * Create an object of the specified type that adheres to the + * restrictions defined by the provided Criteria. The out + * FactoryCreationId parameter may be passed to the delete_object() + * method to delete the object. This signature is modified from + * the generic factory operation to support the use of an object + * name in addition to the factory_creation_id. + */ + virtual CORBA::Object_ptr create_object ( + const char * object_name, + const char * type_id, + const PortableGroup::Criteria & the_criteria, + PortableGroup::GenericFactory::FactoryCreationId_out + factory_creation_id); + + /** + * Delete the object corresponding to the provided + * FactoryCreationId. If the object is actually an ObjectGroup, + * then all members within the ObjectGroup will be deleted. + * Afterward, the ObjectGroup itself will be deleted. + */ + virtual void delete_object ( + const PortableGroup::GenericFactory::FactoryCreationId & + factory_creation_id); + + //@} + + /// Initialize the naming manager. This will provide the poa to + /// the naming manager and underlying components for use in + /// managing the object groups. + void initialize (CORBA::ORB_ptr orb, + PortableServer::POA_ptr root_poa); + + + /// Utilizing the load balancing strategy identified by the object + /// group property, return the next object reference from the object + /// group which should be used to service the next CORBA request + CORBA::Object_ptr next_member (PortableGroup::ObjectGroup_ptr object_group); + + /// Load/save state of object groups from/to file for fault + /// tolerant purposes. + void + set_object_group_storable_factory (TAO::Storable_Factory * + factory); + + /// Indicate the object group state is stale. + /// Only valid when object group persistence is enabled. + void set_object_group_stale (const FT_Naming::ObjectGroupUpdate & group_info); + + /// Destructor. + ~TAO_FT_Naming_Manager (void); + +private: + /// A utility to ensure we can access the latest object reference for + /// the object group when referenced externally. + virtual PortableGroup::ObjectGroup_ptr get_object_group_ref ( + PortableGroup::ObjectGroup_ptr object_group); + + /// TAO specific method /// Preprocess Strategy or CustomStrategy properties. + /** + * This method takes care of converting StrategyInfo properties to + * Strategy properties, and verifying that CustomStrategy references + * are not nil. + */ + void preprocess_properties (PortableGroup::Properties & props); + + /// Utility for accessing the object group name. Returns true if a + /// name is found and allocates a string with the name assigned to + /// the name parameter. + bool group_name (PortableGroup::ObjectGroup_ptr group, char*& name); + + /// Mutex that provides synchronization for the TAO_FT_Naming_Manager's + /// state. + TAO_SYNCH_MUTEX lock_; + + /// an object that manages default and type_id related properties + TAO::PG_Properties_Support properties_support_; + + /// Registry used by the PG_Group_Factory + TAO::PG_FactoryRegistry factory_registry_; + + /// The group factory responsible for creating object groups + TAO::FT_PG_Group_Factory group_factory_; + + /** + * @name Built-in load balancing strategy implementations + * + * "Built-in" load balancing strategies. Currently only RoundRobin + * is supported. + */ + //@{ + + /// The "RoundRobin" load balancing strategy. + TAO_FT_Round_Robin round_robin_; + //@} + + /// Cached instance of the Property name + /// "org.omg.CosLoadBalancing.Strategy". + PortableGroup::Name built_in_balancing_strategy_name_; + + PortableGroup::Name object_group_property_name_; + + TAO_SYNCH_MUTEX validate_lock_; + TAO_Condition<TAO_SYNCH_MUTEX> validate_condition_; + + bool shutdown_; + +}; + + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" + +#endif /* TAO_FT_NAMING_MANAGER_H */ diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Replication_Manager.cpp b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Replication_Manager.cpp new file mode 100644 index 00000000000..f86ffb96e0f --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Replication_Manager.cpp @@ -0,0 +1,179 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file FT_Naming_Replication_Manager.cpp + * + * $Id$ + * + * @author Kevin Stanley <stanleyk@ociweb.com> + */ +//============================================================================= + +#include "orbsvcs/Naming/FaultTolerant/FT_Naming_Replication_Manager.h" +#include "orbsvcs/Naming/FaultTolerant/FT_Naming_Server.h" +#include "tao/corba.h" +#include "ace/SStringfwd.h" + +FT_Naming::ReplicationManager_var +TAO_FT_Naming_Replication_Manager::peer_replica_ (0); + +TAO_FT_Naming_Replication_Manager::TAO_FT_Naming_Replication_Manager ( + TAO_FT_Naming_Server *naming_svr, + const char* repl_mgr_name) + : naming_svr_ (naming_svr), + repl_mgr_name_ (repl_mgr_name) +{ +} + + +TAO_FT_Naming_Replication_Manager::~TAO_FT_Naming_Replication_Manager(void) +{ + this->reference_ = FT_Naming::ReplicationManager::_nil (); +} + +void +TAO_FT_Naming_Replication_Manager::initialize (CORBA::ORB_ptr orb, + PortableServer::POA_ptr repl_mgr_poa) +{ + ACE_UNUSED_ARG (orb); + repl_mgr_poa_ = PortableServer::POA::_duplicate (repl_mgr_poa); + PortableServer::ObjectId_var id = + PortableServer::string_to_ObjectId (this->repl_mgr_name_.c_str ()); + CORBA::Object_var obj = repl_mgr_poa_->id_to_reference (id.in ()); + this->reference_ = FT_Naming::ReplicationManager::_narrow (obj.in ()); +} + +FT_Naming::ReplicaInfo* +TAO_FT_Naming_Replication_Manager::register_replica ( + ::FT_Naming::ReplicationManager_ptr replica, + const ::FT_Naming::ReplicaInfo & replica_info) +{ + ACE_TRACE ( ACE_TEXT("TAO_FT_Naming_Replication_Manager::register_replica")); + + ACE_GUARD_THROW_EX (ACE_SYNCH_MUTEX, + ace_mon, + this->lock_, + CORBA::INTERNAL ()); + + // Store a copy of the provided reference and other ReplicaInfo + peer_replica_ = FT_Naming::ReplicationManager::_duplicate (replica); + + // Store the provided peer references + this->naming_svr_->peer_root_context (replica_info.root_context); + this->naming_svr_->peer_naming_manager (replica_info.naming_manager); + + // Return my references to the peer + FT_Naming::ReplicaInfo* my_info = new FT_Naming::ReplicaInfo; + + my_info->root_context = CosNaming::NamingContext::_duplicate ( + this->naming_svr_->my_root_context ()); + + my_info->naming_manager = FT_Naming::NamingManager::_duplicate ( + this->naming_svr_->my_naming_manager ()); + + return my_info; +} + +void +TAO_FT_Naming_Replication_Manager::notify_updated_object_group ( + const FT_Naming::ObjectGroupUpdate & group_info) +{ + ACE_TRACE ( ACE_TEXT ("TAO_FT_Naming_Replication_Manager::") + ACE_TEXT ("notify_updated_object_group")); + + // Make sure that we have a valid naming server + ACE_ASSERT (naming_svr_); + int result = this->naming_svr_->update_object_group (group_info); + + if (result != 0) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("Unable to update object group.\n"))); +} + +void +TAO_FT_Naming_Replication_Manager::notify_updated_context ( + const FT_Naming::NamingContextUpdate & context_info) +{ + ACE_TRACE (ACE_TEXT ("TAO_FT_Naming_Replication_Manager::") + ACE_TEXT ("notify_updated_context")); + ACE_ASSERT (naming_svr_); + int result = this->naming_svr_->update_naming_context (context_info); + + if (result != 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("Error while updating naming context.\n"))); + } +} + +FT_Naming::ReplicationManager_ptr +TAO_FT_Naming_Replication_Manager::peer_replica (void) +{ + ACE_TRACE (ACE_TEXT ("TAO_FT_Naming_Replication_Manager::peer_replica")); + // Return a copy of the stored peer to the requester + return FT_Naming::ReplicationManager::_duplicate (peer_replica_.in ()); +} + +int +TAO_FT_Naming_Replication_Manager::register_with_peer_replica ( + FT_Naming::ReplicationManager_ptr replica, + CosNaming::NamingContext_ptr nc, + FT_Naming::NamingManager_ptr nm) +{ + ACE_TRACE (ACE_TEXT ("TAO_FT_Naming_Replication_Manager::") + ACE_TEXT ("register_with_peer_replica")); + + int result = 0; + FT_Naming::ReplicaInfo my_info; + { // Guard the access to the Replication Manager state + ACE_GUARD_THROW_EX (ACE_SYNCH_MUTEX, + ace_mon, + this->lock_, + CORBA::INTERNAL ()); + + // Store a copy of the peer reference for future access + this->peer_replica_ = + FT_Naming::ReplicationManager::_duplicate (replica); + + my_info.root_context = CosNaming::NamingContext::_duplicate (nc); + my_info.naming_manager = FT_Naming::NamingManager::_duplicate (nm); + } + + try { + FT_Naming::ReplicationManager_var my_ref = + this->reference (); + + // Register with the peer replica + FT_Naming::ReplicaInfo_var peer_info = + this->peer_replica_->register_replica (my_ref.in (), + my_info); + + ACE_GUARD_THROW_EX (ACE_SYNCH_MUTEX, + ace_mon, + this->lock_, + CORBA::INTERNAL ()); + + // Store the returned references locally + this->naming_svr_->peer_root_context (peer_info->root_context); + this->naming_svr_->peer_naming_manager (peer_info->naming_manager); + } + catch (const CORBA::Exception& ex) { + // Unable to contact the peer replica. + if (TAO_debug_level > 1) + ex._tao_print_exception ( + ACE_TEXT ("TAO_FT_Naming_Replication_Manager::") + ACE_TEXT ("register_with_peer_replica\n")); + result = -1; + } + + return result; + +} + +FT_Naming::ReplicationManager_ptr +TAO_FT_Naming_Replication_Manager::reference (void) +{ + ACE_TRACE (ACE_TEXT ("TAO_FT_Naming_Replication_Manager::reference")); + return FT_Naming::ReplicationManager::_duplicate (reference_.in ()); +} diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Replication_Manager.h b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Replication_Manager.h new file mode 100644 index 00000000000..8dc9521576e --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Replication_Manager.h @@ -0,0 +1,110 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file FT_Naming_Replication_Manager.h + * + * $Id$ + * + * @author Kevin Stanley <stanleyk@ociweb.com> + */ +//============================================================================= + + +#ifndef TAO_FT_NAMING_REPLICATION_MANAGER_H +#define TAO_FT_NAMING_REPLICATION_MANAGER_H + +#include /**/ "ace/pre.h" + +#include "orbsvcs/Naming/FaultTolerant/ftnaming_export.h" +#include "orbsvcs/FT_NamingReplicationS.h" +#include "ace/Recursive_Thread_Mutex.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "orbsvcs/FT_NamingReplicationC.h" + +class TAO_FT_Naming_Server; + +/** + * @class TAO_FT_Naming_Replication_Manager + * @brief The class that implements the FT_Naming::ReplicationManager + * interface. + */ +class TAO_FtNaming_Export TAO_FT_Naming_Replication_Manager + : public virtual POA_FT_Naming::ReplicationManager +{ +public: + + /// Create a Replication Manager and provide it with the naming server + /// to be updated whenever notified by the peer replica + TAO_FT_Naming_Replication_Manager(TAO_FT_Naming_Server *naming_svr, + const char* repl_mgr_name); + + virtual ~TAO_FT_Naming_Replication_Manager(void); + + /// Initialize the naming manager. This will provide the poa to + /// the naming manager and underlying components for use in + /// managing the object groups. + void initialize (CORBA::ORB_ptr orb, + PortableServer::POA_ptr root_poa); + + + /// Implementation of the FT_Naming::ReplicationManager interface + virtual ::FT_Naming::ReplicaInfo * register_replica ( + ::FT_Naming::ReplicationManager_ptr replica, + const ::FT_Naming::ReplicaInfo & replica_info); + + /// This method implements the operation invoked by the peer replica when an + /// object group is updated on the remote process. + virtual void notify_updated_object_group ( + const FT_Naming::ObjectGroupUpdate & group_info); + + /// This method implements the operation invoked by the peer replica when an + /// naming context is updated on the remote process. + virtual void notify_updated_context ( + const FT_Naming::NamingContextUpdate & group_info); + + /// Retrieve the object reference for the peer naming service + /// ReplicationManager. + static FT_Naming::ReplicationManager_ptr peer_replica (void); + + /* + * Utilities for implementing the FT_Naming::ReplicationManager + */ + + /// Stores the peer in the peer_replica_ data member and invokes the + /// register_replica interface method with the peer. Returns 0 if + /// successful and -1 if unable to contact the peer. + int register_with_peer_replica (FT_Naming::ReplicationManager_ptr replica, + CosNaming::NamingContext_ptr nc, + FT_Naming::NamingManager_ptr rm); + + /// The object reference for this servant instance + FT_Naming::ReplicationManager_ptr reference (void); + +protected: + + // The object which implements the naming service and the object manager + TAO_FT_Naming_Server *naming_svr_; + + // Store the reference to the replica object reference + // For now only a single replica is supported. + static FT_Naming::ReplicationManager_var peer_replica_; + + PortableServer::POA_var repl_mgr_poa_; + + ACE_CString repl_mgr_name_; + + FT_Naming::ReplicationManager_var reference_; + + /// Lock used to serialize access to fault tolerant extensions + /// to Naming Service. + TAO_SYNCH_MUTEX lock_; + +}; +#include /**/ "ace/post.h" + +#endif /* TAO_FT_NAMING_REPLICATION_MANAGER_H */ diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Server.cpp b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Server.cpp new file mode 100644 index 00000000000..d5eb451e92d --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Server.cpp @@ -0,0 +1,1196 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file FT_Naming_Server.cpp + * + * $Id$ + * + * @author Kevin Stanley <stanleyk@ociweb.com> + */ +//============================================================================= + + +#include "orbsvcs/Naming/FaultTolerant/FT_Naming_Server.h" +#include "orbsvcs/Naming/Naming_Server.h" + +#include "orbsvcs/Naming/FaultTolerant/FT_Naming_Manager.h" +#include "orbsvcs/Naming/Storable.h" +#include "orbsvcs/Naming/Storable_Naming_Context.h" +#include "orbsvcs/Naming/Storable_Naming_Context_Activator.h" + +#include "orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context.h" +#include "orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context_Factory.h" +#include "orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context_Factory.h" +#include "orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context.h" +#include "orbsvcs/Naming/Persistent_Context_Index.h" +#include "orbsvcs/Naming/Naming_Context_Interface.h" + + +#include "ace/Arg_Shifter.h" +#include "ace/Get_Opt.h" +#include "ace/OS_NS_unistd.h" + +#include "tao/IORTable/IORTable.h" +#include "tao/ORB_Core.h" + +#include "tao/debug.h" +#include "tao/default_ports.h" +#include "tao/Storable_FlatFileStream.h" + +#include "tao/debug.h" +#include "tao/default_ports.h" + +#include "tao/IORManipulation/IORManip_Loader.h" + +#if defined (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 +#include "tao/Messaging/Messaging.h" +#endif + +#include "tao/AnyTypeCode/Any.h" + +const ACE_TCHAR* +TAO_FT_Naming_Server::primary_replica_ior_filename = + ACE_TEXT ("ns_replica_primary.ior"); + +const ACE_TCHAR* +TAO_FT_Naming_Server::backup_replica_ior_filename = + ACE_TEXT ("ns_replica_backup.ior"); + +/// Default Constructor. +TAO_FT_Naming_Server::TAO_FT_Naming_Server (void) + : replica_id_ (0), + naming_manager_ (), + replication_manager_ (0), + combined_naming_service_ior_file_name_ (0), + combined_naming_manager_ior_file_name_ (0), + naming_manager_ior_file_name_ (0), + naming_manager_persistence_file_name_ (0), + use_object_group_persistence_ (0), + server_role_ (STANDALONE) +{ +} + +int +TAO_FT_Naming_Server::init_with_orb (int argc, + ACE_TCHAR *argv [], + CORBA::ORB_ptr orb) +{ + // Invoke the base class initialization to setup the naming service + // What follows after that are the initialization steps to support + // fault tolerance and load balancing with the FT_Naming_Manager + int result = TAO_Naming_Server::init_with_orb (argc, argv, orb); + + // Check the result to make sure it executed Ok. + if (result != 0) + return result; + + if (this->use_object_group_persistence_) + { + // Make sure the object group directory is accessible + if (ACE_OS::access (this->object_group_dir_.c_str (), W_OK|X_OK)) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) ERROR: Invalid object ") + ACE_TEXT ("group persistence directory\n")), + -1); + } + + TAO::Storable_Factory * object_group_storable_factory; + ACE_NEW_RETURN (object_group_storable_factory, + TAO::Storable_FlatFileFactory (this->object_group_dir_), + -1); + + naming_manager_.set_object_group_storable_factory ( + object_group_storable_factory); + } + + // Provide the naming manager reference for use in + // TAO_FT_Persistent_Naming_Contexts for load balancing functionality + TAO_FT_Storable_Naming_Context::set_naming_manager (&naming_manager_); + + // Initialize the naming manager which supports the Object Group Manager + // interface + result = this->init_naming_manager_with_orb (argc, argv, orb); + if (result != 0) + return result; + + try { + + // Initialize the replication manager + result = init_replication_manager_with_orb (argc, argv, orb); + if (result != 0) + return result; + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ( + ACE_TEXT ("TAO_FT_Naming_Server::init_with_orb")); + return -1; + } + + // If we successfully initialized the replication manager and we are + // a backup server, then we should export the multi-profile + // references to files. + if (this->server_role_ == TAO_FT_Naming_Server::BACKUP) + { + // The backup should write out the combined IOR for the primary + // and backup naming service and naming manager. + result = export_ft_naming_references (); + } + + return result; +} + +int +TAO_FT_Naming_Server::init_naming_manager_with_orb (int argc, + ACE_TCHAR *argv [], + CORBA::ORB_ptr orb) +{ + ACE_UNUSED_ARG (argc); + ACE_UNUSED_ARG (argv); + + int result = 0; + + // Need to lock during startup to prevent access of partially + // initialized variables + ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, + ace_mon, + this->lock_, + CORBA::INTERNAL ()); + + try { + + // Get the POA from the ORB. + CORBA::Object_var poa_object = + orb->resolve_initial_references (ACE_TEXT_ALWAYS_CHAR ("RootPOA")); + + if (CORBA::is_nil (poa_object.in ())) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT(" (%P|%t) ERROR: Unable to initialize the POA.\n")), + -1); + } + + if (result != 0) + return result; + + // Get the POA object. + this->root_poa_ = PortableServer::POA::_narrow (poa_object.in ()); + + // Get the POA_Manager. + PortableServer::POAManager_var poa_manager = + this->root_poa_->the_POAManager (); + + int numPolicies = 2; + + CORBA::PolicyList policies (numPolicies); + policies.length (numPolicies); + + // Id Assignment policy + policies[0] = + this->root_poa_->create_id_assignment_policy (PortableServer::USER_ID); + + // Lifespan policy + policies[1] = + this->root_poa_->create_lifespan_policy (PortableServer::PERSISTENT); + + /* Register the naming manager with a POA + * TODO: 1) Error checking + * 2) Write IOR to file + * 3) Persistence for Object Group Manager + */ + + // We use a different POA, otherwise the user would have to change + // the object key each time it invokes the server. + this->naming_manager_poa_ = this->root_poa_->create_POA ( + ACE_TEXT_ALWAYS_CHAR ("NamingManager"), + poa_manager.in (), + policies); + // Warning! If create_POA fails, then the policies won't be + // destroyed and there will be hell to pay in memory leaks! + + // Creation of the new POAs over, so destroy the Policy_ptr's. + for (CORBA::ULong i = 0; + i < policies.length (); + ++i) + { + CORBA::Policy_ptr policy = policies[i]; + policy->destroy (); + } + + poa_manager->activate (); + + // Register with the POA. + PortableServer::ObjectId_var id = + PortableServer::string_to_ObjectId ( + ACE_TEXT_ALWAYS_CHAR ("NamingManager")); + + this->naming_manager_poa_->activate_object_with_id ( + id.in (), + &this->naming_manager_); + + CORBA::Object_var nm_obj = + this->naming_manager_poa_->id_to_reference (id.in ()); + + this->my_naming_manager_ = FT_Naming::NamingManager::_narrow (nm_obj.in ()); + + this->naming_manager_ior_ = + orb->object_to_string (this->my_naming_manager_.in ()); + + // write out our object reference to the file defined in the -h option + if (this->naming_manager_ior_file_name_ != 0) + { + if (this->write_ior_to_file (this->naming_manager_ior_.in (), + this->naming_manager_ior_file_name_) + != 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) ERROR: Unable to open %s ") + ACE_TEXT ("for writing:(%u) %p\n"), + this->naming_manager_ior_file_name_, + ACE_ERRNO_GET, + ACE_TEXT ("TAO_Naming_Server::") + ACE_TEXT ("init_naming_manager_with_orb")), + -1); + } + } + + this->naming_manager_.initialize (this->orb_, + this->naming_manager_poa_); + + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ( + ACE_TEXT ("TAO_FT_Naming_Server::init_naming_manager_with_orb")); + return -1; + } + + // Make the Object Group Manager easily accessible using Interoperable + // Naming Service IORs + CORBA::Object_var table_object = + orb->resolve_initial_references (ACE_TEXT_ALWAYS_CHAR ("IORTable")); + + IORTable::Table_var adapter = + IORTable::Table::_narrow (table_object.in ()); + if (CORBA::is_nil (adapter.in ())) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) ERROR: TAO_FT_Naming_Server::") + ACE_TEXT ("init_naming_manager_with_orb - Nil IORTable\n"))); + } + else + { + CORBA::String_var ior = this->naming_manager_ior (); + adapter->bind (ACE_TEXT_ALWAYS_CHAR ("NamingManager"), ior.in ()); + } + + return 0; +} + +int +TAO_FT_Naming_Server::init_replication_manager_with_orb (int argc, + ACE_TCHAR *argv [], + CORBA::ORB_ptr orb) +{ + ACE_UNUSED_ARG (argc); + ACE_UNUSED_ARG (argv); + + // Need to lock during startup to prevent access of partially initialized + // variables + ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, + ace_mon, + this->lock_, + CORBA::INTERNAL ()); + + // If redundancy is not requested, then do not initialize the + // replication manager + if (!this->use_redundancy_) + return 0; + + int result = 0; + + try { + + // Get the POA from the ORB. + CORBA::Object_var poa_object = + orb->resolve_initial_references (ACE_TEXT_ALWAYS_CHAR ("RootPOA")); + + if (CORBA::is_nil (poa_object.in ())) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT(" (%P|%t) ERROR: Unable to initialize the POA.\n")), + -1); + } + + if (result != 0) + return result; + + // Get the POA object. + this->root_poa_ = PortableServer::POA::_narrow (poa_object.in ()); + + // Get the POA_Manager. + PortableServer::POAManager_var poa_manager = + this->root_poa_->the_POAManager (); + + int numPolicies = 2; + + CORBA::PolicyList policies (numPolicies); + policies.length (numPolicies); + + // Id Assignment policy + policies[0] = + this->root_poa_->create_id_assignment_policy (PortableServer::USER_ID); + + // Lifespan policy + policies[1] = + this->root_poa_->create_lifespan_policy (PortableServer::PERSISTENT); + + // We use a different POA, otherwise the user would have to change + // the object key each time it invokes the server. + this->replication_manager_poa_ = this->root_poa_->create_POA ( + ACE_TEXT_ALWAYS_CHAR (this->replica_id_ ), + poa_manager.in (), + policies); + + // Warning! If create_POA fails, then the policies won't be + // destroyed and there will be hell to pay in memory leaks! + + // Creation of the new POAs over, so destroy the Policy_ptr's. + for (CORBA::ULong i = 0; + i < policies.length (); + ++i) + { + CORBA::Policy_ptr policy = policies[i]; + policy->destroy (); + } + + poa_manager->activate (); + + // Construct the replication manager providing it with its ID + ACE_NEW_RETURN (this->replication_manager_, + TAO_FT_Naming_Replication_Manager (this, + this->replica_id_), + -1); + + // Register with the POA. + PortableServer::ObjectId_var id = + PortableServer::string_to_ObjectId ( + ACE_TEXT_ALWAYS_CHAR (this->replica_id_)); + + this->replication_manager_poa_->activate_object_with_id ( + id.in (), + this->replication_manager_); + + CORBA::Object_var repl_mgr_ref = + this->replication_manager_poa_->id_to_reference (id.in ()); + + this->replication_manager_ior_ = + orb->object_to_string (repl_mgr_ref.in ()); + + // Provide the replication manager its ORB and POA + this->replication_manager_->initialize ( + this->orb_.in (), + this->replication_manager_poa_.in ()); + + ACE_CString primary_file_name (this->persistence_file_name_); + primary_file_name += ACE_TEXT ("/"); + primary_file_name += + TAO_FT_Naming_Server::primary_replica_ior_filename; + + ACE_CString backup_file_name (this->persistence_file_name_); + backup_file_name += ACE_TEXT ("/"); + backup_file_name += + TAO_FT_Naming_Server::backup_replica_ior_filename; + + if (this->server_role_ == PRIMARY) + { // We are the primary + if (TAO_debug_level > 3) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) - FT_Naming_Server ") + ACE_TEXT ("is a primary\n"))); + + // Write out this replicas IOR for the backup to use to bootstrap + CORBA::String_var replication_ior = naming_service_ior (); + this->write_ior_to_file (this->replication_manager_ior_.in (), + primary_file_name.c_str ()); + + // Check if there is already a backup IOR file. If so, then the backup + // may be up and running so we should register with it. + CORBA::Object_var backup_ior; + if (TAO_debug_level > 3) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) - FT_Naming_Server reading ") + ACE_TEXT ("backup ior file\n"))); + + if ((ACE_OS::access (primary_file_name.c_str (), + R_OK) == 0) && + this->read_reference_from_file (backup_file_name.c_str (), + backup_ior.out ()) == 0) + {// Success in reading backup IOR file + // Store the backup reference as our peer + FT_Naming::ReplicationManager_var peer_ref = + FT_Naming::ReplicationManager::_narrow (backup_ior.in ()); + + if (TAO_debug_level > 3) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) - FT_Naming_Server ") + ACE_TEXT ("narrowing IOR\n"))); + if (CORBA::is_nil (peer_ref.in ())) + ACE_ERROR_RETURN ( + (LM_ERROR, + ACE_TEXT ("(%P|%t) ERROR: IOR in file %s is not ") + ACE_TEXT ("a FT_Naming::ReplicationManager\n"), + primary_file_name.c_str ()), + -1); + + try { + if (TAO_debug_level > 3) + ACE_DEBUG ( + (LM_DEBUG, + ACE_TEXT ("(%P|%t) - FT_Naming_Server registering ") + ACE_TEXT ("with backup.\n"))); + + // Register with the backup + CosNaming::NamingContext_var root = this->my_root_context (); + FT_Naming::NamingManager_var nm = this->my_naming_manager (); + + int registration_result = + this->replication_manager_->register_with_peer_replica ( + peer_ref.in (), + root.in (), + nm.in ()); + + if (registration_result == 0) + { + if (TAO_debug_level > 3) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) - FT_Naming_Server ") + ACE_TEXT ("registered with backup.\n"))); + } + else + { + if (TAO_debug_level > 3) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) - FT_Naming_Server:Backup peer ") + ACE_TEXT ("replica not started yet.\n"))); + } + } + catch (const CORBA::Exception& ex) + { + // Its Ok that we were unable to contact the backup peer. + // It has apparently not started yet. + // It will register with the primary when it starts up. + ex._tao_print_exception ( + ACE_TEXT ("Backup peer replica not started yet.\n")); + } + } + else + { + // Could not get the backup replica from the IOR file, which is OK. + // The backup will register with us in the future. + if (TAO_debug_level > 3) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) - FT_Naming_Server no Replica ") + ACE_TEXT ("IOR file. Waiting for registration.\n"))); + } + } + else if (this->server_role_ == TAO_FT_Naming_Server::BACKUP) + { // We are the backup + if (TAO_debug_level > 3) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) - FT_Naming_Server:Is a Backup\n"))); + + if (TAO_debug_level > 3) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) - FT_Naming_Server writing ") + ACE_TEXT ("replica ior\n"))); + // Write out the backup ior for use by the primary if it must be restarted. + this->write_ior_to_file (replication_manager_ior_.in (), + backup_file_name.c_str ()); + + // Get the ior file for the primary from the + // persistence directory. If not there, fail. + CORBA::Object_var primary_ref = CORBA::Object::_nil (); + + if (TAO_debug_level > 3) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) - FT_Naming_Server ") + ACE_TEXT ("reading primary ior file\n"))); + // Check for the primary IOR. We must have it to bootstrap the redundant + // naming pair. + if ((ACE_OS::access (primary_file_name.c_str (), R_OK) == 0) && + (this->read_reference_from_file (primary_file_name.c_str (), + primary_ref.out ()) == 0)) + { + if (TAO_debug_level > 3) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) - FT_Naming_Server ") + ACE_TEXT ("toring the primary reference ior\n"))); + // Store the primary reference as our peer + FT_Naming::ReplicationManager_var peer_ref = + FT_Naming::ReplicationManager::_narrow (primary_ref.in ()); + + if (CORBA::is_nil (peer_ref.in ())) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) ERROR: IOR in file %s ") + ACE_TEXT ("is not a FT_Naming::ReplicationManager\n"), + primary_file_name.c_str ()), + -1); + + if (TAO_debug_level > 3) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) - FT_Naming_Server ") + ACE_TEXT ("backup registering with primary.\n"))); + // Register with the primary + CosNaming::NamingContext_var root = this->my_root_context (); + FT_Naming::NamingManager_var nm = this->my_naming_manager (); + int registration_result = + this->replication_manager_->register_with_peer_replica (peer_ref.in (), + root.in (), + nm.in ()); + if (registration_result == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) ERROR: Backup unable to ") + ACE_TEXT ("register with the primary\n")), + -1); + } + else + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) ERROR: No primary IOR ") + ACE_TEXT ("available. Have you started the ") + ACE_TEXT ("primary? Exiting.\n")), + -1); + } + } + else + {// We are neither a primary or replica, but running in standalone mode + if (TAO_debug_level > 3) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) - FT_Naming_Server:Is Standalone\n"))); + + } + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ( + ACE_TEXT ("TAO_FT_Naming_Server::init_replication_manager_with_orb.\n")); + return -1; + } + + // Success + return 0; +} + + +int +TAO_FT_Naming_Server::parse_args (int argc, + ACE_TCHAR *argv[]) +{ + ACE_Get_Opt get_opts (argc, argv, ACE_TEXT("b:c:do:p:s:f:m:z:r:u:v:g:h:")); + + // Define the arguments for primary and backup + get_opts.long_option (ACE_TEXT ("primary"), ACE_Get_Opt::NO_ARG); + get_opts.long_option (ACE_TEXT ("backup"), ACE_Get_Opt::NO_ARG); + bool role_defined = false; + + int c; + int size; +#if !defined (CORBA_E_MICRO) + int result; + + // This is declared this way to avoid warnings from + // some compilers that complain about mismatching types + // in the sscanf. +#if ACE_SIZEOF_VOID_P == ACE_SIZEOF_LONG_LONG + ptrdiff_t address; +#else + long int address; +#endif /* ACE_SIZEOF_VOID_P */ +#endif /* CORBA_E_MICRO */ + + // Make sure only one naming context persistence option is specified + int f_opt_used = 0; + int u_opt_used = 0; + int r_opt_used = 0; + + int v_opt_used = 0; + + // TODO: remove unsupported options with FT Naming Server + while ((c = get_opts ()) != -1) + switch (c) + { + case 'd': // debug flag. + ++TAO_debug_level; + break; + case 'o': // outputs this servers naming service ior to a file. + this->ior_file_name_ = get_opts.opt_arg (); + break; + case 'c': // outputs the multi-profile naming service ior file + this->combined_naming_service_ior_file_name_ = get_opts.opt_arg (); + break; + case 'g': // outputs the mutli-profile object group manager ior file + this->combined_naming_manager_ior_file_name_ = get_opts.opt_arg (); + break; + case 'h': // outputs the object group manager ior to a file + this->naming_manager_ior_file_name_ = get_opts.opt_arg (); + break; + case 'p': + this->pid_file_name_ = get_opts.opt_arg (); + break; + case 's': + size = ACE_OS::atoi (get_opts.opt_arg ()); + if (size >= 0) + this->context_size_ = size; + break; + case 'm': + this->multicast_ = ACE_OS::atoi(get_opts.opt_arg ()); + break; +#if !defined (CORBA_E_MICRO) + case 'b': + result = ::sscanf (ACE_TEXT_ALWAYS_CHAR (get_opts.opt_arg ()), +#if ACE_SIZEOF_VOID_P == ACE_SIZEOF_LONG_LONG + ACE_INT64_FORMAT_SPECIFIER_ASCII, +#else + "%ld", +#endif /* ACE_SIZEOF_VOID_P */ + &address); + if (result == 0 || result == EOF) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) ERROR: Unable to ") + ACE_TEXT ("process <-b> option")), + -1); + this->base_address_ = (void *) address; + break; + case 'f': + this->persistence_file_name_ = get_opts.opt_arg (); + f_opt_used = 1; + break; +#if (TAO_HAS_MINIMUM_POA == 0) && !defined (CORBA_E_COMPACT) + case 'r': + this->use_redundancy_ = 1; + this->use_storable_context_ = 1; + this->persistence_file_name_ = get_opts.opt_arg (); + r_opt_used = 1; + break; + case 'u': + this->use_storable_context_ = 1; + this->persistence_file_name_ = get_opts.opt_arg (); + u_opt_used = 1; + break; + case 'v': + this->use_object_group_persistence_ = 1; + this->object_group_dir_ = get_opts.opt_arg (); + v_opt_used = 1; + break; + +#endif /* TAO_HAS_MINIMUM_POA == 0 */ +#endif /* !CORBA_E_MICRO */ + case 'z': + this->use_round_trip_timeout_ = 1; + this->round_trip_timeout_ = + (int)1.0e7 * ACE_OS::atoi (get_opts.opt_arg ()); + break; + case 0: // A long option was found + { + const char* long_option = get_opts.long_option (); + if (ACE_OS::strcmp (long_option, ACE_TEXT ("backup")) == 0) + { + this->replica_id_ = ACE_TEXT ("Backup"); + this->server_role_ = TAO_FT_Naming_Server::BACKUP; + role_defined = true; + } + else if (ACE_OS::strcmp (long_option, + ACE_TEXT ("primary")) == 0) + { + this->replica_id_ = ACE_TEXT ("Primary"); + this->server_role_ = TAO_FT_Naming_Server::PRIMARY; + role_defined = true; + } + } + break; + case '?': + default: + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("usage: %s\n") + ACE_TEXT ("--primary (not used with --backup)\n") + ACE_TEXT ("--backup (not used with --primary)\n") + ACE_TEXT ("-d\n") + ACE_TEXT ("-c <multi-profile_name_service_ior_file>\n") + ACE_TEXT ("-o <name_svc_ior_output_file>\n") + ACE_TEXT ("-g <multi-profile_naming_mgr_ior_file>\n") + ACE_TEXT ("-h <naming_mgr_ior_output_file>\n") + ACE_TEXT ("-p <pid_file_name>\n") + ACE_TEXT ("-s <context_size>\n") + ACE_TEXT ("-b <base_address>\n") + ACE_TEXT ("-m <1=enable multicast,") + ACE_TEXT (" 0=disable multicast(default)>\n") + ACE_TEXT ("-n <num_threads>\n") + ACE_TEXT ("-f <persistence_file_name>\n") + ACE_TEXT ("-u <storable_persistence_directory") + ACE_TEXT (" (not used with -f)>\n") + ACE_TEXT ("-v <storable_object_group_persistence") + ACE_TEXT ("_directory>\n") + ACE_TEXT ("-r <redundant_persistence_directory>\n") + ACE_TEXT ("-z <relative round trip timeout>\n") + ACE_TEXT ("\n"), + argv [0]), + -1); + } + + + if (f_opt_used + u_opt_used + r_opt_used > 1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("ERROR: Only one persistence option ") + ACE_TEXT ("can be provided.\n\n")), + -1); + + // If naming context or object group persistence is being used then + // enable backup/restore compability of persitent files. + if (u_opt_used || r_opt_used || v_opt_used) + { + TAO::Storable_Base::use_backup_default = true; + } + + if (!role_defined) + { // No role specified, so we will become a STANDALONE server + this->replica_id_ = ACE_TEXT ("Standalone"); + this->server_role_ = TAO_FT_Naming_Server::STANDALONE; + // User has not provided a role, so we will not use redundancy option + if (this->use_redundancy_ == 1) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("INFO: Cannot run standalone with ") + ACE_TEXT ("-r option. Using -u instead.\n") + ACE_TEXT ("Must start a '--primary' and a '--backup' ") + ACE_TEXT ("server to run as a Fault \n") + ACE_TEXT ("Tolerant Naming Service. \n"))); + this->use_redundancy_ = 0; + } + + } + else + { + // Only the backup should be requested to write the multi-profile IOR + if ((this->server_role_ != TAO_FT_Naming_Server::BACKUP) && + (this->combined_naming_service_ior_file_name_ != 0)) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("ERROR: Must export the multi-profile ") + ACE_TEXT ("IOR (using '-c' option) from the backup") + ACE_TEXT (" server.\n\n")), + -1); + + // Only the backup should be requested to write the multi-profile IOR + if ((this->server_role_ == TAO_FT_Naming_Server::BACKUP) && + (this->combined_naming_service_ior_file_name_ == 0)) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("ERROR: Must export the multi-profile ") + ACE_TEXT ("IOR (using '-c' option) from the backup") + ACE_TEXT (" server.\n\n")), + -1); + + } + return 0; +} + +int +TAO_FT_Naming_Server::fini (void) +{ + // Destroy the child POAs created when initializing + // the FT Naming Service + try + { + if (!CORBA::is_nil (this->naming_manager_poa_.in ())) + this->naming_manager_poa_->destroy (1, 1); + this->naming_manager_poa_ = PortableServer::POA::_nil (); + + if (!CORBA::is_nil (this->replication_manager_poa_.in ())) + this->replication_manager_poa_->destroy (1, 1); + + this->replication_manager_poa_ = PortableServer::POA::_nil (); + CORBA::Object_var table_object = + this->orb_->resolve_initial_references ( + ACE_TEXT_ALWAYS_CHAR ("IORTable")); + + IORTable::Table_var adapter = + IORTable::Table::_narrow (table_object.in ()); + if (CORBA::is_nil (adapter.in ())) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) ERROR: Nil IORTable\n"))); + } + else + { + adapter->unbind (ACE_TEXT_ALWAYS_CHAR ("NameService")); + adapter->unbind (ACE_TEXT_ALWAYS_CHAR ("NamingManager")); + } + +#if !defined (CORBA_E_MICRO) + CORBA::Object_var svc = + this->orb_->unregister_initial_reference ( + ACE_TEXT_ALWAYS_CHAR ("NameService")); + this->orb_->unregister_initial_reference ( + ACE_TEXT_ALWAYS_CHAR ("NamingManager")); +#endif /* CORBA_E_MICRO */ + + } + catch (const CORBA::Exception&) + { + // Ignore + } + + // Specific FT_Naming cleanup + naming_manager_poa_ = PortableServer::POA::_nil (); + replication_manager_poa_ = PortableServer::POA::_nil (); + my_naming_manager_ = FT_Naming::NamingManager::_nil (); + peer_naming_manager_ = FT_Naming::NamingManager::_nil (); + peer_root_context_ = CosNaming::NamingContext::_nil (); + +#if !defined (CORBA_E_MICRO) + delete this->context_index_; + delete replication_manager_; +#endif /* CORBA_E_MICRO */ + + // Invoke the base class fini + return TAO_Naming_Server::fini (); +} + +TAO_Storable_Naming_Context_Factory * +TAO_FT_Naming_Server::storable_naming_context_factory (size_t context_size) +{ + return new (ACE_nothrow) TAO_FT_Storable_Naming_Context_Factory (context_size); +} + +TAO_Persistent_Naming_Context_Factory * +TAO_FT_Naming_Server::persistent_naming_context_factory (void) +{ + return new (ACE_nothrow) TAO_FT_Persistent_Naming_Context_Factory; +} + + +int +TAO_FT_Naming_Server::read_reference_from_file (const char* replica_file_name, + CORBA::Object_out obj_ref) +{ + + ACE_CString replica_ior_string ("file://"); + replica_ior_string += replica_file_name; + + try { + CORBA::Object_var object = + this->orb_->string_to_object (replica_ior_string.c_str ()); + if (CORBA::is_nil (object.in ())) + { + if (TAO_debug_level > 3) + ACE_DEBUG ((LM_ERROR, + ACE_TEXT ("(%P|%t) - invalid ior in file <%s>\n"), + replica_file_name)); + + return -1; + } + + obj_ref = object._retn (); + + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ( + ACE_TEXT ("Invalid object reference in file: %s\n")); + return -1; + } + + return 0; +} + +int +TAO_FT_Naming_Server::export_ft_naming_references (void) +{ + int result = 0; + + switch (this->server_role_) { + // Neither the PRIMARY or STANDALONE server roles are able to write + // a multi-profile IOR for the redundant server pair. + case TAO_FT_Naming_Server::STANDALONE: + case TAO_FT_Naming_Server::PRIMARY: + + if (this->naming_manager_ior_file_name_ != 0) + { + FT_Naming::NamingManager_var my_nm = + this->my_naming_manager (); + CORBA::String_var naming_manager_ior_string = + this->orb_->object_to_string (my_nm.in ()); + this->write_ior_to_file (naming_manager_ior_string.in (), + this->naming_manager_ior_file_name_); + } + + // Make sure the user provided an ior_file_name for the comb + if (this->combined_naming_service_ior_file_name_ != 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) ERROR: Unable to write combined") + ACE_TEXT (" NameService IOR file. ") + ACE_TEXT ("Only supported by the backup naming service.\n") + ACE_TEXT ("Provide the -c option to the --backup role.\n")), + -1); + } + return 0; + break; + + case TAO_FT_Naming_Server::BACKUP: + { + // Make sure the user provided an ior_file_name for the multi-profile ior file + if (this->combined_naming_service_ior_file_name_ == 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) ERROR: Unable to write combined") + ACE_TEXT (" NameService IOR file. ") + ACE_TEXT ("No file name provided.\n")), + -1); + return 0; + } + + CORBA::Object_var peer_root_cxt = this->peer_root_context (); + if (CORBA::is_nil (peer_root_cxt.in ())) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) ERROR: Unable to get the primary") + ACE_TEXT (" NameService object ref")), + -1); + } + + CORBA::Object_var my_root_cxt = this->my_root_context (); + if (CORBA::is_nil (my_root_cxt.in ())) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) ERROR: Unable to get this") + ACE_TEXT (" services NameService object ref")), + -1); + } + + CORBA::Object_ptr IORM = + this->orb_->resolve_initial_references (TAO_OBJID_IORMANIPULATION, 0); + + TAO_IOP::TAO_IOR_Manipulation_var iorm = + TAO_IOP::TAO_IOR_Manipulation::_narrow (IORM); + + // Combine the primary and backup (my) object references for the naming service + CORBA::Object_var combined_obj_ref = + iorm->add_profiles (peer_root_cxt.in (), + my_root_cxt.in ()); + + if (CORBA::is_nil (combined_obj_ref.in ())) + { + ACE_ERROR((LM_ERROR, + ACE_TEXT("(%P|%t) ERROR: could not combine") + ACE_TEXT(" primary and backup IORs for") + ACE_TEXT(" fault tolerant Naming Service.\n"))); + return -1; + } + + CORBA::String_var combined_nameservice_ior_string = + this->orb_->object_to_string (combined_obj_ref.in ()); + + // Write out the combined IOR for the NameService + this->write_ior_to_file (combined_nameservice_ior_string.in (), + this->combined_naming_service_ior_file_name_); + + // Verify that a naming manager ior file name was provided by user + if (this->combined_naming_manager_ior_file_name_ == 0) + { + if (TAO_debug_level > 3) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) - FT_Naming_Server:No NamingManager") + ACE_TEXT (" IOR file name provided") + ACE_TEXT (" with -g option. Not writing IOR.\n"))); + } + else + {// A file name was provided to store the naming manager IOR + + FT_Naming::NamingManager_var peer_nm = + this->peer_naming_manager (); + FT_Naming::NamingManager_var my_nm = + this->my_naming_manager (); + + // This is the object reference for the fault tolerant + // naming manager. The primary should be first. + combined_obj_ref = + iorm->add_profiles (peer_nm.in (), + my_nm.in ()); + + if (CORBA::is_nil (combined_obj_ref.in ())) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT("(%P|%t) ERROR: could not combine") + ACE_TEXT(" primary and backup IORs for") + ACE_TEXT(" fault tolerant Naming Manager.\n")), + -1); + } + + CORBA::String_var combined_naming_manager_ior_string = + this->orb_->object_to_string (combined_obj_ref.in ()); + + // Write out the combined IOR for the NameService + this->write_ior_to_file (combined_naming_manager_ior_string.in (), + this->combined_naming_manager_ior_file_name_); + } + + return 0; + } + break; + }; + return result; +} + + + +/// Return the IOR for the registered replication manager +char* +TAO_FT_Naming_Server::replication_manager_ior (void) +{ + return CORBA::string_dup (this->replication_manager_ior_.in ()); +} + + +/// Return the IOR for the registered object group manager +char* +TAO_FT_Naming_Server::naming_manager_ior (void) +{ + return CORBA::string_dup (this->naming_manager_ior_.in ()); +} + +int +TAO_FT_Naming_Server::update_object_group ( + const FT_Naming::ObjectGroupUpdate & group_info) +{ + ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, + ace_mon, + this->lock_, + CORBA::INTERNAL ()); + + if (this->use_object_group_persistence_) + { + if (TAO_debug_level > 3) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("%T %n (%P|%t) - ") + ACE_TEXT ("An update of object group with ID %lld ") + ACE_TEXT ("has been made by the peer"), + group_info.id + )); + } + this->naming_manager_.set_object_group_stale (group_info); + } + else + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) ERROR: Attempting to update object group ") + ACE_TEXT ("as stale with obect group persistence not ") + ACE_TEXT ("enabled."))); + return -1; + } + + return 0; +} + +int +TAO_FT_Naming_Server::update_naming_context ( + const FT_Naming::NamingContextUpdate & context_info) +{ + ACE_GUARD_THROW_EX (ACE_SYNCH_RECURSIVE_MUTEX, + ace_mon, + this->lock_, + CORBA::INTERNAL ()); + + PortableServer::ServantBase_var servant; + + // Lookup the servant for the identified context and see if it is + // active here locally. + try { + // Get the servant if it exists in this process + PortableServer::ObjectId_var context_id = + PortableServer::string_to_ObjectId (context_info.context_name); + servant = this->ns_poa_->id_to_servant (context_id); + } + catch (PortableServer::POA::ObjectNotActive&) + { // No servant registered for this object reference so no need to create it. + // It will be created on first access in incarnate function + + // This context is not currently active in this server so + // there is nothing to be done, so return success. + return 0; + } + + TAO_Naming_Context* changed_context_servant = + dynamic_cast<TAO_Naming_Context*> (servant.in ()); + + if (changed_context_servant == 0) + { // Another type of class was used as the servant. Should not happen. + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) ERROR: Invalid servant type registered") + ACE_TEXT (" with oid: %s"), + context_info.context_name.in ())); + return -1; + } + + if (TAO_debug_level > 3) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("%T %n (%P|%t) - ") + ACE_TEXT ("An update of naming context with name %s ") + ACE_TEXT ("has been made by the peer"), + context_info.context_name.in () + )); + } + + // Mark the local context stale, so we will reload it next + // time it is modified or accessed. + changed_context_servant->stale (true); + + return 0; +} + +/// Destructor. +TAO_FT_Naming_Server::~TAO_FT_Naming_Server (void) +{ + // Clear out the static naming manager from the persistent naming context + TAO_FT_Persistent_Naming_Context::set_naming_manager_impl (0); +} + + +void +TAO_FT_Naming_Server::peer_root_context (CosNaming::NamingContext_ptr peer_cxt) +{ + peer_root_context_ = CosNaming::NamingContext::_duplicate (peer_cxt); +} + +CosNaming::NamingContext_ptr +TAO_FT_Naming_Server::peer_root_context (void) +{ + return CosNaming::NamingContext::_duplicate (peer_root_context_.in ()); +} + +CosNaming::NamingContext_ptr +TAO_FT_Naming_Server::my_root_context (void) const +{ + return CosNaming::NamingContext::_duplicate (this->naming_context_.in ()); +} + +void +TAO_FT_Naming_Server::peer_naming_manager (FT_Naming::NamingManager_ptr peer_cxt) +{ + peer_naming_manager_ = FT_Naming::NamingManager::_duplicate (peer_cxt); +} + +FT_Naming::NamingManager_ptr +TAO_FT_Naming_Server::peer_naming_manager (void) +{ + return FT_Naming::NamingManager::_duplicate (peer_naming_manager_.in ()); +} + +FT_Naming::NamingManager_ptr +TAO_FT_Naming_Server::my_naming_manager (void) const +{ + return FT_Naming::NamingManager::_duplicate (this->my_naming_manager_.in ()); +} diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Server.h b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Server.h new file mode 100644 index 00000000000..053db29c525 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Server.h @@ -0,0 +1,189 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file FT_Naming_Server.h + * + * $Id$ + * + * Implement functionality necessary for fault tolerant naming service. + * Adds support for Object Group Manager interfaces as well. This class + * extends the TAO_Naming_Server. + * + * @author Kevin Stanley + */ +//============================================================================= +// + +#ifndef TAO_FT_NAMING_SERVER_H +#define TAO_FT_NAMING_SERVER_H + +#include "orbsvcs/Naming/Naming_Server.h" +#include "orbsvcs/Naming/FaultTolerant/FT_Naming_Manager.h" +#include "orbsvcs/Naming/FaultTolerant/FT_Naming_Replication_Manager.h" +#include "orbsvcs/Naming/FaultTolerant/ftnaming_export.h" +#include "tao/IORManipulation/IORManip_Loader.h" +#include "ace/Recursive_Thread_Mutex.h" + +/** + * @class TAO_FT_Naming_Server + * + * @brief Defines a class derived from the TAO_Naming_Server to extend + the functionality to support an ObjectGroupManager interface and a + load balancing capability for objects that are bound within an object + group within the naming service. The Naming Service will extend the + resolve and resolve_str operations to perform load balancing on the + objects within the object group using a specified load balancing + strategy. + */ +class TAO_FtNaming_Export TAO_FT_Naming_Server : public TAO_Naming_Server +{ +public: + /// Default Constructor. + TAO_FT_Naming_Server (void); + + /// Initialize the Naming Service and Object Group Manager with the command line + /// arguments and the ORB. Overrridden from TAO_Naming_Server + virtual int init_with_orb (int argc, ACE_TCHAR *argv [], CORBA::ORB_ptr orb); + + /** + * Accessors and mutators for object references. + */ + /// Returns a <NamingContext_ptr> for the root Naming Context. + CosNaming::NamingContext_ptr my_root_context (void) const; + + /// Returns the reference for this servers local naming manager servant. + FT_Naming::NamingManager_ptr my_naming_manager (void) const; + + void peer_root_context (CosNaming::NamingContext_ptr peer_cxt); + CosNaming::NamingContext_ptr peer_root_context (void); + + void peer_naming_manager (FT_Naming::NamingManager_ptr peer_nm); + FT_Naming::NamingManager_ptr peer_naming_manager (void); + + /// Initialize the naming manager with the ORB. + int init_naming_manager_with_orb (int argc, + ACE_TCHAR *argv [], + CORBA::ORB_ptr orb); + + /// Initialize the replication manager with the ORB. + int init_replication_manager_with_orb (int argc, + ACE_TCHAR *argv [], + CORBA::ORB_ptr orb); + + /// Overridden parse operation. Only allows options supported by the FT_Naming_Server + /// and adds options for the object group manager + virtual int parse_args (int argc, + ACE_TCHAR *argv[]); + + /// Factory method to create a naming context factory for use with + /// the -u and -r options. + virtual TAO_Storable_Naming_Context_Factory * + storable_naming_context_factory (size_t context_size); + + /// Factory method to create a naming context factory for use with + /// the -f option. + virtual TAO_Persistent_Naming_Context_Factory * + persistent_naming_context_factory (void); + + /// Returns the IOR of the replication manager. + char* replication_manager_ior (void); + + /// Returns the IOR of the naming manager. + char * naming_manager_ior (void); + + virtual int update_object_group ( + const FT_Naming::ObjectGroupUpdate & group_info); + + virtual int update_naming_context ( + const FT_Naming::NamingContextUpdate & naming_context); + + /// Destroy the child POAs created in @c init_with_orb, + /// @c init_naming_manager_with_orb, and + /// @c init_replication_manager_with_orb + virtual int fini (void); + + /// Destructor. + virtual ~TAO_FT_Naming_Server (void); + +protected: + + /// Read the replica from the specified file + int read_reference_from_file (const char* replica_file_name, + CORBA::Object_out obj_ref); + + /// Export the NameService and NameManager combined object references + /// to the file names provided + int export_ft_naming_references (void); + + const ACE_TCHAR * replica_id_; + + /// The object that implements the ObjectGroupManager, PropertyManager, + /// and GenericFactory interfaces. + TAO_FT_Naming_Manager naming_manager_; + + /// Object reference for the local naming manager servant. + FT_Naming::NamingManager_var my_naming_manager_; + + /// Object reference for the peer naming service's naming manager. + FT_Naming::NamingManager_var peer_naming_manager_; + + /// Object reference for the peer naming service's naming manager. + CosNaming::NamingContext_var peer_root_context_; + + /// The object that implements the FT_Naming::Replication_Manager + /// interface. + TAO_FT_Naming_Replication_Manager* replication_manager_; + + /// File to output for the multi-profile root naming context IOR. + const ACE_TCHAR *combined_naming_service_ior_file_name_; + + /// File to output the multi-profile object group manager IOR. + const ACE_TCHAR *combined_naming_manager_ior_file_name_; + + /// File to output the object group manager IOR. + const ACE_TCHAR *naming_manager_ior_file_name_; + + /// Path to the file to be used to store/read in Object Group Manager + /// persistent state. + const ACE_TCHAR *naming_manager_persistence_file_name_; + + /// The IOR string of the object group manager. + CORBA::String_var naming_manager_ior_; + + /// The IOR string of the object group manager. + CORBA::String_var replication_manager_ior_; + + /// The IOR string of the peer replica. + CORBA::String_var replica_peer_ior_; + + /// The Object Group Manager POA. + PortableServer::POA_var naming_manager_poa_; + + /// The POA used for replication coordination between + /// primary and backup. + PortableServer::POA_var replication_manager_poa_; + + int use_object_group_persistence_; + ACE_CString object_group_dir_; + + /// The role this server is supporting in the dual redundant + /// replication scheme. + enum ServerRole { PRIMARY, BACKUP, STANDALONE }; + + /// The role this server is to take on. Controlled by the + /// --primary or --backup command line arguments. Defaults + /// to STANDALONE if no role is provided in command line. + ServerRole server_role_; + + /// Lock used to serialize access to fault tolerant extensions + /// to Naming Service. + TAO_SYNCH_RECURSIVE_MUTEX lock_; + +private: + static const ACE_TCHAR* primary_replica_ior_filename; + static const ACE_TCHAR* backup_replica_ior_filename; + + }; + +#endif /* TAO_FT_NAMING_SERVER_H */ diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_PG_Group_Factory.cpp b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_PG_Group_Factory.cpp new file mode 100644 index 00000000000..07e2e52a3f8 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_PG_Group_Factory.cpp @@ -0,0 +1,132 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file FT_PG_Group_Factory.cpp + * + * $Id$ + * + * @author Byron Harris <harrisb@ociweb.com> + */ +//============================================================================= + +#include "orbsvcs/Naming/FaultTolerant/FT_PG_Group_Factory.h" +#include "orbsvcs/Naming/FaultTolerant/FT_PG_Object_Group_Storable.h" + +#include "orbsvcs/PortableGroup/PG_Group_List_Store.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO::FT_PG_Group_Factory::FT_PG_Group_Factory() +{ +} + +TAO::FT_PG_Group_Factory::~FT_PG_Group_Factory() +{ +} + +void +TAO::FT_PG_Group_Factory::set_object_group_stale ( + const FT_Naming::ObjectGroupUpdate & group_info) +{ + if (this->use_persistence_) + { + PortableGroup::ObjectGroupId group_id = group_info.id; + + // If a group was added or destroyed then the group list could be stale. + if (group_info.change_type == FT_Naming::NEW || + group_info.change_type == FT_Naming::DELETED) + { + if (TAO_debug_level > 3) + { + ACE_CString change_type_str (ACE_TEXT ("created")); + if (group_info.change_type == FT_Naming::DELETED) + change_type_str = ACE_TEXT ("deleted"); + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("%T %n (%P|%t) - ") + ACE_TEXT ("Setting list store as stale "), + ACE_TEXT ("because of group with ID %lld "), + ACE_TEXT ("was %s"), + group_id, change_type_str.c_str () + )); + } + this->list_store_->stale(true); + } + + PG_Object_Group * group = 0; + if (!find_group (group_id, group)) + { + throw PortableGroup::ObjectNotFound (); + } + FT_PG_Object_Group_Storable * og = + dynamic_cast<FT_PG_Object_Group_Storable *> (group); + + if (TAO_debug_level > 3) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("%T %n (%P|%t) - ") + ACE_TEXT ("Setting object group with ID %lld as stale"), + group_id + )); + } + og->stale (true); + } + else + { + throw CORBA::INTERNAL (); + } +} + +TAO::PG_Object_Group_Storable * +TAO::FT_PG_Group_Factory::create_persistent_group ( + CORBA::ORB_ptr orb, + PortableGroup::FactoryRegistry_ptr factory_registry, + TAO::PG_Object_Group_Manipulator & manipulator, + CORBA::Object_ptr empty_group, + const PortableGroup::TagGroupTaggedComponent & tagged_component, + const char * type_id, + const PortableGroup::Criteria & the_criteria, + TAO::PG_Property_Set * type_properties, + TAO::Storable_Factory & storable_factory) +{ + TAO::PG_Object_Group_Storable * objectGroup = 0; + ACE_NEW_THROW_EX ( + objectGroup, + TAO::FT_PG_Object_Group_Storable ( + orb, + factory_registry, + manipulator, + empty_group, + tagged_component, + type_id, + the_criteria, + type_properties, + storable_factory + ), + CORBA::NO_MEMORY()); + return objectGroup; +} + +TAO::PG_Object_Group_Storable * +TAO::FT_PG_Group_Factory::restore_persistent_group ( + PortableGroup::ObjectGroupId group_id, + CORBA::ORB_ptr orb, + PortableGroup::FactoryRegistry_ptr factory_registry, + TAO::PG_Object_Group_Manipulator & manipulator, + TAO::Storable_Factory & storable_factory) +{ + TAO::PG_Object_Group_Storable * objectGroup = 0; + ACE_NEW_THROW_EX ( + objectGroup, + TAO::FT_PG_Object_Group_Storable ( + group_id, + orb, + factory_registry, + manipulator, + storable_factory + ), + CORBA::NO_MEMORY()); + return objectGroup; +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_PG_Group_Factory.h b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_PG_Group_Factory.h new file mode 100644 index 00000000000..22d0b0c88b9 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_PG_Group_Factory.h @@ -0,0 +1,82 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file FT_PG_Group_Factory.h + * + * $Id$ + * + * @author Byron Harris <harrisb@ociweb.com> + */ +//============================================================================= + +#ifndef FT_TAO_PG_GROUP_FACTORY_H +#define FT_TAO_PG_GROUP_FACTORY_H + +#include /**/ "ace/pre.h" + +#include "orbsvcs/Naming/FaultTolerant/ftnaming_export.h" + +#include "orbsvcs/PortableGroup/PG_Group_Factory.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace FT_Naming +{ + struct ObjectGroupUpdate; +} + +namespace TAO +{ + + /** + * class FT_PG_Group_Factory + */ + class TAO_FtNaming_Export FT_PG_Group_Factory : public PG_Group_Factory + { + public: + + /// Constructor. + FT_PG_Group_Factory (); + + /// Destructor. + ~FT_PG_Group_Factory (); + + /** + * indicate the object group state is stale. + * only valid when object group persistence is enabled. + */ + void set_object_group_stale (const FT_Naming::ObjectGroupUpdate & group_info); + + protected: + + virtual PG_Object_Group_Storable * create_persistent_group ( + CORBA::ORB_ptr orb, + PortableGroup::FactoryRegistry_ptr factory_registry, + TAO::PG_Object_Group_Manipulator & manipulator, + CORBA::Object_ptr empty_group, + const PortableGroup::TagGroupTaggedComponent & tagged_component, + const char * type_id, + const PortableGroup::Criteria & the_criteria, + TAO::PG_Property_Set * type_properties, + TAO::Storable_Factory & storable_factory); + + virtual PG_Object_Group_Storable * restore_persistent_group ( + PortableGroup::ObjectGroupId group_id, + CORBA::ORB_ptr orb, + PortableGroup::FactoryRegistry_ptr factory_registry, + TAO::PG_Object_Group_Manipulator & manipulator, + TAO::Storable_Factory & storable_factory); + + }; +} // namespace TAO + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" + +#endif /* FT_TAO_PG_GROUP_FACTORY_H */ diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_PG_Object_Group_Storable.cpp b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_PG_Object_Group_Storable.cpp new file mode 100644 index 00000000000..4617755347d --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_PG_Object_Group_Storable.cpp @@ -0,0 +1,182 @@ +// $Id$ + +#include "orbsvcs/Naming/FaultTolerant/FT_PG_Object_Group_Storable.h" +#include "orbsvcs/PortableGroup/PG_Object_Group_Storable.h" + +#include "orbsvcs/Naming/FaultTolerant/FT_Naming_Replication_Manager.h" +#include "tao/Stub.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO::FT_PG_Object_Group_Storable::FT_PG_Object_Group_Storable ( + CORBA::ORB_ptr orb, + PortableGroup::FactoryRegistry_ptr factory_registry, + TAO::PG_Object_Group_Manipulator & manipulator, + CORBA::Object_ptr empty_group, + const PortableGroup::TagGroupTaggedComponent & tagged_component, + const char * type_id, + const PortableGroup::Criteria & the_criteria, + TAO::PG_Property_Set * type_properties, + TAO::Storable_Factory & storable_factory) + : PG_Object_Group_Storable(orb, + factory_registry, + manipulator, + empty_group, + tagged_component, + type_id, + the_criteria, + type_properties, + storable_factory) + , stale_ (false) + , file_created_ (false) +{ +} + +TAO::FT_PG_Object_Group_Storable::FT_PG_Object_Group_Storable ( + PortableGroup::ObjectGroupId group_id, + CORBA::ORB_ptr orb, + PortableGroup::FactoryRegistry_ptr factory_registry, + TAO::PG_Object_Group_Manipulator & manipulator, + TAO::Storable_Factory & storable_factory) + : PG_Object_Group_Storable(group_id, + orb, + factory_registry, + manipulator, + storable_factory) + , stale_ (false) + , file_created_ (true) +{ +} + +TAO::FT_PG_Object_Group_Storable::~FT_PG_Object_Group_Storable (void) +{ +} + +void +TAO::FT_PG_Object_Group_Storable::stale (bool is_stale) +{ + this->stale_ = is_stale; +} + +bool +TAO::FT_PG_Object_Group_Storable::stale () +{ + return this->stale_; +} + +int +TAO::FT_PG_Object_Group_Storable::propagate_update_notification + (FT_Naming::ChangeType change_type) +{ + // Notify the peer of the changed context + FT_Naming::ReplicationManager_var peer = + TAO_FT_Naming_Replication_Manager::peer_replica (); + + if (CORBA::is_nil (peer.in ())) + { + // Replication is not supported without a peer replica. + return 1; + } + + FT_Naming::ObjectGroupUpdate object_group_info; + object_group_info.id = PG_Object_Group::get_object_group_id (); + object_group_info.change_type = change_type; + + try { + // Notify the naming_manager of the updated context + if (TAO_debug_level > 3) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("%T %n (%P|%t) - ") + ACE_TEXT ("Notifying peer that object group with ID %lld ") + ACE_TEXT ("has been updated"), object_group_info.id + )); + } + peer->notify_updated_object_group (object_group_info); + } + catch (CORBA::Exception& ex) + { + if (TAO_debug_level > 3) + ex._tao_print_exception ( + ACE_TEXT ("Unable to communicate with peer.\n")); + return -1; + } + + return 0; +} + +void +TAO::FT_PG_Object_Group_Storable::state_written (void) +{ + FT_Naming::ChangeType change_type; + + if (!this->file_created_) + { + change_type = FT_Naming::NEW; + this->file_created_ = true; + } + else if (this->destroyed_) + change_type = FT_Naming::DELETED; + else + change_type = FT_Naming::UPDATED; + + // If peer is available notify that state has changed. + // Otherwise, rely on file time stamps exclusively + // for update notification. + this->propagate_update_notification (change_type); + + this->write_occurred_ = false; +} + +bool +TAO::FT_PG_Object_Group_Storable::is_obsolete (time_t stored_time) +{ + ACE_UNUSED_ARG (stored_time); + return (!this->loaded_from_stream_) || this->stale_; +} + +PortableGroup::ObjectGroup_ptr +TAO::FT_PG_Object_Group_Storable::add_member_to_iogr (CORBA::Object_ptr member) +{ + // If this is the first member added to the group and it's type_id does + // not match the member, then the object group should assume the same + // type id as the first member. We will need to replace the object + // reference with an empty reference of the specified type id. + + if (CORBA::is_nil (member)) + {// A null object reference is not an acceptable member of the group. + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) ERROR: Unable to add null member ") + ACE_TEXT ("to object group with id: %s\n"), + this->tagged_component_.object_group_id)); + return CORBA::Object::_nil (); + } + + const char* member_type_id = member->_stubobj ()->type_id.in (); + + if ((this->members_.current_size () == 0) && + (ACE_OS::strcmp (this->type_id_, member_type_id) != 0) ) + { + try { + this->type_id_ = member_type_id; + this->reference_ = manipulator_.create_object_group_using_id ( + this->type_id_, + this->tagged_component_.group_domain_id, + this->tagged_component_.object_group_id); + } + catch (const CORBA::Exception&) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) ERROR: Unable to add member ") + ACE_TEXT ("to object group with id: %s for object ") + ACE_TEXT ("of type: %s\n"), + this->tagged_component_.object_group_id, + member_type_id)); + return CORBA::Object::_nil (); + } + } + + return PG_Object_Group::add_member_to_iogr (member); +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_PG_Object_Group_Storable.h b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_PG_Object_Group_Storable.h new file mode 100644 index 00000000000..374400188f0 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_PG_Object_Group_Storable.h @@ -0,0 +1,132 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file FT_PG_Object_Group_Storable.h + * + * $Id$ + * + * Contains declaration for class FT_PG_Object_Group_Storable. + * + * @author Byron Harris <harrisb@ociweb.com> + */ +//============================================================================= + +#ifndef FT_TAO_PG_OBJECT_GROUP_STORABLE_H_ +#define FT_TAO_PG_OBJECT_GROUP_STORABLE_H_ +#include /**/ "ace/pre.h" + +#include "orbsvcs/Naming/FaultTolerant/ftnaming_export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + + +///////////////////////////////// +// Includes needed by this header +#include "orbsvcs/PortableGroup/PG_Object_Group_Storable.h" +#include "orbsvcs/FT_NamingReplicationC.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +//////////////// +// Class declarations +namespace TAO +{ + /** + * An object group whose state persists to a stream so that its state + * can be saved/retrieved between processes that use the group. + */ + class TAO_FtNaming_Export FT_PG_Object_Group_Storable + : public PG_Object_Group_Storable + { + + ///////////////////// + // Construct/Destruct + public: + + /** + * This constructor is suitable for creating an object group from + * scratch. + */ + FT_PG_Object_Group_Storable ( + CORBA::ORB_ptr orb, + PortableGroup::FactoryRegistry_ptr factory_registry, + TAO::PG_Object_Group_Manipulator & manipulator, + CORBA::Object_ptr empty_group, + const PortableGroup::TagGroupTaggedComponent & tagged_component, + const char * type_id, + const PortableGroup::Criteria & the_criteria, + TAO::PG_Property_Set * type_properties, + TAO::Storable_Factory & storable_factory); + + /** + * This constructor is suitable for creating an object group from + * persistent store. + */ + FT_PG_Object_Group_Storable ( + PortableGroup::ObjectGroupId group_id, + CORBA::ORB_ptr orb, + PortableGroup::FactoryRegistry_ptr factory_registry, + TAO::PG_Object_Group_Manipulator & manipulator, + TAO::Storable_Factory & storable_factory); + + /// Destructor + ~FT_PG_Object_Group_Storable (); + + ///////////////// + // public methods + + public: + + virtual void stale (bool is_stale); + virtual bool stale (); + + protected: + + virtual void state_written (); + + virtual bool is_obsolete (time_t stored_time); + + /// Provide support for modifying the object group type_id when first + /// member is added to the group. + virtual PortableGroup::ObjectGroup_ptr add_member_to_iogr( + CORBA::Object_ptr member); + + private: + + ///////////////////////// + // Forbidden methods + FT_PG_Object_Group_Storable (); + FT_PG_Object_Group_Storable (const FT_PG_Object_Group_Storable & rhs); + FT_PG_Object_Group_Storable & operator = ( + const FT_PG_Object_Group_Storable & rhs); + + /// Replication persistence support + + bool stale_; + + /// Track if the persistent file used for storage has been created yet + /// so can know if we should propagate a change type of NEW. + bool file_created_; + + /** + * Although it is assumed for replication that services + * using object groups share the persistent store, a + * CORBA message is sent upon update from one replica to + * another so the object group data can be marked as stale. + * This is because using the file time stamp to detect + * if the data has been updated only provides one second + * resolution. + */ + int propagate_update_notification (FT_Naming::ChangeType change_type); + + }; +} // namespace TAO + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" + +#endif // FT_TAO_PG_OBJECT_GROUP_STORABLE_H_ diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context.cpp b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context.cpp new file mode 100644 index 00000000000..ab1a1ae2737 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context.cpp @@ -0,0 +1,111 @@ +// $Id$ + +#include "orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context.h" +#include "orbsvcs/Naming/FaultTolerant/FT_Naming_Manager.h" +#include "orbsvcs/FT_NamingManagerC.h" +#include "orbsvcs/PortableGroup/PG_Utils.h" +#include "orbsvcs/PortableGroup/PG_Property_Utils.h" + +#include "orbsvcs/Naming/Persistent_Context_Index.h" +#include "ace/OS_NS_stdio.h" + +#include "ace/Auto_Ptr.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +// Initialize the static naming manager +TAO_FT_Naming_Manager *TAO_FT_Persistent_Naming_Context::naming_manager_impl_ = 0; + +TAO_FT_Persistent_Naming_Context::TAO_FT_Persistent_Naming_Context ( + PortableServer::POA_ptr poa, + const char *poa_id, + TAO_Persistent_Context_Index *context_index, + HASH_MAP *map, + ACE_UINT32 *counter) + : TAO_Persistent_Naming_Context (poa, + poa_id, + context_index, + map, + counter) +{ + +} + + +TAO_FT_Persistent_Naming_Context::~TAO_FT_Persistent_Naming_Context (void) +{ + // Perform appropriate cleanup based on the destruction level specified. +} + + +CORBA::Boolean +TAO_FT_Persistent_Naming_Context::is_object_group (CORBA::Object_ptr obj) const +{ + // If there is a tagged component with tag = IOP::TAG_FT_GROUP in + // the object reference then it is an object group + PortableGroup::TagGroupTaggedComponent tagged_component; + return TAO::PG_Utils::get_tagged_component (obj, tagged_component); +} + +CORBA::Object_ptr +TAO_FT_Persistent_Naming_Context::resolve (const CosNaming::Name& n) +{ + // Invoke the base class resolve operation to acquire the object at the + // specified compound name. + // Any exceptions should flow back to client. + CORBA::Object_var resolved_ref = + TAO_Persistent_Naming_Context::resolve(n); + + ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, this->lock_, + CORBA::INTERNAL ()); + + // Get the locations of the object group members and we will use them to + // do the load balancing + try { + + // Make sure object is an object group. + // We will return the object reference all the way back out to the client + // if not + if (!this->is_object_group (resolved_ref.in ())) + return resolved_ref._retn (); + + // If there is no naming manager, we will fail and report an error. + if ( this->naming_manager_impl_ == 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO_FT_Persistent_Naming_Context::resolve ") + ACE_TEXT ("- No NamingManager defined.\n"))); + + throw CORBA::INTERNAL (); + } + + // The Naming Manager will apply the appropriate strategy to get the + // next object reference from the object group. + resolved_ref = this->naming_manager_impl_->next_member (resolved_ref.in ()); + } + catch (const PortableGroup::ObjectGroupNotFound&) + { + // This is apparently not an object group, so we should return the + // object reference itself + // No action required + } + catch (CORBA::Exception& ex) + { + ex._tao_print_exception ( + ACE_TEXT ("TAO_FT_Persistent_Naming_Context::resolve ") + ACE_TEXT ("- Some unhandled error occurred\n")); + return CORBA::Object::_nil (); + } + + return resolved_ref._retn (); +} + +void +TAO_FT_Persistent_Naming_Context::set_naming_manager_impl ( + TAO_FT_Naming_Manager *mgr_impl) +{ + naming_manager_impl_ = (mgr_impl); +} + + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context.h b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context.h new file mode 100644 index 00000000000..1303c78daae --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context.h @@ -0,0 +1,75 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file FT_Persistent_Naming_Context.h + * + * $Id$ + * + * @author Kevin Stanley <stanleyk@ociweb.com> + */ +//============================================================================= + + +#ifndef TAO_FT_PERSISTENT_NAMING_CONTEXT_H +#define TAO_FT_PERSISTENT_NAMING_CONTEXT_H +#include /**/ "ace/pre.h" + +#include "orbsvcs/Naming/Persistent_Naming_Context.h" +#include "orbsvcs/Naming/FaultTolerant/ftnaming_export.h" +#include "orbsvcs/orbsvcs/PortableGroupC.h" +#include "orbsvcs/Naming/FaultTolerant/FT_Naming_Manager.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class TAO_FT_Persistent_Naming_Context + * + * @brief This class specializes the TAO_Persistent_Naming_Context + * 'ConcreteImplementor' in the Bridge pattern architecture of the + * CosNaming::NamingContext implementation. + * + */ +class TAO_FtNaming_Export TAO_FT_Persistent_Naming_Context : + public TAO_Persistent_Naming_Context +{ +public: + /// Underlying data structure - typedef for ease of use. + typedef TAO_Persistent_Naming_Context::HASH_MAP HASH_MAP; + + // = Initialization and termination methods. + + /** + * Constructor that takes in preallocated data structure and takes + * ownership of it. Derived class from TAO_Persistent_Naming_Context + * provides specialization of the resolve operation to support + * load balancing. + */ + TAO_FT_Persistent_Naming_Context (PortableServer::POA_ptr poa, + const char *poa_id, + TAO_Persistent_Context_Index *context_index, + HASH_MAP * map = 0, + ACE_UINT32 *counter = 0); + + /// Destructor. + virtual ~TAO_FT_Persistent_Naming_Context (void); + + /** + * Override the resolve operation to support load balancing using + * the object group manager and associated strategy. + */ + virtual CORBA::Object_ptr resolve (const CosNaming::Name &n); + + static void set_naming_manager_impl (TAO_FT_Naming_Manager *mgr_impl); + + bool is_object_group (const CORBA::Object_ptr obj) const; + +protected: + static TAO_FT_Naming_Manager *naming_manager_impl_; + +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" +#endif /* TAO_FT_PERSISTENT_NAMING_CONTEXT_H */ diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context_Factory.cpp b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context_Factory.cpp new file mode 100644 index 00000000000..5ba6a1d38c4 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context_Factory.cpp @@ -0,0 +1,40 @@ +// $Id$ + +#include "orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context_Factory.h" +#include "orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + + /// Constructor. +TAO_FT_Persistent_Naming_Context_Factory::TAO_FT_Persistent_Naming_Context_Factory (void) +: TAO_Persistent_Naming_Context_Factory () +{ + +} + + /// Destructor. Does not deallocate the hash map: if an instance of + /// this class goes out of scope, its hash_map remains in persistent storage. +TAO_FT_Persistent_Naming_Context_Factory::~TAO_FT_Persistent_Naming_Context_Factory (void) +{ +} + + +/// Factory method for creating an implementation object for naming contexts +TAO_Persistent_Naming_Context* +TAO_FT_Persistent_Naming_Context_Factory::create_naming_context_impl ( + PortableServer::POA_ptr poa, + const char *poa_id, + TAO_Persistent_Context_Index *context_index, + HASH_MAP * map, + ACE_UINT32 *counter) +{ + // Construct the naming context, forwarding the map and counter even if they + // are defaulted + return new (ACE_nothrow) TAO_FT_Persistent_Naming_Context (poa, + poa_id, + context_index, + map, + counter); +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context_Factory.h b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context_Factory.h new file mode 100644 index 00000000000..bebf02fdbc7 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context_Factory.h @@ -0,0 +1,56 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file FT_Persistent_Naming_Context_Factory.h + * + * $Id$ + * + * @author Kevin Stanley stanleyk@ociweb.com> + */ +//============================================================================= + + +#ifndef TAO_FT_PERSISTENT_NAMING_CONTEXT_FACTORY_H +#define TAO_FT_PERSISTENT_NAMING_CONTEXT_FACTORY_H +#include /**/ "ace/pre.h" + +#include "orbsvcs/Naming/Persistent_Naming_Context_Factory.h" +#include "orbsvcs/Naming/FaultTolerant/ftnaming_export.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class TAO_FT_Persistent_Naming_Context_Factory + * + * @brief An implementation of the TAO_Naming_Context_Factory that creates + * TAO_FT_Persistent_Naming_Context to implement the COS Naming Service + * NamingContext interface. + */ +class TAO_FtNaming_Export TAO_FT_Persistent_Naming_Context_Factory + : public TAO_Persistent_Naming_Context_Factory +{ +public: + + // = Initialization and termination methods. + + /// Constructor. + TAO_FT_Persistent_Naming_Context_Factory (void); + + /// Destructor. Does not deallocate the hash map: if an instance of + /// this class goes out of scope, its hash_map remains in persistent storage. + virtual ~TAO_FT_Persistent_Naming_Context_Factory (void); + + /// Factory method for creating an implementation object for naming contexts + virtual TAO_Persistent_Naming_Context* create_naming_context_impl ( + PortableServer::POA_ptr poa, + const char *poa_id, + TAO_Persistent_Context_Index *context_index, + HASH_MAP * map = 0, + ACE_UINT32 *counter = 0); +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" +#endif /* TAO_FT_PERSISTENT_NAMING_CONTEXT_FACTORY_H */ diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Round_Robin.cpp b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Round_Robin.cpp new file mode 100644 index 00000000000..132d2a25d3a --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Round_Robin.cpp @@ -0,0 +1,76 @@ +// -*- C++ -*- +// $Id$ + +#include "orbsvcs/Naming/FaultTolerant/FT_Round_Robin.h" +#include "orbsvcs/Naming/FaultTolerant/FT_Naming_Manager.h" + +#include "orbsvcs/PortableGroup/PG_conf.h" + +#include "tao/debug.h" +#include "tao/ORB_Constants.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_FT_Round_Robin::TAO_FT_Round_Robin (void) + : lock_ (), + location_index_map_ (TAO_PG_MAX_OBJECT_GROUPS) +{ +} + +TAO_FT_Round_Robin::~TAO_FT_Round_Robin (void) +{ +} + + +bool +TAO_FT_Round_Robin::next_location ( + PortableGroup::ObjectGroup_ptr object_group, + TAO_FT_Naming_Manager *naming_manager, + PortableGroup::Location& location) +{ + const PortableGroup::ObjectGroupId id = + naming_manager->get_object_group_id (object_group); + + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, + monitor, + this->lock_, + 0); + + PortableGroup::Locations_var locations = + naming_manager->locations_of_members (object_group); + + const CORBA::ULong len = locations->length (); + + // No locations exist, so we can't get the next one + if (len == 0) + return false; + + TAO_FT_Location_Index_Map::ENTRY * entry; + if (this->location_index_map_.find (id, entry) == 0) + { + CORBA::ULong & i = entry->int_id_; + + if (len <= i) + i = 0; // Reset, i.e. wrap around + + location = locations[i]; + + // Increment index to point to next location. + ++i; + + return true; + } + + // Could not find an entry + // Create an entry at location 0 + CORBA::ULong start = 0; + location = locations[start++]; + if (this->location_index_map_.bind (id, start) != 0) + { // The location was already bound or some failure occured. Should not happen. + throw CORBA::INTERNAL (); + } + return true; +} + + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Round_Robin.h b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Round_Robin.h new file mode 100644 index 00000000000..3708771bba8 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Round_Robin.h @@ -0,0 +1,95 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file FT_Round_Robin.h + * + * $Id$ + * + * @author Kevin Stanley <stanleyk@ociweb.com> + */ +//============================================================================= + + +#ifndef FT_ROUND_ROBIN_H +#define FT_ROUND_ROBIN_H + +#include /**/ "ace/pre.h" + +#include "ace/Null_Mutex.h" + +# if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +# endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "orbsvcs/Naming/FaultTolerant/FT_Location_Index_Map.h" + + +#include "orbsvcs/CosLoadBalancingS.h" +#include "ace/Vector_T.h" +#include "orbsvcs/Naming/FaultTolerant/ftnaming_export.h" + +class TAO_FT_Naming_Manager; + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class TAO_LB_RoundRobin_Strategy + * + * @brief "Round Robin" load balancing strategy used by the + * TAO_FT_Naming_Service. + * + * This load balancing strategy is designed to select an object group + * member residing at the next location from an object group managed + * by a specific Naming Manager. It selects an object from the object + * group in the order in which they are stored. + */ +class TAO_FtNaming_Export TAO_FT_Round_Robin +{ +public: + + /// Constructor. + TAO_FT_Round_Robin (void); + + /// This function obtains the next object's location as it is bound + /// within the object group. + /// @param naming_manager The TAO_FT_Naming_Manager which houses the + /// object groups. + /// @param location The resulting location + /// @param object_group The object group from which the object is to + /// be selected + /// @return False on error. Returns true if a valid object can + /// be selected using the Round Robin load balancing strategy. + virtual bool next_location ( + PortableGroup::ObjectGroup_ptr object_group, + TAO_FT_Naming_Manager *naming_manager, + PortableGroup::Location& location); + + /// Destructor + virtual ~TAO_FT_Round_Robin (void); + +private: + + /// Lock used to ensure atomic access to state retained by this + /// class. + TAO_SYNCH_MUTEX lock_; + + /// Table that maps PortableGroup::ObjectGroupId to location + /// sequence index specific to a given object group. + /** + * The location sequence corresponds to the sequence containing the + * locations of the members of a given object group. The value + * stored in this map corresponds to the index of the next element + * in that sequence. For example, if the index stored in the map is + * 2, location[2] will be used when retrieving the object reference + * to be returned from the Strategy::next_member() method. + */ + TAO_FT_Location_Index_Map location_index_map_; + +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" + +#endif /* FT_ROUND_ROBIN_H */ diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context.cpp b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context.cpp new file mode 100644 index 00000000000..653b4ef90c0 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context.cpp @@ -0,0 +1,183 @@ +// $Id$ + +#include "orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context.h" +#include "orbsvcs/Naming/FaultTolerant/FT_Naming_Manager.h" +#include "orbsvcs/Naming/FaultTolerant/FT_Naming_Replication_Manager.h" +#include "orbsvcs/FT_NamingManagerC.h" +#include "orbsvcs/PortableGroup/PG_Utils.h" +#include "orbsvcs/PortableGroup/PG_Property_Utils.h" + +#include "orbsvcs/Naming/Persistent_Context_Index.h" +#include "ace/OS_NS_stdio.h" + +#include "ace/Auto_Ptr.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +// Initialize the static naming manager +TAO_FT_Naming_Manager *TAO_FT_Storable_Naming_Context::naming_manager_ = 0; + +TAO_FT_Storable_Naming_Context::TAO_FT_Storable_Naming_Context (CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + const char *poa_id, + TAO_Storable_Naming_Context_Factory *cxt_factory, + TAO::Storable_Factory *pers_factory) + : TAO_Storable_Naming_Context (orb, + poa, + poa_id, + cxt_factory, + pers_factory), + stale_ (false) +{ + +} + + +TAO_FT_Storable_Naming_Context::~TAO_FT_Storable_Naming_Context (void) +{ + // Perform appropriate cleanup based on the destruction level specified. +} + + +CORBA::Boolean +TAO_FT_Storable_Naming_Context::is_object_group (CORBA::Object_ptr obj) const +{ + // Ensure the object is not nil first. If so, it cannot be an ObjectGroup. + if (CORBA::is_nil (obj)) + return 0; + + // If there is a tagged component with tag = IOP::TAG_FT_GROUP in the + // object reference then it is an object group + PortableGroup::TagGroupTaggedComponent tagged_component; + return TAO::PG_Utils::get_tagged_component (obj, tagged_component); +} + +CORBA::Object_ptr +TAO_FT_Storable_Naming_Context::resolve (const CosNaming::Name& n) +{ + // Invoke the base class resolve operation to acquire the object at the + // specified compound name. Any exceptions should flow back to client. + CORBA::Object_var resolved_ref = + TAO_Storable_Naming_Context::resolve(n); + + ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, this->lock_, + CORBA::INTERNAL ()); + + try { + + // Make sure object is an object group. + // We will return the object reference as is all the way back + // out to the client if not + if (!this->is_object_group (resolved_ref.in ())) + return resolved_ref._retn (); + + // If there is no naming manager, we will fail and report an error. + if ( this->naming_manager_ == 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO_FT_Storable_Naming_Context::resolve ") + ACE_TEXT ("- No NamingManager defined.\n"))); + + throw CORBA::INTERNAL (); + } + + // The Naming Manager will apply the appropriate strategy to get the + // next object reference from the object group. + resolved_ref = this->naming_manager_->next_member (resolved_ref.in ()); + } + catch (const PortableGroup::ObjectGroupNotFound&) + { + // This is apparently not an object group, so we should return the + // object reference itself + // No action required + } + catch (CORBA::Exception& ex) + { + ex._tao_print_exception ( + ACE_TEXT ("TAO_FT_Storable_Naming_Context::resolve - ") + ACE_TEXT ("Some unhandled error occurred\n")); + return CORBA::Object::_nil (); + } + + return resolved_ref._retn (); +} + +int +TAO_FT_Storable_Naming_Context::propagate_update_notification ( + FT_Naming::ChangeType change_type) +{ + // Notify the peer of the changed context + FT_Naming::ReplicationManager_var peer = + TAO_FT_Naming_Replication_Manager::peer_replica (); + + if (CORBA::is_nil (peer.in ())) + { + // Replication is not supported without a peer replica. + return 1; + } + + FT_Naming::NamingContextUpdate context_info; + context_info.context_name = this->context_name_.c_str (); + + // We are are updating the context one element before the specified name + context_info.change_type = change_type; + + try { + // Notify the naming_manager of the updated context + peer->notify_updated_context (context_info); + } + catch (CORBA::Exception& ex) + { + if (TAO_debug_level > 3) + ex._tao_print_exception (ACE_TEXT ("Unable to communicate with peer.\n")); + return -1; + } + + return 0; +} + +void +TAO_FT_Storable_Naming_Context::set_naming_manager ( + TAO_FT_Naming_Manager *mgr_impl) +{ + naming_manager_ = mgr_impl; +} + +void +TAO_FT_Storable_Naming_Context::stale (bool is_stale) +{ + this->stale_ = is_stale; +} + + +bool +TAO_FT_Storable_Naming_Context::stale (void) +{ + return stale_; +} + + +void +TAO_FT_Storable_Naming_Context::context_written (void) +{ + FT_Naming::ChangeType change_type; + + if (this->destroyed_) + change_type = FT_Naming::DELETED; + else + change_type = FT_Naming::UPDATED; + + propagate_update_notification (change_type); +} + +bool +TAO_FT_Storable_Naming_Context::is_obsolete (time_t stored_time) +{ + // If data has never been loaded, then the context_ object will + // be a null pointer. + return ((this->context_ == 0) || // Has not been loaded + this->stale () || // Explicitly marked stale by peer + (stored_time > this->last_changed_)); // File has been updated +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context.h b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context.h new file mode 100644 index 00000000000..96b0f4d0317 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context.h @@ -0,0 +1,112 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file FT_Storable_Naming_Context.h + * + * $Id$ + * + * @author Kevin Stanley <stanleyk@ociweb.com> + */ +//============================================================================= + + +#ifndef TAO_FT_STORABLE_NAMING_CONTEXT_H +#define TAO_FT_STORABLE_NAMING_CONTEXT_H +#include /**/ "ace/pre.h" + +#include "orbsvcs/Naming/Storable_Naming_Context.h" +#include "orbsvcs/Naming/FaultTolerant/ftnaming_export.h" +#include "orbsvcs/orbsvcs/PortableGroupC.h" +#include "orbsvcs/Naming/FaultTolerant/FT_Naming_Manager.h" +#include "orbsvcs/FT_NamingReplicationC.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class FT_TAO_Storable_Naming_Context + * + * @brief This class specializes the TAO_Storable_Naming_Context + * 'ConcreteImplementor' in the Bridge pattern architecture of the + * CosNaming::NamingContext implementation. + * + */ +class TAO_FtNaming_Export TAO_FT_Storable_Naming_Context : + public TAO_Storable_Naming_Context +{ +public: + // = Initialization and termination methods. + + /** + * Constructor that takes in preallocated data structure and takes + * ownership of it. Derived class from TAO_Persistent_Naming_Context + * provides specialization of the resolve operation to support + * load balancing. + */ + TAO_FT_Storable_Naming_Context (CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + const char *poa_id, + TAO_Storable_Naming_Context_Factory *cxt_factory, + TAO::Storable_Factory *factory); + + /// Destructor. + virtual ~TAO_FT_Storable_Naming_Context (void); + + /** + * Override the resolve operation to support load balancing using + * the object group manager and associated strategy. + */ + virtual CORBA::Object_ptr resolve (const CosNaming::Name &n); + + // Set the Naming Manager as a static so that it is available for all + // naming context implementations. + static void set_naming_manager (TAO_FT_Naming_Manager *mgr_impl); + + bool is_object_group (const CORBA::Object_ptr obj) const; + + /** + * Tell the peer replica that this context has been updated. + * Returns 0 if successfully reported. Returns 1 if no peer + * has been registered. Returns -1 on failure to communicate + * with the peer. + */ + int propagate_update_notification (FT_Naming::ChangeType change_type); + + /** + * Find the indicated context below this context. Returns 0 + * if it cannot be found. + */ + TAO_FT_Storable_Naming_Context* find_relative_context ( + const CosNaming::Name &n); + + /** + * Mark the implementation as stale for replicated persistence support. + */ + virtual void stale (bool is_stale); + + virtual bool stale (void); + + /** + * An internal utility used to signal that this context was updated. + * Check the last_changed_ attribute for the time of the write. + */ + void context_written (void); + + /** + * An internal callback invoked by the File_Open_Lock_and_Check + * object to determine if this context is obsolete with respect to the + * file object . + */ + virtual bool is_obsolete (time_t stored_time); + +protected: + + static TAO_FT_Naming_Manager *naming_manager_; + bool stale_; + +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" +#endif /* TAO_FT_STORABLE_NAMING_CONTEXT_H */ diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context_Factory.cpp b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context_Factory.cpp new file mode 100644 index 00000000000..9a35f407ab7 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context_Factory.cpp @@ -0,0 +1,47 @@ +// $Id$ + +#include "orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context_Factory.h" +#include "orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + + /// Constructor. +TAO_FT_Storable_Naming_Context_Factory::TAO_FT_Storable_Naming_Context_Factory ( + size_t hash_table_size) + : TAO_Storable_Naming_Context_Factory (hash_table_size) +{ + +} + + /// Destructor. Does not deallocate the hash map: if an instance of + /// this class goes out of scope, its hash_map remains in persistent storage. +TAO_FT_Storable_Naming_Context_Factory::~TAO_FT_Storable_Naming_Context_Factory (void) +{ + +} + + +TAO_Storable_Naming_Context* +TAO_FT_Storable_Naming_Context_Factory::create_naming_context_impl ( + CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + const char *poa_id, + TAO::Storable_Factory *persistence_factory + ) +{ + // Construct the naming context, forwarding the map and counter + // even if they are defaulted + TAO_FT_Storable_Naming_Context *context_impl; + ACE_NEW_THROW_EX (context_impl, + TAO_FT_Storable_Naming_Context (orb, + poa, + poa_id, + this, + persistence_factory), + CORBA::NO_MEMORY ()); + + return context_impl; +} + + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context_Factory.h b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context_Factory.h new file mode 100644 index 00000000000..b714d052914 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context_Factory.h @@ -0,0 +1,66 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file FT_Storable_Naming_Context_Factory.h + * + * $Id$ + * + * @author Kevin Stanley stanleyk@ociweb.com> + */ +//============================================================================= + + +#ifndef TAO_FT_STORABLE_NAMING_CONTEXT_FACTORY_H +#define TAO_FT_STORABLE_NAMING_CONTEXT_FACTORY_H +#include /**/ "ace/pre.h" + +#include "orbsvcs/Naming/Storable_Naming_Context_Factory.h" +#include "tao/ORB.h" +#include "orbsvcs/Naming/nsconf.h" +#include "orbsvcs/Naming/FaultTolerant/ftnaming_export.h" +#include "orbsvcs/Naming/Hash_Naming_Context.h" +#include "orbsvcs/Naming/Storable_Naming_Context.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class TAO_Naming_Context_Factory + * + * @brief + */ +class TAO_FtNaming_Export TAO_FT_Storable_Naming_Context_Factory : + public TAO_Storable_Naming_Context_Factory +{ +public: + + /// Data structure used by TAO_Persistent_Context_Index - + /// typedef for ease of use. + typedef TAO_Storable_Naming_Context_Factory::HASH_MAP HASH_MAP; + + // = Initialization and termination methods. + + /// Constructor. + TAO_FT_Storable_Naming_Context_Factory ( + size_t hash_table_size = ACE_DEFAULT_MAP_SIZE); + + /// Destructor. Does not deallocate the hash map: if an instance of + /// this class goes out of scope, its hash_map remains in persistent storage. + virtual ~TAO_FT_Storable_Naming_Context_Factory (void); + + /// Factory method for creating an implementation object for naming contexts. + /// If an existing naming context implementation is being rebuilt, + /// the map and counter parameters should be provided to the underlying + /// HASH_MAP implementation + virtual TAO_Storable_Naming_Context* create_naming_context_impl ( + CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + const char *poa_id, + TAO::Storable_Factory *factory); + +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" +#endif /* TAO_FT_STORABLE_NAMING_CONTEXT_FACTORY_H */ diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/ftnaming_export.h b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/ftnaming_export.h new file mode 100644 index 00000000000..e8a204363c9 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/ftnaming_export.h @@ -0,0 +1,58 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl TAO_FtNaming +// ------------------------------ +#ifndef TAO_FTNAMING_EXPORT_H +#define TAO_FTNAMING_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (TAO_FTNAMING_HAS_DLL) +# define TAO_FTNAMING_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && TAO_FTNAMING_HAS_DLL */ + +#if !defined (TAO_FTNAMING_HAS_DLL) +# define TAO_FTNAMING_HAS_DLL 1 +#endif /* ! TAO_FTNAMING_HAS_DLL */ + +#if defined (TAO_FTNAMING_HAS_DLL) && (TAO_FTNAMING_HAS_DLL == 1) +# if defined (TAO_FTNAMING_BUILD_DLL) +# define TAO_FtNaming_Export ACE_Proper_Export_Flag +# define TAO_FTNAMING_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define TAO_FTNAMING_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* TAO_FTNAMING_BUILD_DLL */ +# define TAO_FtNaming_Export ACE_Proper_Import_Flag +# define TAO_FTNAMING_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define TAO_FTNAMING_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* TAO_FTNAMING_BUILD_DLL */ +#else /* TAO_FTNAMING_HAS_DLL == 1 */ +# define TAO_FtNaming_Export +# define TAO_FTNAMING_SINGLETON_DECLARATION(T) +# define TAO_FTNAMING_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* TAO_FTNAMING_HAS_DLL == 1 */ + +// Set TAO_FTNAMING_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (TAO_FTNAMING_NTRACE) +# if (ACE_NTRACE == 1) +# define TAO_FTNAMING_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define TAO_FTNAMING_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !TAO_FTNAMING_NTRACE */ + +#if (TAO_FTNAMING_NTRACE == 1) +# define TAO_FTNAMING_TRACE(X) +#else /* (TAO_FTNAMING_NTRACE == 1) */ +# if !defined (ACE_HAS_TRACE) +# define ACE_HAS_TRACE +# endif /* ACE_HAS_TRACE */ +# define TAO_FTNAMING_TRACE(X) ACE_TRACE_IMPL(X) +# include "ace/Trace.h" +#endif /* (TAO_FTNAMING_NTRACE == 1) */ + +#endif /* TAO_FTNAMING_EXPORT_H */ + +// End of auto generated file. diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/ftnaming_intf_export.h b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/ftnaming_intf_export.h new file mode 100644 index 00000000000..6b52adde64a --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/ftnaming_intf_export.h @@ -0,0 +1,58 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl TAO_FtNaming_Intf +// ------------------------------ +#ifndef TAO_FTNAMING_INTF_EXPORT_H +#define TAO_FTNAMING_INTF_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (TAO_FTNAMING_INTF_HAS_DLL) +# define TAO_FTNAMING_INTF_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && TAO_FTNAMING_INTF_HAS_DLL */ + +#if !defined (TAO_FTNAMING_INTF_HAS_DLL) +# define TAO_FTNAMING_INTF_HAS_DLL 1 +#endif /* ! TAO_FTNAMING_INTF_HAS_DLL */ + +#if defined (TAO_FTNAMING_INTF_HAS_DLL) && (TAO_FTNAMING_INTF_HAS_DLL == 1) +# if defined (TAO_FTNAMING_INTF_BUILD_DLL) +# define TAO_FtNaming_Intf_Export ACE_Proper_Export_Flag +# define TAO_FTNAMING_INTF_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define TAO_FTNAMING_INTF_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* TAO_FTNAMING_INTF_BUILD_DLL */ +# define TAO_FtNaming_Intf_Export ACE_Proper_Import_Flag +# define TAO_FTNAMING_INTF_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define TAO_FTNAMING_INTF_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* TAO_FTNAMING_INTF_BUILD_DLL */ +#else /* TAO_FTNAMING_INTF_HAS_DLL == 1 */ +# define TAO_FtNaming_Intf_Export +# define TAO_FTNAMING_INTF_SINGLETON_DECLARATION(T) +# define TAO_FTNAMING_INTF_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* TAO_FTNAMING_INTF_HAS_DLL == 1 */ + +// Set TAO_FTNAMING_INTF_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (TAO_FTNAMING_INTF_NTRACE) +# if (ACE_NTRACE == 1) +# define TAO_FTNAMING_INTF_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define TAO_FTNAMING_INTF_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !TAO_FTNAMING_INTF_NTRACE */ + +#if (TAO_FTNAMING_INTF_NTRACE == 1) +# define TAO_FTNAMING_INTF_TRACE(X) +#else /* (TAO_FTNAMING_INTF_NTRACE == 1) */ +# if !defined (ACE_HAS_TRACE) +# define ACE_HAS_TRACE +# endif /* ACE_HAS_TRACE */ +# define TAO_FTNAMING_INTF_TRACE(X) ACE_TRACE_IMPL(X) +# include "ace/Trace.h" +#endif /* (TAO_FTNAMING_INTF_NTRACE == 1) */ + +#endif /* TAO_FTNAMING_INTF_EXPORT_H */ + +// End of auto generated file. diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/nsgroup_svc.cpp b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/nsgroup_svc.cpp new file mode 100644 index 00000000000..bc134bd8626 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/nsgroup_svc.cpp @@ -0,0 +1,717 @@ +//============================================================================= +/** + * @file nsgroup_svc.cpp + * + * $Id$ + * + * This file implements nsgroup utility operations + * + * @author Phillip LaBanca <labancap@ociweb.com> + */ +//============================================================================= + +#include "orbsvcs/Naming/FaultTolerant/nsgroup_svc.h" +#include "ace/OS_NS_strings.h" + + +NS_group_svc::NS_group_svc (void) +{ +} + +FT_Naming::LoadBalancingStrategyValue +NS_group_svc::determine_policy_string (const ACE_TCHAR *policy) +{ + if (ACE_OS::strcasecmp (policy, + ACE_TEXT_ALWAYS_CHAR ("rand")) == 0) { + return FT_Naming::RANDOM; + } else if (ACE_OS::strcasecmp (policy, + ACE_TEXT_ALWAYS_CHAR ("least")) == 0) { + return FT_Naming::LEAST; + } else { + return FT_Naming::ROUND_ROBIN; // Default case + } +} + +int +NS_group_svc::set_orb( CORBA::ORB_ptr orb) +{ + + this->orb_ = CORBA::ORB::_duplicate (orb); + + if (CORBA::is_nil (this->orb_)) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT (" (%P|%t) Unable to initialize the ") + ACE_TEXT ("ORB.\n")), + -1); + return 0; +} + +int +NS_group_svc::set_naming_manager( FT_Naming::NamingManager_ptr nm) +{ + + this->naming_manager_ = FT_Naming::NamingManager::_duplicate (nm); + + if (CORBA::is_nil (this->naming_manager_)) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT (" (%P|%t) Invalid Naming Manager.\n")), + -1); + return 0; +} + +int +NS_group_svc::set_name_context( CosNaming::NamingContextExt_ptr nc) +{ + + this->name_service_ = CosNaming::NamingContextExt::_duplicate (nc); + + if (CORBA::is_nil (this->name_service_)) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT (" (%P|%t) Invalid Name Context.\n")), + -1); + return 0; +} + +bool +NS_group_svc::group_exist ( + const ACE_TCHAR* group_name +) +{ + if (group_name == 0 ) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("group_exist args not provided\n")), + false); + } + + try + { + PortableGroup::ObjectGroup_var group_var = + this->naming_manager_->get_object_group_ref_from_name (group_name); + } + catch (const PortableGroup::ObjectGroupNotFound&) + { + return false; + } + + return true; +} + +/** + * The naming service shall provide a command line utility for creating + * object groups. Adds the object group to to the load balancing service + * with the specified selection policy. On Creation, an object group + * contains no member objects. + */ + +int +NS_group_svc::group_create ( + const ACE_TCHAR* group_name, + const ACE_TCHAR* policy ) +{ + + if (group_name == 0 || policy == 0 ) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("group_create args not provided\n")), + -2); + } + + try + { + + /// Verify that the group does not already exist + /// Group names must be unique + if ( true == group_exist (ACE_TEXT_ALWAYS_CHAR (group_name))) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("Group %C already exists\n"), + group_name), + -1); + } + + PortableGroup::Criteria criteria (1); + criteria.length (1); + + PortableGroup::Property &property = criteria[0]; + property.nam.length (1); + + property.nam[0].id = CORBA::string_dup ( + ACE_TEXT_ALWAYS_CHAR ("org.omg.PortableGroup.MembershipStyle")); + + PortableGroup::MembershipStyleValue msv = PortableGroup::MEMB_APP_CTRL; + property.val <<= msv; + + CORBA::Object_var obj = + this->naming_manager_->create_object_group ( + ACE_TEXT_ALWAYS_CHAR (group_name), + determine_policy_string(ACE_TEXT_ALWAYS_CHAR (policy)), + criteria); + + if (CORBA::is_nil (obj.in ())) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to create group %C.\n"), + group_name), + -1); + } + + } + catch (const CORBA::Exception&) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to create group %C\n"), + group_name), + -1); + } + + return 0; +} + +/** + * The naming service shall provide a command line utility for binding an object + * group to a path in the naming service. + * Binds the specified object group to the specified path in the naming service. + * When clients resolve that path, they tranparently obtain a member of the + * specified object group. + */ +int +NS_group_svc::group_bind ( + const ACE_TCHAR* group_name, + const ACE_TCHAR* path) +{ + + if (group_name == 0 || path == 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("group_bind args not provided\n")), + -2); + } + + try + { + + PortableGroup::ObjectGroup_var group_var = + this->naming_manager_->get_object_group_ref_from_name ( + ACE_TEXT_ALWAYS_CHAR(group_name)); + + if (CORBA::is_nil (group_var.in())) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("Unable to get reference.\n")), + -1); + + CORBA::String_var str = CORBA::string_dup( ACE_TEXT_ALWAYS_CHAR (path) ); + CosNaming::Name_var name = this->name_service_->to_name ( str.in() ); + + this->name_service_->rebind (name.in(), group_var.in()); + + } + catch (const CosNaming::NamingContextExt::InvalidName& ex){ + ex._tao_print_exception ("InvalidName Exception in group_bind"); + + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\n%C is invalid\n"), + path), + -1); + } + catch (const CosNaming::NamingContext::CannotProceed&){ + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nCannot proceed with %C\n"), + path), + -1); + } + catch (const CosNaming::NamingContext::NotFound&){ + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to find %C\n"), + path), + -1); + } + catch (const CORBA::SystemException& ex){ + + ex._tao_print_exception ("SystemException Exception in group_bind"); + + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to bind %C\n"), + path), + -1); + } + catch (const CORBA::Exception& ex){ + + ex._tao_print_exception ("Exception in group_bind"); + + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to bind %C\n"), + path), + -1); + } + return 0; +} + +int +NS_group_svc::group_unbind (const ACE_TCHAR* path){ + if ( path == 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("group_unbind args not provided\n")), + -2); + } + + try + { + + CORBA::String_var str = CORBA::string_dup (ACE_TEXT_ALWAYS_CHAR (path)); + CosNaming::Name_var name = this->name_service_->to_name ( str.in() ); + this->name_service_->unbind (name.in()); + + } + catch (const CosNaming::NamingContext::NotFound&){ + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to find %C\n"), + path), + -1); + } + catch (const CosNaming::NamingContext::CannotProceed&){ + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nCannot proceed with %C\n"), + path), + -1); + } + catch (const CosNaming::NamingContext::InvalidName&) { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\n%C is invalid\n"), + path), + -1); + } + catch (const CORBA::SystemException& ex) { + + ex._tao_print_exception ("Exception in group_unbind"); + + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to unbind %C\n"), + path), + -1); + } + catch (const CORBA::Exception& ex) { + + ex._tao_print_exception ("Exception in group_unbind"); + + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to unbind %C\n"), + path), + -1); + } + return 0; +} + +/** + * The naming service shall provide a command line utility to display all + * defined object groups within the naming service. + * Displays all object groups that currently exist in the naming service. + */ +int +NS_group_svc::group_list (void) +{ + + // KCS: The group list is independent of locations. I created a new operation in the + // naming manager IDL to support requesting the group list - which is a list of names + + /// Display object group list for each load balancing strategy + int rc = 0; + if( display_load_policy_group (FT_Naming::ROUND_ROBIN, + ACE_TEXT ("Round Robin")) < 0 ) + { + rc = -1; + } + if( display_load_policy_group (FT_Naming::RANDOM, + ACE_TEXT ("Random")) < 0 ) + { + rc = -1; + } + if( display_load_policy_group (FT_Naming::LEAST, + ACE_TEXT ("Least")) < 0 ) + { + rc = -1; + } + return rc; +} + +int +NS_group_svc::display_load_policy_group( + FT_Naming::LoadBalancingStrategyValue strategy, + const ACE_TCHAR *display_label) { + + if( display_label == 0 ) { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("display_load_policy_group args ") + ACE_TEXT ("not provided\n")), + -2); + } + + try + { + + FT_Naming::GroupNames_var list = this->naming_manager_->groups (strategy); + + std::cout << ACE_TEXT ("\n") + << display_label + << ACE_TEXT (" Load Balancing Groups:") + << std::endl; + + if ( list->length () > 0 ) { + + for (unsigned int i = 0; i < list->length (); ++i) + { + std::cout << ACE_TEXT (" ") + << (*list)[i] + << std::endl; + } + + } else { + + std::cout << ACE_TEXT ("No ") + << display_label + << ACE_TEXT (" Load Balancing Groups Registered") + << std::endl; + + } + + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ("Exception in group_list"); + + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("Unable to get %C group list\n"), + display_label), + -1); + } + return 0; +} + +/** + * The naming service shall provide a command line utility to modify the load + * balancing strategy for a specified object group. + * Changes the selection algorithm for the specified object group. An object + * group's selection algorithm determines how the naming service directs client + * requests to object group members. + */ +int +NS_group_svc::group_modify ( + const ACE_TCHAR* group_name, + const ACE_TCHAR* policy) +{ + if (group_name == 0 || policy == 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("group_modify args not provided\n")), + -2); + } + + try + { + this->naming_manager_->set_load_balancing_strategy ( + ACE_TEXT_ALWAYS_CHAR (group_name), + determine_policy_string(policy) ); + } + catch (const PortableGroup::ObjectGroupNotFound&) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to find group %C\n"), + group_name), + -1); + } + catch (const CORBA::Exception&) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to modify group %C\n"), + group_name), + -1); + } + + return 0; +} + +/** + * The naming service shall provide a command line utility to remove a specified + * object group from the naming service. + * Removes the specified object group from the naming service. + */ +int +NS_group_svc::group_remove (const ACE_TCHAR* group_name) +{ + if (group_name == 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("group_remove args not provided\n")), + -2); + } + + try + { + this->naming_manager_->delete_object_group ( + ACE_TEXT_ALWAYS_CHAR (group_name)); + } + catch (const PortableGroup::ObjectGroupNotFound&) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to find group %C\n"), + group_name), + -1); + } + catch (const CORBA::Exception&) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to remove group %C\n"), + group_name), + -1); + } + + return 0; +} + +/** + * The naming service shall provide a command line utility for adding object + * references to an object group. + * Adds an object to the specified object group. After being added, the object + * is available for selection. + */ +int +NS_group_svc::member_add ( + const ACE_TCHAR* group_name, + const ACE_TCHAR* location, + const ACE_TCHAR* ior) +{ + if (group_name == 0 || location == 0 || ior == 0 ) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("member_add args not provided\n")), + -2); + } + + try + { + PortableGroup::Location location_name; + location_name.length (1); + location_name[0].id = CORBA::string_dup (ACE_TEXT_ALWAYS_CHAR (location)); + + PortableGroup::ObjectGroup_var group_var = + this->naming_manager_->get_object_group_ref_from_name ( + ACE_TEXT_ALWAYS_CHAR (group_name)); + + CORBA::Object_var ior_var = + this->orb_->string_to_object(ACE_TEXT_ALWAYS_CHAR (ior)); + + if (CORBA::is_nil (ior_var.in ())) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nInvalid member IOR provided.\n")), + -1); + } + + this->naming_manager_->add_member ( + group_var.in(), + location_name, + ior_var.in()); + + } + catch (const PortableGroup::ObjectGroupNotFound&) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to find group %C\n"), + group_name), + -1); + } + catch (const PortableGroup::ObjectNotAdded&) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to add location %C to group %C\n"), + location, group_name), + -1); + } + catch (const CORBA::Exception&) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to add location %C to group %C\n"), + location, group_name), + -1); + } + + return 0; +} + +/** + * The naming service shall provide a command line utility for displaying all + * members (object references) for a specified object group. + * Lists the members of the specified object group. + */ +int +NS_group_svc::member_list (const ACE_TCHAR* group_name) +{ + if (group_name == 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("member_list args not provided\n")), + -2); + } + + try + { + PortableGroup::ObjectGroup_var group_var = + this->naming_manager_->get_object_group_ref_from_name ( + ACE_TEXT_ALWAYS_CHAR (group_name)); + + PortableGroup::Locations_var locations = + this->naming_manager_->locations_of_members (group_var.in()); + + for (unsigned int i = 0; i < locations->length(); ++i) + { + const PortableGroup::Location & loc = locations[i]; + if (loc.length() > 0) { + std::cout << loc[0].id.in() << std::endl; + } + } + + } + catch (const PortableGroup::ObjectGroupNotFound&) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to find group %C\n"), + group_name), + -1); + } + catch (const CORBA::Exception&) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to list members for group %C\n"), + group_name), + -1); + } + + return 0; +} + +/** + * The naming service shall provide a command line utility for removing object + * references from an object group. + * Removes the specified member object from the specified object group. + */ +int +NS_group_svc::member_remove ( + const ACE_TCHAR* group_name, + const ACE_TCHAR* location) +{ + if (group_name == 0 || location == 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("member_remove args not provided\n")), + -2); + } + + /** + * Remove an object at a specific location from the given + * ObjectGroup. Deletion of application created objects must be + * deleted by the application. Objects created by the + * infrastructure (load balancer) will be deleted by the + * infrastructure. + */ + + try + { + PortableGroup::Location location_name; + location_name.length (1); + location_name[0].id = CORBA::string_dup (ACE_TEXT_ALWAYS_CHAR (location)); + + PortableGroup::ObjectGroup_var group_var = + this->naming_manager_->get_object_group_ref_from_name ( + ACE_TEXT_ALWAYS_CHAR (group_name)); + + this->naming_manager_->remove_member ( + group_var.in(), + location_name); + } + catch (const PortableGroup::ObjectGroupNotFound&) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to find group %C\n"), + group_name), + -1); + } + catch (const PortableGroup::MemberNotFound&) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to find member %C\n"), + location), + -1); + } + catch (const CORBA::Exception&) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to remove member %C\n"), + location), + -1); + } + + return 0; +} + +/** + * The naming service shall provide a command line utility to display an object + * reference from a specified object group. + * Displays the object reference that cooresponds to the specified member of an + * object group. + */ +int +NS_group_svc::member_show ( + const ACE_TCHAR* group_name, + const ACE_TCHAR* location) +{ + if (group_name == 0 || location == 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("member_show args not provided\n")), + -2); + } + + //Get and display IOR for the member location + try + { + PortableGroup::Location location_name (1); + location_name.length (1); + location_name[0].id = CORBA::string_dup (ACE_TEXT_ALWAYS_CHAR (location)); + + PortableGroup::ObjectGroup_var group_var = + this->naming_manager_->get_object_group_ref_from_name ( + ACE_TEXT_ALWAYS_CHAR (group_name)); + + CORBA::Object_var ior_var = + this->naming_manager_->get_member_ref (group_var.in(), location_name); + + CORBA::String_var ior_string = + this->orb_->object_to_string (ior_var.in()); + + std::cout << ior_string.in() << std::endl; + } + catch (const PortableGroup::ObjectGroupNotFound&) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to find group %C\n"), + group_name), + -1); + } + catch (const PortableGroup::MemberNotFound&) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to find member location %C\n"), + location), + -1); + } + catch (const CORBA::Exception&) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("\nUnable to show member location %C\n"), + location), + -1); + } + + return 0; +} diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/nsgroup_svc.h b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/nsgroup_svc.h new file mode 100644 index 00000000000..6f819780764 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/nsgroup_svc.h @@ -0,0 +1,184 @@ +//========================================================================== +/** + * @file nsgroup_svc.h + * + * $Id$ + * + * @author Phillip LaBanca <labancap@ociweb.com> + */ +//========================================================================== + +#ifndef i_nsgroup_svc_h +#define i_nsgroup_svc_h + +#include "orbsvcs/FT_NamingManagerC.h" +#include /**/ "orbsvcs/Naming/FaultTolerant/ftnaming_intf_export.h" + +/** + * @class NS_group_svc + * + * @brief Encapsulate the NS group operations in a class. + * + * + */ +class TAO_FtNaming_Intf_Export NS_group_svc +{ +public: + + /** + * Constructor + */ + NS_group_svc (void); + + /** + * The naming service shall provide a command line utility for creating + * object groups. + * + * @param group group name + * @param policy round | rand | least + * + * @return 0 on success, -1 on failure, -2 on bad argument. + */ + int group_create (const ACE_TCHAR* group, const ACE_TCHAR* policy); + + /** + * The naming service shall provide a command line utility for binding an + * object group to a path in the naming service. + * + * @param group group name + * @param path stringified name in the naming service + * + * @return 0 on success, -1 on failure, -2 on bad argument. + */ + int group_bind (const ACE_TCHAR* group, const ACE_TCHAR* path); + + /** + * @param group group name + * @param path stringified name in the naming service + * + * @return 0 on success, -1 on failure, -2 on bad argument. + */ + int group_unbind (const ACE_TCHAR* path); + + /** + * The naming service shall provide a command line utility to display all + * defined object groups within the naming service. + * + * @return 0 on success, -1 on failure, -2 on bad argument. + */ + int group_list (void); + + /** + * The naming service shall provide a command line utility to modify the load + * balancing strategy for a specified object group. + * + * @param group group name + * @param policy round | rand | least + * + * @return 0 on success, -1 on failure, -2 on bad argument. + */ + int group_modify (const ACE_TCHAR* group, const ACE_TCHAR* policy); + + /** + * The naming service shall provide a command line utility to remove a + * specified object group from the naming service. + * + * @param group group name + * + * @return 0 on success, -1 on failure, -2 on bad argument. + */ + int group_remove (const ACE_TCHAR* group); + + /** + * The naming service shall provide a command line utility for adding object + * references to an object group. + * + * @param group group name + * @param location member location string + * @param ior member stringified ior + * + * @return 0 on success, -1 on failure, -2 on bad argument. + */ + int member_add (const ACE_TCHAR* group, + const ACE_TCHAR* location, + const ACE_TCHAR* ior); + + /** + * The naming service shall provide a command line utility for displaying all + * members (object references) for a specified object group. + * + * @param group group name + * + * @return 0 on success, -1 on failure, -2 on bad argument. + */ + int member_list (const ACE_TCHAR* group); + + /** + * The naming service shall provide a command line utility for removing + * object references from an object group. + * + * @param group group name + * @param location member location string + * + * @return 0 on success, -1 on failure, -2 on bad argument. + */ + int member_remove (const ACE_TCHAR* group, const ACE_TCHAR* location); + + /** + * The naming service shall provide a command line utility to display an + * object reference from a specified object group. + * + * @param group group name + * @param location member location string + * + * @return zero for success; nonzero for failure. + */ + int member_show (const ACE_TCHAR* group, const ACE_TCHAR* location); + + /** + * @param group group name + * + * @return true if the specified object group name is found + */ + bool group_exist (const ACE_TCHAR* group_name); + + /** + * @return 0 on success, -1 on failure. + */ + int set_orb( CORBA::ORB_ptr value); + + /** + * @return 0 on success, -1 on failure. + */ + int set_naming_manager( FT_Naming::NamingManager_ptr value); + + /** + * @return 0 on success, -1 on failure. + */ + int set_name_context( CosNaming::NamingContextExt_ptr value); + +private: + + /** + * determine stategy based on policy string value default to ROUND_ROBIN + * + * @param policy round | rand | least + */ + FT_Naming::LoadBalancingStrategyValue determine_policy_string (const ACE_TCHAR *policy); + + /** + * @return 0 on success, -1 on failure. + */ + int display_load_policy_group( FT_Naming::LoadBalancingStrategyValue strategy, const ACE_TCHAR *display_label); + +private: + + FT_Naming::NamingManager_var naming_manager_; + + CosNaming::NamingContextExt_var name_service_; + + CORBA::ORB_var orb_; + +}; + +#endif |