diff options
author | stanleyk <stanleyk@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2013-02-05 21:11:03 +0000 |
---|---|---|
committer | stanleyk <stanleyk@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2013-02-05 21:11:03 +0000 |
commit | 5e030faf84086ab02059fcbcc3faed224bd57b95 (patch) | |
tree | 3a62df45ac6ccf599fb07cf6a03d672456ce2e3d /TAO/orbsvcs/orbsvcs | |
parent | 9d296f7fa51116ff7040ecb2ad18612cd94b5fd1 (diff) | |
download | ATCD-5e030faf84086ab02059fcbcc3faed224bd57b95.tar.gz |
Merge in OCI_Reliability_Enhancements branch.
Diffstat (limited to 'TAO/orbsvcs/orbsvcs')
77 files changed, 8441 insertions, 1300 deletions
diff --git a/TAO/orbsvcs/orbsvcs/CosEvent.mpc b/TAO/orbsvcs/orbsvcs/CosEvent.mpc index 80efa635a0a..97b0de957d9 100644 --- a/TAO/orbsvcs/orbsvcs/CosEvent.mpc +++ b/TAO/orbsvcs/orbsvcs/CosEvent.mpc @@ -84,7 +84,7 @@ project (CosEvent_Skel) : orbsvcslib, orbsvcs_output, install, avoids_minimum_co } -project (CosEvent_Serv) : orbsvcslib, orbsvcs_output, install, avoids_minimum_corba, event_skel, ec_typed_events_serv, messaging_optional, naming, svc_utils { +project (CosEvent_Serv) : orbsvcslib, orbsvcs_output, install, avoids_minimum_corba, event_skel, ec_typed_events_serv, messaging_optional, ifr_client, naming, svc_utils { sharedname = TAO_CosEvent_Serv dynamicflags += TAO_EVENT_SERV_BUILD_DLL tagchecks += CosEvent diff --git a/TAO/orbsvcs/orbsvcs/CosNaming_Serv.mpc b/TAO/orbsvcs/orbsvcs/CosNaming_Serv.mpc index 9e683abb6d9..9cd821e7bf3 100644 --- a/TAO/orbsvcs/orbsvcs/CosNaming_Serv.mpc +++ b/TAO/orbsvcs/orbsvcs/CosNaming_Serv.mpc @@ -17,6 +17,7 @@ project(CosNaming_Serv) : cosnaming_serv_persistence, orbsvcslib, orbsvcs_output Naming/Naming_Context_Interface.cpp Naming/Naming_Loader.cpp Naming/Naming_Server.cpp + Naming/Storable_Naming_Context_Factory.cpp Naming/Transient_Naming_Context.cpp } } diff --git a/TAO/orbsvcs/orbsvcs/FT_NamingManager.idl b/TAO/orbsvcs/orbsvcs/FT_NamingManager.idl new file mode 100644 index 00000000000..ae13105d9aa --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/FT_NamingManager.idl @@ -0,0 +1,63 @@ +/* -*- IDL -*- */ +//============================================================================= +/** + * @file FT_NamingManager.idl + * + * $Id$ + * + * This file is part of Fault Tolerant Naming Service. + * + * @author Kevin Stanley <stanleyk@ociweb.com> + */ +//============================================================================= + +#ifndef _FT_NAMING_MANAGER_IDL_ +#define _FT_NAMING_MANAGER_IDL_ + +#include "orbsvcs/PortableGroup.idl" + +module FT_Naming +{ + typedef PortableGroup::ObjectGroup ObjectGroup; + + const string TAO_FT_OBJECT_GROUP_NAME = "TAO_FT_GroupName"; + const string TAO_FT_LOAD_BALANCING_STRATEGY = "TAO_FT_LB_Strategy"; + + typedef long LoadBalancingStrategyValue; + const LoadBalancingStrategyValue ROUND_ROBIN = 0; + const LoadBalancingStrategyValue RANDOM = 1; + const LoadBalancingStrategyValue LEAST = 2; + + typedef string GroupName; + typedef sequence<string> GroupNames; + + // Specification of NamingManager Interface + interface NamingManager : PortableGroup::PropertyManager, + PortableGroup::ObjectGroupManager + { + ObjectGroup create_object_group (in GroupName group_name, + in LoadBalancingStrategyValue lb_strategy, + in PortableGroup::Criteria the_criteria) + raises (PortableGroup::ObjectNotCreated, + PortableGroup::InvalidCriteria, + PortableGroup::InvalidProperty, + PortableGroup::CannotMeetCriteria); + + void delete_object_group (in string group_name) + raises (PortableGroup::ObjectGroupNotFound); + + ObjectGroup get_object_group_ref_from_name ( + in string group_name) + raises (PortableGroup::ObjectGroupNotFound); + + void set_load_balancing_strategy (in string group_name, + in LoadBalancingStrategyValue lb_strategy); + + // Return names of all groups defined in the NamingManager + GroupNames groups (in LoadBalancingStrategyValue target_stategy); + + }; +}; + + +#endif // _FT_NAMING_MANAGER_IDL_ diff --git a/TAO/orbsvcs/orbsvcs/FT_NamingReplication.idl b/TAO/orbsvcs/orbsvcs/FT_NamingReplication.idl new file mode 100644 index 00000000000..df1c1178422 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/FT_NamingReplication.idl @@ -0,0 +1,79 @@ +/* -*- IDL -*- */ +//============================================================================= +/** + * @file FT_NamingReplication.idl + * + * $Id$ + * + * This file is part of Fault Tolerant Naming Service in support of + * replication between redundant servers. + * + * @author Kevin Stanley <stanleyk@ociweb.com> + */ +//============================================================================= + +#ifndef _FT_NAMING_REPLICATION_IDL_ +#define _FT_NAMING_REPLICATION_IDL_ + +#include <orbsvcs/CosNaming.idl> +#include <orbsvcs/FT_NamingManager.idl> +#include <orbsvcs/FT_CORBA_ORB.idl> + +module FT_Naming +{ + + enum ChangeType { NEW, UPDATED, DELETED }; + + exception NotAvailable + { + }; + + /* + * A structure that describes the updated element in a Naming Service + */ + struct NamingContextUpdate + { + /// The name of context being updated + string context_name; + /// The type of change that is being reported + ChangeType change_type; + }; + + struct ReplicaInfo + { + CosNaming::NamingContext root_context; + FT_Naming::NamingManager naming_manager; + }; + + /* + * A structure that describes the updated element within + * an Object Group Manager + */ + struct ObjectGroupUpdate + { + /// This is used to identify object group references. + PortableGroup::ObjectGroupId id; + /// The type of change that is being reported + ChangeType change_type; + }; + + interface ReplicationManager + { + /* + * Register with a peer replica providing an object reference for + * notification of updates. Each replica will maintain their state + * in a shared repository and the update notification indicates the + * element that was changed. + */ + ReplicaInfo register_replica (in ReplicationManager replica, + in ReplicaInfo replica_info) + raises (NotAvailable); + + oneway void notify_updated_object_group(in ObjectGroupUpdate group_info); + + oneway void notify_updated_context(in NamingContextUpdate context_info); + }; +}; + + +#endif // _FT_NAMING_REPLICATION_IDL_ diff --git a/TAO/orbsvcs/orbsvcs/FT_Naming_Serv.mpc b/TAO/orbsvcs/orbsvcs/FT_Naming_Serv.mpc new file mode 100644 index 00000000000..6f963a8f725 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/FT_Naming_Serv.mpc @@ -0,0 +1,42 @@ +// -*- MPC -*- +// $Id$ + +project (FT_Naming_Serv) : orbsvcslib, orbsvcs_output, ftnaming, ftnaming_replication, install, naming_serv, naming, portablegroup, avoids_minimum_corba { + sharedname = TAO_FT_Naming_Serv + idlflags += -Wb,export_macro=TAO_FtNaming_Export -Wb,export_include=orbsvcs/Naming/FaultTolerant/ftnaming_export.h + dynamicflags += TAO_FTNAMING_BUILD_DLL + tagchecks += FaultTolerantNaming + + IDL_Files { + } + + Source_Files (ORBSVCS_COMPONENTS) { + Naming/FaultTolerant/FT_Naming_Manager.cpp + Naming/FaultTolerant/FT_Naming_Replication_Manager.cpp + Naming/FaultTolerant/FT_Naming_Server.cpp + Naming/FaultTolerant/FT_Persistent_Naming_Context.cpp + Naming/FaultTolerant/FT_Persistent_Naming_Context_Factory.cpp + Naming/FaultTolerant/FT_Round_Robin.cpp + Naming/FaultTolerant/FT_Storable_Naming_Context.cpp + Naming/FaultTolerant/FT_Storable_Naming_Context_Factory.cpp + Naming/FaultTolerant/FT_PG_Object_Group_Storable.cpp + Naming/FaultTolerant/FT_PG_Group_Factory.cpp + } + + Header_Files { + Naming/FaultTolerant/FT_Naming_Manager.h + Naming/FaultTolerant/FT_Naming_Replication_Manager.h + Naming/FaultTolerant/FT_Naming_Server.h + Naming/FaultTolerant/FT_Persistent_Naming_Context.h + Naming/FaultTolerant/FT_Persistent_Naming_Context_Factory.h + Naming/FaultTolerant/FT_Round_Robin.h + Naming/FaultTolerant/FT_Storable_Naming_Context.h + Naming/FaultTolerant/FT_Storable_Naming_Context_Factory.h + Naming/FaultTolerant/FT_PG_Object_Group_Storable.h + Naming/FaultTolerant/FT_PG_Group_Factory.h + Naming/FaultTolerant/ftnaming_export.h + Naming/FaultTolerant/ftnaming_intf_export.h + } + +} + diff --git a/TAO/orbsvcs/orbsvcs/FtNaming.mpc b/TAO/orbsvcs/orbsvcs/FtNaming.mpc new file mode 100644 index 00000000000..c36764fa984 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/FtNaming.mpc @@ -0,0 +1,28 @@ +// -*- MPC -*- +// $Id$ + +project (FtNaming) : orbsvcslib, orbsvcs_output, install, naming_serv, portablegroup, avoids_minimum_corba { + sharedname = TAO_FtNaming + idlflags += -Wb,export_macro=TAO_FtNaming_Intf_Export \ + -Wb,export_include=orbsvcs/Naming/FaultTolerant/ftnaming_intf_export.h + dynamicflags += TAO_FTNAMING_INTF_BUILD_DLL + tagchecks += FtNaming + + IDL_Files { + idlflags += -GC + FT_NamingManager.idl + } + + Source_Files (ORBSVCS_COMPONENTS) { + FT_NamingManagerC.cpp + FT_NamingManagerS.cpp + Naming/FaultTolerant/nsgroup_svc.cpp + } + + Header_Files { + FT_NamingManagerC.h + FT_NamingManagerS.h + Naming/FaultTolerant/nsgroup_svc.h + } +} + diff --git a/TAO/orbsvcs/orbsvcs/FtNamingReplication.mpc b/TAO/orbsvcs/orbsvcs/FtNamingReplication.mpc new file mode 100644 index 00000000000..cb329f671ca --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/FtNamingReplication.mpc @@ -0,0 +1,25 @@ +// -*- MPC -*- +// $Id$ + +project (FtNamingReplication) : ftnaming, orbsvcslib, orbsvcs_output, install, naming_serv, portablegroup, avoids_minimum_corba { + sharedname = TAO_FtNamingReplication + idlflags += -Wb,export_macro=TAO_FtNaming_Export -Wb,export_include=orbsvcs/Naming/FaultTolerant/ftnaming_export.h + dynamicflags += TAO_FTNAMING_BUILD_DLL + + IDL_Files { + idlflags += -GC + FT_NamingReplication.idl + } + + Source_Files (ORBSVCS_COMPONENTS) { + FT_NamingReplicationC.cpp + FT_NamingReplicationS.cpp + } + + Header_Files { + FT_NamingReplicationC.h + FT_NamingReplicationS.h + } + +} + diff --git a/TAO/orbsvcs/orbsvcs/FtRtEvent/Utils/FTEC_Gateway.cpp b/TAO/orbsvcs/orbsvcs/FtRtEvent/Utils/FTEC_Gateway.cpp index f6592820c0f..18e2bb69a54 100644 --- a/TAO/orbsvcs/orbsvcs/FtRtEvent/Utils/FTEC_Gateway.cpp +++ b/TAO/orbsvcs/orbsvcs/FtRtEvent/Utils/FTEC_Gateway.cpp @@ -242,7 +242,7 @@ void FTEC_Gateway::remove_observer (RtecEventChannelAdmin::Observer_Handle handl void FTEC_Gateway::push(RtecEventChannelAdmin::ProxyPushConsumer_ptr proxy_consumer, const RtecEventComm::EventSet & data) { - PortableServer::ObjectId_var object_id = + const PortableServer::ObjectId_var object_id = impl_->poa->reference_to_id(proxy_consumer); FtRtecEventComm::ObjectId** result; ACE_OS::memcpy(&result, &object_id[0], sizeof(FtRtecEventComm::ObjectId**)); @@ -315,9 +315,9 @@ get_remote_oid_ptr(CORBA::ORB_ptr orb) { PortableServer::Current_var current = resolve_init<PortableServer::Current>(orb, - "POACurrent"); + "POACurrent"); - PortableServer::ObjectId_var object_id = + const PortableServer::ObjectId_var object_id = current->get_object_id(); FtRtecEventComm::ObjectId** result; diff --git a/TAO/orbsvcs/orbsvcs/HTIOP/HTIOP_Profile.cpp b/TAO/orbsvcs/orbsvcs/HTIOP/HTIOP_Profile.cpp index b69a58ea11e..cb65c9c3a69 100644 --- a/TAO/orbsvcs/orbsvcs/HTIOP/HTIOP_Profile.cpp +++ b/TAO/orbsvcs/orbsvcs/HTIOP/HTIOP_Profile.cpp @@ -279,7 +279,7 @@ TAO::HTIOP::Profile::add_endpoint (TAO::HTIOP::Endpoint *endp) } char * -TAO::HTIOP::Profile::to_string (void) +TAO::HTIOP::Profile::to_string (void) const { CORBA::String_var key; TAO::ObjectKey::encode_sequence_to_string (key.inout(), diff --git a/TAO/orbsvcs/orbsvcs/HTIOP/HTIOP_Profile.h b/TAO/orbsvcs/orbsvcs/HTIOP/HTIOP_Profile.h index ef0dc3fa9dc..f292660153d 100644 --- a/TAO/orbsvcs/orbsvcs/HTIOP/HTIOP_Profile.h +++ b/TAO/orbsvcs/orbsvcs/HTIOP/HTIOP_Profile.h @@ -88,7 +88,7 @@ namespace TAO * This is used to create url-style reference. Only one * endpoint is included into the string. */ - virtual char * to_string (void); + virtual char * to_string (void) const; /** * Endpoints are transmitted using TAO-proprietory tagged component. diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.cpp index b14c5612c23..0ba928de2fe 100644 --- a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.cpp +++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LeastLoaded.cpp @@ -155,7 +155,7 @@ TAO_LB_LeastLoaded::get_loads (CosLoadBalancing::LoadManager_ptr load_manager, this->push_loads (the_location, loads.in (), - loads[0]); + loads.inout ()[0]); return loads._retn (); } diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.cpp index 56b5157d4a7..463f4c3da83 100644 --- a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.cpp +++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadAverage.cpp @@ -153,7 +153,7 @@ TAO_LB_LoadAverage::get_loads (CosLoadBalancing::LoadManager_ptr load_manager, this->push_loads (the_location, loads.in (), - loads[0]); + loads.inout ()[0]); return loads._retn (); } diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.cpp index 90dd6c015e4..6f2e8a65abf 100644 --- a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.cpp +++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_LoadMinimum.cpp @@ -154,7 +154,7 @@ TAO_LB_LoadMinimum::get_loads (CosLoadBalancing::LoadManager_ptr load_manager, this->push_loads (the_location, loads.in (), - loads[0]); + loads.inout ()[0]); return loads._retn (); } 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 diff --git a/TAO/orbsvcs/orbsvcs/Naming/Flat_File_Persistence.cpp b/TAO/orbsvcs/orbsvcs/Naming/Flat_File_Persistence.cpp deleted file mode 100644 index 072951cd015..00000000000 --- a/TAO/orbsvcs/orbsvcs/Naming/Flat_File_Persistence.cpp +++ /dev/null @@ -1,386 +0,0 @@ -// $Id$ - -//----------------------------------------------------------------------------- -// Flat File class implementations -//----------------------------------------------------------------------------- -#include "orbsvcs/Naming/Flat_File_Persistence.h" - -#include "ace/Log_Msg.h" -#include "ace/Numeric_Limits.h" -#include "ace/Auto_Ptr.h" -#include "ace/OS_NS_sys_stat.h" -#include "ace/OS_NS_unistd.h" -#include "ace/OS_NS_fcntl.h" - -TAO_BEGIN_VERSIONED_NAMESPACE_DECL - -TAO_NS_FlatFileStream::TAO_NS_FlatFileStream (const ACE_CString & file, - const char * mode) - : fl_ (0) -{ - ACE_TRACE("TAO_NS_FlatFileStream"); - file_ = file; - mode_ = mode; -} - -TAO_NS_FlatFileStream::~TAO_NS_FlatFileStream () -{ - ACE_TRACE("~TAO_NS_FlatFileStream"); - if ( fl_ != 0 ) - this->close(); -} - -void -TAO_NS_FlatFileStream::remove () -{ - ACE_TRACE("remove"); - ACE_OS::unlink(ACE_TEXT_CHAR_TO_TCHAR(file_.c_str())); -} - -int -TAO_NS_FlatFileStream::exists () -{ - ACE_TRACE("exists"); - // We could check the mode for this file, but for now just check exists - return ! ACE_OS::access(file_.c_str(), F_OK); -} - -int -TAO_NS_FlatFileStream::open() -{ - ACE_TRACE("open"); - // For now, three flags exist "r", "w", and "c" - int flags = 0; - const char *fdmode = 0; - if( ACE_OS::strchr(mode_.c_str(), 'r') ) - if( ACE_OS::strchr(mode_.c_str(), 'w') ) - flags = O_RDWR, fdmode = "r+"; - else - flags = O_RDONLY, fdmode = "r"; - else - flags = O_WRONLY, fdmode = "w"; - if( ACE_OS::strchr(mode_.c_str(), 'c') ) - flags |= O_CREAT; -#ifndef ACE_WIN32 - if( ACE_OS::flock_init (&filelock_, flags, ACE_TEXT_CHAR_TO_TCHAR(file_.c_str()), 0666) != 0 ) - ACE_ERROR_RETURN ((LM_ERROR, - "Cannot open file %s for mode %s: (%d) %s\n", - file_.c_str(), mode_.c_str(), - errno, ACE_OS::strerror(errno)), - -1); -#else - if( (filelock_.handle_= ACE_OS::open (ACE_TEXT_CHAR_TO_TCHAR(file_.c_str()), flags, 0)) == ACE_INVALID_HANDLE ) - ACE_ERROR_RETURN ((LM_ERROR, - "Cannot open file %s for mode %s: (%d) %s\n", - file_.c_str(), mode_.c_str(), - ACE_ERRNO_GET, ACE_OS::strerror(ACE_ERRNO_GET)), - -1); -#endif - this->fl_ = ACE_OS::fdopen(filelock_.handle_, ACE_TEXT_CHAR_TO_TCHAR(fdmode)); - if (this->fl_ == 0) - ACE_ERROR_RETURN ((LM_ERROR, - "Cannot fdopen file %s for mode %s: (%d) %s\n", - file_.c_str(), mode_.c_str(), - ACE_ERRNO_GET, ACE_OS::strerror(ACE_ERRNO_GET)), - -1); - return 0; -} - -int -TAO_NS_FlatFileStream::close() -{ - ACE_TRACE("close"); - ACE_OS::fflush(fl_); -#ifndef ACE_WIN32 - ACE_OS::flock_destroy (&filelock_, 0); -#endif - ACE_OS::fclose (fl_); // even though flock_destroy closes the handle - // we still need to destroy the FILE* - - fl_ = 0; - return 0; -} - -int -TAO_NS_FlatFileStream::flock (int whence, int start, int len) -{ - ACE_TRACE("flock"); -#if defined (ACE_WIN32) - ACE_UNUSED_ARG (whence); - ACE_UNUSED_ARG (start); - ACE_UNUSED_ARG (len); -#else - if( ACE_OS::strcmp(mode_.c_str(), "r") == 0 ) - ACE_OS::flock_rdlock(&filelock_, whence, start, len); - else - ACE_OS::flock_wrlock(&filelock_, whence, start, len); -#endif - return 0; -} - -int -TAO_NS_FlatFileStream::funlock (int whence, int start, int len) -{ - ACE_TRACE("funlock"); -#if defined (ACE_WIN32) - ACE_UNUSED_ARG (whence); - ACE_UNUSED_ARG (start); - ACE_UNUSED_ARG (len); -#else - ACE_OS::flock_unlock(&filelock_, whence, start, len); -#endif - return 0; -} - -time_t -TAO_NS_FlatFileStream::last_changed(void) -{ - ACE_TRACE("TAO_NS_FlatFileStream::last_changed"); - ACE_stat st; - ACE_OS::fstat(filelock_.handle_, &st); - return st.st_mtime; -} - -TAO_Storable_Base & -TAO_NS_FlatFileStream::operator <<( - const TAO_NS_Persistence_Header &header) -{ - ACE_TRACE("TAO_NS_FlatFileStream::operator <<"); - ACE_OS::rewind(this->fl_); - ACE_OS::fprintf(this->fl_, "%d\n%d\n", header.size(), header.destroyed()); - ACE_OS::fflush(this->fl_); - - return *this; -} - -TAO_Storable_Base & -TAO_NS_FlatFileStream::operator >>( - TAO_NS_Persistence_Header &header) -{ - ACE_TRACE("TAO_NS_FlatFileStream::operator >>"); - unsigned int size; - int destroyed; - - ACE_OS::rewind(this->fl_); - switch (fscanf(fl_, "%u\n", &size)) - { - case 0: - this->setstate (badbit); - return *this; - case EOF: - this->setstate (eofbit); - return *this; - } - header.size(size); - - switch (fscanf(fl_, "%d\n", &destroyed)) - { - case 0: - this->setstate (badbit); - return *this; - case EOF: - this->setstate (eofbit); - return *this; - } - header.destroyed(destroyed); - - return *this; - -} - -TAO_Storable_Base & -TAO_NS_FlatFileStream::operator <<( - const TAO_NS_Persistence_Record &record) -{ - ACE_TRACE("TAO_NS_FlatFileStream::operator <<"); - TAO_NS_Persistence_Record::Record_Type type = record.type(); - ACE_OS::fprintf(this->fl_, "%d\n", type); - - ACE_CString id = record.id(); - ACE_OS::fprintf(this->fl_, ACE_SIZE_T_FORMAT_SPECIFIER ACE_TEXT("\n%s\n"), - id.length(), id.c_str()); - - ACE_CString kind = record.kind(); - ACE_OS::fprintf(this->fl_, ACE_SIZE_T_FORMAT_SPECIFIER ACE_TEXT ("\n%s\n"), - kind.length(), kind.c_str()); - - ACE_CString ref = record.ref(); - ACE_OS::fprintf(this->fl_, ACE_SIZE_T_FORMAT_SPECIFIER ACE_TEXT ("\n%s\n"), - ref.length(), ref.c_str()); - - ACE_OS::fflush(this->fl_); - - return *this; -} - -TAO_Storable_Base & -TAO_NS_FlatFileStream::operator >>(TAO_NS_Persistence_Record &record) -{ - ACE_TRACE("TAO_NS_FlatFileStream::operator >>"); - - int temp_type_in; - switch (fscanf(fl_, "%d\n", &temp_type_in)) - { - case 0: - this->setstate (badbit); - return *this; - case EOF: - this->setstate (eofbit); - return *this; - } - TAO_NS_Persistence_Record::Record_Type type = - (TAO_NS_Persistence_Record::Record_Type) temp_type_in; - record.type (type); - - int bufSize = 0; - ACE_CString::size_type const max_buf_len = - ACE_Numeric_Limits<ACE_CString::size_type>::max (); - - //id - switch (fscanf(fl_, "%d\n", &bufSize)) - { - case 0: - this->setstate (badbit); - return *this; - case EOF: - this->setstate (eofbit); - return *this; - } - - if (bufSize < 0 - || static_cast<ACE_CString::size_type> (bufSize) >= max_buf_len) - { - this->setstate (badbit); - return *this; - } - { - ACE_Auto_Basic_Array_Ptr<char> the_id (new char[bufSize + 1]); - the_id[0] = '\0'; - if (ACE_OS::fgets (ACE_TEXT_CHAR_TO_TCHAR (the_id.get ()), - bufSize + 1, - fl_) == 0 - && bufSize != 0) - { - this->setstate (badbit); - return *this; - } - record.id (ACE_CString (the_id.get (), 0, false)); - } - - //kind - switch (fscanf(fl_, "%d\n", &bufSize)) - { - case 0: - this->setstate (badbit); - return *this; - case EOF: - this->setstate (eofbit); - return *this; - } - - if (bufSize < 0 - || static_cast<ACE_CString::size_type> (bufSize) >= max_buf_len) - { - this->setstate (badbit); - return *this; - } - - { - ACE_Auto_Basic_Array_Ptr<char> the_kind (new char[bufSize + 1]); - the_kind[0] = '\0'; - if (ACE_OS::fgets (ACE_TEXT_CHAR_TO_TCHAR (the_kind.get ()), - bufSize + 1, - fl_) == 0 - && bufSize != 0) - { - this->setstate (badbit); - return *this; - } - record.kind (ACE_CString (the_kind.get (), 0, false)); - } - - //ref - switch (fscanf(fl_, "%d\n", &bufSize)) - { - case 0: - this->setstate (badbit); - return *this; - case EOF: - this->setstate (eofbit); - return *this; - } - - if (bufSize < 0 - || static_cast<ACE_CString::size_type> (bufSize) >= max_buf_len) - { - this->setstate (badbit); - return *this; - } - - { - ACE_Auto_Basic_Array_Ptr<char> the_ref (new char[bufSize + 1]); - the_ref[0] = '\0'; - if (ACE_OS::fgets (ACE_TEXT_CHAR_TO_TCHAR (the_ref.get ()), - bufSize + 1, - fl_) == 0 - && bufSize != 0) - { - this->setstate (badbit); - return *this; - } - record.ref (ACE_CString (the_ref.get (), 0, false)); - } - - return *this; - -} - -TAO_Storable_Base & -TAO_NS_FlatFileStream::operator <<( - const TAO_NS_Persistence_Global &global) -{ - ACE_TRACE("TAO_NS_FlatFileStream::operator <<"); - ACE_OS::rewind(this->fl_); - ACE_OS::fprintf(this->fl_, "%d\n", global.counter()); - ACE_OS::fflush(this->fl_); - - return *this; -} - -TAO_Storable_Base & -TAO_NS_FlatFileStream::operator >>( - TAO_NS_Persistence_Global &global) -{ - ACE_TRACE("TAO_NS_FlatFileStream::operator >>"); - unsigned int counter = 0; - - ACE_OS::rewind(this->fl_); - switch (fscanf(fl_, "%u\n", &counter)) - { - case 0: - this->setstate (badbit); - break; // Still set the global.counter (to 0) - case EOF: - this->setstate (eofbit); - break; // Still set the global.counter (to 0) - } - global.counter(counter); - - return *this; -} - - -TAO_Storable_Base * -TAO_NS_FlatFileFactory::create_stream (const ACE_CString & file, - const ACE_TCHAR * mode) -{ - ACE_TRACE("TAO_NS_FlatFileFactory::create_stream"); - TAO_Storable_Base *stream = 0; - - ACE_NEW_RETURN (stream, - TAO_NS_FlatFileStream(file, ACE_TEXT_ALWAYS_CHAR (mode)), - 0); - return stream; -} - -TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/Flat_File_Persistence.h b/TAO/orbsvcs/orbsvcs/Naming/Flat_File_Persistence.h deleted file mode 100644 index 7b03ba75b03..00000000000 --- a/TAO/orbsvcs/orbsvcs/Naming/Flat_File_Persistence.h +++ /dev/null @@ -1,95 +0,0 @@ -// -*- C++ -*- - -//============================================================================= -/** - * @file Flat_File_Persistence.h - * - * $Id$ - * - * @author Marina Spivak <marina@cs.wustl.edu> - */ -//============================================================================= - -#ifndef TAO_FLAT_FILE_PERSISTENCE_H -#define TAO_FLAT_FILE_PERSISTENCE_H - -#include "orbsvcs/Naming/Storable.h" -#include "ace/OS_NS_stdio.h" - -TAO_BEGIN_VERSIONED_NAMESPACE_DECL - -//------------------------------------------------------------------------ -// The Flat File concrete classes -//------------------------------------------------------------------------ -class TAO_NS_FlatFileStream : public TAO_Storable_Base -{ -public: - - TAO_NS_FlatFileStream(const ACE_CString & file, const char * mode); - virtual ~TAO_NS_FlatFileStream(); - - /// Remove a file by name (file is not open) - virtual void remove(); - - /// Check if a file exists on disk (file is not open) - virtual int exists(); - - /// Open a file (the remaining methods below all require an open file) - virtual int open(); - - /// Close an open file - virtual int close(); - - /// Acquire a file lock - virtual int flock (int whence, int start, int len); - - /// Release a file lock - virtual int funlock (int whence, int start, int len); - - /// Returns the last time an open file was changed - virtual time_t last_changed(void); - - /// Write a header to disk - virtual TAO_Storable_Base& operator << ( - const TAO_NS_Persistence_Header& header); - - /// Read a header from disk - virtual TAO_Storable_Base& operator >> ( - TAO_NS_Persistence_Header& header); - - /// Write a record to disk - virtual TAO_Storable_Base& operator << ( - const TAO_NS_Persistence_Record& record); - - /// Read a record from disk - virtual TAO_Storable_Base& operator >> ( - TAO_NS_Persistence_Record& record); - - /// Write the global data to disk - virtual TAO_Storable_Base& operator << ( - const TAO_NS_Persistence_Global& global); - - /// Read the global data from disk - virtual TAO_Storable_Base& operator >> ( - TAO_NS_Persistence_Global& global); - -private: - ACE_OS::ace_flock_t filelock_; - FILE* fl_; - ACE_CString file_; - ACE_CString mode_; -}; - -class TAO_NS_FlatFileFactory : public TAO_Naming_Service_Persistence_Factory -{ -public: - // Factory Methods - - /// Create the stream that can operate on a disk file - virtual TAO_Storable_Base *create_stream(const ACE_CString & file, - const ACE_TCHAR * mode); -}; - -TAO_END_VERSIONED_NAMESPACE_DECL - -#endif diff --git a/TAO/orbsvcs/orbsvcs/Naming/Hash_Naming_Context.cpp b/TAO/orbsvcs/orbsvcs/Naming/Hash_Naming_Context.cpp index f3b6182e33e..de3c6d1c4f5 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Hash_Naming_Context.cpp +++ b/TAO/orbsvcs/orbsvcs/Naming/Hash_Naming_Context.cpp @@ -97,10 +97,6 @@ TAO_Hash_Naming_Context::get_context (const CosNaming::Name &name) void TAO_Hash_Naming_Context::bind (const CosNaming::Name& n, CORBA::Object_ptr obj) { - ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, - ace_mon, this->lock_, - CORBA::INTERNAL ()); - // Check to make sure this object didn't have <destroy> method // invoked on it. if (this->destroyed_) @@ -136,6 +132,10 @@ TAO_Hash_Naming_Context::bind (const CosNaming::Name& n, CORBA::Object_ptr obj) // If we received a simple name, we need to bind it in this context. else { + ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, + ace_mon, this->lock_, + CORBA::INTERNAL ()); + // Try binding the name. int result = this->context_->bind (n[0].id, n[0].kind, @@ -154,10 +154,6 @@ void TAO_Hash_Naming_Context::rebind (const CosNaming::Name& n, CORBA::Object_ptr obj) { - ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, - this->lock_, - CORBA::INTERNAL ()); - // Check to make sure this object didn't have <destroy> method // invoked on it. if (this->destroyed_) @@ -194,6 +190,10 @@ TAO_Hash_Naming_Context::rebind (const CosNaming::Name& n, // If we received a simple name, we need to rebind it in this // context. { + ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, + this->lock_, + CORBA::INTERNAL ()); + int result = this->context_->rebind (n[0].id, n[0].kind, obj, @@ -212,10 +212,6 @@ void TAO_Hash_Naming_Context::bind_context (const CosNaming::Name &n, CosNaming::NamingContext_ptr nc) { - ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, - this->lock_, - CORBA::INTERNAL ()); - // Check to make sure this object didn't have <destroy> method // invoked on it. if (this->destroyed_) @@ -255,6 +251,10 @@ TAO_Hash_Naming_Context::bind_context (const CosNaming::Name &n, // If we received a simple name, we need to bind it in this context. else { + ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, + this->lock_, + CORBA::INTERNAL ()); + // Try binding the name. int result = this->context_->bind (n[0].id, n[0].kind, @@ -273,10 +273,6 @@ void TAO_Hash_Naming_Context::rebind_context (const CosNaming::Name &n, CosNaming::NamingContext_ptr nc) { - ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, - this->lock_, - CORBA::INTERNAL ()); - // Check to make sure this object didn't have <destroy> method // invoked on it. if (this->destroyed_) @@ -314,6 +310,10 @@ TAO_Hash_Naming_Context::rebind_context (const CosNaming::Name &n, // If we received a simple name, we need to rebind it in this // context. { + ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, + this->lock_, + CORBA::INTERNAL ()); + int result = this->context_->rebind (n[0].id, n[0].kind, nc, @@ -332,9 +332,6 @@ TAO_Hash_Naming_Context::rebind_context (const CosNaming::Name &n, CORBA::Object_ptr TAO_Hash_Naming_Context::resolve (const CosNaming::Name& n) { - ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, this->lock_, - CORBA::INTERNAL ()); - // Check to make sure this object didn't have <destroy> method // invoked on it. if (this->destroyed_) @@ -355,14 +352,16 @@ TAO_Hash_Naming_Context::resolve (const CosNaming::Name& n) // Stores the object reference bound to the first name component. CORBA::Object_var result; - if (this->context_->find (n[0].id, - n[0].kind, - result.out (), - type) == -1) - throw CosNaming::NamingContext::NotFound( - CosNaming::NamingContext::missing_node, - n); - + { + ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, this->lock_, + CORBA::INTERNAL ()); + if (this->context_->find (n[0].id, + n[0].kind, + result.out (), + type) == -1) + throw CosNaming::NamingContext::NotFound + (CosNaming::NamingContext::missing_node, n); + } // If the name we have to resolve is a compound name, we need to // resolve it recursively. if (name_len > 1) @@ -410,11 +409,25 @@ TAO_Hash_Naming_Context::resolve (const CosNaming::Name& n) } catch (const CORBA::SystemException&) { - throw CosNaming::NamingContext::CannotProceed( - context.in (), rest_of_name); + throw CosNaming::NamingContext::CannotProceed + (context.in (), rest_of_name); } } } + else + { + ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, + this->lock_, + CORBA::INTERNAL ()); + + if (this->context_->find (n[0].id, + n[0].kind, + result.out (), + type) == -1) + throw CosNaming::NamingContext::NotFound + (CosNaming::NamingContext::missing_node, n); + } + // If the name we had to resolve was simple, we just need to return // the result. return result._retn (); @@ -423,10 +436,6 @@ TAO_Hash_Naming_Context::resolve (const CosNaming::Name& n) void TAO_Hash_Naming_Context::unbind (const CosNaming::Name& n) { - ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, - this->lock_, - CORBA::INTERNAL ()); - // Check to make sure this object didn't have <destroy> method // invoked on it. if (this->destroyed_) @@ -463,20 +472,21 @@ TAO_Hash_Naming_Context::unbind (const CosNaming::Name& n) // If we received a simple name, we need to unbind it in this // context. else - if (this->context_->unbind (n[0].id, - n[0].kind) == -1) - throw CosNaming::NamingContext::NotFound( - CosNaming::NamingContext::missing_node, n); + { + ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, ace_mon, + this->lock_, + CORBA::INTERNAL ()); + + if (this->context_->unbind (n[0].id, + n[0].kind) == -1) + throw CosNaming::NamingContext::NotFound + (CosNaming::NamingContext::missing_node, n); + } } CosNaming::NamingContext_ptr TAO_Hash_Naming_Context::bind_new_context (const CosNaming::Name& n) { - ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, - ace_mon, - this->lock_, - CORBA::INTERNAL ()); - // Check to make sure this object didn't have <destroy> method // invoked on it. if (this->destroyed_) @@ -506,16 +516,15 @@ TAO_Hash_Naming_Context::bind_new_context (const CosNaming::Name& n) // If we received a simple name, we need to bind it in this context. // Stores our new Naming Context. - CosNaming::NamingContext_var result = - CosNaming::NamingContext::_nil (); + CosNaming::NamingContext_var result = CosNaming::NamingContext::_nil (); // Create new context. - result = new_context (); + result = this->new_context (); // Bind the new context to the name. try { - bind_context (n, result.in ()); + this->bind_context (n, result.in ()); } catch (const CORBA::Exception&) { @@ -540,11 +549,6 @@ TAO_Hash_Naming_Context::bind_new_context (const CosNaming::Name& n) void TAO_Hash_Naming_Context::destroy (void) { - ACE_GUARD_THROW_EX (TAO_SYNCH_RECURSIVE_MUTEX, - ace_mon, - this->lock_, - CORBA::INTERNAL ()); - // Check to make sure this object didn't have <destroy> method // invoked on it. if (this->destroyed_) diff --git a/TAO/orbsvcs/orbsvcs/Naming/Naming_Context_Interface.cpp b/TAO/orbsvcs/orbsvcs/Naming/Naming_Context_Interface.cpp index df5cb7b77e7..675ce30a086 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Naming_Context_Interface.cpp +++ b/TAO/orbsvcs/orbsvcs/Naming/Naming_Context_Interface.cpp @@ -461,8 +461,28 @@ TAO_Naming_Context::resolve_str (const char * n) return this->resolve (name.in ()); } +void +TAO_Naming_Context::stale (bool value) +{ + this->impl_->stale (value); +} + TAO_Naming_Context_Impl::~TAO_Naming_Context_Impl (void) { } +void +TAO_Naming_Context_Impl::stale (bool value) +{ + ACE_UNUSED_ARG (value); + // Default implementation is no-op +} + +bool +TAO_Naming_Context_Impl::stale (void) +{ + // Default implementation is to reply false + return false; +} + TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/Naming_Context_Interface.h b/TAO/orbsvcs/orbsvcs/Naming/Naming_Context_Interface.h index 27d907e5f36..8a0fb32be8e 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Naming_Context_Interface.h +++ b/TAO/orbsvcs/orbsvcs/Naming/Naming_Context_Interface.h @@ -177,6 +177,12 @@ public: */ virtual CORBA::Object_ptr resolve_str (const char * n); + /** + * Mark the implementation stale state for replicated + * persistence support. + */ + void stale (bool value); + /// Returns the Default POA of this Servant object virtual PortableServer::POA_ptr _default_POA (void); @@ -339,6 +345,18 @@ public: /// Returns the Default POA of this Servant object virtual PortableServer::POA_ptr _default_POA (void) = 0; + + /** + * Set the stale flag for replicated persistence support. + */ + virtual void stale (bool value); + + /** + * Query if the the implementation is stale for replicated + * persistence support. + */ + virtual bool stale (void); + }; TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/Naming_Loader.cpp b/TAO/orbsvcs/orbsvcs/Naming/Naming_Loader.cpp index 44736086700..72b836a1c9f 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Naming_Loader.cpp +++ b/TAO/orbsvcs/orbsvcs/Naming/Naming_Loader.cpp @@ -17,19 +17,25 @@ #include "ace/Dynamic_Service.h" #include "ace/Argv_Type_Converter.h" - - +#include "orbsvcs/Naming/Naming_Server.h" TAO_BEGIN_VERSIONED_NAMESPACE_DECL -TAO_Naming_Loader::TAO_Naming_Loader (void) +TAO_Naming_Loader::TAO_Naming_Loader (TAO_Naming_Server *server) +: naming_server_(server) { // Constructor + + // If no server was provided, then we will construct one of the + // base class type. + if (naming_server_ == 0) + ACE_NEW (naming_server_, TAO_Naming_Server); } TAO_Naming_Loader::~TAO_Naming_Loader (void) { - // Destructor + // Destroy the naming server that was created + delete naming_server_; } int @@ -63,7 +69,7 @@ int TAO_Naming_Loader::fini (void) { // Remove the Naming Service. - return this->naming_server_.fini (); + return this->naming_server_->fini (); } CORBA::Object_ptr @@ -71,10 +77,20 @@ TAO_Naming_Loader::create_object (CORBA::ORB_ptr orb, int argc, ACE_TCHAR *argv[]) { - // Initializes the Naming Service. Returns -1 - // on an error. - if (this->naming_server_.init_with_orb (argc, argv, orb) == -1) - return CORBA::Object::_nil (); + + if (this->naming_server_ == 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO_Naming_Loader::create_object - naming_server_ ") + ACE_TEXT ("never set.\n"))); + } + else + { + // Initializes the Naming Service. Returns -1 + // on an error. + if (this->naming_server_->init_with_orb (argc, argv, orb) == -1) + return CORBA::Object::_nil (); + } return CORBA::Object::_nil (); } diff --git a/TAO/orbsvcs/orbsvcs/Naming/Naming_Loader.h b/TAO/orbsvcs/orbsvcs/Naming/Naming_Loader.h index 7365fa103e7..c5bb1016bee 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Naming_Loader.h +++ b/TAO/orbsvcs/orbsvcs/Naming/Naming_Loader.h @@ -33,7 +33,10 @@ class TAO_Naming_Serv_Export TAO_Naming_Loader : public TAO_Object_Loader public: /// Constructor - TAO_Naming_Loader (void); + /// By default will use the standard Naming_Server. If a server is provided + /// it will use that one instead. This object takes ownership of the provided + /// Naming Server. + TAO_Naming_Loader (TAO_Naming_Server *server = 0); /// Destructor ~TAO_Naming_Loader (void); @@ -53,8 +56,9 @@ public: ACE_TCHAR *argv[]); protected: + /// TODO: Need to set up service configurator to initialize the naming server /// Instance of the TAO_Naming_Server - TAO_Naming_Server naming_server_; + TAO_Naming_Server* naming_server_; private: TAO_Naming_Loader (const TAO_Naming_Loader &); diff --git a/TAO/orbsvcs/orbsvcs/Naming/Naming_Server.cpp b/TAO/orbsvcs/orbsvcs/Naming/Naming_Server.cpp index 1a021f655ff..9aa2073f9b6 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Naming_Server.cpp +++ b/TAO/orbsvcs/orbsvcs/Naming/Naming_Server.cpp @@ -2,12 +2,17 @@ #include "orbsvcs/Naming/Naming_Server.h" #include "orbsvcs/Naming/Transient_Naming_Context.h" +#include "orbsvcs/Naming/Persistent_Naming_Context_Factory.h" +#include "orbsvcs/Naming/Storable_Naming_Context_Factory.h" + #if !defined (CORBA_E_MICRO) #include "orbsvcs/Naming/Persistent_Context_Index.h" #include "orbsvcs/Naming/Storable_Naming_Context.h" #include "orbsvcs/Naming/Storable_Naming_Context_Activator.h" -#include "orbsvcs/Naming/Flat_File_Persistence.h" + +#include "tao/Storable_FlatFileStream.h" + #endif /* CORBA_E_MICRO */ #include "orbsvcs/CosNamingC.h" @@ -269,6 +274,7 @@ TAO_Naming_Server::parse_args (int argc, ACE_TEXT ("-p <pid_file_name> ") ACE_TEXT ("-s <context_size> ") ACE_TEXT ("-b <base_address> ") + ACE_TEXT ("-u <persistence dir name> ") ACE_TEXT ("-m <1=enable multicast, 0=disable multicast(default) ") ACE_TEXT ("%s") ACE_TEXT ("-z <relative round trip timeout> ") @@ -419,10 +425,12 @@ TAO_Naming_Server::init_with_orb (int argc, return -1; } + // If an ior file name was provided on command line if (this->ior_file_name_ != 0) { - FILE *iorf = ACE_OS::fopen (this->ior_file_name_, ACE_TEXT("w")); - if (iorf == 0) + CORBA::String_var ns_ior = this->naming_service_ior (); + if (this->write_ior_to_file (ns_ior.in (), + this->ior_file_name_) != 0) { ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT("Unable to open %s for writing:(%u) %p\n"), @@ -431,11 +439,6 @@ TAO_Naming_Server::init_with_orb (int argc, ACE_TEXT("TAO_Naming_Server::init_with_orb")), -1); } - - CORBA::String_var str = this->naming_service_ior (); - - ACE_OS::fprintf (iorf, "%s\n", str.in ()); - ACE_OS::fclose (iorf); } if (this->pid_file_name_ != 0) @@ -476,9 +479,18 @@ TAO_Naming_Server::init_new_naming (CORBA::ORB_ptr orb, // In lieu of a fully implemented service configurator version // of this Reader and Writer, let's just take something off the // command line for now. - TAO_Naming_Service_Persistence_Factory* pf = 0; - ACE_NEW_RETURN(pf, TAO_NS_FlatFileFactory, -1); - auto_ptr<TAO_Naming_Service_Persistence_Factory> persFactory(pf); + TAO::Storable_Factory* pf = 0; + ACE_NEW_RETURN (pf, TAO::Storable_FlatFileFactory(persistence_location), -1); + auto_ptr<TAO::Storable_Factory> persFactory(pf); + + // Use an auto_ptr to ensure that we clean up the factory in the case + // of a failure in creating and registering the Activator. + TAO_Storable_Naming_Context_Factory* cf = + this->storable_naming_context_factory (context_size); + // Make sure we got a factory + if (cf == 0) return -1; + auto_ptr<TAO_Storable_Naming_Context_Factory> contextFactory (cf); + // This instance will either get deleted after recreate all or, // in the case of a servant activator's use, on destruction of the // activator. @@ -487,7 +499,7 @@ TAO_Naming_Server::init_new_naming (CORBA::ORB_ptr orb, if (persistence_location == 0) { // No, assign the default location "NameService" - persistence_location = ACE_TEXT("NameService"); + persistence_location = ACE_TEXT ("NameService"); } // Now make sure this directory exists @@ -502,34 +514,70 @@ TAO_Naming_Server::init_new_naming (CORBA::ORB_ptr orb, ACE_NEW_THROW_EX (this->servant_activator_, TAO_Storable_Naming_Context_Activator (orb, persFactory.get(), - persistence_location, - context_size), + contextFactory.get (), + persistence_location), CORBA::NO_MEMORY ()); this->ns_poa_->set_servant_manager(this->servant_activator_); } #endif /* TAO_HAS_MINIMUM_POA */ + try { // The following might throw an exception. + this->naming_context_ = + TAO_Storable_Naming_Context::recreate_all (orb, + poa, + TAO_ROOT_NAMING_CONTEXT, + context_size, + 0, + contextFactory.get (), + persFactory.get (), + use_redundancy_); + } + catch (const CORBA::Exception& ex) + { + // The activator already took over the factories so we need to release the auto_ptr + if (this->use_servant_activator_) + { + // The context factory is now owned by the activator + // so we should release it + contextFactory.release (); + // If using a servant activator, the activator now owns the + // factory, so we should release it + persFactory.release (); + } + // Print out the exception and return failure + ex._tao_print_exception ( + "TAO_Naming_Server::init_new_naming"); + return -1; + } + + // Kind of a duplicate of the above here, but we must also release the + // factory autoptrs in the good case as well. + if (this->use_servant_activator_) + { + // The context factory is now owned by the activator + // so we should release it + contextFactory.release (); + // If using a servant activator, the activator now owns the + // factory, so we should release it + persFactory.release (); + } - this->naming_context_ = - TAO_Storable_Naming_Context::recreate_all (orb, - poa, - TAO_ROOT_NAMING_CONTEXT, - context_size, - 0, - persFactory.get(), - persistence_location, - use_redundancy_); - - if (this->use_servant_activator_) - persFactory.release(); - } + } else if (persistence_location != 0) // // Initialize Persistent Naming Service. // { + + // Create Naming Context Implementation Factory to be used for the creation of + // naming contexts by the TAO_Persistent_Context_Index + TAO_Persistent_Naming_Context_Factory *naming_context_factory = + this->persistent_naming_context_factory (); + // Make sure we got a factory. + if (naming_context_factory == 0) return -1; + // Allocate and initialize Persistent Context Index. ACE_NEW_RETURN (this->context_index_, - TAO_Persistent_Context_Index (orb, poa), + TAO_Persistent_Context_Index (orb, poa, naming_context_factory), -1); if (this->context_index_->open (persistence_location, @@ -706,6 +754,51 @@ TAO_Naming_Server::init_new_naming (CORBA::ORB_ptr orb, } int +TAO_Naming_Server::write_ior_to_file (const char* ior_string, + const char* file_name) +{ + if ((file_name != 0) && + (ior_string != 0)) + { + FILE *iorf = ACE_OS::fopen (file_name, ACE_TEXT("w")); + if (iorf == 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT("Unable to open %s for writing:(%u) %p\n"), + file_name, + ACE_ERRNO_GET, + ACE_TEXT("Naming_Server::write_ior_to_file")), + -1); + } + + ACE_OS::fprintf (iorf, "%s\n", ior_string); + ACE_OS::fclose (iorf); + } + else + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("Invalid file name or IOR string provided") + ACE_TEXT ("to TAO_Naming_Server::write_ior_to_file\n")), + -1); + + } + + return 0; +} + +TAO_Storable_Naming_Context_Factory * +TAO_Naming_Server::storable_naming_context_factory (size_t context_size) +{ + return new (ACE_nothrow) TAO_Storable_Naming_Context_Factory (context_size); +} + +TAO_Persistent_Naming_Context_Factory * +TAO_Naming_Server::persistent_naming_context_factory (void) +{ + return new (ACE_nothrow) TAO_Persistent_Naming_Context_Factory; +} + +int TAO_Naming_Server::fini (void) { // First get rid of the multi cast handler @@ -773,12 +866,17 @@ TAO_Naming_Server::operator-> (void) const return this->naming_context_.ptr (); } + TAO_Naming_Server::~TAO_Naming_Server (void) { #if (TAO_HAS_MINIMUM_POA == 0) && \ !defined (CORBA_E_COMPACT) && !defined (CORBA_E_MICRO) - if (this->use_servant_activator_) - delete this->servant_activator_; + if (this->use_servant_activator_ && + this->servant_activator_) + { + // Activator is reference counted. Don't delete it directly. + this->servant_activator_->_remove_ref (); + } #endif /* TAO_HAS_MINIMUM_POA */ } diff --git a/TAO/orbsvcs/orbsvcs/Naming/Naming_Server.h b/TAO/orbsvcs/orbsvcs/Naming/Naming_Server.h index dd609ec461a..4d970da3706 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Naming_Server.h +++ b/TAO/orbsvcs/orbsvcs/Naming/Naming_Server.h @@ -34,6 +34,9 @@ class TAO_Persistent_Context_Index; class TAO_Storable_Naming_Context_Activator; #endif /* !CORBA_E_MICRO */ +class TAO_Storable_Naming_Context_Factory; +class TAO_Persistent_Naming_Context_Factory; + /** * @class TAO_Naming_Server * @@ -121,13 +124,13 @@ public: /// Initialize the Naming Service with the command line arguments and /// the ORB. - int init_with_orb (int argc, ACE_TCHAR *argv [], CORBA::ORB_ptr orb); + virtual int init_with_orb (int argc, ACE_TCHAR *argv [], CORBA::ORB_ptr orb); /// Destroy the child POA created in @c init_with_orb - int fini (void); + virtual int fini (void); /// Destructor. - ~TAO_Naming_Server (void); + virtual ~TAO_Naming_Server (void); /// Returns the IOR of the naming service. char * naming_service_ior (void); @@ -137,7 +140,8 @@ public: protected: /** - * Helper method: create Naming Service locally. + * Helper method: create Naming Service locally. Can be specialized to + * refine how Naming Service components are created and initialized * Make the root context of size * <context_size>, register it under the <root_poa>, and make the Naming * Service persistent if <persistence_location> is not 0. @@ -146,7 +150,7 @@ protected: * If <enable_multicast> is not zero then the service will respond * to multicast location queries. */ - int init_new_naming (CORBA::ORB_ptr orb, + virtual int init_new_naming (CORBA::ORB_ptr orb, PortableServer::POA_ptr root_poa, const ACE_TCHAR *persistence_location, void *base_addr, @@ -157,7 +161,23 @@ protected: int use_round_trip_timeout = 0); /// parses the arguments. - int parse_args (int argc, ACE_TCHAR *argv[]); + virtual int parse_args (int argc, ACE_TCHAR *argv[]); + + /// Write the provided ior_string to the file. Return 0 if success. + int write_ior_to_file (const char* ior_string, + const char* file_name); + + /* 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); /// Root NamingContext_ptr. CosNaming::NamingContext_var naming_context_; @@ -233,6 +253,7 @@ protected: /// If not zero use round trip timeout policy set to value specified int round_trip_timeout_; int use_round_trip_timeout_; + }; TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/Persistent_Context_Index.cpp b/TAO/orbsvcs/orbsvcs/Naming/Persistent_Context_Index.cpp index 34b74c6b5de..5da2864d20e 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Persistent_Context_Index.cpp +++ b/TAO/orbsvcs/orbsvcs/Naming/Persistent_Context_Index.cpp @@ -2,6 +2,7 @@ #include "orbsvcs/Naming/Persistent_Context_Index.h" #include "orbsvcs/Naming/Persistent_Naming_Context.h" +#include "orbsvcs/Naming/Persistent_Naming_Context_Factory.h" #include "tao/debug.h" @@ -80,19 +81,22 @@ TAO_Persistent_Context_Index::bind (const char *poa_id, TAO_Persistent_Context_Index::TAO_Persistent_Context_Index (CORBA::ORB_ptr orb, - PortableServer::POA_ptr poa) + PortableServer::POA_ptr poa, + TAO_Persistent_Naming_Context_Factory * context_impl_factory) : allocator_ (0), index_ (0), index_file_ (0), base_address_ (0), orb_ (CORBA::ORB::_duplicate (orb)), - poa_ (PortableServer::POA::_duplicate (poa)) + poa_ (PortableServer::POA::_duplicate (poa)), + context_impl_factory_ (context_impl_factory) { } TAO_Persistent_Context_Index::~TAO_Persistent_Context_Index (void) { delete allocator_; + delete context_impl_factory_; ACE_OS::free (reinterpret_cast<void *> (const_cast<ACE_TCHAR *> (index_file_))); } @@ -181,17 +185,14 @@ TAO_Persistent_Context_Index::recreate_all (void) { index_iter->next (entry); - // Put together a servant for the new Naming Context. - - TAO_Persistent_Naming_Context *context_impl = 0; - ACE_NEW_RETURN (context_impl, - TAO_Persistent_Naming_Context (poa_.in (), - entry->ext_id_.poa_id_, - this, - entry->int_id_.hash_map_, - entry->int_id_.counter_), - -1); - + // Put together a servant for the new Naming Context + // Using the naming context factory to create a naming context of the appropriate type + TAO_Persistent_Naming_Context *context_impl = + this->context_impl_factory_->create_naming_context_impl (poa_.in (), + entry->ext_id_.poa_id_, + this, + entry->int_id_.hash_map_, + entry->int_id_.counter_); // Put <context_impl> into the auto pointer temporarily, in case next // allocation fails. @@ -228,6 +229,16 @@ TAO_Persistent_Context_Index::recreate_all (void) return 0; } +TAO_Persistent_Naming_Context* +TAO_Persistent_Context_Index::create_naming_context_impl ( + PortableServer::POA_ptr poa, + const char *poa_id) +{ + return this->context_impl_factory_->create_naming_context_impl(poa, + poa_id, + this); +} + int TAO_Persistent_Context_Index::create_index (void) { diff --git a/TAO/orbsvcs/orbsvcs/Naming/Persistent_Context_Index.h b/TAO/orbsvcs/orbsvcs/Naming/Persistent_Context_Index.h index fe807eae71b..9b7f0a26010 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Persistent_Context_Index.h +++ b/TAO/orbsvcs/orbsvcs/Naming/Persistent_Context_Index.h @@ -23,6 +23,9 @@ #include "ace/Malloc_T.h" #include "ace/MMAP_Memory_Pool.h" +class TAO_Persistent_Naming_Context; +class TAO_Persistent_Naming_Context_Factory; + TAO_BEGIN_VERSIONED_NAMESPACE_DECL /** @@ -64,8 +67,10 @@ public: // = Initialization and termination methods. /// Constructor. - TAO_Persistent_Context_Index (CORBA::ORB_ptr orb, - PortableServer::POA_ptr poa); + TAO_Persistent_Context_Index ( + CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + TAO_Persistent_Naming_Context_Factory *context_impl_factory); /** * Create ACE_Allocator, open/create memory-mapped file with the @@ -86,6 +91,15 @@ public: int init (size_t context_size); /** + * Create a naming context implementation to be used for this index + * using the naming context factory that was provided in the ctor + * for the index. + */ + TAO_Persistent_Naming_Context *create_naming_context_impl ( + PortableServer::POA_ptr poa, + const char *poa_id); + + /** * Destructor. The memory mapped file that was opened/created is * not deleted, since we want it to keep the state of the Naming * Service until the next run. @@ -161,6 +175,9 @@ private: /// The reference to the root Naming Context. CosNaming::NamingContext_var root_context_; + + /// The factory for constructing naming contexts within the index + TAO_Persistent_Naming_Context_Factory *context_impl_factory_; }; TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/Persistent_Naming_Context.cpp b/TAO/orbsvcs/orbsvcs/Naming/Persistent_Naming_Context.cpp index caa29847f7b..6a90a325ae9 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Persistent_Naming_Context.cpp +++ b/TAO/orbsvcs/orbsvcs/Naming/Persistent_Naming_Context.cpp @@ -235,23 +235,6 @@ TAO_Persistent_Bindings_Map::shared_bind (const char * id, TAO_Persistent_Naming_Context::TAO_Persistent_Naming_Context (PortableServer::POA_ptr poa, const char *poa_id, - TAO_Persistent_Context_Index *context_index) - - : TAO_Hash_Naming_Context (poa, - poa_id), - counter_ (0), - persistent_context_ (0), - index_ (context_index) -{ - ACE_NEW (this->persistent_context_, - TAO_Persistent_Bindings_Map (context_index->orb ())); - - // Set the superclass pointer. - context_ = persistent_context_; -} - -TAO_Persistent_Naming_Context::TAO_Persistent_Naming_Context (PortableServer::POA_ptr poa, - const char *poa_id, TAO_Persistent_Context_Index *context_index, HASH_MAP *map, ACE_UINT32 *counter) @@ -267,7 +250,10 @@ TAO_Persistent_Naming_Context::TAO_Persistent_Naming_Context (PortableServer::PO // Set the superclass pointer. context_ = persistent_context_; - persistent_context_->set (map, index_->allocator ()); + // If a map was provided (i.e., not defaulted) then set it in the + // persistent_context_ + if (map != 0) + persistent_context_->set (map, index_->allocator ()); } int @@ -309,12 +295,13 @@ TAO_Persistent_Naming_Context::make_new_context (PortableServer::POA_ptr poa, // Put together a servant for the new Naming Context. - TAO_Persistent_Naming_Context *context_impl = 0; - ACE_NEW_THROW_EX (context_impl, - TAO_Persistent_Naming_Context (poa, - poa_id, - ind), - CORBA::NO_MEMORY ()); + TAO_Persistent_Naming_Context *context_impl = ind->create_naming_context_impl( + poa, + poa_id); + + // Verify that a context implementation was created. If not, throw an exception + if (context_impl == 0) + throw CORBA::NO_MEMORY (); // Put <context_impl> into the auto pointer temporarily, in case next // allocation fails. diff --git a/TAO/orbsvcs/orbsvcs/Naming/Persistent_Naming_Context.h b/TAO/orbsvcs/orbsvcs/Naming/Persistent_Naming_Context.h index 8659c497466..56e7a886c1f 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Persistent_Naming_Context.h +++ b/TAO/orbsvcs/orbsvcs/Naming/Persistent_Naming_Context.h @@ -169,12 +169,6 @@ public: // = Initialization and termination methods. - /// Constructor. MUST be followed up by <init> to allocate the - /// underlying data structure from persistent storage! - TAO_Persistent_Naming_Context (PortableServer::POA_ptr poa, - const char *poa_id, - TAO_Persistent_Context_Index *context_index); - /// Allocate the underlying data structure from persistent storage. /// Returns 0 on success and -1 on failure. int init (size_t hash_table_size = ACE_DEFAULT_MAP_SIZE); @@ -182,13 +176,15 @@ public: /** * Constructor that takes in preallocated data structure and takes * ownership of it. This constructor is for 'recreating' servants - * from persistent state. + * from persistent state. If no map is provided, it MUST be followed + * up by <init> to allocate the underlying data structure from + * persistent storage! */ TAO_Persistent_Naming_Context (PortableServer::POA_ptr poa, const char *poa_id, TAO_Persistent_Context_Index *context_index, - HASH_MAP * map, - ACE_UINT32 *counter); + HASH_MAP * map = 0, + ACE_UINT32 *counter = 0); /// Destructor. virtual ~TAO_Persistent_Naming_Context (void); diff --git a/TAO/orbsvcs/orbsvcs/Naming/Persistent_Naming_Context_Factory.cpp b/TAO/orbsvcs/orbsvcs/Naming/Persistent_Naming_Context_Factory.cpp new file mode 100644 index 00000000000..6cc93bdef1f --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/Persistent_Naming_Context_Factory.cpp @@ -0,0 +1,39 @@ +// $Id$ + +#include "orbsvcs/Naming/Persistent_Naming_Context_Factory.h" +#include "orbsvcs/Naming/Persistent_Naming_Context.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +/// Constructor. +TAO_Persistent_Naming_Context_Factory::TAO_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. +TAO_Persistent_Naming_Context_Factory::~TAO_Persistent_Naming_Context_Factory (void) +{ +} + + +/// Factory method for creating an implementation object for naming contexts +TAO_Persistent_Naming_Context* +TAO_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_Persistent_Naming_Context (poa, + poa_id, + context_index, + map, + counter); +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/Persistent_Naming_Context_Factory.h b/TAO/orbsvcs/orbsvcs/Naming/Persistent_Naming_Context_Factory.h new file mode 100644 index 00000000000..570536be79c --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/Persistent_Naming_Context_Factory.h @@ -0,0 +1,62 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Persistent_Naming_Context_Factory.h + * + * $Id$ + * + * @author Kevin Stanley stanleyk@ociweb.com> + */ +//============================================================================= + + +#ifndef TAO_PERSISTENT_NAMING_CONTEXT_FACTORY_H +#define TAO_PERSISTENT_NAMING_CONTEXT_FACTORY_H +#include /**/ "ace/pre.h" + +#include "tao/ORB.h" +#include "orbsvcs/Naming/nsconf.h" +#include "orbsvcs/Naming/naming_serv_export.h" +#include "orbsvcs/Naming/Hash_Naming_Context.h" +#include "orbsvcs/Naming/Persistent_Entries.h" +#include "orbsvcs/Naming/Persistent_Naming_Context.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +class TAO_Persistent_Naming_Context; + +/** + * @class TAO_Persistent_Naming_Context_Factory + * + * @brief A factory that creates TAO_Persistent_Naming_Context + * objects to implement the COS Naming Service NamingContext interface. + */ +class TAO_Naming_Serv_Export TAO_Persistent_Naming_Context_Factory +{ +public: + + // = Initialization and termination methods. + /// Data structure used by TAO_Persistent_Context_Index - typedef for ease of use. + typedef TAO_Persistent_Naming_Context::HASH_MAP HASH_MAP; + + /// Constructor. + TAO_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_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_PERSISTENT_NAMING_CONTEXT_FACTORY_H */ diff --git a/TAO/orbsvcs/orbsvcs/Naming/Storable.h b/TAO/orbsvcs/orbsvcs/Naming/Storable.h index 394a1863447..56755d18a0d 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Storable.h +++ b/TAO/orbsvcs/orbsvcs/Naming/Storable.h @@ -21,8 +21,9 @@ #pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ -#include "tao/Versioned_Namespace.h" +#include "tao/Storable_Base.h" #include "ace/SString.h" +#include "orbsvcs/Naming/naming_serv_export.h" TAO_BEGIN_VERSIONED_NAMESPACE_DECL @@ -68,7 +69,7 @@ class TAO_NS_Persistence_Record ACE_CString ref_; }; -class TAO_NS_Persistence_Global +class TAO_Naming_Serv_Export TAO_NS_Persistence_Global { public: void counter (unsigned int counter); @@ -78,84 +79,6 @@ class TAO_NS_Persistence_Global unsigned int counter_; }; -class TAO_Storable_Base -{ -public: - TAO_Storable_Base(); - - virtual ~TAO_Storable_Base(); - - virtual void remove() = 0; - - virtual int exists() = 0; - - virtual int open () = 0; - - virtual int close () = 0; - - virtual int flock (int whence, int start, int len) = 0; - - virtual int funlock (int whence, int start, int len) = 0; - - virtual time_t last_changed(void) = 0; - - // Mimic a portion of the std::ios interface. We need to be able - // to indicate error states from the extraction operators below. - enum Storable_State { goodbit = 0, - badbit = 1, - eofbit = 2, - failbit = 4 - }; - - void clear (Storable_State state = goodbit); - - void setstate (Storable_State state); - - Storable_State rdstate (void) const; - - bool good (void) const; - - bool bad (void) const; - - bool eof (void) const; - - bool fail (void) const; - - virtual TAO_Storable_Base& operator << ( - const TAO_NS_Persistence_Header& header) = 0; - - virtual TAO_Storable_Base& operator << ( - const TAO_NS_Persistence_Record& record) = 0; - - virtual TAO_Storable_Base& operator >> ( - TAO_NS_Persistence_Header& header) = 0; - - virtual TAO_Storable_Base& operator >> ( - TAO_NS_Persistence_Record& record) = 0; - - virtual TAO_Storable_Base& operator << ( - const TAO_NS_Persistence_Global& global) = 0; - - virtual TAO_Storable_Base& operator >> ( - TAO_NS_Persistence_Global& global) = 0; - -private: - Storable_State state_; -}; - -class TAO_Naming_Service_Persistence_Factory -{ -public: - TAO_Naming_Service_Persistence_Factory(); - - virtual ~TAO_Naming_Service_Persistence_Factory(); - - // Factory Methods - - virtual TAO_Storable_Base *create_stream(const ACE_CString & file, - const ACE_TCHAR * mode) = 0; -}; - TAO_END_VERSIONED_NAMESPACE_DECL #if defined (__ACE_INLINE__) diff --git a/TAO/orbsvcs/orbsvcs/Naming/Storable.inl b/TAO/orbsvcs/orbsvcs/Naming/Storable.inl index 2df1d497262..c020a68042e 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Storable.inl +++ b/TAO/orbsvcs/orbsvcs/Naming/Storable.inl @@ -99,69 +99,4 @@ TAO_NS_Persistence_Global::counter () const return this->counter_; } - -ACE_INLINE -TAO_Naming_Service_Persistence_Factory::TAO_Naming_Service_Persistence_Factory() -{ -} - -ACE_INLINE -TAO_Naming_Service_Persistence_Factory::~TAO_Naming_Service_Persistence_Factory() -{ -} - -ACE_INLINE -TAO_Storable_Base::TAO_Storable_Base() - : state_ (goodbit) -{ -} - -ACE_INLINE -TAO_Storable_Base::~TAO_Storable_Base() -{ -} - -ACE_INLINE void -TAO_Storable_Base::clear (TAO_Storable_Base::Storable_State state) -{ - this->state_ = state; -} - -ACE_INLINE void -TAO_Storable_Base::setstate (TAO_Storable_Base::Storable_State state) -{ - this->clear (static_cast <TAO_Storable_Base::Storable_State> ( - this->rdstate () | state)); -} - -ACE_INLINE TAO_Storable_Base::Storable_State -TAO_Storable_Base::rdstate (void) const -{ - return this->state_; -} - -ACE_INLINE bool -TAO_Storable_Base::good (void) const -{ - return (this->state_ == goodbit); -} - -ACE_INLINE bool -TAO_Storable_Base::bad (void) const -{ - return (this->state_ & badbit); -} - -ACE_INLINE bool -TAO_Storable_Base::eof (void) const -{ - return (this->state_ & eofbit); -} - -ACE_INLINE bool -TAO_Storable_Base::fail (void) const -{ - return (this->state_ & failbit); -} - TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.cpp b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.cpp index e37f995cce6..51415d75293 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.cpp +++ b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.cpp @@ -1,9 +1,13 @@ // $Id$ #include "orbsvcs/Naming/Storable_Naming_Context.h" +#include "orbsvcs/Naming/Storable_Naming_Context_Factory.h" +#include "orbsvcs/Naming/Storable_Naming_Context_ReaderWriter.h" #include "orbsvcs/Naming/Bindings_Iterator_T.h" #include "tao/debug.h" +#include "tao/Storable_Base.h" +#include "tao/Storable_Factory.h" #include "ace/Auto_Ptr.h" #include "ace/OS_NS_stdio.h" @@ -12,7 +16,7 @@ TAO_BEGIN_VERSIONED_NAMESPACE_DECL const char * TAO_Storable_Naming_Context::root_name_; ACE_UINT32 TAO_Storable_Naming_Context::gcounter_; -ACE_Auto_Ptr<TAO_Storable_Base> TAO_Storable_Naming_Context::gfl_; +ACE_Auto_Ptr<TAO::Storable_Base> TAO_Storable_Naming_Context::gfl_; int TAO_Storable_Naming_Context::redundant_; TAO_Storable_IntId::TAO_Storable_IntId (void) @@ -238,316 +242,138 @@ TAO_Storable_Bindings_Map::shared_bind (const char * id, } } -void TAO_Storable_Naming_Context::Write(TAO_Storable_Base& wrtr) +void TAO_Storable_Naming_Context::Write (TAO::Storable_Base& wrtr) { ACE_TRACE("Write"); - TAO_NS_Persistence_Header header; - - header.size (static_cast<unsigned int> (storable_context_->current_size())); - header.destroyed (destroyed_); - - wrtr << header; - - if (0u == header.size ()) - return; - - ACE_Hash_Map_Iterator<TAO_Storable_ExtId,TAO_Storable_IntId, - ACE_Null_Mutex> it = storable_context_->map().begin(); - ACE_Hash_Map_Iterator<TAO_Storable_ExtId,TAO_Storable_IntId, - ACE_Null_Mutex> itend = storable_context_->map().end(); - - ACE_Hash_Map_Entry<TAO_Storable_ExtId,TAO_Storable_IntId> ent = *it; - - while (!(it == itend)) - { - TAO_NS_Persistence_Record record; - - ACE_CString name; - CosNaming::BindingType bt = (*it).int_id_.type_; - if (bt == CosNaming::ncontext) - { - CORBA::Object_var - obj = orb_->string_to_object ((*it).int_id_.ref_.in ()); - if (obj->_is_collocated ()) - { - // This is a local (i.e. non federated context) we therefore - // store only the ObjectID (persistence filename) for the object. - - // The driving force behind storing ObjectIDs rather than IORs for - // local contexts is to provide for a redundant naming service. - // That is, a naming service that runs simultaneously on multiple - // machines sharing a file system. It allows multiple redundant - // copies to be started and stopped independently. - // The original target platform was Tru64 Clusters where there was - // a cluster address. In that scenario, clients may get different - // servers on each request, hence the requirement to keep - // synchronized to the disk. It also works on non-cluster system - // where the client picks one of the redundant servers and uses it, - // while other systems can pick different servers. (However in this - // scenario, if a server fails and a client must pick a new server, - // that client may not use any saved context IORs, instead starting - // from the root to resolve names. So this latter mode is not quite - // transparent to clients.) [Rich Seibel (seibel_r) of ociweb.com] - - PortableServer::ObjectId_var - oid = poa_->reference_to_id (obj.in ()); - CORBA::String_var - nm = PortableServer::ObjectId_to_string (oid.in ()); - const char - *newname = nm.in (); - name.set (newname); // The local ObjectID (persistance filename) - record.type (TAO_NS_Persistence_Record::LOCAL_NCONTEXT); - } - else - { - // Since this is a foreign (federated) context, we can not store - // the objectID (because it isn't in our storage), if we did, when - // we restore, we would end up either not finding a permanent - // record (and thus ending up incorrectly assuming the context was - // destroyed) or loading another context altogether (just because - // the contexts shares its objectID filename which is very likely). - // [Simon Massey (sma) of prismtech.com] - - name.set ((*it).int_id_.ref_.in ()); // The federated context IOR - record.type (TAO_NS_Persistence_Record::REMOTE_NCONTEXT); - } - } - else // if (bt == CosNaming::nobject) // shouldn't be any other, can there? - { - name.set ((*it).int_id_.ref_.in ()); // The non-context object IOR - record.type (TAO_NS_Persistence_Record::OBJREF); - } - record.ref(name); - - const char *myid = (*it).ext_id_.id(); - ACE_CString id(myid); - record.id(id); - - const char *mykind = (*it).ext_id_.kind(); - ACE_CString kind(mykind); - record.kind(kind); - - wrtr << record; - it.advance(); - } + TAO_Storable_Naming_Context_ReaderWriter rw(wrtr); + rw.write(*this); } -// Helper function to load a new context into the binding_map +// Helpers function to load a new context into the binding_map int -TAO_Storable_Naming_Context::load_map(File_Open_Lock_and_Check *flck) +TAO_Storable_Naming_Context::load_map (TAO::Storable_Base& storable) { ACE_TRACE("load_map"); - // assume file already open for reading - TAO_Storable_Bindings_Map *bindings_map; - - // create the new bindings map - ACE_NEW_THROW_EX (bindings_map, - TAO_Storable_Bindings_Map (hash_table_size_,orb_.in()), - CORBA::NO_MEMORY ()); - - // get the data for this bindings map from the file - - TAO_NS_Persistence_Header header; - TAO_NS_Persistence_Record record; + TAO_Storable_Naming_Context_ReaderWriter rw (storable); + return rw.read (*this); +} - // we are only using the size from this header - flck->peer() >> header; - if (!flck->peer ().good ()) +TAO_Storable_Naming_Context:: +File_Open_Lock_and_Check::File_Open_Lock_and_Check ( + TAO_Storable_Naming_Context * context, + Method_Type method_type) +: TAO::Storable_File_Guard (TAO_Storable_Naming_Context::redundant_), + context_(context) +{ + try { - flck->peer ().clear (); - throw CORBA::INTERNAL (); + this->init (method_type); } - - // reset the destroyed flag - this->destroyed_ = header.destroyed(); - - // read in the data for the map - for (unsigned int i= 0u; i<header.size(); ++i) + catch (const TAO::Storable_Read_Exception &) { - flck->peer() >> record; - if (!flck->peer ().good ()) - { - flck->peer ().clear (); - throw CORBA::INTERNAL (); - } - - if (TAO_NS_Persistence_Record::LOCAL_NCONTEXT == record.type ()) - { - PortableServer::ObjectId_var - id = PortableServer::string_to_ObjectId (record.ref ().c_str ()); - const char - *intf = interface_->_interface_repository_id (); - CORBA::Object_var - objref = poa_->create_reference_with_id (id.in (), intf); - bindings_map->bind ( record.id ().c_str (), - record.kind ().c_str (), - objref.in (), - CosNaming::ncontext ); - } - else - { - CORBA::Object_var - objref = orb_->string_to_object (record.ref ().c_str ()); - bindings_map->bind ( record.id ().c_str (), - record.kind ().c_str (), - objref.in (), - ((TAO_NS_Persistence_Record::REMOTE_NCONTEXT == record.type ()) - ? CosNaming::ncontext // REMOTE_NCONTEXT - : CosNaming::nobject )); // OBJREF - } + throw CORBA::INTERNAL (); } - storable_context_ = bindings_map; - context_ = storable_context_; - return 0; } TAO_Storable_Naming_Context:: -File_Open_Lock_and_Check::File_Open_Lock_and_Check( - TAO_Storable_Naming_Context * context, - const char * mode) -:closed_(1), - context_(context) +File_Open_Lock_and_Check::~File_Open_Lock_and_Check () { - ACE_TRACE("File_Open_Lock_and_Check"); - // We only accept a subset of mode argument, check it - rwflags_ = 0; - for( unsigned int i = 0; i<ACE_OS::strlen(mode); i++ ) - { - switch (mode[i]) + this->release (); + + // Check if a write occurred for this context and + // notify the context if it did. + if (context_->write_occurred_ == 1) { - case 'r': rwflags_ |= mode_read; - break; - case 'w': rwflags_ |= mode_write; - break; - case 'c': rwflags_ |= mode_create; - break; - default: rwflags_ = -1; + context_->context_written (); + // We have to make sure we clear the flag + // for subsequent times through. + context_->write_occurred_ = 0; } - } - if( rwflags_ <= 0 ) - { - errno = EINVAL; - throw CORBA::PERSIST_STORE(); - } - - // build the file name - ACE_CString file_name(context->persistence_directory_); - file_name += "/"; - file_name += context->name_; - - // Create the stream - fl_ = context->factory_->create_stream(file_name, ACE_TEXT_CHAR_TO_TCHAR(mode)); - if (TAO_Storable_Naming_Context::redundant_) - { - if (fl_->open() != 0) - { - delete fl_; - throw CORBA::PERSIST_STORE(); - } +} - // acquire a lock on it - if (fl_ -> flock(0, 0, 0) != 0) - { - fl_->close(); - delete fl_; - throw CORBA::INTERNAL(); - } +bool +TAO_Storable_Naming_Context:: +File_Open_Lock_and_Check::object_obsolete (void) +{ - // now that the file is successfully opened and locked it must be - // unlocked/closed before we leave this class - closed_ = 0; + // Query the underlying context if it is obsolete with respect + // to the provided file last-changed time + return (context_->is_obsolete (fl_->last_changed ())); +} - if ( ! (rwflags_ & mode_create) ) - { - // Check if our copy is up to date - time_t new_last_changed = fl_->last_changed(); - if( new_last_changed > context->last_changed_ ) - { - context->last_changed_ = new_last_changed; - // Throw our map away - delete context->storable_context_; - // and build a new one from disk - context->load_map(this); - } - } - } - else if ( ! context->storable_context_ || (rwflags_ & mode_write) ) - { - if (fl_->open() != 0) - { - delete fl_; - throw CORBA::PERSIST_STORE(); - } +void +TAO_Storable_Naming_Context:: +File_Open_Lock_and_Check::mark_object_current (void) +{ + // Reset the stale flag + context_->stale (false); + // Set the last update time to the file last update time + this->set_object_last_changed (fl_->last_changed ()); +} - // now that the file is successfully opened - // unlocked/closed before we leave this class - closed_ = 0; +void +TAO_Storable_Naming_Context:: +File_Open_Lock_and_Check::set_object_last_changed (const time_t & time) +{ + context_->last_changed_ = time; +} - if(!context->storable_context_) - { - // Load the map from disk - context->load_map(this); - } - } - else - { - // Need to insure that fl_ gets deleted - delete fl_; - } +time_t +TAO_Storable_Naming_Context:: +File_Open_Lock_and_Check::get_object_last_changed () +{ + return context_->last_changed_; } void TAO_Storable_Naming_Context:: -File_Open_Lock_and_Check::release(void) +File_Open_Lock_and_Check::load_from_stream () { - ACE_TRACE("release"); - if ( ! closed_ ) - { - // If we updated the disk, save the time stamp - if(TAO_Storable_Naming_Context::redundant_) - { - if( rwflags_ & mode_write ) - context_->last_changed_ = fl_->last_changed(); - fl_->funlock(0, 0, 0); - } - fl_->close(); - delete fl_; - closed_ = 1; - } + // Throw our map away + delete context_->storable_context_; + // and build a new one from disk + context_->load_map (this->peer()); } +bool TAO_Storable_Naming_Context:: -File_Open_Lock_and_Check::~File_Open_Lock_and_Check(void) +File_Open_Lock_and_Check::is_loaded_from_stream () { - ACE_TRACE("~File_Open_Lock_and_Check"); - this->release(); + return context_->storable_context_ != 0; } -TAO_Storable_Base & -TAO_Storable_Naming_Context::File_Open_Lock_and_Check::peer(void) +TAO::Storable_Base * +TAO_Storable_Naming_Context:: +File_Open_Lock_and_Check::create_stream (const char * mode) { - ACE_TRACE("peer"); - return *fl_; + ACE_CString file_name = context_->context_name_; + + // Create the stream + return context_->factory_->create_stream(file_name, ACE_TEXT_CHAR_TO_TCHAR(mode)); } +// Make shortcut to get to Method_Type enums +typedef TAO::Storable_File_Guard SFG; + TAO_Storable_Naming_Context::TAO_Storable_Naming_Context ( CORBA::ORB_ptr orb, PortableServer::POA_ptr poa, - const char *poa_id, - TAO_Naming_Service_Persistence_Factory *factory, - const ACE_TCHAR *persistence_directory, + const char *context_name, + TAO_Storable_Naming_Context_Factory *cxt_factory, + TAO::Storable_Factory *factory, size_t hash_table_size) : TAO_Hash_Naming_Context (poa, - poa_id), + context_name), counter_ (0), storable_context_ (0), orb_(CORBA::ORB::_duplicate (orb)), - name_ (poa_id), + context_name_ (context_name), poa_ (PortableServer::POA::_duplicate (poa)), - factory_(factory), - persistence_directory_ (ACE_TEXT_ALWAYS_CHAR(persistence_directory)), - hash_table_size_(hash_table_size), - last_changed_(0) + context_factory_ (cxt_factory), + factory_ (factory), + hash_table_size_ (hash_table_size), + last_changed_ (0), + write_occurred_ (0) { ACE_TRACE("TAO_Storable_Naming_Context"); } @@ -562,12 +388,10 @@ TAO_Storable_Naming_Context::~TAO_Storable_Naming_Context (void) if (this->destroyed_) { // Make sure we delete the associated stream - ACE_CString file_name (this->persistence_directory_); - file_name += "/"; - file_name += this->name_; + ACE_CString file_name = this->context_name_; // Now delete the file - ACE_Auto_Ptr<TAO_Storable_Base> + ACE_Auto_Ptr<TAO::Storable_Base> fl ( this->factory_->create_stream(file_name.c_str(), ACE_TEXT("r")) @@ -586,10 +410,9 @@ CosNaming::NamingContext_ptr TAO_Storable_Naming_Context::make_new_context ( CORBA::ORB_ptr orb, PortableServer::POA_ptr poa, - const char *poa_id, - size_t context_size, - TAO_Naming_Service_Persistence_Factory *factory, - const ACE_TCHAR *persistence_directory, + const char *context_name, + TAO_Storable_Naming_Context_Factory *cxt_factory, + TAO::Storable_Factory *pers_factory, TAO_Storable_Naming_Context **new_context) { ACE_TRACE("make_new_context"); @@ -598,15 +421,14 @@ TAO_Storable_Naming_Context::make_new_context ( // Put together a servant for the new Naming Context. - TAO_Storable_Naming_Context *context_impl = 0; - ACE_NEW_THROW_EX (context_impl, - TAO_Storable_Naming_Context (orb, - poa, - poa_id, - factory, - persistence_directory, - context_size), - CORBA::NO_MEMORY ()); + TAO_Storable_Naming_Context *context_impl = + cxt_factory->create_naming_context_impl (orb, + poa, + context_name, + pers_factory); + + if (context_impl == 0) + throw CORBA::NO_MEMORY (); // Put <context_impl> into the auto pointer temporarily, in case next // allocation fails. @@ -627,7 +449,7 @@ TAO_Storable_Naming_Context::make_new_context ( // Register the new context with the POA. PortableServer::ObjectId_var id = - PortableServer::string_to_ObjectId (poa_id); + PortableServer::string_to_ObjectId (context_name); // If we try to register a naming context that is already registered, // the following activation causes a POA::ObjectAlreadyActive exception be @@ -663,7 +485,7 @@ TAO_Storable_Naming_Context::new_context (void) { // Open the backing file - File_Open_Lock_and_Check flck(this, "r"); + File_Open_Lock_and_Check flck(this, SFG::ACCESSOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -672,8 +494,8 @@ TAO_Storable_Naming_Context::new_context (void) } TAO_NS_Persistence_Global global; + TAO_Storable_Naming_Context_ReaderWriter rw(*gfl_.get()); - // Generate a POA id for the new context. if(redundant_) { // acquire a lock on the file that holds our counter @@ -685,25 +507,21 @@ TAO_Storable_Naming_Context::new_context (void) if (gfl_ -> flock(0, 0, 0) != 0) throw CORBA::INTERNAL(); // get the counter from disk - *gfl_.get() >> global; - if (!gfl_.get ()->good () && - gfl_.get ()->rdstate () != TAO_Storable_Base::eofbit) - { - gfl_.get ()->clear (); - throw CORBA::INTERNAL (); - } + rw.read_global(global); gcounter_ = global.counter(); // use it to generate a new name } - char poa_id[BUFSIZ]; - ACE_OS::sprintf (poa_id, + + // Generate an Object id for the new context. + char object_id[BUFSIZ]; + ACE_OS::sprintf (object_id, "%s_%d", root_name_, gcounter_++); // then save it back on disk - global.counter(gcounter_); - *gfl_.get() << global; - if(redundant_) + global.counter (gcounter_); + rw.write_global (global); + if (redundant_) { // and release our lock if (gfl_ -> flock(0, 0, 0) != 0) @@ -716,10 +534,9 @@ TAO_Storable_Naming_Context::new_context (void) CosNaming::NamingContext_var result = make_new_context (this->orb_.in (), this->poa_.in (), - poa_id, - this->storable_context_->total_size (), + object_id, + this->context_factory_, this->factory_, - ACE_TEXT_CHAR_TO_TCHAR (this->persistence_directory_.c_str ()), &new_context); // Since this is a new context, make an empty map in it @@ -728,7 +545,7 @@ TAO_Storable_Naming_Context::new_context (void) CORBA::NO_MEMORY ()); new_context->context_ = new_context->storable_context_; - File_Open_Lock_and_Check flck(new_context, "wc"); + File_Open_Lock_and_Check flck(new_context, SFG::CREATE_WITHOUT_FILE); new_context->Write(flck.peer()); return result._retn (); @@ -752,7 +569,7 @@ TAO_Storable_Naming_Context::rebind (const CosNaming::Name& n, CORBA::INTERNAL ()); // Open the backing file - File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw"); + File_Open_Lock_and_Check flck(this, name_len > 1 ? SFG::ACCESSOR : SFG::MUTATOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -819,7 +636,7 @@ TAO_Storable_Naming_Context::bind_context (const CosNaming::Name &n, CORBA::INTERNAL ()); // Open the backing file - File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw"); + File_Open_Lock_and_Check flck(this, name_len > 1 ? SFG::ACCESSOR : SFG::MUTATOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -879,7 +696,7 @@ TAO_Storable_Naming_Context::rebind_context (const CosNaming::Name &n, CORBA::INTERNAL ()); // Open the backing file - File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw"); + File_Open_Lock_and_Check flck(this, name_len > 1 ? SFG::ACCESSOR : SFG::MUTATOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -938,7 +755,7 @@ TAO_Storable_Naming_Context::resolve (const CosNaming::Name& n) CORBA::INTERNAL ()); // Open the backing file - File_Open_Lock_and_Check flck(this, "r"); + File_Open_Lock_and_Check flck(this, SFG::ACCESSOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -1027,7 +844,8 @@ TAO_Storable_Naming_Context::unbind (const CosNaming::Name& n) CORBA::INTERNAL ()); // Open the backing file - File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw"); + File_Open_Lock_and_Check flck(this, name_len > 1 ? + SFG::ACCESSOR : SFG::MUTATOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -1086,7 +904,8 @@ TAO_Storable_Naming_Context::bind_new_context (const CosNaming::Name& n) throw CORBA::OBJECT_NOT_EXIST (); // Open the backing file - File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw"); + File_Open_Lock_and_Check flck(this, name_len > 1 ? + SFG::ACCESSOR : SFG::MUTATOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -1155,7 +974,7 @@ TAO_Storable_Naming_Context::destroy (void) CORBA::INTERNAL ()); // Open the backing file - File_Open_Lock_and_Check flck(this, "rw"); + File_Open_Lock_and_Check flck(this, SFG::MUTATOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -1190,6 +1009,21 @@ TAO_Storable_Naming_Context::destroy (void) } } +void +TAO_Storable_Naming_Context::context_written (void) +{ + // No-op. Overridden by derived class. +} + +bool +TAO_Storable_Naming_Context::is_obsolete (time_t stored_time) +{ + // If the context_ has not been populated or + // the time in the persistent store is greater than this + // object last change time, the context is obsolete + return (this->context_ == 0) || + (stored_time > this->last_changed_); +} void TAO_Storable_Naming_Context::bind (const CosNaming::Name& n, @@ -1209,7 +1043,8 @@ TAO_Storable_Naming_Context::bind (const CosNaming::Name& n, CORBA::INTERNAL ()); // Open the backing file - File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw"); + File_Open_Lock_and_Check flck(this, name_len > 1 ? + SFG::ACCESSOR : SFG::MUTATOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -1247,7 +1082,7 @@ TAO_Storable_Naming_Context::bind (const CosNaming::Name& n, else if (result == -1) throw CORBA::INTERNAL (); - this->Write(flck.peer()); + this->Write (flck.peer()); } } @@ -1272,7 +1107,7 @@ TAO_Storable_Naming_Context::list (CORBA::ULong how_many, CORBA::INTERNAL ()); // Open the backing file - File_Open_Lock_and_Check flck(this, "r"); + File_Open_Lock_and_Check flck(this, SFG::ACCESSOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -1382,14 +1217,14 @@ TAO_END_VERSIONED_NAMESPACE_DECL TAO_BEGIN_VERSIONED_NAMESPACE_DECL -CosNaming::NamingContext_ptr TAO_Storable_Naming_Context::recreate_all( +CosNaming::NamingContext_ptr TAO_Storable_Naming_Context::recreate_all ( CORBA::ORB_ptr orb, PortableServer::POA_ptr poa, const char *poa_id, size_t context_size, int reentering, - TAO_Naming_Service_Persistence_Factory *factory, - const ACE_TCHAR *persistence_directory, + TAO_Storable_Naming_Context_Factory *cxt_factory, + TAO::Storable_Factory *pers_factory, int use_redundancy) { ACE_TRACE("recreate_all"); @@ -1408,20 +1243,18 @@ CosNaming::NamingContext_ptr TAO_Storable_Naming_Context::recreate_all( make_new_context (orb, poa, poa_id, - context_size, - factory, - persistence_directory, + cxt_factory, + pers_factory, &new_context); // Now does this already exist on disk? - ACE_TString file_name(persistence_directory); - file_name += ACE_TEXT("/"); - file_name += ACE_TEXT_CHAR_TO_TCHAR(poa_id); - ACE_Auto_Ptr<TAO_Storable_Base> fl (factory->create_stream(ACE_TEXT_ALWAYS_CHAR(file_name.c_str()), ACE_TEXT("r"))); - if (fl->exists()) + ACE_TString file_name = ACE_TEXT_CHAR_TO_TCHAR(poa_id); + ACE_Auto_Ptr<TAO::Storable_Base> fl ( + pers_factory->create_stream (ACE_TEXT_ALWAYS_CHAR (file_name.c_str ()), ACE_TEXT ("r"))); + if (fl->exists ()) { // Load the map from disk - File_Open_Lock_and_Check flck(new_context, "r"); + File_Open_Lock_and_Check flck (new_context, SFG::CREATE_WITH_FILE); } else { @@ -1430,15 +1263,20 @@ CosNaming::NamingContext_ptr TAO_Storable_Naming_Context::recreate_all( TAO_Storable_Bindings_Map (context_size,orb), CORBA::NO_MEMORY ()); new_context->context_ = new_context->storable_context_; - File_Open_Lock_and_Check flck(new_context, "wc"); - new_context->Write(flck.peer()); + File_Open_Lock_and_Check flck (new_context, SFG::CREATE_WITHOUT_FILE); + new_context->Write (flck.peer ()); } // build the global file name file_name += ACE_TEXT("_global"); - // Create the stream for the counter used to uniquely creat context names - gfl_.reset(factory->create_stream(ACE_TEXT_ALWAYS_CHAR(file_name.c_str()), ACE_TEXT("crw"))); + // Create the stream for the counter used to uniquely create context names + // Pass false for use_backup since access to this file is not wrapped + // around a Storable_File_Guard derived class. + gfl_.reset(pers_factory-> + create_stream (ACE_TEXT_ALWAYS_CHAR(file_name.c_str()), + ACE_TEXT("crw"), + false)); if (gfl_->open() != 0) { delete gfl_.release(); @@ -1447,13 +1285,8 @@ CosNaming::NamingContext_ptr TAO_Storable_Naming_Context::recreate_all( // get the counter from disk TAO_NS_Persistence_Global global; - *gfl_.get() >> global; - if (!gfl_.get ()->good () && - gfl_.get ()->rdstate () != TAO_Storable_Base::eofbit) - { - gfl_.get ()->clear (); - throw CORBA::INTERNAL (); - } + TAO_Storable_Naming_Context_ReaderWriter rw(*gfl_.get()); + rw.read_global(global); gcounter_ = global.counter(); if(redundant_) gfl_->close(); diff --git a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.h b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.h index fe4d33ae149..9d28d4d4c31 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.h +++ b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.h @@ -15,6 +15,7 @@ #include /**/ "ace/pre.h" #include "orbsvcs/Naming/Hash_Naming_Context.h" +#include "tao/Storable_File_Guard.h" #include "ace/Hash_Map_Manager.h" #include "ace/Auto_Ptr.h" @@ -26,6 +27,14 @@ TAO_BEGIN_VERSIONED_NAMESPACE_DECL +namespace TAO +{ + class Storable_Base; + class Storable_Factory; +} + +class TAO_Storable_Naming_Context_Factory; + class TAO_Naming_Serv_Export TAO_Storable_IntId { public: @@ -229,8 +238,8 @@ public: TAO_Storable_Naming_Context (CORBA::ORB_ptr orb, PortableServer::POA_ptr poa, const char *poa_id, - TAO_Naming_Service_Persistence_Factory *factory, - const ACE_TCHAR *persistence_directory, + TAO_Storable_Naming_Context_Factory *cxt_factory, + TAO::Storable_Factory *factory, size_t hash_table_size = ACE_DEFAULT_MAP_SIZE); /// Destructor. @@ -247,22 +256,21 @@ public: static CosNaming::NamingContext_ptr make_new_context ( CORBA::ORB_ptr orb, PortableServer::POA_ptr poa, - const char *poa_id, - size_t context_size, - TAO_Naming_Service_Persistence_Factory *factory, - const ACE_TCHAR *persistence_directory, + const char *context_id, + TAO_Storable_Naming_Context_Factory *cxt_factory, + TAO::Storable_Factory *pers_factory, TAO_Storable_Naming_Context **new_context); // = Methods not implemented in TAO_Hash_Naming_Context. - static CosNaming::NamingContext_ptr recreate_all( + static CosNaming::NamingContext_ptr recreate_all ( CORBA::ORB_ptr orb, PortableServer::POA_ptr poa, - const char *poa_id, + const char *context_id, size_t context_size, int reentering, - TAO_Naming_Service_Persistence_Factory *factory, - const ACE_TCHAR *persistence_directory, + TAO_Storable_Naming_Context_Factory *cxt_factory, + TAO::Storable_Factory *pers_factory, int use_redundancy); @@ -353,6 +361,21 @@ public: protected: + /** + * An internal callback invoked by the File_Open_Lock_and_Check object to + * signal that this context was updated and written to disk. + * This will have been done after the file is closed. Check the + * last_changed_ attribute for the time of the write. + */ + virtual 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); + /// Global counter used for generation of POA ids for children Naming /// Contexts. static ACE_UINT32 gcounter_; @@ -371,11 +394,16 @@ protected: CORBA::ORB_var orb_; - ACE_CString name_; + /// The name of the context used as its object id when registered + /// with the POA. + ACE_CString context_name_; + /// The POA that this context was registered with. PortableServer::POA_var poa_; - TAO_Naming_Service_Persistence_Factory *factory_; + TAO_Storable_Naming_Context_Factory *context_factory_; + + TAO::Storable_Factory *factory_; /// The directory in which to store the files ACE_CString persistence_directory_; @@ -386,73 +414,72 @@ protected: /// Disk time that match current memory state time_t last_changed_; - /// Flag to tell use whether we are redundant or not + /// Flag to tell us whether we are redundant or not static int redundant_; static const char * root_name_; /// The pointer to the global file used to allocate new contexts - static ACE_Auto_Ptr<TAO_Storable_Base> gfl_; + static ACE_Auto_Ptr<TAO::Storable_Base> gfl_; /** * @class File_Open_Lock_and_Check * - * @brief Helper class for the TAO_Storable_Naming_Context. - * - * Guard class for the TAO_Storable_Naming_Context. It opens - * a file for read/write and sets a lock on it. It then checks - * if the file has changed and re-reads it if it has. + * @brief File guard specific for storable naming contexts. * - * The destructor insures that the lock gets released. - * - * <pre> - * How to use this class: - * File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw"); - * </pre> */ -class File_Open_Lock_and_Check +class TAO_Naming_Serv_Export File_Open_Lock_and_Check : +public TAO::Storable_File_Guard { public: /// Constructor - we always need the object which we guard. - File_Open_Lock_and_Check(TAO_Storable_Naming_Context * context, - const char * mode); + File_Open_Lock_and_Check (TAO_Storable_Naming_Context * context, + Method_Type method_type); + + ~File_Open_Lock_and_Check (); + +protected: + + /// Check if the guarded object is current with the last + /// update which could have been performed independently of + /// the owner of this object. + virtual bool object_obsolete (void); + + /// Mark the object as current with respect to the + /// file to which it was persisted. + virtual void mark_object_current (void); - /// Destructor - ~File_Open_Lock_and_Check(void); + /// Mark the time at which the object was modified and + virtual void set_object_last_changed (const time_t & time); - /// Releases the lock, closes the file, and deletes the I/O stream. - void release(void); + /// Get the time which the object was last written to the + /// file. + virtual time_t get_object_last_changed (); - /// Returns the stream to read/write on - TAO_Storable_Base & peer(void); + virtual void load_from_stream (); + + virtual bool is_loaded_from_stream (); + + virtual TAO::Storable_Base * create_stream (const char * mode); private: /// Default constructor File_Open_Lock_and_Check(void); - /// A flag to keep us from trying to close things more than once. - int closed_; - - /// We need to save the pointer to our parent for cleaning up TAO_Storable_Naming_Context * context_; - /// The pointer to the actual file I/O (bridge pattern) - TAO_Storable_Base *fl_; - - /// The flags that we were opened with - int rwflags_; - - /// Symbolic values for the flags in the above - enum{ mode_write = 1, mode_read = 2, mode_create = 4 }; }; // end of embedded class File_Open_Lock_and_Check friend class File_Open_Lock_and_Check; + friend class TAO_Storable_Naming_Context_ReaderWriter; - int load_map(File_Open_Lock_and_Check *flck); + int load_map(TAO::Storable_Base& storable); - void Write(TAO_Storable_Base& wrtr); + void Write(TAO::Storable_Base& wrtr); + /// Is set by the Write operation. Used to determine + int write_occurred_; }; TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_Activator.cpp b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_Activator.cpp index 5f5f31a4530..28a52a40254 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_Activator.cpp +++ b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_Activator.cpp @@ -14,26 +14,29 @@ #if (TAO_HAS_MINIMUM_POA == 0) && !defined (CORBA_E_COMPACT) && !defined (CORBA_E_MICRO) #include "orbsvcs/Naming/Naming_Context_Interface.h" #include "orbsvcs/Naming/Storable_Naming_Context.h" +#include "orbsvcs/Naming/Storable_Naming_Context_Factory.h" #include "orbsvcs/Naming/Storable.h" +#include "tao/Storable_Factory.h" #include "ace/Auto_Ptr.h" TAO_BEGIN_VERSIONED_NAMESPACE_DECL TAO_Storable_Naming_Context_Activator::TAO_Storable_Naming_Context_Activator ( CORBA::ORB_ptr orb, - TAO_Naming_Service_Persistence_Factory *factory, - const ACE_TCHAR *persistence_directory, - size_t context_size) + TAO::Storable_Factory *persistence_factory, + TAO_Storable_Naming_Context_Factory *context_impl_factory, + const ACE_TCHAR *persistence_directory) : orb_(orb), - factory_(factory), - persistence_directory_(persistence_directory), - context_size_(context_size) + persistence_factory_(persistence_factory), + context_impl_factory_(context_impl_factory), + persistence_directory_(persistence_directory) { } TAO_Storable_Naming_Context_Activator::~TAO_Storable_Naming_Context_Activator () { - delete factory_; + delete persistence_factory_; + delete this->context_impl_factory_; } PortableServer::Servant @@ -43,7 +46,10 @@ TAO_Storable_Naming_Context_Activator::incarnate ( { // Make sure complete initialization has been done - ACE_ASSERT (factory_ != 0); + ACE_ASSERT (persistence_factory_ != 0); + + // Make sure complete initialization has been done + ACE_ASSERT (context_impl_factory_ != 0); CORBA::String_var poa_id = PortableServer::ObjectId_to_string (oid); @@ -53,29 +59,25 @@ TAO_Storable_Naming_Context_Activator::incarnate ( // context is accessed it will be determined that the contents of // the persistence elment needs to be read in. - // Does this already exist on disk? - ACE_TString file_name(persistence_directory_); - file_name += ACE_TEXT("/"); - file_name += ACE_TEXT_CHAR_TO_TCHAR(poa_id.in()); - TAO_Storable_Base * fl = factory_->create_stream(ACE_TEXT_ALWAYS_CHAR(file_name.c_str()), ACE_TEXT("rw")); - if (!fl->exists()) { - throw CORBA::OBJECT_NOT_EXIST (); - } + { // Does this already exist on disk? - // Store the stub we will return here. - CosNaming::NamingContext_var result (CosNaming::NamingContext::_nil()); + ACE_TString file_name = ACE_TEXT_CHAR_TO_TCHAR (poa_id.in ()); + ACE_Auto_Ptr<TAO::Storable_Base> fl ( + persistence_factory_->create_stream (ACE_TEXT_ALWAYS_CHAR (file_name.c_str ()), + ACE_TEXT ("rw"))); - // Put together a servant for the new Naming Context. + if (!fl->exists()) { + throw CORBA::OBJECT_NOT_EXIST (); + } + } - TAO_Storable_Naming_Context *context_impl = 0; - ACE_NEW_THROW_EX (context_impl, - TAO_Storable_Naming_Context (orb_, - poa, - poa_id.in (), - factory_, - persistence_directory_, - context_size_), - CORBA::NO_MEMORY ()); + // Put together a servant for the new Naming Context. + // Will throw NO_MEMORY exception if unable to construct one + TAO_Storable_Naming_Context *context_impl = + this->context_impl_factory_->create_naming_context_impl (orb_, + poa, + poa_id.in (), + persistence_factory_); // Put <context_impl> into the auto pointer temporarily, in case next // allocation fails. diff --git a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_Activator.h b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_Activator.h index d4770ed1c60..d7cbfeb79ba 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_Activator.h +++ b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_Activator.h @@ -26,7 +26,12 @@ TAO_BEGIN_VERSIONED_NAMESPACE_DECL -class TAO_Naming_Service_Persistence_Factory; +namespace TAO +{ + class Storable_Factory; +} + +class TAO_Storable_Naming_Context_Factory; /** * A servant activator to be use with a TAO_Storable_Naming_Context. @@ -43,10 +48,11 @@ public: * The constructor takes arguments needed to create a * TAO_Storable_Naming_Context and TAO_Naming_Context on demand. */ - TAO_Storable_Naming_Context_Activator(CORBA::ORB_ptr orb, - TAO_Naming_Service_Persistence_Factory *factory, - const ACE_TCHAR *persistence_directory, - size_t context_size); + TAO_Storable_Naming_Context_Activator ( + CORBA::ORB_ptr orb, + TAO::Storable_Factory *factory, + TAO_Storable_Naming_Context_Factory *context_impl_factory, + const ACE_TCHAR *persistence_directory); virtual ~TAO_Storable_Naming_Context_Activator(); @@ -70,9 +76,14 @@ public: private: CORBA::ORB_ptr orb_; - TAO_Naming_Service_Persistence_Factory *factory_; + + /// The factory for constructing the persistence mechanism for the contexts + TAO::Storable_Factory *persistence_factory_; + + /// The factory for constructing naming contexts within the index + TAO_Storable_Naming_Context_Factory *context_impl_factory_; + const ACE_TCHAR *persistence_directory_; - size_t context_size_; }; TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_Factory.cpp b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_Factory.cpp new file mode 100644 index 00000000000..78a91dd1a57 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_Factory.cpp @@ -0,0 +1,49 @@ +// $Id$ + +#include "orbsvcs/Naming/Storable_Naming_Context_Factory.h" +#include "orbsvcs/Naming/Storable_Naming_Context.h" + +#include "tao/Storable_Factory.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +/// Constructor. +TAO_Storable_Naming_Context_Factory::TAO_Storable_Naming_Context_Factory ( + size_t hash_table_size) +: context_size_(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_Storable_Naming_Context_Factory::~TAO_Storable_Naming_Context_Factory (void) +{ + +} + + +TAO_Storable_Naming_Context* +TAO_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_Storable_Naming_Context *context_impl; + ACE_NEW_THROW_EX (context_impl, + TAO_Storable_Naming_Context (orb, + poa, + poa_id, + this, + persistence_factory, + this->context_size_), + CORBA::NO_MEMORY ()); + + return context_impl; +} + + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_Factory.h b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_Factory.h new file mode 100644 index 00000000000..748bd60f772 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_Factory.h @@ -0,0 +1,72 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Storable_Naming_Context_Factory.h + * + * $Id$ + * + * @author Kevin Stanley stanleyk@ociweb.com> + */ +//============================================================================= + + +#ifndef TAO_STORABLE_NAMING_CONTEXT_FACTORY_H +#define TAO_STORABLE_NAMING_CONTEXT_FACTORY_H +#include /**/ "ace/pre.h" + +#include "tao/ORB.h" +#include "orbsvcs/Naming/nsconf.h" +#include "orbsvcs/Naming/naming_serv_export.h" +#include "orbsvcs/Naming/Hash_Naming_Context.h" +#include "orbsvcs/Naming/Storable_Naming_Context.h" + +namespace TAO +{ + class Storable_Factory; +} + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class TAO_Storable_Naming_Context_Factory + * + * @brief + */ +class TAO_Naming_Serv_Export TAO_Storable_Naming_Context_Factory +{ +public: + + /// Data structure used by TAO_Persistent_Context_Index + /// - typedef for ease of use. + typedef TAO_Storable_Naming_Context::HASH_MAP HASH_MAP; + + // = Initialization and termination methods. + + /// Constructor. + TAO_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_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); + +protected: + /// The size for persisted naming context objects in hash map + size_t context_size_; +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" +#endif /* TAO_STORABLE_NAMING_CONTEXT_FACTORY_H */ diff --git a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_ReaderWriter.cpp b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_ReaderWriter.cpp new file mode 100644 index 00000000000..c21b331f6d9 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_ReaderWriter.cpp @@ -0,0 +1,270 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Storable_Naming_Context_ReaderWriter.cpp + * + * $Id$ + * + * @author Marina Spivak <marina@cs.wustl.edu> + * @author Byron Harris <harrisb@ociweb.com> + */ +//============================================================================= + +#include "orbsvcs/Naming/Storable_Naming_Context_ReaderWriter.h" +#include "orbsvcs/Naming/Storable_Naming_Context.h" +#include "orbsvcs/Naming/Storable.h" + +#include "tao/Storable_Base.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_Storable_Naming_Context_ReaderWriter:: +TAO_Storable_Naming_Context_ReaderWriter (TAO::Storable_Base & stream) + : stream_(stream) +{ +} + +void +TAO_Storable_Naming_Context_ReaderWriter::write (TAO_Storable_Naming_Context & context) +{ + TAO_NS_Persistence_Header header; + + header.size (static_cast<unsigned int> (context.storable_context_->current_size())); + header.destroyed (context.destroyed_); + + this->write_header(header); + + if (0u == header.size ()) + return; + + ACE_Hash_Map_Iterator<TAO_Storable_ExtId,TAO_Storable_IntId, + ACE_Null_Mutex> it = context.storable_context_->map().begin(); + ACE_Hash_Map_Iterator<TAO_Storable_ExtId,TAO_Storable_IntId, + ACE_Null_Mutex> itend = context.storable_context_->map().end(); + + ACE_Hash_Map_Entry<TAO_Storable_ExtId,TAO_Storable_IntId> ent = *it; + + while (!(it == itend)) + { + TAO_NS_Persistence_Record record; + + ACE_CString name; + CosNaming::BindingType bt = (*it).int_id_.type_; + if (bt == CosNaming::ncontext) + { + CORBA::Object_var + obj = context.orb_->string_to_object ((*it).int_id_.ref_.in ()); + if (obj->_is_collocated ()) + { + // This is a local (i.e. non federated context) we therefore + // store only the ObjectID (persistence filename) for the object. + + // The driving force behind storing ObjectIDs rather than IORs for + // local contexts is to provide for a redundant naming service. + // That is, a naming service that runs simultaneously on multiple + // machines sharing a file system. It allows multiple redundant + // copies to be started and stopped independently. + // The original target platform was Tru64 Clusters where there was + // a cluster address. In that scenario, clients may get different + // servers on each request, hence the requirement to keep + // synchronized to the disk. It also works on non-cluster system + // where the client picks one of the redundant servers and uses it, + // while other systems can pick different servers. (However in this + // scenario, if a server fails and a client must pick a new server, + // that client may not use any saved context IORs, instead starting + // from the root to resolve names. So this latter mode is not quite + // transparent to clients.) [Rich Seibel (seibel_r) of ociweb.com] + + PortableServer::ObjectId_var + oid = context.poa_->reference_to_id (obj.in ()); + CORBA::String_var + nm = PortableServer::ObjectId_to_string (oid.in ()); + const char + *newname = nm.in (); + name.set (newname); // The local ObjectID (persistance filename) + record.type (TAO_NS_Persistence_Record::LOCAL_NCONTEXT); + } + else + { + // Since this is a foreign (federated) context, we can not store + // the objectID (because it isn't in our storage), if we did, when + // we restore, we would end up either not finding a permanent + // record (and thus ending up incorrectly assuming the context was + // destroyed) or loading another context altogether (just because + // the contexts shares its objectID filename which is very likely). + // [Simon Massey (sma) of prismtech.com] + + name.set ((*it).int_id_.ref_.in ()); // The federated context IOR + record.type (TAO_NS_Persistence_Record::REMOTE_NCONTEXT); + } + } + else // if (bt == CosNaming::nobject) // shouldn't be any other, can there? + { + name.set ((*it).int_id_.ref_.in ()); // The non-context object IOR + record.type (TAO_NS_Persistence_Record::OBJREF); + } + record.ref(name); + + const char *myid = (*it).ext_id_.id(); + ACE_CString id(myid); + record.id(id); + + const char *mykind = (*it).ext_id_.kind(); + ACE_CString kind(mykind); + record.kind(kind); + + write_record (record); + it.advance(); + } + + context.write_occurred_ = 1; +} + +int +TAO_Storable_Naming_Context_ReaderWriter::read (TAO_Storable_Naming_Context & context) +{ + // assume file already open for reading + TAO_Storable_Bindings_Map *bindings_map; + + // create the new bindings map + ACE_NEW_THROW_EX (bindings_map, + TAO_Storable_Bindings_Map (context.hash_table_size_, context.orb_.in()), + CORBA::NO_MEMORY ()); + + // get the data for this bindings map from the file + + TAO_NS_Persistence_Header header; + TAO_NS_Persistence_Record record; + + // we are only using the size from this header + this->read_header(header); + + // reset the destroyed flag + context.destroyed_ = header.destroyed(); + + // read in the data for the map + for (unsigned int i= 0u; i<header.size(); ++i) + { + this->read_record(record); + + if (TAO_NS_Persistence_Record::LOCAL_NCONTEXT == record.type ()) + { + PortableServer::ObjectId_var + id = PortableServer::string_to_ObjectId (record.ref ().c_str ()); + const char + *intf = context.interface_->_interface_repository_id (); + CORBA::Object_var + objref = context.poa_->create_reference_with_id (id.in (), intf); + bindings_map->bind ( record.id ().c_str (), + record.kind ().c_str (), + objref.in (), + CosNaming::ncontext ); + } + else + { + CORBA::Object_var + objref = context.orb_->string_to_object (record.ref ().c_str ()); + bindings_map->bind ( record.id ().c_str (), + record.kind ().c_str (), + objref.in (), + ((TAO_NS_Persistence_Record::REMOTE_NCONTEXT == record.type ()) + ? CosNaming::ncontext // REMOTE_NCONTEXT + : CosNaming::nobject )); // OBJREF + } + } + context.storable_context_ = bindings_map; + context.context_ = context.storable_context_; + return 0; +} + +void +TAO_Storable_Naming_Context_ReaderWriter::write_header (const TAO_NS_Persistence_Header & header) +{ + stream_.rewind(); + stream_ << header.size(); + stream_ << header.destroyed(); + stream_.flush(); +} +void +TAO_Storable_Naming_Context_ReaderWriter::read_header (TAO_NS_Persistence_Header & header) +{ + unsigned int size; + int destroyed; + + stream_.rewind(); + + stream_ >> size; + header.size(size); + + stream_ >> destroyed; + header.destroyed(destroyed); +} + +void +TAO_Storable_Naming_Context_ReaderWriter::write_record (const TAO_NS_Persistence_Record & record) +{ + TAO_NS_Persistence_Record::Record_Type type = record.type(); + stream_ << type; + + stream_ << record.id(); + stream_ << record.kind(); + stream_ << record.ref(); + + stream_.flush(); +} + +void +TAO_Storable_Naming_Context_ReaderWriter::read_record (TAO_NS_Persistence_Record & record) +{ + int temp_type_in; + stream_ >> temp_type_in; + TAO_NS_Persistence_Record::Record_Type type = + (TAO_NS_Persistence_Record::Record_Type) temp_type_in; + record.type (type); + + ACE_CString record_id; + stream_ >> record_id; + record.id (record_id); + + ACE_CString record_kind; + stream_ >> record_kind; + record.kind (record_kind); + + ACE_CString record_ref; + stream_ >> record_ref; + record.ref (record_ref); +} + +void +TAO_Storable_Naming_Context_ReaderWriter::write_global (const TAO_NS_Persistence_Global & global) +{ + stream_.rewind(); + stream_ << global.counter(); + stream_.flush(); +} + +void +TAO_Storable_Naming_Context_ReaderWriter::read_global (TAO_NS_Persistence_Global + & global) +{ + unsigned int counter = 0; + + stream_.rewind(); + // We expect an exception to be thrown with EOF state if the file is empty. + try + { + stream_ >> counter; + } + catch (TAO::Storable_Read_Exception &ex) + { + if (ex.get_state() != TAO::Storable_Base::goodbit && + ex.get_state() != TAO::Storable_Base::eofbit) + throw CORBA::INTERNAL (); + } + + global.counter(counter); + +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_ReaderWriter.h b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_ReaderWriter.h new file mode 100644 index 00000000000..e0c06856ae3 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_ReaderWriter.h @@ -0,0 +1,64 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Storable_Naming_Context_ReaderWriter.h + * + * $Id$ + * + * @author Marina Spivak <marina@cs.wustl.edu> + * @author Byron Harris <harrisb@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_STORABLE_NAMING_CONTEXT_READERWRITER_H +#define TAO_STORABLE_NAMING_CONTEXT_READERWRITER_H + +#include /**/ "ace/pre.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/orbconf.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace TAO +{ + class Storable_Base; +} + +class TAO_Storable_Naming_Context; +class TAO_NS_Persistence_Record; +class TAO_NS_Persistence_Header; +class TAO_NS_Persistence_Global; + +class TAO_Storable_Naming_Context_ReaderWriter +{ +public: + + TAO_Storable_Naming_Context_ReaderWriter (TAO::Storable_Base & stream); + + int read (TAO_Storable_Naming_Context & context); + + void write (TAO_Storable_Naming_Context & context); + + void write_global (const TAO_NS_Persistence_Global & global); + void read_global (TAO_NS_Persistence_Global & global); + +private: + + void write_header (const TAO_NS_Persistence_Header & header); + void read_header (TAO_NS_Persistence_Header & header); + + void write_record (const TAO_NS_Persistence_Record & record); + void read_record (TAO_NS_Persistence_Record & record); + + TAO::Storable_Base &stream_; +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" +#endif /* TAO_STORABLE_NAMING_CONTEXT_READERWRITER_H */ diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Factory.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Factory.cpp index fc10e0bb552..3ea3d1ee299 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Factory.cpp +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Factory.cpp @@ -7,24 +7,56 @@ * $Id$ * * @author Dale Wilson <wilson_d@ociweb.com> + * @author Byron Harris <harrisb@ociweb.com> */ //============================================================================= #include "orbsvcs/PortableGroup/PG_Group_Factory.h" #include "orbsvcs/PortableGroup/PG_Property_Utils.h" +#include "orbsvcs/PortableGroup/PG_Group_List_Store.h" #include "orbsvcs/PortableGroup/PG_conf.h" #include "orbsvcs/PortableGroupC.h" #include "orbsvcs/PortableGroup/PG_Object_Group.h" +#include "orbsvcs/PortableGroup/PG_Object_Group_Storable.h" #include <orbsvcs/PortableGroup/PG_Utils.h> +#include "tao/Storable_Factory.h" + +#include <ace/SString.h> + TAO_BEGIN_VERSIONED_NAMESPACE_DECL +namespace +{ + // Find the elements in set1 that + // are missing in set2. + template <class T> + void + find_missing(const std::set<T> & set1, + const std::set<T> & set2, + std::set<T> & missing_in_2) + { + missing_in_2.clear(); + for (typename std::set<T>::const_iterator it = set1.begin(); + it != set1.end(); ++it) + { + if (set2.find(*it) == set2.end()) + { + missing_in_2.insert(*it); + } + } + } +} + TAO::PG_Group_Factory::PG_Group_Factory () - : orb_ (CORBA::ORB::_nil()) + : use_persistence_ (false) + , list_store_ (0) + , orb_ (CORBA::ORB::_nil()) , poa_ (PortableServer::POA::_nil()) , manipulator_ () - , domain_id_ ("default-domain") - + , domain_id_ (ACE_TEXT_ALWAYS_CHAR ("default-domain")) + , groups_read_ (false) + , storable_factory_ (0) { } @@ -38,6 +70,8 @@ TAO::PG_Group_Factory::~PG_Group_Factory (void) delete group; } this->group_map_.unbind_all (); + delete this->list_store_; + delete this->storable_factory_; } @@ -52,7 +86,9 @@ void TAO::PG_Group_Factory::init ( this->orb_ = CORBA::ORB::_duplicate(orb); this->poa_ = PortableServer::POA::_duplicate (poa); - this->factory_registry_ = PortableGroup::FactoryRegistry::_duplicate (factory_registry); + + this->factory_registry_ = + PortableGroup::FactoryRegistry::_duplicate (factory_registry); ACE_ASSERT (!CORBA::is_nil (this->orb_.in ())); @@ -72,11 +108,25 @@ TAO::PG_Object_Group * TAO::PG_Group_Factory::create_group ( // Create an empty group reference PortableGroup::ObjectGroupId group_id = 0; - PortableGroup::ObjectGroup_var empty_group = - this->manipulator_.create_object_group ( - type_id, - this->domain_id_, - group_id); + PortableGroup::ObjectGroup_var empty_group; + + if (this->use_persistence_) + { + group_id = this->list_store_->get_next_group_id (); + empty_group = + this->manipulator_.create_object_group_using_id ( + type_id, + this->domain_id_, + group_id); + } + else + { + empty_group = + this->manipulator_.create_object_group ( + type_id, + this->domain_id_, + group_id); + } // pick up the object group information as assigned by // ObjectGroupManager @@ -89,19 +139,37 @@ TAO::PG_Object_Group * TAO::PG_Group_Factory::create_group ( TAO::PG_Object_Group * objectGroup = 0; - ACE_NEW_THROW_EX ( - objectGroup, - TAO::PG_Object_Group ( - this->orb_.in (), - this->factory_registry_.in (), - this->manipulator_, - empty_group.in (), - tagged_component, - type_id, - the_criteria, - typeid_properties - ), - CORBA::NO_MEMORY()); + if (this->use_persistence_) + { + objectGroup = this->create_persistent_group ( + this->orb_.in (), + this->factory_registry_.in (), + this->manipulator_, + empty_group.in (), + tagged_component, + type_id, + the_criteria, + typeid_properties, + *storable_factory_); + + this->list_store_->add(group_id); + } + else + { + ACE_NEW_THROW_EX ( + objectGroup, + TAO::PG_Object_Group ( + this->orb_.in (), + this->factory_registry_.in (), + this->manipulator_, + empty_group.in (), + tagged_component, + type_id, + the_criteria, + typeid_properties + ), + CORBA::NO_MEMORY()); + } if (this->group_map_.bind (group_id, objectGroup) != 0) { @@ -111,7 +179,8 @@ TAO::PG_Object_Group * TAO::PG_Group_Factory::create_group ( return objectGroup; } -void TAO::PG_Group_Factory::delete_group (PortableGroup::ObjectGroup_ptr object_group) +void TAO::PG_Group_Factory::delete_group ( + PortableGroup::ObjectGroup_ptr object_group) { if (! destroy_group (object_group)) { @@ -120,7 +189,8 @@ void TAO::PG_Group_Factory::delete_group (PortableGroup::ObjectGroup_ptr object_ } -void TAO::PG_Group_Factory::delete_group (PortableGroup::ObjectGroupId group_id) +void TAO::PG_Group_Factory::delete_group ( + PortableGroup::ObjectGroupId group_id) { if (! destroy_group (group_id)) { @@ -134,17 +204,20 @@ int TAO::PG_Group_Factory::insert_group ( ::TAO::PG_Object_Group * group) return insert_group (group->get_object_group_id(), group); } -int TAO::PG_Group_Factory::insert_group (PortableGroup::ObjectGroupId group_id, ::TAO::PG_Object_Group * group) +int TAO::PG_Group_Factory::insert_group (PortableGroup::ObjectGroupId group_id, + ::TAO::PG_Object_Group * group) { - return (this->group_map_.bind (group_id, group) == 0); + return (this->get_group_map ().bind (group_id, group) == 0); } -int TAO::PG_Group_Factory::find_group (PortableGroup::ObjectGroupId group_id, ::TAO::PG_Object_Group *& group) const +int TAO::PG_Group_Factory::find_group (PortableGroup::ObjectGroupId group_id, + ::TAO::PG_Object_Group *& group) { - return (this->group_map_.find (group_id , group) == 0); + return (this->get_group_map ().find (group_id , group) == 0); } -int TAO::PG_Group_Factory::find_group (PortableGroup::ObjectGroup_ptr object_group, ::TAO::PG_Object_Group *& group) const +int TAO::PG_Group_Factory::find_group (PortableGroup::ObjectGroup_ptr object_group, + ::TAO::PG_Object_Group *& group) { int result = 0; PortableGroup::TagGroupTaggedComponent tc; @@ -155,13 +228,49 @@ int TAO::PG_Group_Factory::find_group (PortableGroup::ObjectGroup_ptr object_gro return result; } +int TAO::PG_Group_Factory::find_group_with_name (const char* target_group_name, + TAO::PG_Object_Group *& group_target) +{ + int result = 0; + + // Search through the group map for the group with that property + Group_Map & group_map = this->get_group_map (); + for (Group_Map_Iterator it = group_map.begin (); + it != group_map.end (); + ++it) + { + TAO::PG_Object_Group * a_group = (*it).int_id_; + // If the group has the group name in the property + // + const char* a_group_name = a_group->get_name (); + if (a_group_name != 0 && + ACE_OS::strcmp (target_group_name, + a_group_name) == 0) + { // This is the group we were looking for + group_target = a_group; + result = 1; + break; + } + } + return result; +} + int TAO::PG_Group_Factory::destroy_group (PortableGroup::ObjectGroupId group_id) { ::TAO::PG_Object_Group * group = 0; - int result = (this->group_map_.unbind (group_id, group) == 0); + int result = (this->get_group_map ().unbind (group_id, group) == 0); if (result) { - delete group; + if (this->use_persistence_) + { + PG_Object_Group_Storable *og = + dynamic_cast<PG_Object_Group_Storable *> (group); + og->set_destroyed (true); + result = (this->list_store_->remove (group->get_object_group_id ()) + == 0); + } + if (result) + delete group; } return result; } @@ -179,7 +288,8 @@ PortableGroup::ObjectGroups * TAO::PG_Group_Factory::groups_at_location ( const PortableGroup::Location & the_location) { - size_t upper_limit = this->group_map_.current_size (); + Group_Map & group_map = this->get_group_map (); + size_t upper_limit = group_map.current_size (); PortableGroup::ObjectGroups * result = 0; ACE_NEW_THROW_EX ( result, @@ -189,8 +299,8 @@ TAO::PG_Group_Factory::groups_at_location ( result->length(upper_limit); size_t group_count = 0; - for (Group_Map_Iterator it = this->group_map_.begin (); - it != this->group_map_.end (); + for (Group_Map_Iterator it = group_map.begin (); + it != group_map.end (); ++it) { TAO::PG_Object_Group * group = (*it).int_id_; @@ -204,4 +314,171 @@ TAO::PG_Group_Factory::groups_at_location ( return result; } +PortableGroup::ObjectGroups * +TAO::PG_Group_Factory::all_groups (void) +{ + Group_Map & group_map = this->get_group_map (); + size_t upper_limit = group_map.current_size (); + PortableGroup::ObjectGroups * result = 0; + ACE_NEW_THROW_EX ( + result, + PortableGroup::ObjectGroups (upper_limit), + CORBA::NO_MEMORY()); + + result->length(upper_limit); + + size_t group_count = 0; + for (Group_Map_Iterator it = group_map.begin (); + it != group_map.end (); + ++it) + { + TAO::PG_Object_Group * group = (*it).int_id_; + (*result)[group_count] = CORBA::Object::_duplicate(group->reference ()); + ++group_count; + } + result->length (group_count); + return result; +} + +void +TAO::PG_Group_Factory::set_object_group_storable_factory ( + TAO::Storable_Factory * factory) +{ + this->use_persistence_ = true; + this->storable_factory_ = factory; + ACE_NEW_THROW_EX (this->list_store_, + TAO::PG_Group_List_Store (*this->storable_factory_), + CORBA::NO_MEMORY ()); + +} + +TAO::PG_Group_Factory::Group_Map & +TAO::PG_Group_Factory::get_group_map () +{ + if (this->use_persistence_) + { + // List of groups in persistent store may + // have changed since group_map_ was last + // updated. + + if (!this->groups_read_ || this->list_store_->list_obsolete ()) + { + // Extract IDs from group_map_ to set for comparison with IDs in persistent store + // This is to avoid having to repopulate the map from scratch. + PG_Group_List_Store::Group_Ids map_ids; + for (Group_Map_Iterator it = group_map_.begin (); + it != group_map_.end (); ++it) + { + map_ids.insert (it->key ()); + } + + // Get the latest groups from persistent store + const PG_Group_List_Store::Group_Ids & persistent_ids = + list_store_->get_group_ids (); + + // Find groups added since map was last updated + PG_Group_List_Store::Group_Ids groups_added; + find_missing (persistent_ids, map_ids, groups_added); + + // Find groups removed since map was last updated + PG_Group_List_Store::Group_Ids groups_removed; + find_missing (map_ids, persistent_ids, groups_removed); + + // Bind added groups + for (PG_Group_List_Store::Group_Id_Const_Iterator it = groups_added.begin (); + it != groups_added.end (); ++it) + { + PortableGroup::ObjectGroupId group_id = *it; + TAO::PG_Object_Group * objectGroup = 0; + objectGroup = this->restore_persistent_group ( + group_id, + this->orb_.in (), + this->factory_registry_.in (), + this->manipulator_, + *storable_factory_); + + if (this->group_map_.bind (group_id, objectGroup) != 0) + { + delete objectGroup; + throw PortableGroup::ObjectNotCreated (); + } + } + + // Unbind removed groups + for (PG_Group_List_Store::Group_Id_Const_Iterator it = groups_removed.begin (); + it != groups_removed.end (); ++it) + { + PortableGroup::ObjectGroupId group_id = *it; + PG_Object_Group * group = 0; + int result = (this->get_group_map ().unbind (group_id, group) == 0); + if (result) + { + delete group; + } + else + throw PortableGroup::ObjectGroupNotFound (); + } + + this->groups_read_ = true; + + } + + } + + return group_map_; +} + +TAO::PG_Object_Group_Storable * +TAO::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::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::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::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/PortableGroup/PG_Group_Factory.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Factory.h index 950513257e7..540d2bcd3b8 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Factory.h +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Factory.h @@ -7,6 +7,7 @@ * $Id$ * * @author Dale Wilson <wilson_d@ociweb.com> + * @author Byron Harris <harrisb@ociweb.com> */ //============================================================================= @@ -22,7 +23,6 @@ #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "orbsvcs/PortableGroup/PG_Object_Group_Manipulator.h" - #include "orbsvcs/PortableGroupC.h" #include "tao/PortableServer/PortableServer.h" @@ -34,11 +34,14 @@ TAO_BEGIN_VERSIONED_NAMESPACE_DECL ////////////////// -// Forward reference +// Forward references namespace TAO { class PG_Property_Set; -} // namespace TAO_PG + class PG_Group_List_Store; + class PG_Object_Group_Storable; + class Storable_Factory; +} namespace TAO { @@ -53,14 +56,16 @@ namespace TAO { //////////////////////////////////////////////////////////// // typedef private implementation classes - typedef ACE_Hash_Map_Manager_Ex< + typedef ACE_Hash_Map_Manager_Ex < PortableGroup::ObjectGroupId, ::TAO::PG_Object_Group *, ACE_Hash<ACE_UINT64>, ACE_Equal_To<ACE_UINT64>, TAO_SYNCH_MUTEX> Group_Map; - typedef ACE_Hash_Map_Entry <PortableGroup::ObjectGroupId, ::TAO::PG_Object_Group *> Group_Map_Entry; + typedef ACE_Hash_Map_Entry < + PortableGroup::ObjectGroupId, + ::TAO::PG_Object_Group *> Group_Map_Entry; typedef ACE_Hash_Map_Iterator_Ex < PortableGroup::ObjectGroupId, @@ -75,7 +80,7 @@ namespace TAO PG_Group_Factory (); /// Destructor. - ~PG_Group_Factory (); + virtual ~PG_Group_Factory (); void init ( CORBA::ORB_ptr orb, @@ -98,6 +103,11 @@ namespace TAO groups_at_location ( const PortableGroup::Location & the_location); + /** + * return all groups in the factory + */ + PortableGroup::ObjectGroups * + all_groups (void); /** @@ -105,26 +115,40 @@ namespace TAO * note: uses group id extracted from group object * @return bool true if insertion successful */ - int insert_group ( ::TAO::PG_Object_Group * group); + int insert_group (::TAO::PG_Object_Group * group); /** * insert group. Take ownership * @return bool true if insertion successful */ - int insert_group (PortableGroup::ObjectGroupId group_id, ::TAO::PG_Object_Group * group); + int insert_group ( + PortableGroup::ObjectGroupId group_id, + ::TAO::PG_Object_Group * group); /** * find group * @return bool true if found */ - int find_group (PortableGroup::ObjectGroupId group_id, ::TAO::PG_Object_Group *& group) const; + int find_group ( + PortableGroup::ObjectGroupId group_id, + ::TAO::PG_Object_Group *& group); /** * find group * note: uses group id extracted from object_group * @return bool true if found */ - int find_group (PortableGroup::ObjectGroup_ptr object_group, ::TAO::PG_Object_Group *& group) const; + int find_group ( + PortableGroup::ObjectGroup_ptr object_group, + ::TAO::PG_Object_Group *& group); + + /** + * find group with the property with the designated value + * @return bool true if found + */ + int find_group_with_name ( + const char* group_name, + ::TAO::PG_Object_Group *& group); /** * remove group from map and delete it. @@ -139,7 +163,42 @@ namespace TAO */ int destroy_group (PortableGroup::ObjectGroup_ptr object_group); - private: + /** + * persist internal state to file for fault tolerant purposes. + */ + void set_object_group_storable_factory (TAO::Storable_Factory * factory); + + protected: + + /** + * Factory function to create a storable object object from + * scratch. + */ + 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); + + /** + * Factory function to restore an object group from + * persistent store. + */ + 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); + + bool use_persistence_; + + PG_Group_List_Store * list_store_; private: @@ -155,8 +214,19 @@ namespace TAO const char * domain_id_; + /** + * If persistence is being used, update the map as + * necessary based on what's in the group list store. + */ + Group_Map & get_group_map (); + Group_Map group_map_; + ///// Support for object group persistent ///// + + // Lazily read groups from store + bool groups_read_; + Storable_Factory * storable_factory_; }; } // namespace TAO diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_List_Store.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_List_Store.cpp new file mode 100644 index 00000000000..97541e4c009 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_List_Store.cpp @@ -0,0 +1,289 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file PG_Group_List_Store.cpp + * + * $Id$ + * + * @author Byron Harris <harrisb@ociweb.com> + */ +//============================================================================= + + +#include "orbsvcs/PortableGroup/PG_Group_List_Store.h" + +#include "tao/Storable_Base.h" +#include "tao/Storable_Factory.h" +#include "tao/Storable_File_Guard.h" + +#include <algorithm> + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace TAO +{ + class PG_Group_List_Store_File_Guard : public TAO::Storable_File_Guard + { + public: + PG_Group_List_Store_File_Guard (PG_Group_List_Store & list_store, + Method_Type method_type); + + ~PG_Group_List_Store_File_Guard (); + + virtual void set_object_last_changed (const time_t & time); + + virtual time_t get_object_last_changed (); + + virtual bool object_obsolete (); + + virtual void mark_object_current (); + + virtual void load_from_stream (); + + virtual bool is_loaded_from_stream (); + + virtual TAO::Storable_Base * create_stream (const char * mode); + +private: + + PG_Group_List_Store & list_store_; + }; +} + +TAO::PG_Group_List_Store_File_Guard::PG_Group_List_Store_File_Guard ( + PG_Group_List_Store & list_store, Method_Type method_type) + : TAO::Storable_File_Guard(true), + list_store_(list_store) +{ + try + { + this->init (method_type); + } + catch (const TAO::Storable_Read_Exception &) + { + throw CORBA::INTERNAL (); + } +} + +TAO::PG_Group_List_Store_File_Guard::~PG_Group_List_Store_File_Guard () +{ + this->release (); +} + +void +TAO::PG_Group_List_Store_File_Guard::set_object_last_changed ( + const time_t & time) +{ + list_store_.last_changed_ = time; +} + +time_t +TAO::PG_Group_List_Store_File_Guard::get_object_last_changed () +{ + return list_store_.last_changed_; +} + +bool +TAO::PG_Group_List_Store_File_Guard::object_obsolete () +{ + return list_store_.is_obsolete (fl_->last_changed ()); +} + +void +TAO::PG_Group_List_Store_File_Guard::mark_object_current () +{ + // Reset the stale flag + list_store_.stale(false); + // Set the last update time to the file last update time + this->set_object_last_changed (fl_->last_changed ()); +} + +void +TAO::PG_Group_List_Store_File_Guard::load_from_stream () +{ + list_store_.read (this->peer ()); + list_store_.loaded_from_stream_ = true; + this->peer ().rewind (); +} + +bool +TAO::PG_Group_List_Store_File_Guard::is_loaded_from_stream () +{ + return list_store_.loaded_from_stream_; +} + +TAO::Storable_Base * +TAO::PG_Group_List_Store_File_Guard::create_stream (const char * mode) +{ + return list_store_.create_stream (mode); +} + +typedef TAO::PG_Group_List_Store_File_Guard File_Guard; + +// Make shortcut to get to Method_Type enums +typedef TAO::Storable_File_Guard SFG; + +TAO::PG_Group_List_Store::PG_Group_List_Store ( + Storable_Factory & storable_factory) + : next_group_id_ (0) + , storable_factory_ (storable_factory) + , loaded_from_stream_ (false) + , last_changed_ (0) + , stale_ (false) +{ + // Create a temporary stream simply to check if a readable + // version already exists. + bool stream_exists = false; + { + ACE_Auto_Ptr<TAO::Storable_Base> stream ( + this->create_stream (ACE_TEXT_ALWAYS_CHAR ("r"))); + + if (stream->exists ()) + stream_exists = true; + } + + if (stream_exists) + { + File_Guard fg(*this, SFG::CREATE_WITH_FILE); + } + else + { + File_Guard fg(*this, SFG::CREATE_WITHOUT_FILE); + this->write (fg.peer ()); + } +} + +TAO::PG_Group_List_Store::~PG_Group_List_Store () +{ +} + +PortableGroup::ObjectGroupId +TAO::PG_Group_List_Store::get_next_group_id () +{ + File_Guard fg(*this, SFG::ACCESSOR); + PortableGroup::ObjectGroupId next_id = this->next_group_id_; + ++this->next_group_id_; + this->write (fg.peer ()); + return next_id; +} + +int +TAO::PG_Group_List_Store::add (PortableGroup::ObjectGroupId id) +{ + File_Guard fg(*this, SFG::MUTATOR); + Group_Id_Const_Iterator it = std::find (this->group_ids_.begin (), + this->group_ids_.end (), + id); + if (it != this->group_ids_.end()) + return -1; + this->group_ids_.insert (id); + this->write (fg.peer ()); + return 0; +} + +int +TAO::PG_Group_List_Store::remove (PortableGroup::ObjectGroupId id) +{ + File_Guard fg(*this, SFG::MUTATOR); + Group_Id_Iterator it = std::find (this->group_ids_.begin (), + this->group_ids_.end (), + id); + if (it == this->group_ids_.end ()) + return -1; + this->group_ids_.erase (it); + this->write (fg.peer ()); + return 0; +} + +TAO::PG_Group_List_Store::Group_Ids & +TAO::PG_Group_List_Store::get_group_ids () +{ + File_Guard fg(*this, SFG::ACCESSOR); + return group_ids_; +} + +void +TAO::PG_Group_List_Store::read (TAO::Storable_Base & stream) +{ + group_ids_.clear (); + + stream.rewind (); + + unsigned int next_group_id; + stream >> next_group_id; + this->next_group_id_ = next_group_id; + + int size; + stream >> size; + + // TODO: Look at adding streaming of unsigned long long + // PortableGroup::ObjectGroupId group_id; + int group_id; + for (int i = 0; i < size; ++i) + { + stream >> group_id; + group_ids_.insert (group_id); + } +} + +void +TAO::PG_Group_List_Store::write (TAO::Storable_Base & stream) +{ + stream.rewind (); + + unsigned int next_group_id = static_cast<unsigned int> (this->next_group_id_); + stream << next_group_id; + + int size = group_ids_.size (); + stream << size; + for (Group_Id_Const_Iterator it = group_ids_.begin (); + it != group_ids_.end (); ++it) + { + int group_id = static_cast<int> (*it); + stream << group_id; + } + + stream.flush (); +} + +TAO::Storable_Base * +TAO::PG_Group_List_Store::create_stream (const char * mode) +{ + return this->storable_factory_.create_stream ( + ACE_TEXT_ALWAYS_CHAR ("ObjectGroup_global"), mode); +} + +bool +TAO::PG_Group_List_Store::list_obsolete () +{ + // TODO: Upate if obsolete flag is set based on CORBA call. + ACE_Auto_Ptr<TAO::Storable_Base> stream (this->create_stream ("r")); + if (!stream->exists ()) + throw CORBA::INTERNAL (); + stream->open (); + return this->is_obsolete (stream->last_changed ()); +} + +bool +TAO::PG_Group_List_Store::is_obsolete (time_t stored_time) +{ + return + (!this->loaded_from_stream_) || + this->stale () || + (stored_time > this->last_changed_); +} + +void +TAO::PG_Group_List_Store::stale (bool is_stale) +{ + this->stale_ = is_stale; +} + +bool +TAO::PG_Group_List_Store::stale () +{ + return this->stale_; +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_List_Store.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_List_Store.h new file mode 100644 index 00000000000..8801ec6598d --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_List_Store.h @@ -0,0 +1,119 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file PG_Group_List_Store.h + * + * $Id$ + * + * @author Byron Harris <harrisb@ociweb.com> + */ +//============================================================================= + +#ifndef PG_GROUP_LIST_STORE_H +#define PG_GROUP_LIST_STORE_H + +#include /**/ "ace/pre.h" + +#include "orbsvcs/PortableGroup/portablegroup_export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "orbsvcs/PortableGroupC.h" + +#include <set> + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace TAO +{ + class Storable_Base; + class Storable_Factory; +} + +namespace TAO +{ + /** + * @class PG_Group_List_Store + * Persists a list of object groups that are themselves persisted. + * All creation and deletion of persistent object groups should + * result in the list store being updated. + * This is done to support multiple group factories using the same + * persistent object groups. + * @see PG_Object_Group_Storable + */ + class TAO_PortableGroup_Export PG_Group_List_Store + { + public: + PG_Group_List_Store (Storable_Factory & storable_factory); + + ~PG_Group_List_Store (); + + /** + * Return a group ID that can be used for creating a new object group. + */ + PortableGroup::ObjectGroupId get_next_group_id (); + + int add (PortableGroup::ObjectGroupId id); + + int remove (PortableGroup::ObjectGroupId id); + + typedef std::set<PortableGroup::ObjectGroupId> Group_Ids; + + typedef std::set<PortableGroup::ObjectGroupId>::iterator + Group_Id_Iterator; + + typedef std::set<PortableGroup::ObjectGroupId>::reverse_iterator + Group_Id_Revers_Iterator; + + typedef std::set<PortableGroup::ObjectGroupId>::const_iterator + Group_Id_Const_Iterator; + + Group_Ids & get_group_ids (); + + /** + * Make explicit that state is stale instead of relying only + * on persistent file time stamp. + */ + void stale (bool is_stale); + + bool stale (); + + /** + * Answer if the list is obsolete because the persistent store has been updated. + * Used by PG_Group_Factory to avoid having to compare IDs in group_map_ with + * the list contained here. + */ + bool list_obsolete (); + + private: + + Group_Ids group_ids_; + + /// Ensure ID is monotonically increasing even when groups gets + /// removed. + PortableGroup::ObjectGroupId next_group_id_; + + TAO::Storable_Base * create_stream (const char * mode); + + Storable_Factory & storable_factory_; + bool loaded_from_stream_; + time_t last_changed_; + bool stale_; + void read (TAO::Storable_Base & stream); + void write (TAO::Storable_Base & stream); + + bool is_obsolete (time_t stored_time); + + friend class PG_Group_List_Store_File_Guard; + + }; +} + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" + +#endif /* PG_GROUP_LIST_STORE_H */ diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group.cpp index f0ab31d5342..33ce7d67bb5 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group.cpp +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group.cpp @@ -6,6 +6,9 @@ #include "orbsvcs/PortableGroup/PG_Operators.h" // Borrow operator== on CosNaming::Name #include "orbsvcs/PortableGroup/PG_Utils.h" +#include "tao/MProfile.h" +#include "tao/Profile.h" +#include "tao/Stub.h" #include "tao/debug.h" #include "ace/Get_Opt.h" @@ -61,11 +64,13 @@ TAO::PG_Object_Group::PG_Object_Group ( , orb_ (CORBA::ORB::_duplicate (orb)) , factory_registry_ (PortableGroup::FactoryRegistry::_duplicate (factory_registry)) , manipulator_ (manipulator) + , distribute_ (1) , empty_ (1) , role_ (type_id) , type_id_ (CORBA::string_dup (type_id)) , tagged_component_ (tagged_component) , reference_ (CORBA::Object::_duplicate(empty_group)) + , group_name_ (0) , members_ () , primary_location_(0) , properties_ (the_criteria, type_properties) @@ -75,16 +80,35 @@ TAO::PG_Object_Group::PG_Object_Group ( { } +TAO::PG_Object_Group::PG_Object_Group ( + CORBA::ORB_ptr orb, + PortableGroup::FactoryRegistry_ptr factory_registry, + TAO::PG_Object_Group_Manipulator & manipulator) + : internals_() + , orb_ (CORBA::ORB::_duplicate (orb)) + , factory_registry_ (PortableGroup::FactoryRegistry::_duplicate (factory_registry)) + , manipulator_ (manipulator) + , distribute_ (1) + , empty_ (1) + , role_ ("") + , type_id_ () + , tagged_component_ () + , reference_ (CORBA::Object::_nil ()) + , group_name_ (0) + , members_ () + , primary_location_(0) + , properties_ () + , initial_number_members_ (0) + , minimum_number_members_ (0) + , group_specific_factories_ () +{ +} + TAO::PG_Object_Group::~PG_Object_Group (void) { - for (MemberMap_Iterator it = this->members_.begin(); - it != this->members_.end(); - ++it) - { - MemberInfo * member = (*it).int_id_; - delete member; - } - this->members_.unbind_all (); + CORBA::string_free (this->group_name_); + + this->clear_members_map (); } #if 0 // may want this again someday @@ -127,7 +151,7 @@ TAO::PG_Object_Group::get_group_specific_factories ( } const PortableGroup::Location & -TAO::PG_Object_Group::get_primary_location (void) const +TAO::PG_Object_Group::get_primary_location (void) { ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, @@ -192,11 +216,55 @@ TAO::PG_Object_Group::add_member (const PortableGroup::Location & the_location, // IORs, not IOGRs to send new IOGRs out // to replicas. + // Verify that the member is not using V1.0 profiles + // since IIOP V1.0 does not support tagged components + const TAO_MProfile &member_profiles = + member->_stubobj ()->base_profiles (); + CORBA::ULong member_profile_count = + member_profiles.profile_count (); + if (member_profile_count > 0) + { + const TAO_GIOP_Message_Version & version = + member_profiles.get_profile (0)->version (); + if (version.major_version () == 1 && + version.minor_version () == 0) + { + if (TAO_debug_level > 3) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("%T %n (%P|%t) - ") + ACE_TEXT ("Can't add member because first profile ") + ACE_TEXT ("is IIOP version 1.0, which does not ") + ACE_TEXT ("support tagged components.\n") + )); + } + throw PortableGroup::ObjectNotAdded (); + } + } + CORBA::String_var member_ior_string = orb_->object_to_string (member); - PortableGroup::ObjectGroup_var new_reference = - add_member_to_iogr (member); + PortableGroup::ObjectGroup_var new_reference; + try { + new_reference = + this->add_member_to_iogr (member); + } + catch (const TAO_IOP::Duplicate&) + { + throw PortableGroup::MemberAlreadyPresent (); + } + catch (const TAO_IOP::Invalid_IOR&) + { + throw PortableGroup::ObjectNotAdded (); + } + catch (...) + { + throw; + } + + if (CORBA::is_nil (new_reference.in ())) + throw PortableGroup::ObjectNotAdded (); // Convert new member back to a (non group) ior. CORBA::Object_var member_ior = @@ -216,20 +284,21 @@ TAO::PG_Object_Group::add_member (const PortableGroup::Location & the_location, this->reference_ = new_reference; // note var-to-var assignment does // a duplicate + if (this->increment_version ()) { this->distribute_iogr (); } else - { + { // Issue with incrementing the version throw PortableGroup::ObjectNotAdded (); } if (TAO_debug_level > 6) - { - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT("PG (%P|%t) exit Object_Group add_member\n"))); - } + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT("PG (%P|%t) exit Object_Group add_member\n"))); + } } int @@ -247,8 +316,8 @@ TAO::PG_Object_Group::set_primary_member ( { int cleared = 0; this->primary_location_ = the_location; - for (MemberMap_Iterator it = this->members_.begin(); - !cleared && it != this->members_.end(); + for (MemberMap_Iterator it = this->members_.begin (); + !cleared && it != this->members_.end (); ++it) { cleared = (*it).int_id_->is_primary_; @@ -314,7 +383,7 @@ TAO::PG_Object_Group::remove_member ( MemberInfo * info = 0; if (this->members_.unbind (the_location, info) == 0) { - if (this->members_.current_size() > 0) + if (this->members_.current_size () > 0) { this->reference_ = this->manipulator_.remove_profiles (this->reference_.in (), @@ -329,7 +398,7 @@ TAO::PG_Object_Group::remove_member ( if (the_location == this->primary_location_) { - this->primary_location_.length(0); + this->primary_location_.length (0); } if (this->increment_version ()) @@ -343,8 +412,8 @@ TAO::PG_Object_Group::remove_member ( if (TAO_debug_level > 6) { ACE_DEBUG ((LM_DEBUG, - "TAO-PG (%P|%t) - " - "remove_member throwing MemberNotFound.\n" + ACE_TEXT ("TAO-PG (%P|%t) - ") + ACE_TEXT ("remove_member throwing MemberNotFound.\n") )); } throw PortableGroup::MemberNotFound(); @@ -425,6 +494,10 @@ TAO::PG_Object_Group::increment_version (void) void TAO::PG_Object_Group::distribute_iogr (void) { + // Check if the object group is configured to distribute + if (!this->distribute_) + return; + // assume internals is locked CORBA::String_var iogr = this->orb_->object_to_string (this->reference_.in()); @@ -509,6 +582,7 @@ TAO::PG_Object_Group::locations_of_members (void) const PortableGroup::Location & location = (*it).ext_id_; PortableGroup::Location & out = (*result)[pos]; out = location; + ++pos; } return result; } @@ -795,5 +869,39 @@ TAO::PG_Object_Group::has_member_at (const PortableGroup::Location & location) return (0 == this->members_.find (location)); } +void +TAO::PG_Object_Group::distribute (int value) +{ + this->distribute_ = value; +} + +void +TAO::PG_Object_Group::set_name (const char* group_name) +{ + if (group_name_ != 0) + CORBA::string_free (group_name_); + + group_name_ = CORBA::string_dup (group_name); +} + +const char* +TAO::PG_Object_Group::get_name (void) +{ + return group_name_; +} + +void +TAO::PG_Object_Group::clear_members_map (void) +{ + for (MemberMap_Iterator it = this->members_.begin(); + it != this->members_.end(); + ++it) + { + MemberInfo * member = (*it).int_id_; + delete member; + } + this->members_.unbind_all (); +} + TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group.h index f5b5328b68e..176e3ef2f7d 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group.h +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group.h @@ -57,6 +57,9 @@ namespace TAO */ class TAO_PortableGroup_Export PG_Object_Group { + + protected: + // Information about an object group member struct MemberInfo { @@ -73,7 +76,6 @@ namespace TAO /// Location where this member exists PortableGroup::Location location_; - /// TRUE if this is primary member CORBA::Boolean is_primary_; @@ -126,16 +128,24 @@ namespace TAO const PortableGroup::Criteria & the_criteria, TAO::PG_Property_Set * type_properties); + /** + * This constructor is to be used for initialization when + * reading the object group from a stream. + */ + PG_Object_Group ( + CORBA::ORB_ptr orb, + PortableGroup::FactoryRegistry_ptr factory_registry, + TAO::PG_Object_Group_Manipulator & manipulator); /// Destructor - ~PG_Object_Group (); + virtual ~PG_Object_Group (); ///////////////// // public methods public: /// return a duplicated reference to this group (IOGR) - PortableGroup::ObjectGroup_ptr reference()const; + PortableGroup::ObjectGroup_ptr reference() const; /** * Note the caller receives a copy of the factoryinfos in the result argument. @@ -146,7 +156,7 @@ namespace TAO /** * get location of primary member */ - const PortableGroup::Location & get_primary_location() const; + virtual const PortableGroup::Location & get_primary_location(); /** * returns a duplicate @@ -186,14 +196,14 @@ namespace TAO /** * @@TODO DOC */ - PortableGroup::ObjectGroupId get_object_group_id () const; + virtual PortableGroup::ObjectGroupId get_object_group_id () const; /** * Add a new member to the group. * @param the_location the location for the new member * @param member the member to be added */ - void add_member ( + virtual void add_member ( const PortableGroup::Location & the_location, CORBA::Object_ptr member); @@ -204,21 +214,21 @@ namespace TAO * it returns a boolean result. A false return means caller should * throw FT::PrimaryNot_Set. */ - int set_primary_member ( + virtual int set_primary_member ( TAO_IOP::TAO_IOR_Property * prop, const PortableGroup::Location & the_location); /** * @@TODO DOC */ - void remove_member ( + virtual void remove_member ( const PortableGroup::Location & the_location); /** * @@TODO DOC */ - void create_member ( + virtual void create_member ( const PortableGroup::Location & the_location, const char * type_id, const PortableGroup::Criteria & the_criteria); @@ -226,30 +236,41 @@ namespace TAO /** * @@TODO DOC */ - PortableGroup::Locations * locations_of_members (void); + virtual PortableGroup::Locations * locations_of_members (void); /** * @@TODO DOC */ - CORBA::Object_ptr get_member_reference ( + virtual CORBA::Object_ptr get_member_reference ( const PortableGroup::Location & the_location); /** * @@TODO DOC */ - void initial_populate (void); + virtual void initial_populate (void); /** * @@TODO DOC */ - void minimum_populate (void); + virtual void minimum_populate (void); /** * @@TODO DOC */ - int has_member_at (const PortableGroup::Location & location ); + virtual int has_member_at (const PortableGroup::Location & location ); + + + /** + * Tell the object group that it should distribute updates to the object + * group state. + */ + virtual void distribute (int value); + + virtual void set_name (const char* group_name); + + virtual const char* get_name (void); ///////////////////////// // Implementation methods @@ -259,11 +280,13 @@ namespace TAO void distribute_iogr (void); - PortableGroup::ObjectGroup_ptr add_member_to_iogr(CORBA::Object_ptr member); + void create_members (size_t count); + protected: - void create_members (size_t count); + virtual PortableGroup::ObjectGroup_ptr add_member_to_iogr(CORBA::Object_ptr member); + void clear_members_map (void); ///////////////////////// // Forbidden methods @@ -290,19 +313,28 @@ namespace TAO */ mutable TAO_SYNCH_MUTEX internals_; + protected: CORBA::ORB_var orb_; + private: + /// Where to find the factories for replicas. PortableGroup::FactoryRegistry_var factory_registry_; + protected: // The object group manipulator TAO::PG_Object_Group_Manipulator & manipulator_; + /// boolean true if updates should be distributed + int distribute_; + /// boolean true if empty group int empty_; ACE_CString role_; + + PortableGroup::TypeId_var type_id_; /** @@ -325,6 +357,12 @@ namespace TAO */ PortableServer::ObjectId_var object_id_; + /** + * an optional attribute of the object group which is a string + * name that is assigned to the object group by the creator. + */ + char* group_name_; + // group members MemberMap members_; diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Manipulator.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Manipulator.cpp index 8e91038f8be..e8ccd41d89b 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Manipulator.cpp +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Manipulator.cpp @@ -61,7 +61,16 @@ TAO::PG_Object_Group_Manipulator::create_object_group ( PortableGroup::ObjectGroupId & group_id) { allocate_ogid(group_id); - PortableServer::ObjectId_var oid = convert_ogid_to_oid (group_id); + return this->create_object_group_using_id(type_id, domain_id, group_id); +} + +PortableGroup::ObjectGroup_ptr +TAO::PG_Object_Group_Manipulator::create_object_group_using_id( + const char * type_id, + const char * domain_id, + const PortableGroup::ObjectGroupId & group_id) +{ + PortableServer::ObjectId_var oid = convert_ogid_to_oid (group_id); // Create a reference for the ObjectGroup CORBA::Object_var object_group = diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Manipulator.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Manipulator.h index 91c37045d1f..35a2fbbd524 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Manipulator.h +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Manipulator.h @@ -63,6 +63,16 @@ namespace TAO const char * domain_id, PortableGroup::ObjectGroupId & group_id); + /** + * Create an empty object group using a specific ID. + * Note that this should not also be used with create_object_group () + * as the next object group ID to use will not necessarily be unique. + */ + PortableGroup::ObjectGroup_ptr create_object_group_using_id ( + const char * type_id, + const char * domain_id, + const PortableGroup::ObjectGroupId & group_id); + PortableGroup::ObjectGroup_ptr remove_profiles ( PortableGroup::ObjectGroup_ptr group, PortableGroup::ObjectGroup_ptr profile) const; diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Storable.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Storable.cpp new file mode 100644 index 00000000000..7a457881ca4 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Storable.cpp @@ -0,0 +1,571 @@ +// $Id$ + +#include "orbsvcs/PortableGroup/PG_Object_Group_Storable.h" + +#include "tao/Storable_File_Guard.h" +#include "tao/Storable_Factory.h" +#include "tao/CDR.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace +{ + template <typename T> + void read_cdr (TAO::Storable_Base & stream, T & corba_data) + { + int size; + stream >> size; + + char *tmp = 0; + ACE_NEW_THROW_EX (tmp, char [size], CORBA::NO_MEMORY ()); + ACE_Auto_Basic_Array_Ptr<char> buf (tmp); + stream.read (size, buf.get ()); + + TAO_InputCDR cdr (buf.get (), size); + cdr >> corba_data; + if (!cdr.good_bit ()) + { + stream.clear (); + throw CORBA::INTERNAL (); + } + } +} + +namespace TAO +{ + + class Object_Group_File_Guard : public TAO::Storable_File_Guard + { + public: + + Object_Group_File_Guard ( TAO::PG_Object_Group_Storable & object_group, + Method_Type method_type); + + ~Object_Group_File_Guard (); + + virtual void set_object_last_changed (const time_t & time); + + virtual time_t get_object_last_changed (); + + /// Check if the guarded object is current with the last + /// update which could have been performed independently of + /// the owner of this object. + virtual bool object_obsolete (); + + /// Mark the object as current with respect to the + /// file to which it was persisted. + virtual void mark_object_current (); + + virtual void load_from_stream (); + + virtual bool is_loaded_from_stream (); + + virtual TAO::Storable_Base * create_stream (const char * mode); + + private: + + TAO::PG_Object_Group_Storable & object_group_; + }; + +} + +TAO::Object_Group_File_Guard::Object_Group_File_Guard ( + TAO::PG_Object_Group_Storable & object_group, + Method_Type method_type) + : TAO::Storable_File_Guard(true) + , object_group_(object_group) +{ + try + { + this->init (method_type); + } + catch (const TAO::Storable_Read_Exception &) + { + throw CORBA::INTERNAL (); + } +} + +TAO::Object_Group_File_Guard::~Object_Group_File_Guard () +{ + this->release (); + + // Notify if persistent store was updated. + if (object_group_.write_occurred_) + object_group_.state_written (); +} + +void +TAO::Object_Group_File_Guard::set_object_last_changed (const time_t & time) +{ + object_group_.last_changed_ = time; +} + +time_t +TAO::Object_Group_File_Guard::get_object_last_changed () +{ + return object_group_.last_changed_; +} + +bool +TAO::Object_Group_File_Guard::object_obsolete () +{ + return object_group_.is_obsolete (fl_->last_changed ()); +} + +void +TAO::Object_Group_File_Guard::mark_object_current () +{ + object_group_.stale (false); + TAO::Storable_File_Guard::mark_object_current (); +} + +void +TAO::Object_Group_File_Guard::load_from_stream () +{ + object_group_.read (this->peer ()); + object_group_.loaded_from_stream_ = true; +} + +bool +TAO::Object_Group_File_Guard::is_loaded_from_stream () +{ + return object_group_.loaded_from_stream_; +} + +TAO::Storable_Base * +TAO::Object_Group_File_Guard::create_stream (const char * mode) +{ + return object_group_.create_stream (mode); +} + +// Make shortcut to get to Method_Type enums +typedef TAO::Storable_File_Guard SFG; + +TAO::PG_Object_Group_Storable::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(orb, + factory_registry, + manipulator, + empty_group, + tagged_component, + type_id, + the_criteria, + type_properties) + , group_previously_stored_(false) + , group_id_previously_stored_(0) + , storable_factory_ (storable_factory) + , last_changed_ (0) + , loaded_from_stream_ (false) + , destroyed_ (false) + , write_occurred_ (false) +{ + // Create a temporary stream simply to check if a readable + // version already exists. + bool stream_exists = false; + { + ACE_Auto_Ptr<TAO::Storable_Base> stream ( + this->create_stream (ACE_TEXT_ALWAYS_CHAR ("r"))); + + if (stream->exists ()) + stream_exists = true; + } + + if (stream_exists) + { + Object_Group_File_Guard fg (*this, SFG::CREATE_WITH_FILE); + } + else + { + Object_Group_File_Guard fg (*this, SFG::CREATE_WITHOUT_FILE); + this->write (fg.peer ()); + } +} + +TAO::PG_Object_Group_Storable::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(orb, + factory_registry, + manipulator) + , group_previously_stored_(true) + , group_id_previously_stored_(group_id) + , storable_factory_ (storable_factory) + , last_changed_ (0) + , loaded_from_stream_ (false) + , destroyed_ (false) + , write_occurred_ (false) +{ + // Create a temporary stream to simply to check if a readable + // version already exists. + bool stream_exists = false; + { + ACE_Auto_Ptr<TAO::Storable_Base> stream ( + this->create_stream (ACE_TEXT_ALWAYS_CHAR ("r"))); + + if (stream->exists ()) + stream_exists = true; + } + + if (stream_exists) + { + Object_Group_File_Guard fg (*this, SFG::ACCESSOR); + } + else + { + throw CORBA::INTERNAL (); + } +} + +TAO::PG_Object_Group_Storable::~PG_Object_Group_Storable (void) +{ + if (destroyed_) + { + ACE_Auto_Ptr<TAO::Storable_Base> stream ( + this->create_stream (ACE_TEXT_ALWAYS_CHAR ("r"))); + + if (stream->exists ()) + { + stream->remove (); + } + + } + +} + +void +TAO::PG_Object_Group_Storable::set_destroyed (bool destroyed) +{ + this->destroyed_ = destroyed; +} + +const PortableGroup::Location & +TAO::PG_Object_Group_Storable::get_primary_location (void) +{ + Object_Group_File_Guard fg (*this, SFG::ACCESSOR); + return TAO::PG_Object_Group::get_primary_location (); +} + + +void +TAO::PG_Object_Group_Storable::add_member ( + const PortableGroup::Location & the_location, + CORBA::Object_ptr member) +{ + Object_Group_File_Guard fg (*this, SFG::MUTATOR); + PG_Object_Group::add_member (the_location, member); + this->write (fg.peer ()); +} + +int +TAO::PG_Object_Group_Storable::set_primary_member ( + TAO_IOP::TAO_IOR_Property * prop, + const PortableGroup::Location & the_location) +{ + Object_Group_File_Guard fg (*this, SFG::MUTATOR); + int primary_member = PG_Object_Group::set_primary_member (prop, the_location); + this->write (fg.peer ()); + return primary_member; +} + +void +TAO::PG_Object_Group_Storable::remove_member ( + const PortableGroup::Location & the_location) +{ + Object_Group_File_Guard fg (*this, SFG::MUTATOR); + PG_Object_Group::remove_member (the_location); + this->write (fg.peer ()); +} + + +PortableGroup::Locations * +TAO::PG_Object_Group_Storable::locations_of_members (void) +{ + Object_Group_File_Guard fg (*this, SFG::ACCESSOR); + return PG_Object_Group::locations_of_members (); +} + +void +TAO::PG_Object_Group_Storable::create_member ( + const PortableGroup::Location & the_location, + const char * type_id, + const PortableGroup::Criteria & the_criteria) +{ + Object_Group_File_Guard fg (*this, SFG::MUTATOR); + PG_Object_Group::create_member (the_location, + type_id, + the_criteria); + this->write (fg.peer ()); +} + +void +TAO::PG_Object_Group_Storable::set_name (const char* group_name) +{ + Object_Group_File_Guard fg (*this, SFG::MUTATOR); + PG_Object_Group::set_name (group_name); + this->write (fg.peer ()); +} + +const char* +TAO::PG_Object_Group_Storable::get_name (void) +{ + Object_Group_File_Guard fg (*this, SFG::ACCESSOR); + return PG_Object_Group::get_name (); +} + +void +TAO::PG_Object_Group_Storable::initial_populate (void) +{ + Object_Group_File_Guard fg (*this, SFG::MUTATOR); + PG_Object_Group::initial_populate (); + this->write (fg.peer ()); +} + +void +TAO::PG_Object_Group_Storable::minimum_populate (void) +{ + Object_Group_File_Guard fg (*this, SFG::MUTATOR); + PG_Object_Group::minimum_populate (); + this->write (fg.peer ()); +} + +int +TAO::PG_Object_Group_Storable::has_member_at ( + const PortableGroup::Location & location) +{ + Object_Group_File_Guard fg (*this, SFG::ACCESSOR); + return PG_Object_Group::has_member_at (location); +} + +void +TAO::PG_Object_Group_Storable::distribute (int value) +{ + Object_Group_File_Guard fg (*this, SFG::MUTATOR); + PG_Object_Group::distribute (value); + this->write (fg.peer ()); +} + +CORBA::Object_ptr +TAO::PG_Object_Group_Storable::get_member_reference ( + const PortableGroup::Location & the_location) +{ + Object_Group_File_Guard fg (*this, SFG::ACCESSOR); + return PG_Object_Group::get_member_reference (the_location); +} + +PortableGroup::ObjectGroupId +TAO::PG_Object_Group_Storable::get_object_group_id () const +{ + if (this->group_previously_stored_) + return this->group_id_previously_stored_; + + return PG_Object_Group::get_object_group_id (); +} + +TAO::Storable_Base * +TAO::PG_Object_Group_Storable::create_stream (const char * mode) +{ + char file_name[BUFSIZ]; + // Although PortableGroup::ObjectGroupId is a typedef + // to long long int, make ID type explicit to avoid + // GNU C++ warning on sprintf statement. + long long int id = this->get_object_group_id (); + ACE_OS::sprintf (file_name, ACE_TEXT_ALWAYS_CHAR ("ObjectGroup_%lld"), id); + return this->storable_factory_.create_stream (file_name, mode); +} + +void +TAO::PG_Object_Group_Storable::read (TAO::Storable_Base & stream) +{ + stream.rewind (); + + ACE_CString group_name; + stream >> group_name; + + PG_Object_Group::set_name(group_name.c_str()); + + stream >> this->distribute_; + + stream >> this->role_; + + ///// primary_location_ ///// + read_cdr (stream, this->primary_location_); + + ///// reference_ ///// + ACE_CString reference_ior; + stream >> reference_ior; + this->reference_ = this->orb_->string_to_object (reference_ior.c_str ()); + + ///// tagged_component_ ///// + read_cdr (stream, this->tagged_component_); + + ///// type_id_ ///// + read_cdr(stream, this->type_id_); + + ///// properties_ ///// + PortableGroup::Criteria properties; + read_cdr (stream, properties); + PG_Object_Group::set_properties_dynamically (properties); + + ///// members_ ///// + int num_members; + stream >> num_members; + + this->clear_members_map (); + + for (int i = 0; i < num_members; ++i) + { + ///// location used as members_ key ///// + PortableGroup::Location the_location; + read_cdr (stream, the_location); + + ///// member ///// + ACE_CString member_ior; + stream >> member_ior; + CORBA::Object_var member = + this->orb_->string_to_object (member_ior.c_str ()); + if (CORBA::is_nil (member)) + throw CORBA::INV_OBJREF (); + + ///// location ///// + PortableGroup::Location location; + read_cdr (stream, location); + + ///// factory ///// + ACE_CString factory_ior; + stream >> factory_ior; + CORBA::Object_var obj = + this->orb_->string_to_object (factory_ior.c_str ()); + PortableGroup::GenericFactory_var factory = + PortableGroup::GenericFactory::_narrow (obj.in()); + + ///// factory_id (typedef of CORBA::Any) ///// + PortableGroup::GenericFactory::FactoryCreationId factory_id; + read_cdr (stream, factory_id); + + ///// is_primary ///// + int is_primary; + stream >> is_primary; + + MemberInfo * info = 0; + ACE_NEW_THROW_EX (info, MemberInfo(member.in (), + the_location, + factory, + factory_id), + CORBA::NO_MEMORY()); + + info->is_primary_ = is_primary; + + if (this->members_.bind (the_location, info) != 0) + { + throw CORBA::NO_MEMORY(); + } + } +} + +void +TAO::PG_Object_Group_Storable::write (TAO::Storable_Base & stream) +{ + stream.rewind (); + + ACE_CString group_name = PG_Object_Group::get_name (); + stream << group_name; + stream << this->distribute_; + stream << this->role_; + + TAO_OutputCDR primary_location_cdr; + primary_location_cdr << PG_Object_Group::get_primary_location (); + stream << primary_location_cdr; + + ACE_CString reference_ior = + this->orb_->object_to_string (this->reference_.in ()); + stream << reference_ior; + + TAO_OutputCDR tagged_component_cdr; + tagged_component_cdr << this->tagged_component_; + stream << tagged_component_cdr; + + TAO_OutputCDR type_id_cdr; + PortableGroup::TypeId_var type_id = PG_Object_Group::get_type_id (); + type_id_cdr << type_id; + stream << type_id_cdr; + + TAO_OutputCDR properties_cdr; + PortableGroup::Criteria properties; + this->properties_.export_properties (properties); + properties_cdr << properties; + stream << properties_cdr; + + ///// members_ ///// + int num_members = this->members_.current_size (); + stream << num_members; + for (MemberMap_Iterator it = this->members_.begin (); + it != this->members_.end (); + ++it) + { + PortableGroup::Location the_location = it->key (); + TAO_OutputCDR the_location_cdr; + the_location_cdr << the_location; + stream << the_location_cdr; + + MemberInfo * member = it->item (); + ACE_CString member_ior = + this->orb_->object_to_string (member->member_.in ()); + stream << member_ior; + + TAO_OutputCDR location_cdr; + location_cdr << member->location_; + stream << location_cdr; + + ACE_CString factory_ior = + this->orb_->object_to_string (member->factory_.in ()); + stream << factory_ior; + + TAO_OutputCDR factory_id_cdr; + factory_id_cdr << member->factory_id_; + stream << factory_id_cdr; + + stream << member->is_primary_; + } + stream.flush (); + this->write_occurred_ = true; +} + +void +TAO::PG_Object_Group_Storable::stale (bool is_stale) +{ + ACE_UNUSED_ARG (is_stale); + // Default implementation is no-op +} + +bool +TAO::PG_Object_Group_Storable::stale () +{ + // Default is to return false + return false; +} + +void +TAO::PG_Object_Group_Storable::state_written (void) +{ + // No-op. Overridden by derived class. +} + +bool +TAO::PG_Object_Group_Storable::is_obsolete (time_t stored_time) +{ + return (!this->loaded_from_stream_) || + stored_time > this->last_changed_; +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Storable.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Storable.h new file mode 100644 index 00000000000..56d86677624 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Storable.h @@ -0,0 +1,194 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file PG_Object_Group_Storable.h + * + * $Id$ + * + * Contains declaration for class PG_Object_Group_Storable. + * + * @author Byron Harris <harrisb@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_PG_OBJECT_GROUP_STORABLE_H_ +#define TAO_PG_OBJECT_GROUP_STORABLE_H_ +#include /**/ "ace/pre.h" + +#include "orbsvcs/PortableGroup/portablegroup_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.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +///////////////////// +// Forward references +namespace TAO +{ + class Storable_Factory; + class Storable_Base; +} + +//////////////// +// 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_PortableGroup_Export PG_Object_Group_Storable + : public PG_Object_Group + { + + ///////////////////// + // Construct/Destruct + public: + + /** + * This constructor is suitable for creating an object group from + * scratch. + */ + 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. + */ + 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 + ~PG_Object_Group_Storable (); + + ///////////////// + // public methods + + public: + + /** + * Indicate that this object group is to be permanently + * destroyed. During destruction the persistent store + * for this will then be removed. + * This is to distinguish between deletion from a process + * shutdown verses deletion from a destroy request. + */ + void set_destroyed (bool destroyed); + + /** + * Allow for replication persistence support by + * derived classes. + */ + virtual void stale (bool is_stale); + virtual bool stale (); + + virtual const PortableGroup::Location & get_primary_location (); + + virtual void add_member ( + const PortableGroup::Location & the_location, + CORBA::Object_ptr member); + + virtual int set_primary_member ( + TAO_IOP::TAO_IOR_Property * prop, + const PortableGroup::Location & the_location); + + virtual void remove_member ( + const PortableGroup::Location & the_location); + + virtual void create_member ( + const PortableGroup::Location & the_location, + const char * type_id, + const PortableGroup::Criteria & the_criteria); + + virtual PortableGroup::Locations * locations_of_members (void); + + virtual CORBA::Object_ptr get_member_reference ( + const PortableGroup::Location & the_location); + + virtual void initial_populate (void); + + virtual void minimum_populate (void); + + virtual int has_member_at (const PortableGroup::Location & location ); + + virtual void distribute (int value); + + virtual void set_name (const char* group_name); + + virtual const char* get_name (void); + + virtual PortableGroup::ObjectGroupId get_object_group_id () const; + + private: + + ///////////////////////// + // Forbidden methods + PG_Object_Group_Storable (); + PG_Object_Group_Storable (const PG_Object_Group_Storable & rhs); + PG_Object_Group_Storable & operator = (const PG_Object_Group_Storable & rhs); + + /// Indicate if instance of object group has been restored from store + bool group_previously_stored_; + PortableGroup::ObjectGroupId group_id_previously_stored_; + + TAO::Storable_Base * create_stream (const char * mode); + + void read (TAO::Storable_Base & stream); + + void write (TAO::Storable_Base & stream); + + TAO::Storable_Factory & storable_factory_; + time_t last_changed_; + + protected: + + bool loaded_from_stream_; + + bool destroyed_; + + /// To set when state written out. + bool write_occurred_; + + /** + * Signals that this context was updated. + */ + virtual void state_written (void); + + /** + * A callback invoked by the object group file guard + * to determine if this context is obsolete with respect to + * the peristent store. + */ + virtual bool is_obsolete (time_t stored_time); + + friend class Object_Group_File_Guard; + + }; +} // namespace TAO + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" + +#endif // TAO_PG_OBJECT_GROUP_STORABLE_H_ diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Set.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Set.cpp index 07739231579..ede4d544d03 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Set.cpp +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Set.cpp @@ -149,24 +149,22 @@ void TAO::PG_Property_Set::set_property ( CORBA::NO_MEMORY ()); const PortableGroup::Value * replaced_value = 0; - if (0 == this->values_.rebind (name, value_copy, replaced_value)) - { - if (0 != replaced_value) - { + int rebind_result = this->values_.rebind (name, value_copy, replaced_value); + if (1 == rebind_result) + { // Existing value was replaced delete replaced_value; } - } - else - { - if (TAO_debug_level > 3) - { - ACE_ERROR ( (LM_ERROR, - "%n\n%T: Property_set: rebind failed.\n" - )); + else if (-1 == rebind_result) + { // Value was not rebound. + if (TAO_debug_level > 3) + { + ACE_ERROR ( (LM_ERROR, + "%n\n%T: Property_set: rebind failed.\n" + )); + } + // @@ should throw something here + throw CORBA::NO_MEMORY (); } - // @@ should throw something here - throw CORBA::NO_MEMORY (); - } } diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Profile.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Profile.cpp index fecf55c86b8..10a7057b444 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Profile.cpp +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Profile.cpp @@ -547,7 +547,7 @@ TAO_UIPMC_Profile::endpoint_count (void) const } char * -TAO_UIPMC_Profile::to_string (void) +TAO_UIPMC_Profile::to_string (void) const { // corbaloc:miop:1.0@1.0-group_id-1-1/host:port diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Profile.h b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Profile.h index 994af6d4274..7406a16b0d1 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Profile.h +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Profile.h @@ -82,7 +82,7 @@ public: /// a useable decode_endpoints virtual int decode (TAO_InputCDR &cdr); virtual void parse_string (const char *string); - virtual char * to_string (void); + virtual char * to_string (void) const; virtual int encode_endpoints (void); virtual void encodeAddressInfo (TAO_OutputCDR &stream) const; virtual TAO_Endpoint *endpoint (void); diff --git a/TAO/orbsvcs/orbsvcs/cosnaming_serv_persistence.mpb b/TAO/orbsvcs/orbsvcs/cosnaming_serv_persistence.mpb index 1caf3ca3f1f..8318fbecd86 100644 --- a/TAO/orbsvcs/orbsvcs/cosnaming_serv_persistence.mpb +++ b/TAO/orbsvcs/orbsvcs/cosnaming_serv_persistence.mpb @@ -5,13 +5,15 @@ feature(!corba_e_micro) { Source_Files(ORBSVCS_COMPONENTS) { Naming { - Naming/Flat_File_Persistence.cpp Naming/Persistent_Context_Index.cpp Naming/Persistent_Entries.cpp Naming/Persistent_Naming_Context.cpp Naming/Storable.cpp Naming/Storable_Naming_Context.cpp Naming/Storable_Naming_Context_Activator.cpp + Naming/Storable_Naming_Context_ReaderWriter.cpp + Naming/Persistent_Naming_Context_Factory.cpp + Naming/Storable_Naming_Context_Factory.cpp } } } |