summaryrefslogtreecommitdiff
path: root/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/orbsvcs/orbsvcs/Naming/FaultTolerant')
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Location_Index_Map.h42
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Manager.cpp747
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Manager.h351
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Replication_Manager.cpp179
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Replication_Manager.h110
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Server.cpp1196
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Server.h189
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_PG_Group_Factory.cpp132
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_PG_Group_Factory.h82
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_PG_Object_Group_Storable.cpp182
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_PG_Object_Group_Storable.h132
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context.cpp111
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context.h75
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context_Factory.cpp40
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Persistent_Naming_Context_Factory.h56
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Round_Robin.cpp76
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Round_Robin.h95
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context.cpp183
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context.h112
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context_Factory.cpp47
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Storable_Naming_Context_Factory.h66
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/ftnaming_export.h58
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/ftnaming_intf_export.h58
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/nsgroup_svc.cpp717
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/nsgroup_svc.h184
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