summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOssama Othman <ossama-othman@users.noreply.github.com>2002-11-04 00:01:11 +0000
committerOssama Othman <ossama-othman@users.noreply.github.com>2002-11-04 00:01:11 +0000
commit905b63b063e5a02b89d5a33b184bf75d38f16e2e (patch)
tree79aa73624278cff6e244f76b713cfc1b841d9718
parentedd19466edcce8b2c591c63d85d37834f10cc9e0 (diff)
downloadATCD-905b63b063e5a02b89d5a33b184bf75d38f16e2e.tar.gz
ChangeLogTag:Sun Nov 3 15:59:57 2002 Ossama Othman <ossama@uci.edu>
-rw-r--r--TAO/ChangeLog128
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Factory_Set.h5
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.cpp450
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.h45
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.cpp160
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.h53
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 <ossama@uci.edu>
+
+ * 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 <ossama@uci.edu>
+
+ 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 <bala@isis-server.isis.vanderbilt.edu>
* 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 ();
@@ -293,6 +305,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)
{
ACE_ASSERT (CORBA::is_nil (this->poa_.in ())
@@ -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<TAO_PG_Factory_Node>;
+ // 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<TAO_PG_Factory_Node>;
-# 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<TAO_PG_Factory_Node>
+ 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<TAO_PG_Factory_Node>
+ 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_;