From 905b63b063e5a02b89d5a33b184bf75d38f16e2e Mon Sep 17 00:00:00 2001 From: Ossama Othman Date: Mon, 4 Nov 2002 00:01:11 +0000 Subject: ChangeLogTag:Sun Nov 3 15:59:57 2002 Ossama Othman --- TAO/ChangeLog | 128 ++++++ TAO/orbsvcs/orbsvcs/PortableGroup/PG_Factory_Set.h | 5 +- .../orbsvcs/PortableGroup/PG_GenericFactory.cpp | 450 ++++++++++++++------- .../orbsvcs/PortableGroup/PG_GenericFactory.h | 45 ++- .../PortableGroup/PG_ObjectGroupManager.cpp | 160 +++++++- .../orbsvcs/PortableGroup/PG_ObjectGroupManager.h | 53 +++ 6 files changed, 680 insertions(+), 161 deletions(-) diff --git a/TAO/ChangeLog b/TAO/ChangeLog index 0536c830141..6cf86302381 100644 --- a/TAO/ChangeLog +++ b/TAO/ChangeLog @@ -1,3 +1,131 @@ +Sun Nov 3 15:59:59 2002 Ossama Othman + + * orbsvcs/orbsvcs/LB_ORT.idl: + + Updated to CORBA 3.0 conventions. Use the CORBA 3.0 + "typeprefix" keyword instead of "#pragma prefix". + +Sun Nov 3 15:59:57 2002 Ossama Othman + + The following fix some problems with the infrastructure-controlled + membership support in TAO's PortableGroup library: + + * orbsvcs/orbsvcs/PortableGroup/PG_Factory_Set.h + (TAO_PG_Factory_Node): + + Replaced GenericFactory object reference attribute with a + FactoryInfo attribute. The latter is necessary to correctly + implement infrastructure-controlled membership + + * orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.h + (delete_member): + + New method used to implement the + ObjectGroupManager::remove_member() method when the object group + in question is under infrastructure control. The + ObjectGroupManager will call back on the GenericFactory. + + (check_minimum_number_members): + + New method that creates new members if the object group in + question is under infrastructure control. Enough new members + will be created to satisfy the MinimumNumberMembers property of + the object group (assuming there are enough unused + application-supplied GenericFactorys). + + (create_member): + + New method used to create a single member via the + infrastructure. This method is only used internally by the + infrastructure. It should not be confused with the + ObjectGroupManager::create_member() method. + + (populate_object_group): + + Removed FactoryCreationId and ObjectId parameters. They are no + longer used by this method. + + * orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.cpp: + + No need to include `PG_Group_Guard.h'. That file has been + removed. + + (TAO_PG_GenericFactory): + + Pass the "this" pointer to the ObjectGroupManager + implementation. The ObjectGroupManager will potentially call + back on the GenericFactory in the infrastructure-controlled + membership case. + + (create_object): + + Reorganized this method so that the TAO_PG_Group_Guard class is + no longer needed. In particular, the FactoryCreationId is + + The object group's factory set is now bound to the factory map + in this method instead of the populate_object_group() method. + This allowed the latter method to be cleaned up. + + (delete_object_i): + + Updated to access FactoryInfo field in the TAO_PG_Factory_Node + structure that replaced the old GenericFactory object reference + field. + + (populate_object_group): + + Fixed problem where only the number of factories equal to the + initial number of members were bound to the factory map. All + factories should be bound to the map, but only + InitialNumberMembers factories should be invoked. + + Refactored member creation code to the new create_member() + method since the same code is also used by the new + check_minimum_number_members() method. + + * orbsvcs/orbsvcs/PortableGroup/PG_Group_Guard.h: + * orbsvcs/orbsvcs/PortableGroup/PG_Group_Guard.cpp: + + Remove these files. The "guard" implementation contained in + these files is no longer necessary due to improvements in the + TAO_PG_GenericFactory::create_object() method. + + * orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.h: + * orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.cpp + (_tao_add_member): + + TAO-specific object group member addition method intended for + use by TAO's GenericFactory implementation. It merely calls the + new protected add_member_i() method in a way that prevents that + method from performing remote member type checking via the + CORBA::Object::_is_a() call. TAO's GenericFactory + implementation already performs member type checking in the + infrastructure-controlled case. This is an optimization to + prevent redundant remote type checks. + + (add_member): + + Refactored object group member addition code to the new + protected add_member_i() method. It calls the add_member_i() + method in a way that allows member type checking to occur. + + (add_member_i): + + New protected underlying and non-locking implementation of the + add_member() and _tao_add_member() methods. + + (member_count): + + New accessor method that returns the number of members currently + in a given object group. Used by the new + TAO_PG_GenericFactory::check_minimum_number_members() method. + + (generic_factory): + + Mutator method used to set the cached pointer to the + TAO_PG_GenericFactory object which the TAO_PG_ObjectGroupManager + will call back on. + Sun Nov 3 11:04:27 2002 Balachandran Natarajan * orbsvcs/orbsvcs/Event/EC_Gateway_UDP.h: Fixed a compile errors diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Factory_Set.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Factory_Set.h index 82e07838757..498c85c527f 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Factory_Set.h +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Factory_Set.h @@ -40,9 +40,8 @@ */ struct TAO_PG_Factory_Node { - - /// Reference to the GenericFactory that created the member. - PortableGroup::GenericFactory_var factory; + /// Member factory information. + PortableGroup::FactoryInfo factory_info; /// FactoryCreationId assigned to the member. PortableGroup::GenericFactory::FactoryCreationId_var factory_creation_id; diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.cpp index 482fc25f02c..facd5510116 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.cpp +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.cpp @@ -3,10 +3,8 @@ #include "PG_ObjectGroupManager.h" #include "PG_PropertyManager.h" #include "PG_Property_Utils.h" -#include "PG_Group_Guard.h" #include "PG_conf.h" -//#include "ace/Auto_Ptr.h" ACE_RCSID (PortableGroup, PG_GenericFactory, @@ -23,6 +21,7 @@ TAO_PG_GenericFactory::TAO_PG_GenericFactory ( next_fcid_ (0), lock_ () { + this->object_group_manager_.generic_factory (this); } TAO_PG_GenericFactory::~TAO_PG_GenericFactory (void) @@ -138,42 +137,57 @@ TAO_PG_GenericFactory::create_object ( TAO_PG_Factory_Set factory_set; - TAO_PG_Group_Guard group_guard (*this, - factory_set, - this->object_group_manager_, - oid.in ()); - const CORBA::ULong factory_infos_count = (factory_infos == 0 ? 0 : factory_infos->length ()); - if (factory_infos_count > 0 - && membership_style == PortableGroup::MEMB_INF_CTRL) + ACE_TRY { - this->populate_object_group (fcid, - object_group.in (), - oid.in (), - type_id, - *factory_infos, - initial_number_members, - factory_set - ACE_ENV_ARG_PARAMETER); + if (factory_infos_count > 0 + && membership_style == PortableGroup::MEMB_INF_CTRL) + { + this->populate_object_group (object_group.in (), + type_id, + *factory_infos, + initial_number_members, + factory_set + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (this->factory_map_.bind (fcid, factory_set) != 0) + ACE_TRY_THROW (PortableGroup::ObjectNotCreated ()); + + } + + // Allocate a new FactoryCreationId for use as an "out" parameter. + PortableGroup::GenericFactory::FactoryCreationId * tmp = 0; + ACE_NEW_THROW_EX (tmp, + PortableGroup::GenericFactory::FactoryCreationId, + CORBA::NO_MEMORY ( + CORBA::SystemException::_tao_minor_code ( + TAO_DEFAULT_MINOR_CODE, + ENOMEM), + CORBA::COMPLETED_NO)); ACE_CHECK_RETURN (CORBA::Object::_nil ()); - } - // Allocate a new FactoryCreationId for use as an "out" parameter. - PortableGroup::GenericFactory::FactoryCreationId * tmp = 0; - ACE_NEW_THROW_EX (tmp, - PortableGroup::GenericFactory::FactoryCreationId, - CORBA::NO_MEMORY ( - CORBA::SystemException::_tao_minor_code ( - TAO_DEFAULT_MINOR_CODE, - ENOMEM), - CORBA::COMPLETED_NO)); - ACE_CHECK_RETURN (CORBA::Object::_nil ()); + factory_creation_id = tmp; - factory_creation_id = tmp; + *tmp <<= fcid; + } + ACE_CATCHANY + { + this->delete_object_i (factory_set, + 1 /* Ignore exceptions */ + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->object_group_manager_.destroy_object_group (oid.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; - *tmp <<= fcid; + ACE_RE_THROW; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (CORBA::Object::_nil ()); { ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, @@ -186,8 +200,6 @@ TAO_PG_GenericFactory::create_object ( this->next_fcid_++; } - group_guard.release (); - return object_group._retn (); } @@ -259,7 +271,7 @@ TAO_PG_GenericFactory::delete_object_i (TAO_PG_Factory_Set & factory_set, TAO_PG_Factory_Node & factory_node = factory_set[ilen]; PortableGroup::GenericFactory_ptr factory = - factory_node.factory.in (); + factory_node.factory_info.the_factory.in (); const PortableGroup::GenericFactory::FactoryCreationId & member_fcid = factory_node.factory_creation_id.in (); @@ -292,6 +304,67 @@ TAO_PG_GenericFactory::delete_object_i (TAO_PG_Factory_Set & factory_set, } } +void +TAO_PG_GenericFactory::delete_member ( + CORBA::ULong group_id, + const PortableGroup::Location & location + ACE_ENV_ARG_DECL) +{ + ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_); + + // If no entry exists in the factory map, infrastructure + // controlled membership was not used. + TAO_PG_Factory_Map::ENTRY *entry = 0; + if (this->factory_map_.find (group_id, entry) == 0) + { + TAO_PG_Factory_Set & factory_set = entry->int_id_; + + const size_t len = factory_set.size (); + + // Iterate through the factory_set until a location match + // occurs. If a location match occurs, the member was created + // by the infrastructure, i.e. this GenericFactory + // implementation. If no location matches, the member was + // created by the application, and no operation will be + // performed. + // + // @todo This is linear search. Change to use a container with + // better search times. + for (size_t i = 0; i < len; ++i) + { + TAO_PG_Factory_Node & node = factory_set[i]; + PortableGroup::FactoryInfo & info = node.factory_info; + + if (info.the_location == location) + { + info.the_factory->delete_object (node.factory_creation_id.in () + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + // The member has been successfully deleted. Reduce the + // size of the factory_set accordingly. + if (len > 1) + { + // Move the last element to the location of the + // current one and reduce the size of the set by + // one. + const size_t new_len = len - 1; + node = factory_set[new_len]; // Memberwise copy + factory_set.size (new_len); + } + else + { + // A copy isn't necessary if the last member was + // deleted. + factory_set.size (0); + } + + return; + } + } + } +} + void TAO_PG_GenericFactory::poa (PortableServer::POA_ptr p) { @@ -303,9 +376,7 @@ TAO_PG_GenericFactory::poa (PortableServer::POA_ptr p) void TAO_PG_GenericFactory::populate_object_group ( - const CORBA::ULong fcid, PortableGroup::ObjectGroup_ptr object_group, - const PortableServer::ObjectId & oid, const char * type_id, const PortableGroup::FactoryInfos & factory_infos, const PortableGroup::InitialNumberMembersValue initial_number_members, @@ -314,106 +385,39 @@ TAO_PG_GenericFactory::populate_object_group ( { CORBA::ULong factory_infos_count = factory_infos.length (); factory_set.size (factory_infos_count); - for (CORBA::ULong j = 0; - j < ACE_static_cast (CORBA::ULong, initial_number_members); - ++j) - { - const PortableGroup::FactoryInfo &factory_info = - factory_infos[j]; - - PortableGroup::GenericFactory_ptr factory = - factory_info.the_factory.in (); - if (CORBA::is_nil (factory)) - ACE_THROW (PortableGroup::NoFactory ()); // @@ - // InvalidProperty - // instead? + for (CORBA::ULong j = 0; j < factory_infos_count; ++j) + { + TAO_PG_Factory_Node & factory_node = factory_set[j]; - PortableGroup::GenericFactory::FactoryCreationId_var - member_fcid; + const PortableGroup::FactoryInfo &factory_info = factory_infos[j]; - CORBA::Object_var member = - factory->create_object (type_id, - factory_info.the_criteria, - member_fcid.out () - ACE_ENV_ARG_PARAMETER); - ACE_CHECK; - - ACE_TRY + if (j < ACE_static_cast (CORBA::ULong, initial_number_members)) { - // @@ Should an "_is_a()" be performed here? While it - // appears to be the right thing to do, it can be expensive. - // - // Make sure an Object of the correct type was created. It - // is possible that an object of the wrong type was created - // if the type_id parameter does not match the type of - // object the GenericFactory creates. - CORBA::Boolean right_type_id = - member->_is_a (type_id - ACE_ENV_ARG_PARAMETER); - ACE_TRY_CHECK; + PortableGroup::GenericFactory_ptr factory = + factory_info.the_factory.in (); - // @todo Strategize this -- e.g. strict type checking. - if (!right_type_id) + if (CORBA::is_nil (factory)) { - // An Object of incorrect type was created. Delete it, and - // throw a NoFactory exception. - factory->delete_object (member_fcid.in () - ACE_ENV_ARG_PARAMETER); - ACE_TRY_CHECK; - - ACE_TRY_THROW (PortableGroup::NoFactory ()); + // @@ instead InvalidProperty? + ACE_THROW (PortableGroup::NoFactory (factory_info.the_location, + type_id)); } - TAO_PG_Factory_Node factory_node; - factory_node.factory = - PortableGroup::GenericFactory::_duplicate (factory); - factory_node.factory_creation_id = member_fcid; - - factory_set[j] = factory_node; - - this->object_group_manager_.add_member (object_group, - factory_info.the_location, - member.in () - ACE_ENV_ARG_PARAMETER); - ACE_TRY_CHECK; - } - ACE_CATCHANY - { - // If the member reference is not nil, then the factory was - // successfully invoked. Since an exception was thrown, - // clean up the up created member. - if (!CORBA::is_nil (member.in ())) - { - factory->delete_object (member_fcid.in () - ACE_ENV_ARG_PARAMETER); - ACE_TRY_CHECK; - } + // Do not allow the PortableGroup::MemberAlreadyPresent + // exception to be propagated to this scope. + const CORBA::Boolean propagate_member_already_present = 0; - this->object_group_manager_.destroy_object_group ( - oid - ACE_ENV_ARG_PARAMETER); - ACE_TRY_CHECK; - - ACE_RE_THROW; + factory_node.factory_creation_id = + this->create_member (object_group, + factory_info, + type_id, + propagate_member_already_present + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; } - ACE_ENDTRY; - ACE_CHECK; - } - - if (this->factory_map_.bind (fcid, factory_set) != 0) - { - this->delete_object_i (factory_set, - 1 /* Ignore exceptions */ - ACE_ENV_ARG_PARAMETER); - ACE_CHECK; - - this->object_group_manager_.destroy_object_group ( - oid - ACE_ENV_ARG_PARAMETER); - ACE_CHECK; - ACE_THROW (PortableGroup::ObjectNotCreated ()); + factory_node.factory_info = factory_info; // Memberwise copy } } @@ -572,27 +576,191 @@ TAO_PG_GenericFactory::process_criteria ( } } -#if 0 -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +void +TAO_PG_GenericFactory::check_minimum_number_members ( + PortableGroup::ObjectGroup_ptr object_group, + CORBA::ULong group_id, + const char * type_id + ACE_ENV_ARG_DECL) +{ + // Check if we've dropped below the MinimumNumberMembers threshold. + // If so, attempt to create enough new members to fill the gap. -template class auto_ptr; + // If no entry exists in the factory map, infrastructure (this + // GenericFactory implementation) controlled membership was not + // used. + TAO_PG_Factory_Map::ENTRY *entry = 0; + if (this->factory_map_.find (group_id, entry) != 0) + return; -# if defined (ACE_LACKS_AUTO_PTR) \ - || !(defined (ACE_HAS_STANDARD_CPP_LIBRARY) \ - && (ACE_HAS_STANDARD_CPP_LIBRARY != 0)) -template class ACE_Auto_Basic_Ptr; -# endif /* ACE_LACKS_AUTO_PTR */ + TAO_PG_Factory_Set & factory_set = entry->int_id_; -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) + PortableGroup::Properties_var props = + this->property_manager_.get_properties (object_group + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; -#pragma instantiate auto_ptr + PortableGroup::Name name (1); + name.length (1); -# if defined (ACE_LACKS_AUTO_PTR) \ - || !(defined (ACE_HAS_STANDARD_CPP_LIBRARY) \ - && (ACE_HAS_STANDARD_CPP_LIBRARY != 0)) -#pragma instantiate ACE_Auto_Basic_Ptr + PortableGroup::Value value; -# endif /* ACE_LACKS_AUTO_PTR */ + // MinimumNumberMembers + name[0].id = + CORBA::string_dup ("org.omg.PortableGroup.MinimumNumberMembers"); + + PortableGroup::MinimumNumberMembersValue minimum_number_members; + + if (TAO_PG::get_property_value (name, props.in (), value)) + { + if (!(value >>= minimum_number_members)) + { + // This only occurs if extraction of the actual value from + // the Any fails. It shouldn't fail at this point. + ACE_THROW (CORBA::INTERNAL ()); + } -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ -#endif /* 0 */ + const CORBA::ULong count = + this->object_group_manager_.member_count (object_group + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + if (count >= ACE_static_cast (CORBA::ULong, minimum_number_members)) + return; + + const CORBA::ULong gap = + ACE_static_cast (CORBA::ULong, + minimum_number_members) - count; + + CORBA::ULong creation_count = 0; + + const size_t len = factory_set.size (); + + static const PortableGroup::GenericFactory::FactoryCreationId * + nil_fcid = 0; + + for (size_t i = 0; i < len; ++i) + { + TAO_PG_Factory_Node & node = factory_set[i]; + + PortableGroup::GenericFactory::FactoryCreationId * const tmp_fcid = + node.factory_creation_id; + + // Check if the application supplied GenericFactory was + // already invoked. + if (tmp_fcid != nil_fcid) + continue; + + ACE_TRY + { + const CORBA::Boolean propagate_member_already_present = 1; + + node.factory_creation_id = + this->create_member (object_group, + node.factory_info, + type_id, + propagate_member_already_present + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + ++creation_count; + + // Check if the MinimumNumberMembers threshold gap has + // been filled. + if (gap == creation_count) + return; + } + ACE_CATCH (PortableGroup::MemberAlreadyPresent, ex) + { + // Ignore this exception and continue. + } + ACE_ENDTRY; + ACE_CHECK; + } + + // @todo If we get this far, and the MinimumNumberMembers + // threshold gap hasn't been filled, what do we do? Throw + // a CORBA::TRANSIENT? + } +} + +PortableGroup::GenericFactory::FactoryCreationId * +TAO_PG_GenericFactory::create_member ( + PortableGroup::ObjectGroup_ptr object_group, + const PortableGroup::FactoryInfo & factory_info, + const char * type_id, + const CORBA::Boolean propagate_member_already_present + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableGroup::NoFactory, + PortableGroup::ObjectNotCreated, + PortableGroup::InvalidCriteria, + PortableGroup::InvalidProperty, + PortableGroup::CannotMeetCriteria, + PortableGroup::MemberAlreadyPresent)) +{ + PortableGroup::GenericFactory::FactoryCreationId_var fcid; + + CORBA::Object_var member = + factory_info.the_factory->create_object (type_id, + factory_info.the_criteria, + fcid.out () + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + + ACE_TRY + { + // @@ Should an "_is_a()" be performed here? While it + // appears to be the right thing to do, it can be + // expensive. + // + // Make sure an Object of the correct type was created. + // It is possible that an object of the wrong type was + // created if the type_id parameter does not match the + // type of object the GenericFactory creates. + CORBA::Boolean right_type_id = + member->_is_a (type_id + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // @todo Strategize this -- e.g. strict type checking. + if (!right_type_id) + { + // An Object of incorrect type was created. Delete + // it, and throw a NoFactory exception. + factory_info.the_factory->delete_object (fcid.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_TRY_THROW (PortableGroup::NoFactory (factory_info.the_location, + type_id)); + } + + this->object_group_manager_._tao_add_member ( + object_group, + factory_info.the_location, + member.in (), + type_id, + propagate_member_already_present + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + // If the member reference is not nil, then the factory + // was successfully invoked. Since an exception was + // thrown, clean up the up created member. + if (!CORBA::is_nil (member.in ())) + { + factory_info.the_factory->delete_object (fcid.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + + ACE_RE_THROW; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + + return fcid._retn (); +} diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.h index d1289d2c0e4..d0d89838dea 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.h +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.h @@ -111,15 +111,56 @@ public: CORBA::Boolean ignore_exceptions ACE_ENV_ARG_DECL); + /// If the member corresponding to the given group ID and location + /// was created by the infrastructure, call delete_object() on the + /// remote GenericFactory that created it. + /** + * This method is only used by the TAO_PG_ObjectGroupManager class + * when ObjectGroupManager::remove_member() is explicitly called. + */ + void delete_member (CORBA::ULong group_id, + const PortableGroup::Location & location + ACE_ENV_ARG_DECL); + + /// Verify that the MinimumNumberMembers criterion is satisfied. + /** + * If the current number of members in the given object group is + * less than the MinimumNumberMembers criterion in effect for that + * group, the infrastructure will attempt create and add more + * members to the group by invoking any unused application-supplied + * GenericFactorys. + */ + void check_minimum_number_members ( + PortableGroup::ObjectGroup_ptr object_group, + CORBA::ULong group_id, + const char * type_id + ACE_ENV_ARG_DECL); + + /// Create a new object group member using the supplied FactoryInfo + /// and RepositoryId and add it to the given object group. + /** + * @note This method is only used by the infrastructure. + */ + PortableGroup::GenericFactory::FactoryCreationId * create_member ( + PortableGroup::ObjectGroup_ptr object_group, + const PortableGroup::FactoryInfo & factory_info, + const char * type_id, + const CORBA::Boolean propagate_member_already_present + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableGroup::NoFactory, + PortableGroup::ObjectNotCreated, + PortableGroup::InvalidCriteria, + PortableGroup::InvalidProperty, + PortableGroup::CannotMeetCriteria)); + private: /// Populate the object group being created. Called when the /// infrastructure-controlled membership style is used for the /// object group being created. void populate_object_group ( - const CORBA::ULong fcid, PortableGroup::ObjectGroup_ptr object_group, - const PortableServer::ObjectId & oid, const char * type_id, const PortableGroup::FactoryInfos &factory_infos, const PortableGroup::InitialNumberMembersValue initial_number_members, diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.cpp index 9267b475d6d..6ce4110da71 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.cpp +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.cpp @@ -1,6 +1,5 @@ -// -*- C++ -*- - #include "PG_ObjectGroupManager.h" +#include "PG_GenericFactory.h" #include "PG_conf.h" #include "PG_Operators.h" @@ -8,6 +7,7 @@ #include "ace/Auto_Ptr.h" + ACE_RCSID (PortableGroup, PG_ObjectGroupManager, "$Id$") @@ -17,6 +17,7 @@ TAO_PG_ObjectGroupManager::TAO_PG_ObjectGroupManager (void) : poa_ (), object_group_map_ (TAO_PG_MAX_OBJECT_GROUPS), location_map_ (TAO_PG_MAX_LOCATIONS), + generic_factory_ (0), lock_ () { } @@ -81,24 +82,109 @@ TAO_PG_ObjectGroupManager::add_member ( this->lock_, PortableGroup::ObjectGroup::_nil ()); + // Verify that the member's RepositoryId matches the object group's + // type ID. + const CORBA::Boolean check_type_id = 1; + + return this->add_member_i (object_group, + the_location, + member, + check_type_id + ACE_ENV_ARG_PARAMETER); + +} + + +PortableGroup::ObjectGroup_ptr +TAO_PG_ObjectGroupManager::_tao_add_member ( + PortableGroup::ObjectGroup_ptr object_group, + const PortableGroup::Location & the_location, + CORBA::Object_ptr member, + const char * type_id, + const CORBA::Boolean propagate_member_already_present + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableGroup::MemberAlreadyPresent, + PortableGroup::NoFactory)) +{ + if (CORBA::is_nil (member)) + ACE_THROW_RETURN (CORBA::BAD_PARAM (), + PortableGroup::ObjectGroup::_nil ()); + + ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, + guard, + this->lock_, + PortableGroup::ObjectGroup::_nil ()); + + PortableGroup::ObjectGroup_var new_group; + + ACE_TRY + { + // TypeId already checked by GenericFactory. + const CORBA::Boolean check_type_id = 0; + + new_group = this->add_member_i (object_group, + the_location, + member, + check_type_id + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCH (PortableGroup::ObjectGroupNotFound, ex) + { + ACE_TRY_THROW (CORBA::INTERNAL ()); + } + ACE_CATCH (PortableGroup::MemberAlreadyPresent, ex) + { + if (propagate_member_already_present) + ACE_RE_THROW; + else + ACE_TRY_THROW (CORBA::INTERNAL ()); + } + ACE_CATCH (PortableGroup::ObjectNotAdded, ex) + { + ACE_TRY_THROW (PortableGroup::NoFactory (the_location, + type_id)); + } + ACE_ENDTRY; + ACE_CHECK_RETURN (PortableGroup::ObjectGroup::_nil ()); + + return new_group._retn (); +} + +PortableGroup::ObjectGroup_ptr +TAO_PG_ObjectGroupManager::add_member_i ( + PortableGroup::ObjectGroup_ptr object_group, + const PortableGroup::Location & the_location, + CORBA::Object_ptr member, + const CORBA::Boolean check_type_id + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableGroup::ObjectGroupNotFound, + PortableGroup::MemberAlreadyPresent, + PortableGroup::ObjectNotAdded)) +{ TAO_PG_ObjectGroup_Map_Entry * group_entry = this->get_group_entry (object_group ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (PortableGroup::ObjectGroup::_nil ()); - CORBA::Boolean right_type_id = - this->valid_type_id (object_group, - group_entry, - member - ACE_ENV_ARG_PARAMETER); - ACE_CHECK_RETURN (PortableGroup::ObjectGroup::_nil ()); - - if (!right_type_id) + if (check_type_id) { - // The member's type_id does not match the object group's - // type_id. - ACE_THROW_RETURN (PortableGroup::ObjectNotAdded (), - PortableGroup::ObjectGroup::_nil ()); + CORBA::Boolean right_type_id = + this->valid_type_id (object_group, + group_entry, + member + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableGroup::ObjectGroup::_nil ()); + + if (!right_type_id) + { + // The member's type_id does not match the object group's + // type_id. + ACE_THROW_RETURN (PortableGroup::ObjectNotAdded (), + PortableGroup::ObjectGroup::_nil ()); + } } TAO_PG_ObjectGroup_Array * groups = 0; @@ -178,8 +264,24 @@ TAO_PG_ObjectGroupManager::remove_member ( if (info.location == the_location) { + // Give the GenericFactory a chance to delete a member if + // its membership is under infrastructure control. + this->generic_factory_->delete_member (group_entry->group_id, + the_location + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableGroup::ObjectGroup::_nil ()); + if (member_infos.remove (info) == 0) - return PortableGroup::ObjectGroup::_duplicate (object_group); + { + this->generic_factory_->check_minimum_number_members ( + object_group, + group_entry->group_id, + group_entry->type_id.in () + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableGroup::ObjectGroup::_nil ()); + + return PortableGroup::ObjectGroup::_duplicate (object_group); + } else break; } @@ -438,6 +540,26 @@ TAO_PG_ObjectGroupManager::object_group (const PortableServer::ObjectId & oid) return PortableGroup::ObjectGroup::_nil (); } +CORBA::ULong +TAO_PG_ObjectGroupManager::member_count ( + PortableGroup::ObjectGroup_ptr group + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableGroup::ObjectGroupNotFound)) +{ +// ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, +// guard, +// this->lock_, +// 0); + + TAO_PG_ObjectGroup_Map_Entry * group_entry = + this->get_group_entry (group + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + + return group_entry->member_infos.size (); +} + void TAO_PG_ObjectGroupManager::poa (PortableServer::POA_ptr p) { @@ -607,6 +729,14 @@ TAO_PG_ObjectGroupManager::valid_type_id ( return right_type_id; } +void +TAO_PG_ObjectGroupManager::generic_factory ( + TAO_PG_GenericFactory * generic_factory) +{ + ACE_ASSERT (generic_factory != 0); + + this->generic_factory_ = generic_factory; +} #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.h index 9802a020b67..9a2e2497583 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.h +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.h @@ -29,6 +29,10 @@ #include "tao/PortableServer/PortableServerC.h" +/// Forward declarations +class TAO_PG_GenericFactory; + + /** * @class TAO_PG_ObjectGroupManager * @@ -131,6 +135,24 @@ public: //@} + /// TAO-specific member addition method. + /** + * This method is meant to be invoked by TAO's GenericFactory + * implementation. It is designed to allow only certain exceptions + * to be propagated to the caller, and to prevent redundant remote + * RepositoryId checking. + */ + PortableGroup::ObjectGroup_ptr _tao_add_member ( + PortableGroup::ObjectGroup_ptr object_group, + const PortableGroup::Location & the_location, + CORBA::Object_ptr member, + const char * type_id, + const CORBA::Boolean propagate_member_already_present + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableGroup::MemberAlreadyPresent, + PortableGroup::NoFactory)); + /// Create object group hash map entry that represents an actual /// ObjectGroup. /** @@ -172,12 +194,39 @@ public: PortableGroup::ObjectGroup_ptr object_group ( const PortableServer::ObjectId & oid); + /// Return the number of members in the given object group. + CORBA::ULong member_count (PortableGroup::ObjectGroup_ptr group + ACE_ENV_ARG_DECL); + /// Set the POA to use when converting object group references to /// ObjectIds. void poa (PortableServer::POA_ptr p); + /// Set the pointer to the GenericFactory associated with this + /// ObjectGroupManager. + /** + * The TAO_PG_GenericFactory will only be used when + * ObjectGroupManager::remove_member() is explicitly called so that + * the infrastructure may be given an opportunity to clean up any + * object group members it may have created. + */ + void generic_factory (TAO_PG_GenericFactory * generic_factory); + protected: + /// Underlying and non-locking implementation of the add_member() + /// and _tao_add_member() methods in this class. + PortableGroup::ObjectGroup_ptr add_member_i ( + PortableGroup::ObjectGroup_ptr object_group, + const PortableGroup::Location & the_location, + CORBA::Object_ptr member, + const CORBA::Boolean check_type_id + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableGroup::ObjectGroupNotFound, + PortableGroup::MemberAlreadyPresent, + PortableGroup::ObjectNotAdded)); + /// Obtain the ObjectGroup hash map entry corresponding to the given /// ObjectGroup reference. TAO_PG_ObjectGroup_Map_Entry * get_group_entry ( @@ -221,6 +270,10 @@ private: /// addition to the load monitor at that location. TAO_PG_Location_Map location_map_; + /// Pointer to the TAO_PG_GenericFactory class responsible for + /// object group creation/destruction. + TAO_PG_GenericFactory * generic_factory_; + /// Lock used to synchronize access to the underlying tables. TAO_SYNCH_MUTEX lock_; -- cgit v1.2.1