summaryrefslogtreecommitdiff
path: root/TAO/orbsvcs/orbsvcs/PortableGroup
diff options
context:
space:
mode:
authorWilliam R. Otte <wotte@dre.vanderbilt.edu>2006-07-24 15:50:21 +0000
committerWilliam R. Otte <wotte@dre.vanderbilt.edu>2006-07-24 15:50:21 +0000
commit3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c (patch)
tree197c810e5f5bce17b1233a7cb8d7b50c0bcd25e2 /TAO/orbsvcs/orbsvcs/PortableGroup
parent6b846cf03c0bcbd8c276cb0af61a181e5f98eaae (diff)
downloadATCD-3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c.tar.gz
Repo restructuring
Diffstat (limited to 'TAO/orbsvcs/orbsvcs/PortableGroup')
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/GOA.cpp711
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/GOA.h329
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/MIOP.cpp29
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/MIOP.h45
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Default_Property_Validator.cpp151
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Default_Property_Validator.h86
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_FactoryRegistry.cpp733
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_FactoryRegistry.h263
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Factory_Map.h46
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Factory_Set.h58
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.cpp780
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.h248
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Factory.cpp232
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Factory.h184
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Guard.cpp59
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Guard.h93
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Equal_To.cpp11
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Equal_To.h59
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Equal_To.inl15
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Hash.cpp13
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Hash.h53
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Hash.inl25
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Map.h54
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_MemberInfo.cpp18
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_MemberInfo.h62
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Null_Property_Validator.cpp30
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Null_Property_Validator.h67
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.cpp871
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.h314
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroup_Map.h84
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Adapter_Factory.cpp48
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Adapter_Factory.h47
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group.cpp896
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group.h382
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Manipulator.cpp190
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Manipulator.h123
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Operators.cpp33
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Operators.h50
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Encoder.cpp67
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Encoder.h101
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Encoder.inl64
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Support.cpp151
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Support.h214
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_PropertyManager.cpp368
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_PropertyManager.h192
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Set.cpp360
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Set.h200
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Set_Find.h55
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Utils.cpp82
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Utils.h57
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Servant_Dispatcher.cpp70
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Servant_Dispatcher.h72
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Utils.cpp176
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Utils.h59
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_conf.h64
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Acceptor_Registry.cpp191
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Acceptor_Registry.h117
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Loader.cpp83
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Loader.h68
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_ORBInitializer.cpp71
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_ORBInitializer.h61
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Request_Dispatcher.cpp61
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Request_Dispatcher.h70
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/Portable_Group_Map.cpp180
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/Portable_Group_Map.h139
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/README43
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.cpp354
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.h160
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.i29
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.cpp267
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.h149
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connector.cpp215
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connector.h99
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Endpoint.cpp150
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Endpoint.h129
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Endpoint.i52
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.cpp99
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.h72
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Message_Block_Data_Iterator.cpp89
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Message_Block_Data_Iterator.h70
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Profile.cpp800
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Profile.h165
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.cpp613
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.h131
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Wait_Never.cpp53
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Wait_Never.h58
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/miopconf.h41
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/portablegroup_export.h40
88 files changed, 14763 insertions, 0 deletions
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/GOA.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/GOA.cpp
new file mode 100644
index 00000000000..804e235f797
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/GOA.cpp
@@ -0,0 +1,711 @@
+#include "orbsvcs/PortableGroup/GOA.h"
+
+
+ACE_RCSID (PortableGroup,
+ GOA,
+ "$Id$")
+
+
+#include "orbsvcs/PortableGroup/PortableGroup_Acceptor_Registry.h"
+#include "orbsvcs/PortableGroup/PortableGroup_Request_Dispatcher.h"
+
+#include "tao/ORB_Core.h"
+#include "tao/ORB.h"
+#include "tao/Stub.h"
+#include "tao/Tagged_Components.h"
+#include "tao/Profile.h"
+#include "tao/CDR.h"
+
+#include "ace/Auto_Ptr.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+PortableServer::ObjectId *
+TAO_GOA::create_id_for_reference (CORBA::Object_ptr the_ref
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((
+ CORBA::SystemException,
+ PortableGroup::NotAGroupObject
+ ))
+{
+ // Get the RepositoryId from the Group reference so
+ // we know what kind of reference to make.
+ const char* repository_id = the_ref->_stubobj ()->type_id.in ();
+
+ // Create a temporary object reference and then get the
+ // ObjectId out of it.
+ CORBA::Object_var obj_ref = this->create_reference (repository_id
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ PortableServer::ObjectId_var obj_id =
+ this->reference_to_id (obj_ref.in () ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // Associate the object reference with the group reference.
+ this->associate_group_with_ref (the_ref,
+ obj_ref.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ return obj_id._retn ();
+}
+
+PortableGroup::IDs *
+TAO_GOA::reference_to_ids (CORBA::Object_ptr the_ref
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((
+ CORBA::SystemException,
+ PortableGroup::NotAGroupObject
+ ))
+{
+ ACE_UNUSED_ARG (the_ref);
+
+ return 0;
+}
+
+void
+TAO_GOA::associate_reference_with_id (CORBA::Object_ptr ref,
+ const PortableServer::ObjectId & oid
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((
+ CORBA::SystemException,
+ PortableGroup::NotAGroupObject
+ ))
+{
+ // Create a reference for the specified ObjectId, since
+ // it is much easier to extract the object key from the
+ // reference.
+ CORBA::Object_var obj_ref = this->id_to_reference (oid
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // Associate the object reference with the group reference.
+ this->associate_group_with_ref (ref,
+ obj_ref.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+void
+TAO_GOA::disassociate_reference_with_id (CORBA::Object_ptr ref,
+ const PortableServer::ObjectId & oid
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((
+ CORBA::SystemException,
+ PortableGroup::NotAGroupObject
+ ))
+{
+ ACE_UNUSED_ARG (ref);
+ ACE_UNUSED_ARG (oid);
+}
+
+
+TAO_GOA::TAO_GOA (const TAO_Root_POA::String &name,
+ PortableServer::POAManager_ptr poa_manager,
+ const TAO_POA_Policy_Set &policies,
+ TAO_Root_POA *parent,
+ ACE_Lock &lock,
+ TAO_SYNCH_MUTEX &thread_lock,
+ TAO_ORB_Core &orb_core,
+ TAO_Object_Adapter *object_adapter
+ ACE_ENV_ARG_DECL)
+ : TAO_Regular_POA (name,
+ poa_manager,
+ policies,
+ parent,
+ lock,
+ thread_lock,
+ orb_core,
+ object_adapter
+ ACE_ENV_ARG_PARAMETER)
+{
+}
+
+TAO_GOA::~TAO_GOA (void)
+{
+}
+
+TAO_Root_POA *
+TAO_GOA::new_POA (const String &name,
+ PortableServer::POAManager_ptr poa_manager,
+ const TAO_POA_Policy_Set &policies,
+ TAO_Root_POA *parent,
+ ACE_Lock &lock,
+ TAO_SYNCH_MUTEX &thread_lock,
+ TAO_ORB_Core &orb_core,
+ TAO_Object_Adapter *object_adapter
+ ACE_ENV_ARG_DECL)
+{
+ TAO_GOA *poa = 0;
+
+ ACE_NEW_THROW_EX (poa,
+ TAO_GOA (name,
+ poa_manager,
+ policies,
+ parent,
+ lock,
+ thread_lock,
+ orb_core,
+ object_adapter
+ ACE_ENV_ARG_PARAMETER),
+ CORBA::NO_MEMORY ());
+ ACE_CHECK_RETURN (0);
+
+ return poa;
+}
+
+// Standard POA interfaces
+PortableServer::POA_ptr
+TAO_GOA::create_POA (const char *adapter_name,
+ PortableServer::POAManager_ptr poa_manager,
+ const CORBA::PolicyList &policies
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::AdapterAlreadyExists,
+ PortableServer::POA::InvalidPolicy))
+{
+ PortableServer::POA_ptr poa = this->TAO_Regular_POA::create_POA (adapter_name,
+ poa_manager,
+ policies
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (poa);
+ return poa;
+}
+
+PortableServer::POA_ptr
+TAO_GOA::find_POA (const char *adapter_name,
+ CORBA::Boolean activate_it
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::AdapterNonExistent))
+{
+ PortableServer::POA_ptr poa = this->TAO_Regular_POA::find_POA (adapter_name,
+ activate_it
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (poa);
+ return poa;
+}
+
+void
+TAO_GOA::destroy (CORBA::Boolean etherealize_objects,
+ CORBA::Boolean wait_for_completion
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->TAO_Regular_POA::destroy (etherealize_objects,
+ wait_for_completion
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+
+#if (TAO_HAS_MINIMUM_POA == 0)
+
+PortableServer::ThreadPolicy_ptr
+TAO_GOA::create_thread_policy (PortableServer::ThreadPolicyValue value
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ PortableServer::ThreadPolicy_ptr policy =
+ this->TAO_Regular_POA::create_thread_policy (value
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (policy);
+ return policy;
+}
+
+#endif /* TAO_HAS_MINIMUM_POA == 0 */
+
+PortableServer::LifespanPolicy_ptr
+TAO_GOA::create_lifespan_policy (PortableServer::LifespanPolicyValue value
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ PortableServer::LifespanPolicy_ptr policy =
+ this->TAO_Regular_POA::create_lifespan_policy (value
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (policy);
+ return policy;
+}
+
+PortableServer::IdUniquenessPolicy_ptr
+TAO_GOA::create_id_uniqueness_policy (PortableServer::IdUniquenessPolicyValue value
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ PortableServer::IdUniquenessPolicy_ptr policy =
+ this->TAO_Regular_POA::create_id_uniqueness_policy (value
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (policy);
+ return policy;
+}
+
+
+PortableServer::IdAssignmentPolicy_ptr
+TAO_GOA::create_id_assignment_policy (PortableServer::IdAssignmentPolicyValue value
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ PortableServer::IdAssignmentPolicy_ptr policy =
+ this->TAO_Regular_POA::create_id_assignment_policy (value
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (policy);
+ return policy;
+}
+
+
+#if (TAO_HAS_MINIMUM_POA == 0)
+
+PortableServer::ImplicitActivationPolicy_ptr
+TAO_GOA::create_implicit_activation_policy (PortableServer::ImplicitActivationPolicyValue value
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ PortableServer::ImplicitActivationPolicy_ptr policy =
+ this->TAO_Regular_POA::create_implicit_activation_policy (value
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (policy);
+ return policy;
+}
+
+PortableServer::ServantRetentionPolicy_ptr
+TAO_GOA::create_servant_retention_policy (PortableServer::ServantRetentionPolicyValue value
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ PortableServer::ServantRetentionPolicy_ptr policy =
+ this->TAO_Regular_POA::create_servant_retention_policy (value
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (policy);
+ return policy;
+}
+
+
+PortableServer::RequestProcessingPolicy_ptr
+TAO_GOA::create_request_processing_policy (PortableServer::RequestProcessingPolicyValue value
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ PortableServer::RequestProcessingPolicy_ptr policy =
+ this->TAO_Regular_POA::create_request_processing_policy (value
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (policy);
+ return policy;
+}
+
+
+#endif /* TAO_HAS_MINIMUM_POA == 0 */
+
+char *
+TAO_GOA::the_name (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ char * name =
+ this->TAO_Regular_POA::the_name (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (name);
+ return name;
+}
+
+PortableServer::POA_ptr
+TAO_GOA::the_parent (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ PortableServer::POA_ptr parent =
+ this->TAO_Regular_POA::the_parent (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (parent);
+ return parent;
+}
+
+PortableServer::POAList *
+TAO_GOA::the_children (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ PortableServer::POAList *children =
+ this->TAO_Regular_POA::the_children (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (children);
+ return children;
+}
+
+PortableServer::POAManager_ptr
+TAO_GOA::the_POAManager (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ PortableServer::POAManager_ptr poa_manager =
+ this->TAO_Regular_POA::the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (poa_manager);
+ return poa_manager;
+}
+
+
+#if (TAO_HAS_MINIMUM_POA == 0)
+
+PortableServer::AdapterActivator_ptr
+TAO_GOA::the_activator (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ PortableServer::AdapterActivator_ptr activator =
+ this->TAO_Regular_POA::the_activator (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (activator);
+ return activator;
+}
+
+void
+TAO_GOA::the_activator (PortableServer::AdapterActivator_ptr adapter_activator
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->TAO_Regular_POA::the_activator (adapter_activator
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+PortableServer::ServantManager_ptr
+TAO_GOA::get_servant_manager (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::WrongPolicy))
+{
+ PortableServer::ServantManager_ptr servant_manager =
+ this->TAO_Regular_POA::get_servant_manager (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (servant_manager);
+ return servant_manager;
+}
+
+void
+TAO_GOA::set_servant_manager (PortableServer::ServantManager_ptr imgr
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::WrongPolicy))
+{
+ this->TAO_Regular_POA::set_servant_manager (imgr
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+PortableServer::Servant
+TAO_GOA::get_servant (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::NoServant,
+ PortableServer::POA::WrongPolicy))
+{
+ PortableServer::Servant servant =
+ this->TAO_Regular_POA::get_servant (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (servant);
+ return servant;
+}
+
+void
+TAO_GOA::set_servant (PortableServer::Servant servant
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::WrongPolicy))
+{
+ this->TAO_Regular_POA::set_servant (servant
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+#endif /* TAO_HAS_MINIMUM_POA == 0 */
+
+PortableServer::ObjectId *
+TAO_GOA::activate_object (PortableServer::Servant p_servant
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ServantAlreadyActive,
+ PortableServer::POA::WrongPolicy))
+{
+ PortableServer::ObjectId *object_id =
+ this->TAO_Regular_POA::activate_object (p_servant
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (object_id);
+ return object_id;
+}
+
+void
+TAO_GOA::activate_object_with_id (const PortableServer::ObjectId &id,
+ PortableServer::Servant p_servant
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ServantAlreadyActive,
+ PortableServer::POA::ObjectAlreadyActive,
+ PortableServer::POA::WrongPolicy))
+{
+ this->TAO_Regular_POA::activate_object_with_id (id,
+ p_servant
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+void
+TAO_GOA::deactivate_object (const PortableServer::ObjectId &oid
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ObjectNotActive,
+ PortableServer::POA::WrongPolicy))
+{
+ this->TAO_Regular_POA::deactivate_object (oid
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+CORBA::Object_ptr
+TAO_GOA::create_reference (const char *intf
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::WrongPolicy))
+{
+ CORBA::Object_ptr obj =
+ this->TAO_Regular_POA::create_reference (intf
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (obj);
+ return obj;
+}
+
+CORBA::Object_ptr
+TAO_GOA::create_reference_with_id (const PortableServer::ObjectId &oid,
+ const char *intf
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ CORBA::Object_ptr obj =
+ this->TAO_Regular_POA::create_reference_with_id (oid,
+ intf
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (obj);
+ return obj;
+}
+
+PortableServer::ObjectId *
+TAO_GOA::servant_to_id (PortableServer::Servant p_servant
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ServantNotActive,
+ PortableServer::POA::WrongPolicy))
+{
+ PortableServer::ObjectId *object_id =
+ this->TAO_Regular_POA::servant_to_id (p_servant
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (object_id);
+ return object_id;
+}
+
+CORBA::Object_ptr
+TAO_GOA::servant_to_reference (PortableServer::Servant p_servant
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ServantNotActive,
+ PortableServer::POA::WrongPolicy))
+{
+ CORBA::Object_ptr obj =
+ this->TAO_Regular_POA::servant_to_reference (p_servant
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (obj);
+ return obj;
+}
+
+
+PortableServer::Servant
+TAO_GOA::reference_to_servant (CORBA::Object_ptr reference
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ObjectNotActive,
+ PortableServer::POA::WrongAdapter,
+ PortableServer::POA::WrongPolicy))
+{
+ PortableServer::Servant servant =
+ this->TAO_Regular_POA::reference_to_servant (reference
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (servant);
+ return servant;
+}
+
+PortableServer::ObjectId *
+TAO_GOA::reference_to_id (CORBA::Object_ptr reference
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::WrongAdapter,
+ PortableServer::POA::WrongPolicy))
+{
+ PortableServer::ObjectId *object_id =
+ this->TAO_Regular_POA::reference_to_id (reference
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (object_id);
+ return object_id;
+}
+
+PortableServer::Servant
+TAO_GOA::id_to_servant (const PortableServer::ObjectId &oid
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ObjectNotActive,
+ PortableServer::POA::WrongPolicy))
+{
+ PortableServer::Servant servant =
+ this->TAO_Regular_POA::id_to_servant (oid
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (servant);
+ return servant;
+}
+
+CORBA::Object_ptr
+TAO_GOA::id_to_reference (const PortableServer::ObjectId &oid
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ObjectNotActive,
+ PortableServer::POA::WrongPolicy))
+{
+ CORBA::Object_ptr obj =
+ this->TAO_Regular_POA::id_to_reference (oid
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (obj);
+ return obj;
+}
+
+CORBA::OctetSeq *
+TAO_GOA::id (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return this->TAO_Regular_POA::id (ACE_ENV_SINGLE_ARG_PARAMETER);
+}
+
+int
+TAO_GOA::find_group_component (const CORBA::Object_ptr the_ref,
+ PortableGroup::TagGroupTaggedComponent &group)
+{
+ const TAO_MProfile& profiles = the_ref->_stubobj ()->base_profiles ();
+ const TAO_Profile* profile;
+ CORBA::ULong slot;
+
+ // Iterate through the tagged profiles, and
+ // create acceptors for the multicast ones.
+ slot = 0;
+ while (0 != (profile = profiles.get_profile (slot)))
+ {
+ if (this->find_group_component_in_profile (profile, group) == 0)
+ return 0;
+
+ ++slot;
+ }
+
+ // Not found.
+ return -1;
+}
+
+int
+TAO_GOA::find_group_component_in_profile (const TAO_Profile* profile,
+ PortableGroup::TagGroupTaggedComponent &group)
+{
+ // Iterate through the tagged components looking for
+ // group tag.
+ const TAO_Tagged_Components& components = profile->tagged_components ();
+
+ IOP::TaggedComponent tagged_component;
+ tagged_component.tag = IOP::TAG_GROUP;
+
+ // Try to find it.
+ if (components.get_component (tagged_component) == 0)
+ return -1;
+
+ // Found it.
+ const CORBA::Octet *buf =
+ tagged_component.component_data.get_buffer ();
+
+ TAO_InputCDR in_cdr (reinterpret_cast <const char*> (buf),
+ tagged_component.component_data.length ());
+
+ // Extract the Byte Order.
+ CORBA::Boolean byte_order;
+ if ((in_cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
+ return -1;
+ in_cdr.reset_byte_order (static_cast <int> (byte_order));
+
+ if ((in_cdr >> group) == 0)
+ return -1;
+
+ return 0;
+}
+
+int
+TAO_GOA::create_group_acceptors (CORBA::Object_ptr the_ref,
+ TAO_PortableGroup_Acceptor_Registry &acceptor_registry,
+ TAO_ORB_Core &orb_core
+ ACE_ENV_ARG_DECL)
+{
+ const TAO_MProfile& profiles = the_ref->_stubobj ()->base_profiles ();
+ const TAO_Profile* profile;
+ CORBA::ULong slot;
+ int num = 0;
+
+ // Iterate through the tagged profiles, and
+ // create acceptors for the multicast ones.
+ slot = 0;
+ while (0 != (profile = profiles.get_profile (slot)))
+ {
+ if (profile->supports_multicast ())
+ {
+ acceptor_registry.open (profile,
+ orb_core
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+ ++num;
+ }
+
+ ++slot;
+ }
+
+ // Return the number of acceptors registered.
+ return num;
+}
+
+void
+TAO_GOA::associate_group_with_ref (
+ CORBA::Object_ptr group_ref,
+ CORBA::Object_ptr obj_ref
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::NotAGroupObject))
+{
+ // Find the Group Component so that we can extract the Group ID.
+ PortableGroup::TagGroupTaggedComponent *tmp_group_id;
+ ACE_NEW_THROW_EX (tmp_group_id,
+ PortableGroup::TagGroupTaggedComponent,
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK;
+
+ PortableGroup::TagGroupTaggedComponent_var group_id = tmp_group_id;
+
+ if (this->find_group_component (group_ref, group_id.inout ()) != 0)
+ {
+ // Group component wasn't found. The group reference
+ // that was passed in must be bogus.
+ ACE_THROW (PortableGroup::NotAGroupObject ());
+ }
+
+ PortableGroup_Request_Dispatcher *rd =
+ dynamic_cast <PortableGroup_Request_Dispatcher*>(
+ this->orb_core_.request_dispatcher());
+
+ // Create the acceptors necessary to receive requests for the
+ // specified group reference.
+ this->create_group_acceptors (group_ref,
+ rd->acceptor_registry_,
+ this->orb_core_
+ ACE_ENV_ARG_PARAMETER);
+
+ ACE_CHECK;
+
+
+ // Add a mapping from GroupId to Object key in the PortableGroup
+ const TAO::ObjectKey &key =
+ obj_ref->_stubobj ()->profile_in_use ()->object_key ();
+ rd->group_map_.add_groupid_objectkey_pair (group_id._retn (),
+ key
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/GOA.h b/TAO/orbsvcs/orbsvcs/PortableGroup/GOA.h
new file mode 100644
index 00000000000..d5bbdeb04dd
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/GOA.h
@@ -0,0 +1,329 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file GOA.h
+ *
+ * $Id$
+ *
+ * Header file for Group Object Adapter
+ *
+ * @author Several
+ */
+//=============================================================================
+
+#ifndef TAO_GOA_H
+#define TAO_GOA_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 "tao/PortableServer/Regular_POA.h"
+
+// This is to remove "inherits via dominance" warnings from MSVC.
+// MSVC is being a little too paranoid.
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:4250)
+#endif /* _MSC_VER */
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class TAO_Profile;
+class TAO_PortableGroup_Acceptor_Registry;
+
+/**
+ * @class TAO_GOA
+ *
+ * @brief Implementation of the PortableGroup::GOA interface.
+ *
+ * Implementation of the PortableGroup::GOA interface.
+ */
+class TAO_PortableGroup_Export TAO_GOA :
+ public virtual PortableGroup::GOA,
+ public virtual TAO_Regular_POA
+{
+public:
+ // Methods added by the
+ /// @name MIOP specification methods
+ //@{
+ virtual PortableServer::ObjectId * create_id_for_reference (
+ CORBA::Object_ptr the_ref
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS
+ )
+ ACE_THROW_SPEC ((
+ CORBA::SystemException,
+ PortableGroup::NotAGroupObject
+ ));
+
+
+ virtual PortableGroup::IDs * reference_to_ids (
+ CORBA::Object_ptr the_ref
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS
+ )
+ ACE_THROW_SPEC ((
+ CORBA::SystemException,
+ PortableGroup::NotAGroupObject
+ ));
+
+ virtual void associate_reference_with_id (
+ CORBA::Object_ptr ref,
+ const PortableServer::ObjectId & oid
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS
+ )
+ ACE_THROW_SPEC ((
+ CORBA::SystemException,
+ PortableGroup::NotAGroupObject
+ ));
+
+ virtual void disassociate_reference_with_id (
+ CORBA::Object_ptr ref,
+ const PortableServer::ObjectId & oid
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS
+ )
+ ACE_THROW_SPEC ((
+ CORBA::SystemException,
+ PortableGroup::NotAGroupObject
+ ));
+ //@}
+
+ // Standard POA interface methods
+ PortableServer::POA_ptr create_POA (const char *adapter_name,
+ PortableServer::POAManager_ptr poa_manager,
+ const CORBA::PolicyList &policies
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::AdapterAlreadyExists,
+ PortableServer::POA::InvalidPolicy));
+
+ PortableServer::POA_ptr find_POA (const char *adapter_name,
+ CORBA::Boolean activate_it
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::AdapterNonExistent));
+
+ void destroy (CORBA::Boolean etherealize_objects,
+ CORBA::Boolean wait_for_completion
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+#if (TAO_HAS_MINIMUM_POA == 0)
+
+ PortableServer::ThreadPolicy_ptr create_thread_policy (PortableServer::ThreadPolicyValue value
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+#endif /* TAO_HAS_MINIMUM_POA == 0 */
+
+ PortableServer::LifespanPolicy_ptr create_lifespan_policy (PortableServer::LifespanPolicyValue value
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ PortableServer::IdUniquenessPolicy_ptr create_id_uniqueness_policy (PortableServer::IdUniquenessPolicyValue value
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ PortableServer::IdAssignmentPolicy_ptr create_id_assignment_policy (PortableServer::IdAssignmentPolicyValue value
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+#if (TAO_HAS_MINIMUM_POA == 0)
+
+ PortableServer::ImplicitActivationPolicy_ptr create_implicit_activation_policy (PortableServer::ImplicitActivationPolicyValue value
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ PortableServer::ServantRetentionPolicy_ptr create_servant_retention_policy (PortableServer::ServantRetentionPolicyValue value
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ PortableServer::RequestProcessingPolicy_ptr create_request_processing_policy (PortableServer::RequestProcessingPolicyValue value
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+#endif /* TAO_HAS_MINIMUM_POA == 0 */
+
+ char * the_name (ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ PortableServer::POA_ptr the_parent (ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ PortableServer::POAList *the_children (ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ PortableServer::POAManager_ptr the_POAManager (ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+#if (TAO_HAS_MINIMUM_POA == 0)
+
+ PortableServer::AdapterActivator_ptr the_activator (ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ void the_activator (PortableServer::AdapterActivator_ptr adapter_activator
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ PortableServer::ServantManager_ptr get_servant_manager (ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::WrongPolicy));
+
+ void set_servant_manager (PortableServer::ServantManager_ptr imgr
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::WrongPolicy));
+
+ PortableServer::Servant get_servant (ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::NoServant,
+ PortableServer::POA::WrongPolicy));
+
+ void set_servant (PortableServer::Servant servant
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::WrongPolicy));
+
+#endif /* TAO_HAS_MINIMUM_POA == 0 */
+
+ PortableServer::ObjectId *activate_object (PortableServer::Servant p_servant
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ServantAlreadyActive,
+ PortableServer::POA::WrongPolicy));
+
+ void activate_object_with_id (const PortableServer::ObjectId &id,
+ PortableServer::Servant p_servant
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ServantAlreadyActive,
+ PortableServer::POA::ObjectAlreadyActive,
+ PortableServer::POA::WrongPolicy));
+
+ void deactivate_object (const PortableServer::ObjectId &oid
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ObjectNotActive,
+ PortableServer::POA::WrongPolicy));
+
+ CORBA::Object_ptr create_reference (const char *intf
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::WrongPolicy));
+
+ CORBA::Object_ptr create_reference_with_id (const PortableServer::ObjectId &oid,
+ const char *intf
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ PortableServer::ObjectId *servant_to_id (PortableServer::Servant p_servant
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ServantNotActive,
+ PortableServer::POA::WrongPolicy));
+
+ CORBA::Object_ptr servant_to_reference (PortableServer::Servant p_servant
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ServantNotActive,
+ PortableServer::POA::WrongPolicy));
+
+ PortableServer::Servant reference_to_servant (CORBA::Object_ptr reference
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ObjectNotActive,
+ PortableServer::POA::WrongAdapter,
+ PortableServer::POA::WrongPolicy));
+
+ PortableServer::ObjectId *reference_to_id (CORBA::Object_ptr reference
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::WrongAdapter,
+ PortableServer::POA::WrongPolicy));
+
+ PortableServer::Servant id_to_servant (const PortableServer::ObjectId &oid
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ObjectNotActive,
+ PortableServer::POA::WrongPolicy));
+
+ CORBA::Object_ptr id_to_reference (const PortableServer::ObjectId &oid
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableServer::POA::ObjectNotActive,
+ PortableServer::POA::WrongPolicy));
+
+ CORBA::OctetSeq *id (ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ // End standard POA interface methods.
+
+ TAO_GOA (const String &name,
+ PortableServer::POAManager_ptr poa_manager,
+ const TAO_POA_Policy_Set &policies,
+ TAO_Root_POA *parent,
+ ACE_Lock &lock,
+ TAO_SYNCH_MUTEX &thread_lock,
+ TAO_ORB_Core &orb_core,
+ TAO_Object_Adapter *object_adapter
+ ACE_ENV_ARG_DECL);
+
+ virtual ~TAO_GOA (void);
+
+ // Used to force the initialization of the code.
+ static int Initializer (void);
+
+protected:
+
+ /// Template method for creating new POA's of this type.
+ virtual TAO_Root_POA *new_POA (const String &name,
+ PortableServer::POAManager_ptr poa_manager,
+ const TAO_POA_Policy_Set &policies,
+ TAO_Root_POA *parent,
+ ACE_Lock &lock,
+ TAO_SYNCH_MUTEX &thread_lock,
+ TAO_ORB_Core &orb_core,
+ TAO_Object_Adapter *object_adapter
+ ACE_ENV_ARG_DECL);
+
+ int find_group_component (const CORBA::Object_ptr the_ref,
+ PortableGroup::TagGroupTaggedComponent &group);
+
+ int find_group_component_in_profile (
+ const TAO_Profile* profile,
+ PortableGroup::TagGroupTaggedComponent &group
+ );
+
+ int create_group_acceptors (
+ CORBA::Object_ptr the_ref,
+ TAO_PortableGroup_Acceptor_Registry &acceptor_registry,
+ TAO_ORB_Core &orb_core
+ ACE_ENV_ARG_DECL
+ );
+
+ /// Helper function to associate group references with
+ /// object references.
+ void associate_group_with_ref (
+ CORBA::Object_ptr group_ref,
+ CORBA::Object_ptr obj_ref
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::NotAGroupObject));
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+// ****************************************************************
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif /* _MSC_VER */
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_GOA_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/MIOP.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/MIOP.cpp
new file mode 100644
index 00000000000..ac2bbec66cf
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/MIOP.cpp
@@ -0,0 +1,29 @@
+#include "orbsvcs/PortableGroup/MIOP.h"
+#include "orbsvcs/PortableGroup/UIPMC_Factory.h"
+#include "ace/Service_Config.h"
+#include "orbsvcs/PortableGroup/PortableGroup_Loader.h"
+#include "orbsvcs/PortableGroup/PG_Object_Adapter_Factory.h"
+
+ACE_RCSID (PortableGroup,
+ UIPMC_Factory,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace TAO
+{
+ /*static*/ int
+ MIOP_Loader::Initializer (void)
+ {
+ ACE_Service_Config::process_directive (
+ ace_svc_desc_TAO_PortableGroup_Loader);
+
+ ACE_Service_Config::process_directive (
+ ace_svc_desc_TAO_PG_Object_Adapter_Factory);
+
+ return ACE_Service_Config::process_directive (
+ ace_svc_desc_TAO_UIPMC_Protocol_Factory);
+ }
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/MIOP.h b/TAO/orbsvcs/orbsvcs/PortableGroup/MIOP.h
new file mode 100644
index 00000000000..7e6219a5e67
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/MIOP.h
@@ -0,0 +1,45 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file MIOP.h
+ *
+ * $Id$
+ *
+ * @author Bala Natarajan
+ */
+//=============================================================================
+#ifndef TAO_MIOP_H
+#define TAO_MIOP_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 "tao/Versioned_Namespace.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace TAO
+{
+
+ class TAO_PortableGroup_Export MIOP_Loader
+ {
+ public:
+ /// Used to force the insertion of UIPMC_Factory in the service
+ /// configurator.
+ static int Initializer (void);
+ };
+
+ static int
+ Requires_MIOP_Initializer = MIOP_Loader::Initializer ();
+
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /*TAO_MIOP_H*/
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Default_Property_Validator.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Default_Property_Validator.cpp
new file mode 100644
index 00000000000..fe3650caa71
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Default_Property_Validator.cpp
@@ -0,0 +1,151 @@
+#include "orbsvcs/PortableGroup/PG_Default_Property_Validator.h"
+#include "orbsvcs/PortableGroup/PG_Operators.h"
+
+
+ACE_RCSID (PortableGroup,
+ PG_Default_Property_Validator,
+ "$Id$")
+
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO_PG_Default_Property_Validator::TAO_PG_Default_Property_Validator (void)
+ : membership_ (1),
+ factories_ (1)
+{
+ this->membership_.length (1);
+ this->membership_[0].id = CORBA::string_dup ("org.omg.PortableGroup.MembershipStyle");
+
+ this->factories_.length (1);
+ this->factories_[0].id = CORBA::string_dup ("org.omg.PortableGroup.Factories");
+}
+
+TAO_PG_Default_Property_Validator::~TAO_PG_Default_Property_Validator (void)
+{
+}
+
+void
+TAO_PG_Default_Property_Validator::validate_property (
+ const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty))
+{
+ const CORBA::ULong len = props.length ();
+
+ for (CORBA::ULong i = 0; i < len; ++i)
+ {
+ const PortableGroup::Property & property = props[i];
+
+ if (property.nam == this->membership_)
+ {
+ PortableGroup::MembershipStyleValue membership;
+ if (!(property.val >>= membership)
+ || (membership != PortableGroup::MEMB_APP_CTRL
+ && membership != PortableGroup::MEMB_INF_CTRL))
+ ACE_THROW (PortableGroup::InvalidProperty (property.nam,
+ property.val));
+ }
+ else if (property.nam == this->factories_)
+ {
+ const PortableGroup::FactoriesValue * factories;
+ if (!(property.val >>= factories))
+ ACE_THROW (PortableGroup::InvalidProperty (property.nam,
+ property.val));
+ else
+ {
+ const CORBA::ULong flen = factories->length ();
+
+ if (flen == 0)
+ ACE_THROW (PortableGroup::InvalidProperty (property.nam,
+ property.val));
+
+ for (CORBA::ULong j = 0; j < flen; ++j)
+ {
+ const PortableGroup::FactoryInfo & factory_info =
+ (*factories)[j];
+
+ if (CORBA::is_nil (factory_info.the_factory.in ())
+ || factory_info.the_location.length () == 0)
+ ACE_THROW (PortableGroup::InvalidProperty (property.nam,
+ property.val));
+ }
+ }
+ }
+ }
+}
+
+void
+TAO_PG_Default_Property_Validator::validate_criteria (
+ const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidCriteria,
+ PortableGroup::CannotMeetCriteria))
+{
+ const CORBA::ULong len = props.length ();
+ PortableGroup::Criteria invalid_criteria;
+
+ // Optimize for the worst case scenario where all properties are
+ // invalid.
+ invalid_criteria.length (len);
+
+ /// The invalid criteria index.
+ CORBA::ULong p = 0;
+
+ for (CORBA::ULong i = 0; i < len; ++i)
+ {
+ const PortableGroup::Property & property = props[i];
+
+ if (property.nam == this->membership_)
+ {
+ PortableGroup::MembershipStyleValue membership;
+ if (!(property.val >>= membership)
+ || (membership != PortableGroup::MEMB_APP_CTRL
+ && membership != PortableGroup::MEMB_INF_CTRL))
+ invalid_criteria[p++] = property;
+ }
+ else if (property.nam == this->factories_)
+ {
+ PortableGroup::FactoriesValue * factories;
+ if (!(property.val >>= factories))
+ invalid_criteria[p++] = property;
+ else
+ {
+ const CORBA::ULong flen = factories->length ();
+
+ if (flen == 0)
+ invalid_criteria[p++] = property;
+ else
+ {
+ for (CORBA::ULong j = 0; j < flen; ++j)
+ {
+ const PortableGroup::FactoryInfo & factory_info =
+ (*factories)[j];
+
+ if (CORBA::is_nil (factory_info.the_factory.in ())
+ || factory_info.the_location.length () == 0)
+ {
+ invalid_criteria[p++] = property;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (p > 0)
+ {
+ // Reduce the length of the invalid criteria sequence in an
+ // effort to optimize the copying that will occur when the below
+ // exception is thrown. Reducing the length is fast since no
+ // deallocations should occur.
+ invalid_criteria.length (p);
+
+ ACE_THROW (PortableGroup::InvalidCriteria (invalid_criteria));
+ }
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Default_Property_Validator.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Default_Property_Validator.h
new file mode 100644
index 00000000000..9f9ced075d9
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Default_Property_Validator.h
@@ -0,0 +1,86 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Default_Property_Validator.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+#ifndef TAO_PG_DEFAULT_PROPERTY_VALIDATOR_H
+#define TAO_PG_DEFAULT_PROPERTY_VALIDATOR_H
+
+#include /**/ "ace/pre.h"
+
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+#include "orbsvcs/PortableGroupC.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class TAO_PG_Default_Property_Validator
+ *
+ * @brief Default property validator implementation.
+ *
+ * This Property_Validator verifies that all properties defined in the
+ * PortableGroup IDL module are valid. This property validator can be
+ * subclassed to validate a different property set.
+ */
+class TAO_PortableGroup_Export TAO_PG_Default_Property_Validator
+{
+public:
+
+ /// Constructor.
+ TAO_PG_Default_Property_Validator (void);
+
+ /// Destructor
+ virtual ~TAO_PG_Default_Property_Validator (void);
+
+ /// Validate the given properties. Throw an exception when the
+ /// first invalid property is encountered. The remaining properties
+ /// will not be validated.
+ virtual void validate_property (const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty));
+
+ /// Validate the given properties/criteria. All criteria
+ /// will be validated regardless of whether or not an invalid
+ /// property was encountered.
+ virtual void validate_criteria (const PortableGroup::Properties & criteria
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidCriteria,
+ PortableGroup::CannotMeetCriteria));
+
+private:
+
+ /**
+ * @name Pre-initialize property Names.
+ *
+ * These properties are pre-initialized once to reduce property
+ * validation overhead. Note that the InitialNumberReplicas and
+ * MinimumNumberReplicas properties are not validated since there are
+ * no restrictions imposed by TAO's PortableGroup implementation
+ * regarding the number of such members.
+ */
+ //@{
+ PortableGroup::Name membership_;
+ PortableGroup::Name factories_;
+ //@}
+
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PG_PROPERTY_VALIDATOR_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_FactoryRegistry.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_FactoryRegistry.cpp
new file mode 100644
index 00000000000..330d3984006
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_FactoryRegistry.cpp
@@ -0,0 +1,733 @@
+// -*- C++ -*-
+// $Id$
+
+#include "orbsvcs/PortableGroup/PG_FactoryRegistry.h"
+
+#include "ace/Get_Opt.h"
+#include "ace/Vector_T.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Auto_Ptr.h"
+#include "tao/debug.h"
+#include "tao/ORB_Constants.h"
+#include "tao/PortableServer/POAManagerC.h"
+#include "orbsvcs/PortableGroup/PG_Operators.h" // operator == on CosNaming::Name
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Use this macro at the beginning of CORBA methods
+// to aid in debugging.
+#define METHOD_ENTRY(name) \
+ if (TAO_debug_level <= 6){} else \
+ 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){} else \
+ ACE_DEBUG (( LM_DEBUG, \
+ "Leave %s\n", #name \
+ )); \
+ return /* value goes here */
+
+TAO::PG_FactoryRegistry::PG_FactoryRegistry (const char * name)
+ : identity_(name)
+ , orb_ (0)
+ , poa_ (0)
+ , object_id_ (0)
+ , this_obj_ (0)
+ , ior_output_file_(0)
+ , ns_name_(0)
+ , naming_context_(0)
+ , this_name_(1)
+ , quit_on_idle_(0)
+ , quit_state_(LIVE)
+ , linger_(0)
+{
+}
+
+TAO::PG_FactoryRegistry::~PG_FactoryRegistry (void)
+{
+}
+
+//////////////////////////////////////////////////////
+// PG_FactoryRegistry public, non-CORBA methods
+
+int TAO::PG_FactoryRegistry::parse_args (int argc, char * argv[])
+{
+ ACE_Get_Opt get_opts (argc, argv, "o:n:q");
+ int c;
+
+ while ((c = get_opts ()) != -1)
+ {
+ switch (c)
+ {
+ case 'o':
+ {
+ this->ior_output_file_ = get_opts.opt_arg ();
+ break;
+ }
+ case 'n':
+ {
+ this->ns_name_ = get_opts.opt_arg();
+ break;
+ }
+ case 'q':
+ {
+ this->quit_on_idle_ = 1;
+ break;
+ }
+
+ case '?':
+ // fall thru
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s"
+ " -o <registry ior file>"
+ " -n <name to use to register with name service>"
+ " -q{uit on idle}"
+ "\n",
+ argv [0]),
+ -1);
+ break;
+ }
+ }
+ // Indicates sucessful parsing of the command line
+ return 0;
+}
+
+const char * TAO::PG_FactoryRegistry::identity () const
+{
+ return this->identity_.c_str();
+}
+
+void TAO::PG_FactoryRegistry::_remove_ref (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+{
+ this->quit_state_ = GONE;
+}
+
+int TAO::PG_FactoryRegistry::idle (int & result ACE_ENV_ARG_DECL_NOT_USED)
+{
+ result = 0;
+ int quit = 0;
+ if (this->quit_state_ == GONE)
+ {
+ if (linger_ < 2)
+ {
+ ++linger_;
+ }
+ else
+ {
+ quit = 1;
+ }
+ }
+ return quit;
+}
+
+
+int TAO::PG_FactoryRegistry::fini (ACE_ENV_SINGLE_ARG_DECL)
+{
+ if (this->ior_output_file_ != 0)
+ {
+ ACE_OS::unlink (this->ior_output_file_);
+ this->ior_output_file_ = 0;
+ }
+ if (this->ns_name_ != 0)
+ {
+ this->naming_context_->unbind (this_name_
+ ACE_ENV_ARG_PARAMETER);
+ this->ns_name_ = 0;
+ }
+ return 0;
+}
+
+
+void TAO::PG_FactoryRegistry::init (CORBA::ORB_ptr orb, PortableServer::POA_ptr poa ACE_ENV_ARG_DECL)
+{
+ ACE_ASSERT (CORBA::is_nil (this->orb_.in ()));
+ ACE_ASSERT (CORBA::is_nil (this->poa_.in ()));
+ this->orb_ = CORBA::ORB::_duplicate (orb);
+ this->poa_ = PortableServer::POA::_duplicate (poa);
+ ACE_ASSERT ( ! CORBA::is_nil (this->orb_.in ()));
+ ACE_ASSERT ( ! CORBA::is_nil (this->poa_.in ()));
+
+ // Register with the POA.
+ this->object_id_ = this->poa_->activate_object (this ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // find my identity as a corba object
+ this->this_obj_ =
+ this->poa_->id_to_reference (object_id_.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // and create a ior string
+ this->ior_ = this->orb_->object_to_string (this->this_obj_.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+}
+
+int TAO::PG_FactoryRegistry::init (CORBA::ORB_ptr orb
+ ACE_ENV_ARG_DECL)
+{
+ int result = 0;
+
+ this->orb_ = CORBA::ORB::_duplicate (orb);
+
+ // Use the ROOT POA for now
+ CORBA::Object_var poa_object =
+ this->orb_->resolve_initial_references (TAO_OBJID_ROOTPOA
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (-1);
+
+ if (CORBA::is_nil (poa_object.in ()))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT (" (%P|%t) Unable to initialize the POA.\n")),
+ -1);
+
+ // Get the POA object.
+ this->poa_ =
+ PortableServer::POA::_narrow (poa_object.in ()
+ ACE_ENV_ARG_PARAMETER);
+
+ ACE_CHECK_RETURN (-1);
+
+ if (CORBA::is_nil (this->poa_.in()))
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT (" (%P|%t) Unable to narrow the POA.\n")),
+ -1);
+ }
+
+ PortableServer::POAManager_var poa_manager =
+ this->poa_->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN(-1);
+
+ poa_manager->activate (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN(-1);
+
+ // Register with the POA.
+ this->object_id_ = this->poa_->activate_object (this ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN(-1);
+
+ // find my identity as a corba object
+ this->this_obj_ =
+ this->poa_->id_to_reference (object_id_.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN(-1);
+
+
+ // and create a ior string
+ this->ior_ = this->orb_->object_to_string (this->this_obj_.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN(-1);
+
+
+ if (this->ior_output_file_ != 0)
+ {
+ this->identity_ = "file:";
+ this->identity_ += this->ior_output_file_;
+ result = write_ior_file (this->ior_output_file_,
+ this->ior_.in ());
+ }
+
+ if (this->ns_name_ != 0)
+ {
+ this->identity_ = "name:";
+ this->identity_ += this->ns_name_;
+
+ CORBA::Object_var naming_obj =
+ this->orb_->resolve_initial_references ("NameService" ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN(-1);
+
+ if (CORBA::is_nil(naming_obj.in ())){
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%T %n (%P|%t) Unable to find the Naming Service\n"),
+ 1);
+ }
+
+ this->naming_context_ =
+ CosNaming::NamingContext::_narrow (naming_obj.in () ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN(-1);
+
+ this->this_name_.length (1);
+ this->this_name_[0].id = CORBA::string_dup (this->ns_name_);
+
+ this->naming_context_->rebind (this->this_name_, this->this_obj_.in() //CORBA::Object::_duplicate(this_obj)
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN(-1);
+ }
+
+ return result;
+}
+
+
+::PortableGroup::FactoryRegistry_ptr TAO::PG_FactoryRegistry::reference()
+{
+ // narrow and duplicate
+ return ::PortableGroup::FactoryRegistry::_narrow(this->this_obj_.in ());
+}
+
+
+//////////////////////////////////////////
+// PG_FactoryRegistry CORBA methods
+
+/* Reference:info
+ typedef CosNaming::Name Name;
+ typedef Name Location;
+ struct FactoryInfo {
+ GenericFactory the_factory;
+ Location the_location;
+ Criteria the_criteria;
+ };
+ typedef sequence<FactoryInfo> FactoryInfos;
+*/
+
+TAO::PG_FactoryRegistry::RoleInfo::RoleInfo(size_t estimated_number_entries)
+ : infos_(estimated_number_entries)
+{
+}
+
+
+void TAO::PG_FactoryRegistry::register_factory (
+ const char * role,
+ const char * type_id,
+ const PortableGroup::FactoryInfo & factory_info
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((
+ CORBA::SystemException
+ , PortableGroup::MemberAlreadyPresent
+ , PortableGroup::TypeConflict))
+{
+ METHOD_ENTRY(TAO::PG_FactoryRegistry::register_factory);
+
+ RoleInfo * role_info = 0;
+ auto_ptr<RoleInfo> safe_entry;
+ if (this->registry_.find(role, role_info) != 0)
+ {
+ ACE_DEBUG(( LM_DEBUG,
+ "%s: adding new role: %s:%s\n",
+ this->identity_.c_str(), role, type_id));
+
+ // Note the 5. It's a guess about the number of factories
+ // that might exist for any particular role object.
+ // todo: make it a parameter.
+ ACE_NEW_THROW_EX (role_info,
+ RoleInfo(5),
+ CORBA::NO_MEMORY());
+ ACE_CHECK;
+
+ ACE_AUTO_PTR_RESET (safe_entry, role_info, RoleInfo);
+ role_info->type_id_ = type_id;
+ }
+ else
+ {
+ if (role_info->type_id_ != type_id)
+ {
+ ACE_THROW ( PortableGroup::TypeConflict() );
+ }
+ }
+
+ PortableGroup::FactoryInfos & infos = role_info->infos_;;
+ size_t length = infos.length();
+ for (size_t nInfo = 0; nInfo < length; ++nInfo)
+ {
+ PortableGroup::FactoryInfo & info = infos[nInfo];
+ if (info.the_location == factory_info.the_location)
+ {
+ ACE_ERROR(( LM_ERROR,
+ "%s: Attempt to register duplicate location %s for role: %s\n" ,
+ this->identity_.c_str(),
+ static_cast<const char *> (info.the_location[0].id),
+ role));
+ ACE_THROW (PortableGroup::MemberAlreadyPresent() );
+ }
+ }
+
+ infos.length(length + 1);
+ infos[length] = factory_info;
+
+ if (safe_entry.get() != 0)
+ {
+ this->registry_.bind(role, safe_entry.release());
+ }
+
+ ACE_DEBUG(( LM_DEBUG,
+ "%s: Added factory: [%d] %s@%s \n",
+ this->identity_.c_str(),
+ static_cast<int> (length + 1),
+ role,
+ static_cast<const char *> (factory_info.the_location[0].id)
+ ));
+
+ METHOD_RETURN(TAO::PG_FactoryRegistry::register_factory);
+}
+
+void TAO::PG_FactoryRegistry::unregister_factory (
+ const char * role,
+ const PortableGroup::Location & location
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException, PortableGroup::MemberNotFound))
+{
+ METHOD_ENTRY(TAO::PG_FactoryRegistry::unregister_factory);
+
+ RoleInfo * role_info = 0;
+ if (this->registry_.find(role, role_info) == 0)
+ {
+ PortableGroup::FactoryInfos & infos = role_info->infos_;
+ int found = 0;
+ size_t length = infos.length();
+ for (size_t nInfo = 0; !found && nInfo < length; ++nInfo)
+ {
+ PortableGroup::FactoryInfo & info = infos[nInfo];
+ if (info.the_location == location)
+ {
+ found = 1;
+
+ ACE_ERROR(( LM_INFO,
+ "%s: Unregistering factory %s@%s\n",
+ this->identity_.c_str(),
+ role,
+ static_cast<const char *> (location[0].id)
+ ));
+ if (length > 1)
+ {
+ // if this is not the last entry
+ if (nInfo + 1 < length)
+ {
+ // move last entry into newly-emptied slot
+ infos[nInfo] = infos[length - 1];
+ nInfo = length -1;
+ }
+ infos.length(nInfo);
+ }
+ else
+ {
+ ACE_ASSERT ( length == 1 );
+ if (this->registry_.unbind (role) == 0)
+ {
+ ACE_DEBUG(( LM_INFO,
+ "%s: No more factories registered for %s\n",
+ this->identity_.c_str(),
+ role
+ ));
+ delete role_info;
+ }
+ else
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%s: LOGIC ERROR AT " __FILE__ " (%d): Entry to be deleted disappeared\n",
+ this->identity_.c_str(),
+ __LINE__));
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ ACE_ERROR(( LM_ERROR,
+ "%s, Attempt to unregister factory for unknown role %s\n",
+ this->identity_.c_str(),
+ role
+ ));
+ ACE_THROW ( PortableGroup::MemberNotFound() );
+ }
+
+ //////////////////////
+ // request complete
+ // check quit-on-idle
+ if (registry_.current_size() == 0 && quit_state_ == LIVE)
+ {
+ ACE_ERROR(( LM_INFO,
+ "%s is idle\n",
+ identity()
+ ));
+ if (quit_on_idle_)
+ {
+ this->poa_->deactivate_object (this->object_id_.in ()
+ ACE_ENV_ARG_PARAMETER);
+ quit_state_ = DEACTIVATED;
+ }
+ }
+
+ METHOD_RETURN(TAO::PG_FactoryRegistry::unregister_factory);
+}
+
+void TAO::PG_FactoryRegistry::unregister_factory_by_role (
+ const char * role
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ METHOD_ENTRY(TAO::PG_FactoryRegistry::unregister_factory_by_role);
+
+ RoleInfo * role_info = 0;
+ if (this->registry_.unbind(role, role_info) == 0)
+ {
+ ACE_DEBUG(( LM_DEBUG,
+ "%s: Unregistering all factories for role %s\n",
+ this->identity_.c_str(),
+ role
+ ));
+ // delete the entire set of factories for this location.
+ delete role_info;
+ }
+ else
+ {
+ ACE_ERROR(( LM_INFO,
+ "%s: Unregister_factory_by_role: unknown role: %s\n",
+ this->identity_.c_str(),
+ role
+ ));
+ }
+
+ /////////////////////
+ // Function complete
+ // check quit options
+ if (registry_.current_size() == 0 && quit_state_ == LIVE)
+ {
+ ACE_ERROR(( LM_INFO,
+ "%s is idle\n",
+ identity()
+ ));
+ if (quit_on_idle_)
+ {
+ this->poa_->deactivate_object (this->object_id_.in ()
+ ACE_ENV_ARG_PARAMETER);
+ quit_state_ = DEACTIVATED;
+ }
+ }
+
+ METHOD_RETURN(TAO::PG_FactoryRegistry::unregister_factory_by_role);
+}
+
+void TAO::PG_FactoryRegistry::unregister_factory_by_location (
+ const PortableGroup::Location & location
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ METHOD_ENTRY(TAO::PG_FactoryRegistry::unregister_factory_by_location);
+
+ ////////////////////////////////////////////
+ // a vector of roles that need to be deleted.
+ ACE_Vector<ACE_CString> emptyRoles;
+
+ // iterate through the registery
+ for (RegistryType_Iterator it = this->registry_.begin();
+ it != this->registry_.end();
+ ++it)
+ {
+ RegistryType_Entry & entry = *it;
+ ACE_CString & role = entry.ext_id_;
+ RoleInfo * role_info = entry.int_id_;
+
+ PortableGroup::FactoryInfos & infos = role_info->infos_;
+ // ACE_ERROR((LM_INFO, "unregister_factory_by_location: Checking role %s\n", role.c_str() ));
+
+ int found = 0;
+ size_t length = infos.length();
+ for (size_t nInfo = 0; !found && nInfo < length; ++nInfo)
+ {
+ PortableGroup::FactoryInfo & info = infos[nInfo];
+ if (info.the_location == location)
+ {
+
+ ACE_ERROR((LM_INFO,
+ "%s: Unregister_factory_by_location: Removing: [%d] %s@%s\n",
+ this->identity_.c_str(),
+ static_cast<int> (nInfo),
+ role.c_str(),
+ static_cast<const char *> (location[0].id)
+ ));
+ found = 1;
+ if (length > 1)
+ {
+ while (nInfo + 1 < length)
+ {
+ ACE_ERROR((LM_INFO,
+ "%s: Unregister_factory_by_location: Move: [%d] %s to [%d]\n",
+ this->identity_.c_str(),
+ (int)nInfo + 1, role.c_str(), (int)nInfo
+ ));
+ infos[nInfo] = infos[nInfo + 1];
+ nInfo += 1;
+ }
+ ACE_ERROR((LM_INFO,
+ "%s: unregister_factory_by_location: New length [%d] %s\n",
+ this->identity_.c_str(),
+ (int)nInfo, role.c_str()
+ ));
+ infos.length(nInfo);
+ }
+ else
+ {
+ ACE_ERROR((LM_INFO,
+ "%s: Removed all entries for %s\n",
+ this->identity_.c_str(),
+ role.c_str()
+ ));
+ ACE_ASSERT ( length == 1 );
+ // remember entries to be deleted
+ emptyRoles.push_back(entry.ext_id_);
+ }
+ }
+ }
+ }
+
+ // now remove any roles that became empty
+
+ for (size_t nRole = 0; nRole < emptyRoles.size(); ++nRole)
+ {
+ ACE_ERROR((LM_INFO,
+ "%s: Remove role %s\n",
+ this->identity_.c_str(),
+ emptyRoles[nRole].c_str()
+ ));
+ RoleInfo * role_info;
+ if (this->registry_.unbind(emptyRoles[nRole], role_info) == 0)
+ {
+ delete role_info;
+ }
+ else
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%s: LOGIC ERROR AT " __FILE__ " (%d): Role to be deleted disappeared\n",
+ this->identity_.c_str(),
+ __LINE__));
+ }
+ }
+ //////////////////////////
+ // If all types are gone...
+ if (registry_.current_size() == 0 && quit_state_ == LIVE)
+ {
+ ACE_ERROR(( LM_INFO,
+ "%s is idle\n",
+ identity()
+ ));
+ if (quit_on_idle_)
+ {
+ this->poa_->deactivate_object (this->object_id_.in ()
+ ACE_ENV_ARG_PARAMETER);
+ quit_state_ = DEACTIVATED;
+ }
+ }
+
+ METHOD_RETURN(TAO::PG_FactoryRegistry::unregister_factory_by_location);
+}
+
+::PortableGroup::FactoryInfos * TAO::PG_FactoryRegistry::list_factories_by_role (
+ const char * role,
+ CORBA::String_out type_id
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ METHOD_ENTRY(TAO::PG_FactoryRegistry::list_factories_by_role);
+
+ // allocate stucture to be returned.
+ PortableGroup::FactoryInfos_var result = 0;
+ ACE_NEW_THROW_EX (result, ::PortableGroup::FactoryInfos(),
+ CORBA::NO_MEMORY (TAO::VMCID, CORBA::COMPLETED_NO));
+
+ ACE_CHECK_RETURN (0);
+
+ RoleInfo * role_info = 0;
+ if (this->registry_.find(role, role_info) == 0)
+ {
+ type_id = CORBA::string_dup(role_info->type_id_.c_str());
+ (*result) = role_info->infos_;
+ }
+ else
+ {
+ type_id = CORBA::string_dup("");
+ ACE_ERROR(( LM_INFO,
+ "%s: list_factories_by_role: unknown role %s\n",
+ this->identity_.c_str(),
+ role
+ ));
+ }
+ METHOD_RETURN(TAO::PG_FactoryRegistry::list_factories_by_role) result._retn();
+}
+
+::PortableGroup::FactoryInfos * TAO::PG_FactoryRegistry::list_factories_by_location (
+ const PortableGroup::Location & location
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ METHOD_ENTRY(TAO::PG_FactoryRegistry::list_factories_by_location);
+ ::PortableGroup::FactoryInfos_var result;
+ ACE_NEW_THROW_EX (result, ::PortableGroup::FactoryInfos(this->registry_.current_size()),
+ CORBA::NO_MEMORY (TAO::VMCID, CORBA::COMPLETED_NO));
+
+ ACE_CHECK_RETURN (0);
+
+ size_t result_length = 0;
+
+ // iterate through the registery
+ for (RegistryType_Iterator it = this->registry_.begin();
+ it != this->registry_.end();
+ ++it)
+ {
+ RegistryType_Entry & entry = *it;
+ RoleInfo * role_info = entry.int_id_;
+
+ PortableGroup::FactoryInfos & found_infos = role_info->infos_;
+ // iterate through the entry for this type
+ int found = 0;
+ size_t length = found_infos.length();
+ for (size_t nInfo = 0; !found && nInfo < length; ++nInfo)
+ {
+ PortableGroup::FactoryInfo & info = found_infos[nInfo];
+ if (info.the_location == location)
+ {
+ found = 1;
+ result_length += 1;
+ result->length(result_length);
+ (*result)[result_length-1] = info;
+ }
+ }
+ }
+
+ METHOD_RETURN(TAO::PG_FactoryRegistry::list_factories_by_location) result._retn();
+}
+
+//////////////////////////////
+// Implementation methods
+
+int TAO::PG_FactoryRegistry::write_ior_file(const char * outputFile, const char * ior)
+{
+ int result = -1;
+ FILE* out = ACE_OS::fopen (outputFile, "w");
+ if (out)
+ {
+ ACE_OS::fprintf (out, "%s", ior);
+ ACE_OS::fclose (out);
+ result = 0;
+ }
+ else
+ {
+ ACE_ERROR ((LM_ERROR,
+ "Open failed for %s\n", outputFile
+ ));
+ }
+ return result;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_FactoryRegistry.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_FactoryRegistry.h
new file mode 100644
index 00000000000..b16268b5f66
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_FactoryRegistry.h
@@ -0,0 +1,263 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_FactoryRegistry.h
+ *
+ * $Id$
+ *
+ * This file declares the implementation of PortableGroup::FactoryRegistry.
+ * Eventually this should be folded into the Fault Tolerance ReplicationManager
+ *
+ * @author Dale Wilson <wilson_d@ociweb.com>
+ */
+//=============================================================================
+
+#ifndef TAO_PG_FACTORYREGISTRY_H_
+#define TAO_PG_FACTORYREGISTRY_H_
+#include /**/ "ace/pre.h"
+#include /**/ "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "tao/Versioned_Namespace.h"
+
+/////////////////////////////////
+// Includes needed by this header
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+#include "orbsvcs/PortableGroupS.h"
+#include "ace/Hash_Map_Manager.h"
+#include "ace/SString.h"
+#include "ace/Null_Mutex.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+//////////////////////////////////
+// Classes declared in this header
+namespace TAO
+{
+ class PG_FactoryRegistry;
+}
+
+/////////////////////
+// Forward references
+
+namespace TAO
+{
+ /**
+ * Implement the PortableGroup::FactoryRegistry interface
+ * Note FactoryRegistry is not part of the OMG standard. It was added
+ * as part of the TAO implementation of Fault Tolerant CORBA
+ */
+ class TAO_PortableGroup_Export PG_FactoryRegistry
+ : public virtual POA_PortableGroup::FactoryRegistry
+ {
+ struct RoleInfo
+ {
+ ACE_CString type_id_;
+ PortableGroup::FactoryInfos infos_;
+
+ RoleInfo(size_t estimated_number_entries = 5);
+ };
+ typedef ACE_Null_Mutex MapMutex;
+ typedef ACE_Hash_Map_Manager <ACE_CString, RoleInfo *, MapMutex> RegistryType;
+ typedef ACE_Hash_Map_Entry <ACE_CString, RoleInfo *> RegistryType_Entry;
+ typedef ACE_Hash_Map_Iterator <ACE_CString, RoleInfo *, MapMutex> RegistryType_Iterator;
+
+ //////////////////////
+ // non-CORBA interface
+ public:
+ /// Constructor
+ PG_FactoryRegistry (const char * name = "FactoryRegistry");
+
+ /// virtual Destructor
+ virtual ~PG_FactoryRegistry (void);
+
+ /**
+ * Parse command line arguments.
+ * @param argc traditional C argc
+ * @param argv traditional C argv
+ * @return zero for success; nonzero is process return code for failure.
+ */
+ int parse_args (int argc, char * argv[]);
+
+ /**
+ * Initialize this object.
+ * @param orbManager our ORB -- we keep var to it.
+ * @return zero for success; nonzero is process return code for failure.
+ */
+ int init (CORBA::ORB_ptr orb ACE_ENV_ARG_DECL);
+
+ /**
+ * alternative init using designated poa
+ */
+ void init (CORBA::ORB_ptr orb, PortableServer::POA_ptr poa ACE_ENV_ARG_DECL);
+
+ /**
+ * Prepare to exit.
+ * @return zero for success; nonzero is process return code for failure.
+ */
+ int fini (ACE_ENV_SINGLE_ARG_DECL);
+
+ /**
+ * Processing to happen when the ORB's event loop is idle.
+ * @param result is a place to return status to be returned by the process
+ * @returns 0 to continue. 1 to quit.
+ */
+ int idle(int & result ACE_ENV_ARG_DECL);
+
+ /**
+ * Identify this object.
+ * @return a string to identify this object for logging/console message purposes.
+ */
+ const char * identity () const;
+
+ /**
+ * An object reference to the this object.
+ * Duplicated by the call so it may (and probably should) be assigned to a _var..
+ */
+ ::PortableGroup::FactoryRegistry_ptr reference();
+
+ ////////////////////////////////
+ // override servant base methods
+ virtual void _remove_ref (ACE_ENV_SINGLE_ARG_DECL);
+
+ //////////////////
+ // CORBA interface
+ // See IDL for documentation
+
+ virtual void register_factory (
+ const char * role,
+ const char * type_id,
+ const PortableGroup::FactoryInfo & factory_info
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((
+ CORBA::SystemException
+ , PortableGroup::MemberAlreadyPresent
+ , PortableGroup::TypeConflict));
+
+ virtual void unregister_factory (
+ const char * role,
+ const PortableGroup::Location & location
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException, PortableGroup::MemberNotFound));
+
+ virtual void unregister_factory_by_role (
+ const char * role
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+
+ virtual void unregister_factory_by_location (
+ const PortableGroup::Location & location
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual ::PortableGroup::FactoryInfos * list_factories_by_role (
+ const char * role,
+ CORBA::String_out type_id
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual ::PortableGroup::FactoryInfos * list_factories_by_location (
+ const PortableGroup::Location & location
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /////////////////////////
+ // Implementation methods
+ private:
+ /**
+ * Write this factory's IOR to a file
+ */
+ int write_ior_file (const char * outputFile, const char * ior);
+
+ ///////////////
+ // Data Members
+ private:
+
+ /**
+ * A human-readable string to distinguish this from other Notifiers.
+ */
+ ACE_CString identity_;
+
+ /**
+ * Protect internal state.
+ * Mutex should be locked by corba methods, or by
+ * external (public) methods before calling implementation
+ * methods.
+ * Implementation methods should assume the mutex is
+ * locked if necessary.
+ */
+ TAO_SYNCH_MUTEX internals_;
+ typedef ACE_Guard<TAO_SYNCH_MUTEX> InternalGuard;
+
+ /**
+ * The orb
+ */
+ CORBA::ORB_var orb_;
+
+ /**
+ * The POA used to activate this object.
+ */
+ PortableServer::POA_var poa_;
+
+ /**
+ * The CORBA object id assigned to this object.
+ */
+ PortableServer::ObjectId_var object_id_;
+
+ /**
+ * This objects identity as a CORBA object.
+ */
+ CORBA::Object_var this_obj_;
+
+ /**
+ * IOR of this object as assigned by poa.
+ */
+ CORBA::String_var ior_;
+
+ /**
+ * A file to which the factory's IOR should be written.
+ */
+ const char * ior_output_file_;
+
+ /**
+ * A name to be used to register the factory with the name service.
+ */
+ const char * ns_name_;
+
+ CosNaming::NamingContext_var naming_context_;
+
+ CosNaming::Name this_name_;
+
+ /**
+ * Quit on idle flag.
+ */
+ int quit_on_idle_;
+
+ /**
+ * State of the quit process
+ */
+ enum {LIVE, DEACTIVATED, GONE} quit_state_;
+
+ int linger_;
+
+ RegistryType registry_;
+
+ };
+} // namespace TAO
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif // TAO_PG_FACTORYREGISTRY_H_
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Factory_Map.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Factory_Map.h
new file mode 100644
index 00000000000..33c4e1cf421
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Factory_Map.h
@@ -0,0 +1,46 @@
+// -*- C++ -*-
+
+//=======================================================================
+/**
+ * @file PG_Factory_Map.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=======================================================================
+
+
+#ifndef TAO_PG_FACTORY_MAP_H
+#define TAO_PG_FACTORY_MAP_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroup/PG_Factory_Set.h"
+
+#include "orbsvcs/PortableGroupC.h"
+
+#include "ace/Hash_Map_Manager_T.h"
+#include "ace/Null_Mutex.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// Factory hash map.
+typedef ACE_Hash_Map_Manager_Ex<
+ ACE_UINT32,
+ TAO_PG_Factory_Set,
+ ACE_Hash<ACE_UINT32>,
+ ACE_Equal_To<ACE_UINT32>,
+ ACE_Null_Mutex> TAO_PG_Factory_Map;
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PG_FACTORY_MAP_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Factory_Set.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Factory_Set.h
new file mode 100644
index 00000000000..9b545e49831
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Factory_Set.h
@@ -0,0 +1,58 @@
+// -*- C++ -*-
+
+//=======================================================================
+/**
+ * @file PG_Factory_Set.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=======================================================================
+
+
+#ifndef TAO_PG_FACTORY_SET_H
+#define TAO_PG_FACTORY_SET_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroupC.h"
+
+#include "ace/Array_Base.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class TAO_PG_Factory_Node
+ *
+ * @brief Structure that contains all factory-specific information.
+ *
+ * Each member created by the infrastructure instead of the
+ * application will have a corresponding TAO_PG_Factory_Node structure
+ * associated with it. A list of these will be maintained by the
+ * infrastructure so that it is possible for the instrastructure to
+ * destroy members it created when destroying the object group.
+ */
+struct TAO_PG_Factory_Node
+{
+ /// Member factory information.
+ PortableGroup::FactoryInfo factory_info;
+
+ /// FactoryCreationId assigned to the member.
+ PortableGroup::GenericFactory::FactoryCreationId_var factory_creation_id;
+
+};
+
+typedef ACE_Array_Base<TAO_PG_Factory_Node> TAO_PG_Factory_Set;
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PG_FACTORY_SET_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.cpp
new file mode 100644
index 00000000000..0461276bea1
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.cpp
@@ -0,0 +1,780 @@
+#include "orbsvcs/PortableGroup/PG_GenericFactory.h"
+#include "orbsvcs/PortableGroup/PG_MemberInfo.h"
+#include "orbsvcs/PortableGroup/PG_ObjectGroupManager.h"
+#include "orbsvcs/PortableGroup/PG_PropertyManager.h"
+#include "orbsvcs/PortableGroup/PG_Property_Utils.h"
+#include "orbsvcs/PortableGroup/PG_conf.h"
+
+#include "ace/OS_NS_stdio.h"
+
+#include "tao/ORB_Constants.h"
+
+ACE_RCSID (PortableGroup,
+ PG_GenericFactory,
+ "$Id$")
+
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO_PG_GenericFactory::TAO_PG_GenericFactory (
+ TAO_PG_ObjectGroupManager & object_group_manager,
+ TAO_PG_PropertyManager & property_manager)
+ : poa_ (),
+ object_group_manager_ (object_group_manager),
+ property_manager_ (property_manager),
+ factory_map_ (TAO_PG_MAX_OBJECT_GROUPS),
+ next_fcid_ (0),
+ lock_ ()
+{
+ this->object_group_manager_.generic_factory (this);
+}
+
+TAO_PG_GenericFactory::~TAO_PG_GenericFactory (void)
+{
+ ACE_DECLARE_NEW_CORBA_ENV;
+
+ TAO_PG_Factory_Map::iterator end = this->factory_map_.end ();
+ for (TAO_PG_Factory_Map::iterator i = this->factory_map_.begin ();
+ i != end;
+ ++i)
+ {
+ TAO_PG_Factory_Set & factory_set = (*i).int_id_;
+
+ ACE_TRY
+ {
+ this->delete_object_i (factory_set,
+ 1 /* Ignore exceptions */
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ ACE_CATCHANY
+ {
+ // Ignore all exceptions.
+ }
+ ACE_ENDTRY;
+ }
+
+ (void) this->factory_map_.close ();
+}
+
+CORBA::Object_ptr
+TAO_PG_GenericFactory::create_object (
+ const char * type_id,
+ const PortableGroup::Criteria & the_criteria,
+ PortableGroup::GenericFactory::FactoryCreationId_out factory_creation_id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::NoFactory,
+ PortableGroup::ObjectNotCreated,
+ PortableGroup::InvalidCriteria,
+ PortableGroup::InvalidProperty,
+ PortableGroup::CannotMeetCriteria))
+{
+ PortableGroup::Properties_var properties =
+ this->property_manager_.get_type_properties (type_id
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (CORBA::Object::_nil ());
+
+ PortableGroup::MembershipStyleValue membership_style =
+ TAO_PG_MEMBERSHIP_STYLE;
+ PortableGroup::FactoriesValue factory_infos(0);
+
+ PortableGroup::InitialNumberMembersValue initial_number_members =
+ TAO_PG_INITIAL_NUMBER_MEMBERS;
+ PortableGroup::MinimumNumberMembersValue minimum_number_members =
+ TAO_PG_MINIMUM_NUMBER_MEMBERS;
+
+ // Make sure the criteria for the object group being created are
+ // valid.
+ this->process_criteria (type_id,
+ the_criteria,
+ membership_style,
+ factory_infos,
+ initial_number_members,
+ minimum_number_members
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (CORBA::Object::_nil ());
+
+ CORBA::ULong fcid = 0;
+
+ {
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->lock_,
+ CORBA::Object::_nil ());
+
+ // Start out with an initial value.
+ fcid = this->next_fcid_;
+
+ // Loop until a free FactoryCreationId is found, being careful to
+ // search through the range of FactoryCreationIds only once.
+ while (this->factory_map_.find (this->next_fcid_) == 0)
+ {
+ this->next_fcid_++;
+
+ // If this is true, then no FactoryCreationIds are available.
+ // This is highly unlikely since TAO implements a
+ // FactoryCreationId as a 32 bit unsigned integer, meaning
+ // that over 4 billion object groups are being managed by this
+ // generic factory!
+ if (this->next_fcid_ == fcid)
+ ACE_THROW_RETURN (PortableGroup::ObjectNotCreated (),
+ CORBA::Object::_nil ());
+ }
+
+ // Just in case this->next_fcid_ was modified in the above search,
+ // reassign the value.
+ fcid = this->next_fcid_;
+ }
+
+ // The ObjectId for the newly created object group is comprised
+ // solely of the FactoryCreationId.
+ PortableServer::ObjectId_var oid;
+ this->get_ObjectId (fcid, oid.out ());
+
+ PortableGroup::ObjectGroup_var object_group =
+ this->object_group_manager_.create_object_group (fcid,
+ oid.in (),
+ type_id,
+ the_criteria
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (CORBA::Object::_nil ());
+
+ TAO_PG_Factory_Set factory_set;
+
+ const CORBA::ULong factory_infos_count = factory_infos.length ();
+
+ ACE_TRY
+ {
+ 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::VMCID,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (CORBA::Object::_nil ());
+
+ 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;
+
+ ACE_RE_THROW;
+ }
+ ACE_ENDTRY;
+ ACE_CHECK_RETURN (CORBA::Object::_nil ());
+
+ {
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->lock_,
+ CORBA::Object::_nil ());
+
+ // Object group was successfully created. Increment the next
+ // FactoryCreationId in preparation for the next object group.
+ this->next_fcid_++;
+ }
+
+ return object_group._retn ();
+}
+
+void
+TAO_PG_GenericFactory::delete_object (
+ const PortableGroup::GenericFactory::FactoryCreationId &
+ factory_creation_id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectNotFound))
+{
+ CORBA::ULong fcid = 0;
+
+ if (factory_creation_id >>= fcid) // Extract the actual FactoryCreationId.
+ {
+ // Successfully extracted the FactoryCreationId. Now find the
+ // TAO_PG_Factory_Set corresponding to it.
+
+ 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 (fcid, entry) == 0)
+ {
+ TAO_PG_Factory_Set & factory_set = entry->int_id_;
+
+ this->delete_object_i (factory_set,
+ 0 /* Do not ignore exceptions */
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ if (this->factory_map_.unbind (fcid) != 0)
+ ACE_THROW (CORBA::INTERNAL ());
+ }
+ }
+ else
+ ACE_THROW (PortableGroup::ObjectNotFound ()); // @@
+ // CORBA::BAD_PARAM
+ // instead?
+
+ // The ObjectId for the newly created object group is comprised
+ // solely of the FactoryCreationId.
+ PortableServer::ObjectId_var oid;
+ this->get_ObjectId (fcid, oid.out ());
+
+ // Destroy the object group entry.
+ this->object_group_manager_.destroy_object_group (
+ oid.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+void
+TAO_PG_GenericFactory::delete_object_i (TAO_PG_Factory_Set & factory_set,
+ CORBA::Boolean ignore_exceptions
+ ACE_ENV_ARG_DECL)
+{
+ const size_t len = factory_set.size ();
+
+ size_t ilen = len;
+ for (size_t i = 0; i != len; ++i)
+ {
+ // Destroy the object group member in reverse order in case the
+ // array list is only partially destroyed and another call to
+ // GenericFactory::delete_object() occurs afterwards.
+ --ilen;
+
+ TAO_PG_Factory_Node & factory_node = factory_set[ilen];
+
+ PortableGroup::GenericFactory_ptr factory =
+ factory_node.factory_info.the_factory.in ();
+ const PortableGroup::GenericFactory::FactoryCreationId & member_fcid =
+ factory_node.factory_creation_id.in ();
+
+ ACE_TRY
+ {
+ factory->delete_object (member_fcid
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ ACE_CATCHANY
+ {
+ // Exceptions are generally only ignored when this
+ // GenericFactory (not the one being invoked above) is
+ // destroyed. The idea is to allow the GenericFactory to be
+ // destroyed regardless of whether or not all object group
+ // members have been destroyed, and minimize the number of
+ // object group members that have not been destroyed.
+ if (!ignore_exceptions)
+ ACE_RE_THROW;
+ }
+ ACE_ENDTRY;
+ ACE_CHECK;
+
+ // Since GenericFactory::delete_object() can throw an exception,
+ // decrease the size of the factory array incrementally since
+ // some object group members may not have been destroyed yet.
+ // Note that this size reduction is fast since no memory is
+ // actually deallocated.
+ factory_set.size (ilen);
+ }
+}
+
+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 ())
+ && !CORBA::is_nil (p));
+
+ this->poa_ = PortableServer::POA::_duplicate (p);
+}
+
+void
+TAO_PG_GenericFactory::populate_object_group (
+ PortableGroup::ObjectGroup_ptr object_group,
+ const char * type_id,
+ const PortableGroup::FactoryInfos & factory_infos,
+ PortableGroup::InitialNumberMembersValue initial_number_members,
+ TAO_PG_Factory_Set & factory_set
+ ACE_ENV_ARG_DECL)
+{
+ CORBA::ULong factory_infos_count = factory_infos.length ();
+ factory_set.size (factory_infos_count);
+
+ for (CORBA::ULong j = 0; j < factory_infos_count; ++j)
+ {
+ TAO_PG_Factory_Node & factory_node = factory_set[j];
+
+ const PortableGroup::FactoryInfo &factory_info = factory_infos[j];
+
+ if (j < static_cast<CORBA::ULong> (initial_number_members))
+ {
+ PortableGroup::GenericFactory_ptr factory =
+ factory_info.the_factory.in ();
+
+ if (CORBA::is_nil (factory))
+ {
+ // @@ instead InvalidProperty?
+ ACE_THROW (PortableGroup::NoFactory (factory_info.the_location,
+ type_id));
+ }
+
+ // Do not allow the PortableGroup::MemberAlreadyPresent
+ // exception to be propagated to this scope.
+ const CORBA::Boolean propagate_member_already_present = 0;
+
+ factory_node.factory_creation_id =
+ this->create_member (object_group,
+ factory_info,
+ type_id,
+ propagate_member_already_present
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+
+ factory_node.factory_info = factory_info; // Memberwise copy
+ }
+}
+
+void
+TAO_PG_GenericFactory::get_ObjectId (
+ CORBA::ULong fcid,
+ PortableServer::ObjectId_out oid)
+{
+ // Since the POA used by the LoadManager uses the NON_RETAIN
+ // policy, explicitly choose an ObjectId that is unique to a given
+ // type.
+
+ // Make the ObjectId be the next value of the number of types that
+ // have been registered with the LoadManager. For example, if two
+ // types of objects have been registered with the LoadManager, then
+ // the ObjectId for the object currently being registered will be
+ // "3" since the object will be the third type of object registered
+ // with the LoadManager. Previously used values will not be reused
+ // to ensure that a ServantLocator does not inadvertently return a
+ // reference to an object that had a previously used ObjectId.
+ // Specifcally, the numerical value used for the ObjectId increases
+ // monotonically.
+
+ // 4294967295UL -- Largest 32 bit unsigned integer
+ // 123456789012 -- 10 digits
+ // + 2 for "UL" (unnecessary, but let's be safe)
+ // + 1 for null terminator
+ // + 1 for good luck. :-)
+ const size_t MAX_OID_LEN = 14;
+
+ char oid_str[MAX_OID_LEN] = { 0 };
+ ACE_OS::sprintf (oid_str,
+ "%ul",
+ fcid);
+
+ oid = PortableServer::string_to_ObjectId (oid_str);
+}
+
+void
+TAO_PG_GenericFactory::process_criteria (
+ const char * type_id,
+ const PortableGroup::Criteria & criteria,
+ PortableGroup::MembershipStyleValue & membership_style,
+ PortableGroup::FactoriesValue & factory_infos,
+ PortableGroup::InitialNumberMembersValue & initial_number_members,
+ PortableGroup::MinimumNumberMembersValue & minimum_number_members
+ ACE_ENV_ARG_DECL)
+{
+ // Get type-specific properties.
+ PortableGroup::Properties_var props =
+ this->property_manager_.get_type_properties (type_id
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // Merge the given criteria with the type-specific criteria.
+ TAO_PG::override_properties (criteria, props.inout ());
+
+ PortableGroup::Criteria unmet_criteria;
+ unmet_criteria.length (4); // The four criteria understood by this
+ // method.
+
+ // Unmet criteria count.
+ CORBA::ULong uc = 0;
+
+ PortableGroup::Name name (1);
+ name.length (1);
+
+ PortableGroup::Value value;
+ PortableGroup::Value value1;
+ PortableGroup::Value value2;
+ PortableGroup::Value value3;
+
+ // MembershipStyle
+ name[0].id = CORBA::string_dup ("org.omg.PortableGroup.MembershipStyle");
+ if (TAO_PG::get_property_value (name, props.in (), value)
+ && (!(value >>= membership_style)
+ || (membership_style != PortableGroup::MEMB_APP_CTRL
+ && membership_style != PortableGroup::MEMB_INF_CTRL)))
+ {
+ // This only occurs if extraction of the actual value from the
+ // Any fails.
+ ACE_THROW (PortableGroup::InvalidProperty (name, value));
+ }
+
+ // Factories
+ const PortableGroup::FactoryInfos * factory_infos_tmp = 0;
+ name[0].id = CORBA::string_dup ("org.omg.PortableGroup.Factories");
+ if (TAO_PG::get_property_value (name, props.in (), value1)
+ && !(value1 >>= factory_infos_tmp))
+ {
+ // This only occurs if extraction of the actual value from the
+ // Any fails.
+ ACE_THROW (PortableGroup::InvalidProperty (name, value1));
+ }
+
+ const CORBA::ULong factory_infos_count =
+ (factory_infos_tmp == 0 ? 0 : factory_infos_tmp->length ());
+
+ // InitialNumberMembers
+ name[0].id =
+ CORBA::string_dup ("org.omg.PortableGroup.InitialNumberMembers");
+ if (TAO_PG::get_property_value (name, props.in (), value2)
+ && !(value2 >>= initial_number_members))
+ {
+ // This only occurs if extraction of the actual value from the
+ // Any fails.
+ ACE_THROW (PortableGroup::InvalidProperty (name, value2));
+ }
+
+ if (membership_style == PortableGroup::MEMB_INF_CTRL)
+ {
+ // If the number of factories is less than the initial number of
+ // members or the desired number of initial members cannot
+ // possibly be created.
+
+ if (factory_infos_count < static_cast<CORBA::ULong> (initial_number_members))
+ {
+ unmet_criteria[uc].nam = name;
+ unmet_criteria[uc++].val = value2;
+ }
+ }
+
+ // MinimumNumberMembers
+ name[0].id =
+ CORBA::string_dup ("org.omg.PortableGroup.MinimumNumberMembers");
+ if (TAO_PG::get_property_value (name, props.in (), value3)
+ && !(value3 >>= minimum_number_members))
+ {
+ // This only occurs if extraction of the actual value from the
+ // Any fails.
+ ACE_THROW (PortableGroup::InvalidProperty (name, value3));
+ }
+
+ // If the minimum number of members is less than the initial number
+ // of members, the MinimumNumberMembers property is cannot be
+ // initially met.
+ //
+ // @note This code is not part of the above "MEMB_INF_CTRL" criteria
+ // check since the "name" and "value" variables have been
+ // changed.
+ if (membership_style == PortableGroup::MEMB_INF_CTRL)
+ {
+ if (minimum_number_members < initial_number_members
+ || static_cast<CORBA::ULong> (minimum_number_members) > factory_infos_count)
+ {
+ unmet_criteria[uc].nam = name;
+ unmet_criteria[uc++].val = value3;
+ }
+ else if (factory_infos_tmp != 0)
+ {
+ factory_infos.length (factory_infos_count);
+ factory_infos = *factory_infos_tmp;
+ }
+ }
+
+ if (uc > 0)
+ {
+ // Reduce the length of the unmet criteria sequence in an effort
+ // to optimize the copying that will occur when the below
+ // exception is thrown. Reducing the length is fast since no
+ // deallocations should occur.
+ unmet_criteria.length (uc);
+
+ ACE_THROW (PortableGroup::CannotMeetCriteria (unmet_criteria));
+ }
+}
+
+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.
+
+ // 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;
+
+ TAO_PG_Factory_Set & factory_set = entry->int_id_;
+
+ PortableGroup::Properties_var props =
+ this->property_manager_.get_properties (object_group
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ PortableGroup::Name name (1);
+ name.length (1);
+
+ PortableGroup::Value value;
+
+ // 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 ());
+ }
+
+ const CORBA::ULong count =
+ this->object_group_manager_.member_count (object_group
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ if (count >= static_cast<CORBA::ULong> (minimum_number_members))
+ return;
+
+ const CORBA::ULong gap =
+ 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 ();
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.h
new file mode 100644
index 00000000000..96b725c941a
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_GenericFactory.h
@@ -0,0 +1,248 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_GenericFactory.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@dre.vanderbilt.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_PG_GENERIC_FACTORY_H
+#define TAO_PG_GENERIC_FACTORY_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroup/PG_Factory_Map.h"
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+#include "tao/PortableServer/PortableServerC.h"
+#include "orbsvcs/PortableGroupC.h"
+#include "ace/Null_Mutex.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// Forward declarations.
+class TAO_PG_ObjectGroupManager;
+class TAO_PG_PropertyManager;
+
+struct TAO_PG_ObjectGroup_Map_Entry;
+
+
+/**
+ * @class TAO_PG_GenericFactory
+ *
+ * @brief PortableGroup::GenericFactory implementation used by the
+ * load balancer when creating object groups.
+ *
+ * This GenericFactory creates an object group reference for given set
+ * of replicas. Those replicas will be created by this GenericFactory
+ * if the "infrastructure-controlled" membership style is configured.
+ */
+class TAO_PortableGroup_Export TAO_PG_GenericFactory
+ : public virtual PortableGroup::GenericFactory
+{
+public:
+
+ /// Constructor.
+ TAO_PG_GenericFactory (TAO_PG_ObjectGroupManager & object_group_map,
+ TAO_PG_PropertyManager & property_manager);
+
+ /// Destructor.
+ ~TAO_PG_GenericFactory (void);
+
+ /**
+ * @name TAO_LoadBalancer::GenericFactory methods
+ */
+ //@{
+
+ /**
+ * 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.
+ */
+ virtual CORBA::Object_ptr create_object (
+ const char * type_id,
+ const PortableGroup::Criteria & the_criteria,
+ PortableGroup::GenericFactory::FactoryCreationId_out
+ factory_creation_id
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::NoFactory,
+ PortableGroup::ObjectNotCreated,
+ PortableGroup::InvalidCriteria,
+ PortableGroup::InvalidProperty,
+ PortableGroup::CannotMeetCriteria));
+
+ /**
+ * 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
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectNotFound));
+
+ //@}
+
+ /// Set the POA to use when creating object references.
+ void poa (PortableServer::POA_ptr p);
+
+ /// Call delete_object() on all factories use to create members in a
+ /// given object group.
+ /**
+ * If ignore_exceptions is true, any exception returned from the
+ * delete_object() call on the remote factory will be ignored in
+ * order to allow other objects to be deleted via other registered
+ * factories.
+ */
+ void delete_object_i (TAO_PG_Factory_Set & factory_set,
+ 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,
+ PortableGroup::MemberAlreadyPresent));
+
+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 (
+ PortableGroup::ObjectGroup_ptr object_group,
+ const char * type_id,
+ const PortableGroup::FactoryInfos &factory_infos,
+ PortableGroup::InitialNumberMembersValue initial_number_members,
+ TAO_PG_Factory_Set & factory_set
+ ACE_ENV_ARG_DECL);
+
+ /// Get a new ObjectId to be used when creating a new ObjectGroup.
+ /**
+ * An ObjectId created by this method will never be reused within
+ * the scope of a given ReplicationManager. A value suitable for
+ * use in a map association <ext_id> is also returned.
+ */
+ void get_ObjectId (CORBA::ULong fcid,
+ PortableServer::ObjectId_out oid);
+
+ /// Process criteria to be applied to the object group being
+ /// created.
+ /**
+ * Only the MemberShipStyle, Factories, InitialNumberMembers and
+ * MinimumNumberMembers criteria/properties are defined by the
+ * PortableGroup IDL. Other services that implement the
+ * GenericFactory interface, such as load balancing and fault
+ * tolerance, may choose to support more.
+ * @par
+ * The extracted criteria are object group-specific. In particular,
+ * they are the object group creation time criteria.
+ */
+ void process_criteria (
+ const char * type_id,
+ const PortableGroup::Criteria & criteria,
+ PortableGroup::MembershipStyleValue & membership_style,
+ PortableGroup::FactoriesValue & factory_infos,
+ PortableGroup::InitialNumberMembersValue & initial_number_members,
+ PortableGroup::MinimumNumberMembersValue & minimum_number_members
+ ACE_ENV_ARG_DECL);
+
+private:
+
+ /// Reference to the POA used to create object group references.
+ PortableServer::POA_var poa_;
+
+ /// Reference to the ObjectGroup map.
+ TAO_PG_ObjectGroupManager & object_group_manager_;
+
+ /// Reference to the PropertyManager.
+ TAO_PG_PropertyManager & property_manager_;
+
+ /// Table that maps FactoryCreationId to TAO_PG_Factory_Set.
+ /**
+ * The TAO_PG_Factory_Set corresponding to a given FactoryCreationId
+ * contains the information necessary to clean up objects (members)
+ * that were created by the infrastructure, i.e. this
+ * GenericFactory. For example, this GenericFactory will invoke
+ * other application defined GenericFactorys when creating new
+ * object group members. The information returned from those
+ * application defined GenericFactorys is stored in a
+ * TAO_PG_Factory_Set, and thus this table.
+ */
+ TAO_PG_Factory_Map factory_map_;
+
+ /// The FactoryCreationId that will be assigned to the next object
+ /// group that is created.
+ /**
+ * Value that is used when assigning a FactoryCreationId to the
+ * factory that was used to create a given ObjectGroup. The
+ * FactoryCreationId is typically comprised of this value in
+ * addition to another value that makes it unique to a given Load
+ * Balancer.
+ */
+ CORBA::ULong next_fcid_;
+
+ /// Lock used to synchronize access to the factory creation id
+ /// index (i.e. next_fcid_).
+ TAO_SYNCH_MUTEX lock_;
+
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PG_GENERIC_FACTORY_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Factory.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Factory.cpp
new file mode 100644
index 00000000000..3c84812d454
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Factory.cpp
@@ -0,0 +1,232 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Group_Factory.cpp
+ *
+ * $Id$
+ *
+ * @author Dale Wilson <wilson_d@ociweb.com>
+ */
+//=============================================================================
+
+#include "orbsvcs/PortableGroup/PG_Group_Factory.h"
+#include "orbsvcs/PortableGroup/PG_Property_Utils.h"
+#include "orbsvcs/PortableGroup/PG_conf.h"
+#include "orbsvcs/PortableGroupC.h"
+#include "orbsvcs/PortableGroup/PG_Object_Group.h"
+#include <orbsvcs/PortableGroup/PG_Utils.h>
+
+ACE_RCSID (PortableGroup,
+ PG_Group_Factory,
+ "$Id$")
+
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO::PG_Group_Factory::PG_Group_Factory ()
+ : orb_ (CORBA::ORB::_nil())
+ , poa_ (PortableServer::POA::_nil())
+ , manipulator_ ()
+ , domain_id_ ("default-domain")
+
+{
+}
+
+TAO::PG_Group_Factory::~PG_Group_Factory (void)
+{
+ for (Group_Map_Iterator it = this->group_map_.begin ();
+ it != this->group_map_.end ();
+ ++it)
+ {
+ TAO::PG_Object_Group * group = (*it).int_id_;
+ delete group;
+ }
+ this->group_map_.unbind_all ();
+}
+
+
+void TAO::PG_Group_Factory::init (
+ CORBA::ORB_ptr orb,
+ PortableServer::POA_ptr poa,
+ PortableGroup::FactoryRegistry_ptr factory_registry
+ ACE_ENV_ARG_DECL)
+{
+ ACE_ASSERT (CORBA::is_nil (this->orb_.in ()));
+ ACE_ASSERT (CORBA::is_nil (this->poa_.in ()));
+ ACE_ASSERT (CORBA::is_nil (this->factory_registry_.in ()));
+
+ this->orb_ = CORBA::ORB::_duplicate(orb);
+ this->poa_ = PortableServer::POA::_duplicate (poa);
+ this->factory_registry_ = PortableGroup::FactoryRegistry::_duplicate (factory_registry);
+
+
+ ACE_ASSERT (!CORBA::is_nil (this->orb_.in ()));
+ ACE_ASSERT (!CORBA::is_nil (this->poa_.in ()));
+ ACE_ASSERT (!CORBA::is_nil (this->factory_registry_.in ()));
+
+ this->manipulator_.init (orb, poa ACE_ENV_ARG_PARAMETER);
+// ACE_CHECK;
+}
+
+
+TAO::PG_Object_Group * TAO::PG_Group_Factory::create_group (
+ const char * type_id,
+ const PortableGroup::Criteria & the_criteria,
+ TAO::PG_Property_Set * typeid_properties
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::NoFactory,
+ PortableGroup::ObjectNotCreated,
+ PortableGroup::InvalidCriteria,
+ PortableGroup::InvalidProperty,
+ PortableGroup::CannotMeetCriteria))
+{
+ ///////////////////////////////////
+ // 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
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // pick up the object group information as assigned by
+ // ObjectGroupManager
+
+ PortableGroup::TagGroupTaggedComponent tagged_component;
+ if (! TAO::PG_Utils::get_tagged_component (empty_group, tagged_component))
+ {
+ ACE_THROW_RETURN (PortableGroup::ObjectNotCreated(), 0);
+ }
+
+ 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->group_map_.bind (group_id, objectGroup) != 0)
+ {
+ delete objectGroup;
+ ACE_THROW_RETURN (PortableGroup::ObjectNotCreated(), 0);
+ }
+ return objectGroup;
+}
+
+void TAO::PG_Group_Factory::delete_group (PortableGroup::ObjectGroup_ptr object_group
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectNotFound))
+{
+ if (! destroy_group (object_group))
+ {
+ ACE_THROW (PortableGroup::ObjectNotFound ());
+ }
+}
+
+
+void TAO::PG_Group_Factory::delete_group (PortableGroup::ObjectGroupId group_id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectNotFound))
+{
+ if (! destroy_group (group_id))
+ {
+ ACE_THROW (PortableGroup::ObjectNotFound ());
+ }
+}
+
+ // insert group. Take ownership
+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)
+{
+ return (this->group_map_.bind (group_id, group) == 0);
+}
+
+int TAO::PG_Group_Factory::find_group (PortableGroup::ObjectGroupId group_id, ::TAO::PG_Object_Group *& group) const
+{
+ return (this->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 result = 0;
+ PortableGroup::TagGroupTaggedComponent tc;
+ if (TAO::PG_Utils::get_tagged_component (object_group, tc))
+ {
+ result = find_group (tc.object_group_id, group);
+ }
+ 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);
+ if (result)
+ {
+ delete group;
+ }
+ return result;
+}
+
+int TAO::PG_Group_Factory::destroy_group (PortableGroup::ObjectGroup_ptr object_group)
+{
+ PortableGroup::TagGroupTaggedComponent tc;
+ TAO::PG_Utils::get_tagged_component (object_group, tc);
+ return destroy_group (tc.object_group_id);
+}
+
+
+
+PortableGroup::ObjectGroups *
+TAO::PG_Group_Factory::groups_at_location (
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ( (CORBA::SystemException))
+{
+ size_t upper_limit = this->group_map_.current_size ();
+ PortableGroup::ObjectGroups * result = 0;
+ ACE_NEW_THROW_EX (
+ result,
+ PortableGroup::ObjectGroups (upper_limit),
+ CORBA::NO_MEMORY());
+ ACE_CHECK_RETURN (0);
+
+ result->length(upper_limit);
+
+ size_t group_count = 0;
+ for (Group_Map_Iterator it = this->group_map_.begin ();
+ it != this->group_map_.end ();
+ ++it)
+ {
+ TAO::PG_Object_Group * group = (*it).int_id_;
+ if (group->has_member_at (the_location))
+ {
+ (*result)[group_count] = group->reference ();
+ ++group_count;
+ }
+ }
+ result->length (group_count);
+ return result;
+}
+
+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
new file mode 100644
index 00000000000..b9bd1309492
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Factory.h
@@ -0,0 +1,184 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Group_Factory.h
+ *
+ * $Id$
+ *
+ * @author Dale Wilson <wilson_d@ociweb.com>
+ */
+//=============================================================================
+
+#ifndef TAO_PG_GROUP_FACTORY_H
+#define TAO_PG_GROUP_FACTORY_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/PortableGroup/PG_Object_Group_Manipulator.h"
+
+#include "orbsvcs/PortableGroupC.h"
+
+#include "tao/PortableServer/PortableServer.h"
+
+#include "ace/ACE.h"
+#include "ace/Hash_Map_Manager.h"
+
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+//////////////////
+// Forward reference
+namespace TAO
+{
+ class PG_Property_Set;
+} // namespace TAO_PG
+
+namespace TAO
+{
+ /////////////////////
+ // forward references
+ class PG_Object_Group;
+
+ /**
+ * class PG_Group_Factory
+ */
+ class TAO_PortableGroup_Export PG_Group_Factory
+ {
+ ////////////////////////////////////////////////////////////
+ // typedef private implementation classes
+ 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_Iterator_Ex <
+ PortableGroup::ObjectGroupId,
+ ::TAO::PG_Object_Group *,
+ ACE_Hash<ACE_UINT64>,
+ ACE_Equal_To<ACE_UINT64>,
+ TAO_SYNCH_MUTEX> Group_Map_Iterator;
+
+ public:
+
+ /// Constructor.
+ PG_Group_Factory ();
+
+ /// Destructor.
+ ~PG_Group_Factory ();
+
+ void init (
+ CORBA::ORB_ptr orb,
+ PortableServer::POA_ptr poa,
+ PortableGroup::FactoryRegistry_ptr factory_registry
+ ACE_ENV_ARG_DECL);
+
+
+ TAO::PG_Object_Group * create_group (
+ const char * type_id,
+ const PortableGroup::Criteria & the_criteria,
+ TAO::PG_Property_Set * typeid_properties
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::NoFactory,
+ PortableGroup::ObjectNotCreated,
+ PortableGroup::InvalidCriteria,
+ PortableGroup::InvalidProperty,
+ PortableGroup::CannotMeetCriteria));
+
+
+ void delete_group (PortableGroup::ObjectGroup_ptr object_group
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectNotFound));
+
+
+ void delete_group (PortableGroup::ObjectGroupId group_id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectNotFound));
+
+ PortableGroup::ObjectGroups *
+ groups_at_location (
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ( (CORBA::SystemException));
+
+
+
+ /**
+ * insert existing group. Take ownership
+ * note: uses group id extracted from group object
+ * @return bool true if insertion successful
+ */
+ 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);
+
+ /**
+ * find group
+ * @return bool true if found
+ */
+ int find_group (PortableGroup::ObjectGroupId group_id, ::TAO::PG_Object_Group *& group) const;
+
+ /**
+ * 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;
+
+ /**
+ * remove group from map and delete it.
+ * @return bool true if found
+ */
+ int destroy_group (PortableGroup::ObjectGroupId object_group_id);
+
+ /**
+ * remove group from map and delete it.
+ * note: uses group id extracted from object_group
+ * @return bool true if found
+ */
+ int destroy_group (PortableGroup::ObjectGroup_ptr object_group);
+
+ private:
+
+ private:
+
+ CORBA::ORB_var orb_;
+
+ /// Reference to the POA used to create object group references.
+ PortableServer::POA_var poa_;
+
+ /// The factory registry for replica factories
+ PortableGroup::FactoryRegistry_var factory_registry_;
+
+ ::TAO::PG_Object_Group_Manipulator manipulator_;
+
+ const char * domain_id_;
+
+ Group_Map group_map_;
+
+
+ };
+} // namespace TAO
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PG_GROUP_FACTORY_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Guard.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Guard.cpp
new file mode 100644
index 00000000000..dc93a9e2e2c
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Guard.cpp
@@ -0,0 +1,59 @@
+#include "orbsvcs/PortableGroup/PG_Group_Guard.h"
+
+#include "orbsvcs/PortableGroup/PG_GenericFactory.h"
+#include "orbsvcs/PortableGroup/PG_ObjectGroupManager.h"
+
+
+ACE_RCSID (PortableGroup,
+ PG_Group_Guard,
+ "$Id$")
+
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO_PG_Group_Guard::TAO_PG_Group_Guard (
+ TAO_PG_GenericFactory & generic_factory,
+ TAO_PG_Factory_Set & factory_set,
+ TAO_PG_ObjectGroupManager & group_manager,
+ const PortableServer::ObjectId & oid)
+ : generic_factory_ (generic_factory),
+ factory_set_ (factory_set),
+ group_manager_ (group_manager),
+ oid_ (oid),
+ released_ (0)
+{
+}
+
+TAO_PG_Group_Guard::~TAO_PG_Group_Guard (void)
+{
+ if (!this->released_)
+ {
+ ACE_DECLARE_NEW_CORBA_ENV;
+ ACE_TRY
+ {
+ this->generic_factory_.delete_object_i (this->factory_set_,
+ 1 // Ignore exceptions
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ // This should never throw an exception if this Guard is
+ // used properly.
+ this->group_manager_.destroy_object_group (this->oid_
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ ACE_CATCHANY
+ {
+ // Ignore all exceptions.
+ }
+ ACE_ENDTRY;
+ }
+}
+
+void
+TAO_PG_Group_Guard::release (void)
+{
+ this->released_ = 1;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Guard.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Guard.h
new file mode 100644
index 00000000000..2c6ca8fe9ee
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_Guard.h
@@ -0,0 +1,93 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Group_Guard.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_PG_GROUP_GUARD_H
+#define TAO_PG_GROUP_GUARD_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroup/PG_Factory_Set.h"
+
+#include "tao/PortableServer/PortableServerC.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// Forward declarations.
+class TAO_PG_GenericFactory;
+class TAO_PG_ObjectGroupManager;
+
+/**
+ * @class TAO_PG_Group_Guard
+ *
+ * @brief Guard implementation used to make object group cleanup
+ * exception-safe.
+ *
+ * This guard's destructor performs cleanup of object group
+ * resources. Thus, cleanup is performed when this guard goes out of
+ * scope unless explicitly released from that responsibility.
+ *
+ * This guard is meant to be used internally by the
+ * TAO_PG_GenericFactory class.
+ */
+class TAO_PG_Group_Guard
+{
+public:
+
+ /// Constructor.
+ TAO_PG_Group_Guard (TAO_PG_GenericFactory & generic_factory,
+ TAO_PG_Factory_Set & factory_set,
+ TAO_PG_ObjectGroupManager & group_manager,
+ const PortableServer::ObjectId & oid);
+
+ /// Destructor.
+ ~TAO_PG_Group_Guard (void);
+
+ /// Relinquish cleanup responsibility.
+ void release (void);
+
+private:
+
+ /// Reference to the infrastructure TAO_PG_GenericFactory that
+ /// created the below TAO_PG_Factory_Set.
+ TAO_PG_GenericFactory & generic_factory_;
+
+ /// Reference to the TAO_PG_Factory_Set that contains all
+ /// application-specific GenericFactory object references.
+ TAO_PG_Factory_Set & factory_set_;
+
+ /// Reference to the TAO_PG_ObjectGroupManager that maintains the
+ /// object group map.
+ TAO_PG_ObjectGroupManager & group_manager_;
+
+ /// Reference to the ObjectId that is the map key necessary to
+ /// unbind the corresponding object group map entry from the map
+ /// upon destruction.
+ const PortableServer::ObjectId & oid_;
+
+ /// Flag that dictates whether or not the destructor will perform
+ /// cleanup.
+ int released_;
+
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PG_GROUP_GUARD_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Equal_To.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Equal_To.cpp
new file mode 100644
index 00000000000..2fc8e11dadc
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Equal_To.cpp
@@ -0,0 +1,11 @@
+// -*- C++ -*-
+
+#include "orbsvcs/PortableGroup/PG_Location_Equal_To.h"
+
+ACE_RCSID (PortableGroup,
+ PG_Location_Equal_To,
+ "$Id$")
+
+#if !defined (__ACE_INLINE__)
+#include "orbsvcs/PortableGroup/PG_Location_Equal_To.inl"
+#endif /* !__ACE_INLINE__ */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Equal_To.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Equal_To.h
new file mode 100644
index 00000000000..cbfc12a8949
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Equal_To.h
@@ -0,0 +1,59 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Location_Equal_To.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_PG_LOCATION_EQUAL_TO_H
+#define TAO_PG_LOCATION_EQUAL_TO_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroup/PG_Operators.h"
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+#include "orbsvcs/PortableGroupC.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class TAO_PG_Location_Equal_To
+ *
+ * @brief "Equal_To" function object that determines if two location
+ * names are the same.
+ *
+ * This functor simply does a string comparison of each of the
+ * elements in the given TAO_PortableGroup::Location name sequences.
+ */
+class TAO_PortableGroup_Export TAO_PG_Location_Equal_To
+{
+public:
+
+ /// Perform a string comparison on each of the sequence elements in
+ /// the given locations.
+ int operator() (const PortableGroup::Location &lhs,
+ const PortableGroup::Location &rhs) const;
+
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "orbsvcs/PortableGroup/PG_Location_Equal_To.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PG_LOCATION_EQUAL_TO_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Equal_To.inl b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Equal_To.inl
new file mode 100644
index 00000000000..052d968242b
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Equal_To.inl
@@ -0,0 +1,15 @@
+// -*- C++ -*-
+//
+// $Id$
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE int
+TAO_PG_Location_Equal_To::operator () (
+ const PortableGroup::Location &lhs,
+ const PortableGroup::Location &rhs) const
+{
+ return lhs == rhs;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Hash.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Hash.cpp
new file mode 100644
index 00000000000..0197726bfe8
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Hash.cpp
@@ -0,0 +1,13 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "orbsvcs/PortableGroup/PG_Location_Hash.h"
+
+#if !defined (__ACE_INLINE__)
+#include "orbsvcs/PortableGroup/PG_Location_Hash.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (PortableGroup,
+ PG_Location_Hash,
+ "$Id$")
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Hash.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Hash.h
new file mode 100644
index 00000000000..d59b5320ff0
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Hash.h
@@ -0,0 +1,53 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Location_Hash.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_PG_LOCATION_HASH_H
+#define TAO_PG_LOCATION_HASH_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+#include "orbsvcs/PortableGroupC.h"
+#include "ace/ACE.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class TAO_PG_Location_Hash
+ *
+ * @brief Hash function object for generating a hash for a Location.
+ */
+class TAO_PortableGroup_Export TAO_PG_Location_Hash
+{
+
+public:
+
+ /// Creates a hash based on all of elements of the given Location
+ CORBA::ULong operator() (const PortableGroup::Location &) const;
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "orbsvcs/PortableGroup/PG_Location_Hash.inl"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PG_LOCATION_HASH_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Hash.inl b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Hash.inl
new file mode 100644
index 00000000000..a0b591b1068
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Hash.inl
@@ -0,0 +1,25 @@
+// -*- C++ -*-
+//
+// $Id$
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE CORBA::ULong
+TAO_PG_Location_Hash::operator() (
+ const PortableGroup::Location &location) const
+{
+ // @todo Interim implementation until we figure out what to do when a
+ // location has multiple components.
+
+ CORBA::ULong len = location.length ();
+ CORBA::ULong hash = 0;
+
+ for (CORBA::ULong i = 0; i < len; ++i)
+ hash +=
+ ACE::hash_pjw (location[i].id.in ()) +
+ ACE::hash_pjw (location[i].kind.in ());
+
+ return hash;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Map.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Map.h
new file mode 100644
index 00000000000..e0eb6dbf756
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Location_Map.h
@@ -0,0 +1,54 @@
+// -*- C++ -*-
+
+//=======================================================================
+/**
+ * @file PG_Location_Map.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=======================================================================
+
+
+#ifndef TAO_PG_LOCATION_MAP_H
+#define TAO_PG_LOCATION_MAP_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroup/PG_Location_Hash.h"
+#include "orbsvcs/PortableGroup/PG_Location_Equal_To.h"
+
+#include "orbsvcs/PortableGroupC.h"
+
+#include "ace/Array_Base.h"
+#include "ace/Hash_Map_Manager_T.h"
+#include "ace/Null_Mutex.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// Forward declarations.
+struct TAO_PG_ObjectGroup_Map_Entry;
+
+typedef ACE_Array_Base<TAO_PG_ObjectGroup_Map_Entry *>
+ TAO_PG_ObjectGroup_Array;
+
+/// Location hash map.
+typedef ACE_Hash_Map_Manager_Ex<
+ PortableGroup::Location,
+ TAO_PG_ObjectGroup_Array *,
+ TAO_PG_Location_Hash,
+ TAO_PG_Location_Equal_To,
+ ACE_Null_Mutex> TAO_PG_Location_Map;
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PG_LOCATION_MAP_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_MemberInfo.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_MemberInfo.cpp
new file mode 100644
index 00000000000..1485e8277d9
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_MemberInfo.cpp
@@ -0,0 +1,18 @@
+#include "orbsvcs/PortableGroup/PG_MemberInfo.h"
+#include "orbsvcs/PortableGroup/PG_Operators.h"
+
+ACE_RCSID (PortableGroup,
+ PG_MemberInfo,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+bool
+TAO_PG_MemberInfo::operator== (const TAO_PG_MemberInfo & rhs)
+{
+ // For the purposes of the member info set, only the location is
+ // important.
+ return location == rhs.location;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_MemberInfo.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_MemberInfo.h
new file mode 100644
index 00000000000..41d428bd0bb
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_MemberInfo.h
@@ -0,0 +1,62 @@
+// -*- C++ -*-
+
+//=======================================================================
+/**
+ * @file PG_MemberInfo.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=======================================================================
+
+
+#ifndef TAO_PG_MEMBER_INFO_H
+#define TAO_PG_MEMBER_INFO_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroupC.h"
+#include "ace/Unbounded_Set.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class TAO_PG_MemberInfo
+ *
+ * @brief Structure that contains all member-specific information.
+ *
+ * Structure that contains all member-specific information.
+ */
+struct TAO_PG_MemberInfo
+{
+
+ /// Reference to the member.
+ CORBA::Object_var member;
+
+ /// The location at which the member resides.
+ PortableGroup::Location location;
+
+ /// Equality operator.
+ /**
+ * For the purposes of the member info set, only the location is
+ * important. In particular, if a member already resides at the
+ * given location, this equality operator will return true.
+ */
+ bool operator== (const TAO_PG_MemberInfo & rhs);
+
+};
+
+typedef ACE_Unbounded_Set<TAO_PG_MemberInfo> TAO_PG_MemberInfo_Set;
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PG_MEMBER_INFO_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Null_Property_Validator.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Null_Property_Validator.cpp
new file mode 100644
index 00000000000..5251b3d7931
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Null_Property_Validator.cpp
@@ -0,0 +1,30 @@
+#include "orbsvcs/PortableGroup/PG_Null_Property_Validator.h"
+
+
+ACE_RCSID (PortableGroup,
+ PG_Null_Property_Validator,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+TAO_PG_Null_Property_Validator::validate_property (
+ const PortableGroup::Properties &
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty))
+{
+}
+
+void
+TAO_PG_Null_Property_Validator::validate_criteria (
+ const PortableGroup::Properties &
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidCriteria,
+ PortableGroup::CannotMeetCriteria))
+{
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Null_Property_Validator.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Null_Property_Validator.h
new file mode 100644
index 00000000000..41047a90c99
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Null_Property_Validator.h
@@ -0,0 +1,67 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Null_Property_Validator.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+#ifndef TAO_PG_NULL_PROPERTY_VALIDATOR_H
+#define TAO_PG_NULL_PROPERTY_VALIDATOR_H
+
+#include /**/ "ace/pre.h"
+
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+#include "orbsvcs/PortableGroupC.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class TAO_PG_Null_Property_Validator
+ *
+ * @brief No-op property validator.
+ *
+ * This property validator performs no validation whatsoever.
+ */
+class TAO_PortableGroup_Export TAO_PG_Null_Property_Validator
+{
+public:
+
+ /// Validate the given properties.
+ /**
+ * This particular implementation performs no validation
+ * whatsoever.
+ */
+ void validate_property (const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty));
+
+ /// Validate the given criteria.
+ /**
+ * This particular implementation performs no validation
+ * whatsoever.
+ */
+ void validate_criteria (const PortableGroup::Properties & criteria
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidCriteria,
+ PortableGroup::CannotMeetCriteria));
+
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PG_PROPERTY_VALIDATOR_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.cpp
new file mode 100644
index 00000000000..7b78ef895bc
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.cpp
@@ -0,0 +1,871 @@
+#include "orbsvcs/PortableGroup/PG_ObjectGroupManager.h"
+#include "orbsvcs/PortableGroup/PG_GenericFactory.h"
+#include "orbsvcs/PortableGroup/PG_conf.h"
+#include "orbsvcs/PortableGroup/PG_Operators.h"
+
+#include "tao/debug.h"
+#include "tao/ORB_Constants.h"
+
+#include "ace/Auto_Ptr.h"
+#include "ace/Reverse_Lock_T.h"
+
+ACE_RCSID (PortableGroup,
+ PG_ObjectGroupManager,
+ "$Id$")
+
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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_ ()
+{
+}
+
+TAO_PG_ObjectGroupManager::~TAO_PG_ObjectGroupManager (void)
+{
+ for (TAO_PG_Location_Map::iterator i = this->location_map_.begin ();
+ i != this->location_map_.end ();
+ ++i)
+ {
+ // Destroy the group array
+ delete (*i).int_id_;
+ }
+ (void) this->location_map_.close ();
+
+ for (TAO_PG_ObjectGroup_Map::iterator j = this->object_group_map_.begin ();
+ j != this->object_group_map_.end ();
+ ++j)
+ {
+ // Destroy the object group entry
+ delete (*j).int_id_;
+ }
+ (void) this->object_group_map_.close ();
+}
+
+PortableGroup::ObjectGroup_ptr
+TAO_PG_ObjectGroupManager::create_member (
+ PortableGroup::ObjectGroup_ptr /* object_group */,
+ const PortableGroup::Location & /* the_location */,
+ const char * /* type_id */,
+ const PortableGroup::Criteria & /* the_criteria */
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound,
+ PortableGroup::MemberAlreadyPresent,
+ PortableGroup::NoFactory,
+ PortableGroup::ObjectNotCreated,
+ PortableGroup::InvalidCriteria,
+ PortableGroup::CannotMeetCriteria))
+{
+ ACE_THROW_RETURN (CORBA::NO_IMPLEMENT (),
+ PortableGroup::ObjectGroup::_nil ());
+}
+
+PortableGroup::ObjectGroup_ptr
+TAO_PG_ObjectGroupManager::add_member (
+ PortableGroup::ObjectGroup_ptr object_group,
+ const PortableGroup::Location & the_location,
+ CORBA::Object_ptr member
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound,
+ PortableGroup::MemberAlreadyPresent,
+ PortableGroup::ObjectNotAdded))
+{
+ 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 ());
+
+ // 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 ());
+
+ if (check_type_id)
+ {
+ 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;
+ if (this->location_map_.find (the_location, groups) == 0
+ && this->member_already_present (*groups, group_entry))
+ ACE_THROW_RETURN (PortableGroup::MemberAlreadyPresent (),
+ PortableGroup::ObjectGroup::_nil ());
+
+ TAO_PG_MemberInfo member_info;
+ member_info.member = CORBA::Object::_duplicate (member);
+ member_info.location = the_location;
+
+ if (groups == 0)
+ {
+ ACE_NEW_THROW_EX (groups,
+ TAO_PG_ObjectGroup_Array,
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (0);
+
+ auto_ptr<TAO_PG_ObjectGroup_Array> safe_groups (groups);
+
+ // This should not fail!
+ if (this->location_map_.bind (the_location, groups) != 0)
+ {
+ ACE_THROW_RETURN (PortableGroup::ObjectNotAdded (),
+ PortableGroup::ObjectGroup::_nil ());
+ }
+
+ (void) safe_groups.release ();
+ }
+
+ // No object group member of the object group with the given
+ // ObjectGroupId resides at the location. Add the object group
+ // entry to array of object groups residing at the location.
+ const size_t groups_len = groups->size ();
+ groups->size (groups_len + 1);
+ (*groups)[groups_len] = group_entry;
+
+ // Don't bother checking for duplicates since a check is already
+ // performed when binding to the location map above.
+ if (group_entry->member_infos.insert_tail (member_info) != 0)
+ ACE_THROW_RETURN (PortableGroup::ObjectNotAdded (),
+ PortableGroup::ObjectGroup::_nil ());
+
+ return PortableGroup::ObjectGroup::_duplicate (object_group);
+}
+
+PortableGroup::ObjectGroup_ptr
+TAO_PG_ObjectGroupManager::remove_member (
+ PortableGroup::ObjectGroup_ptr object_group,
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound,
+ PortableGroup::MemberNotFound))
+{
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->lock_, 0);
+
+ TAO_PG_ObjectGroup_Map_Entry * group_entry =
+ this->get_group_entry (object_group
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (PortableGroup::ObjectGroup::_nil ());
+
+ TAO_PG_ObjectGroup_Array * groups = 0;
+ if (this->location_map_.find (the_location, groups) != 0)
+ ACE_THROW_RETURN (PortableGroup::ObjectGroupNotFound (),
+ PortableGroup::ObjectGroup::_nil ());
+
+ // Multiple members from different object groups may reside at the
+ // same location. Iterate through the list to attempt to find a
+ // match for the exact object group.
+ size_t to_be_removed = 0;
+
+ // get the position of the object group in the object_group_array
+ to_be_removed = this->get_object_group_position (*groups, group_entry);
+
+ // remove the element from the array and resize the array.
+ const size_t groups_len = groups->size ();
+ size_t j;
+ for (size_t i = to_be_removed; i < groups_len - 1; ++i)
+ {
+ j = i + 1;
+ (*groups)[i] = (*groups)[j];
+ }
+
+ groups->size (groups_len - 1);
+
+ TAO_PG_MemberInfo_Set & member_infos = group_entry->member_infos;
+
+ TAO_PG_MemberInfo_Set::iterator end = member_infos.end ();
+
+ for (TAO_PG_MemberInfo_Set::iterator iter = member_infos.begin ();
+ iter != end;
+ ++iter)
+ {
+ const TAO_PG_MemberInfo & info = *iter;
+
+ if (info.location == the_location)
+ {
+ // Give the GenericFactory a chance to delete a member if
+ // its membership is under infrastructure control.
+ if (this->generic_factory_)
+ {
+ 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)
+ {
+ if (this->generic_factory_)
+ {
+ 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;
+ }
+ }
+
+ ACE_THROW_RETURN (PortableGroup::MemberNotFound (),
+ PortableGroup::ObjectGroup::_nil ());
+}
+
+PortableGroup::Locations *
+TAO_PG_ObjectGroupManager::locations_of_members (
+ PortableGroup::ObjectGroup_ptr object_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 (object_group
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ PortableGroup::Locations *temp = 0;
+ ACE_NEW_THROW_EX (temp,
+ PortableGroup::Locations,
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (0);
+
+ PortableGroup::Locations_var locations = temp;
+
+ TAO_PG_MemberInfo_Set & member_infos = group_entry->member_infos;
+
+ locations->length (static_cast<CORBA::ULong> (member_infos.size ()));
+
+ CORBA::ULong loc = 0;
+ TAO_PG_MemberInfo_Set::iterator end = member_infos.end ();
+
+ for (TAO_PG_MemberInfo_Set::iterator i = member_infos.begin ();
+ i != end;
+ ++i)
+ locations[loc++] = (*i).location;
+
+ return locations._retn ();
+}
+
+PortableGroup::ObjectGroups *
+TAO_PG_ObjectGroupManager::groups_at_location (
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ PortableGroup::ObjectGroups * ogs;
+ ACE_NEW_THROW_EX (ogs,
+ PortableGroup::ObjectGroups,
+ CORBA::NO_MEMORY ());
+ ACE_CHECK_RETURN (0);
+
+ PortableGroup::ObjectGroups_var object_groups = ogs;
+
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->lock_, 0);
+
+ TAO_PG_ObjectGroup_Array * groups;
+ if (this->location_map_.find (the_location, groups) == 0)
+ {
+ CORBA::ULong len = static_cast<CORBA::ULong> (groups->size ());
+
+ ogs->length (len);
+
+ for (CORBA::ULong i = 0; i < len; ++i)
+ {
+ object_groups[i] =
+ PortableGroup::ObjectGroup::_duplicate (
+ (*groups)[i]->object_group.in ());
+ }
+ }
+
+ return object_groups._retn ();
+}
+
+PortableGroup::ObjectGroupId
+TAO_PG_ObjectGroupManager::get_object_group_id (
+ PortableGroup::ObjectGroup_ptr object_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 * entry =
+ this->get_group_entry (object_group
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ if (entry == 0)
+ ACE_THROW_RETURN (CORBA::INTERNAL (), 0);
+
+ // Only the lower 32 bits of the 64 bit PortableGroup::ObjectGroupId
+ // are ever used.
+ return entry->group_id;
+}
+
+PortableGroup::ObjectGroup_ptr
+TAO_PG_ObjectGroupManager::get_object_group_ref (
+ PortableGroup::ObjectGroup_ptr object_group
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound))
+{
+ TAO_PG_ObjectGroup_Map_Entry * entry = 0;
+
+ {
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->lock_,
+ PortableGroup::ObjectGroup::_nil ());
+
+
+ entry = this->get_group_entry (object_group
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (PortableGroup::ObjectGroup::_nil ());
+ }
+
+ if (entry == 0)
+ ACE_THROW_RETURN (CORBA::INTERNAL (),
+ PortableGroup::ObjectGroup::_nil ());
+
+ // This implemenation does not change the object group reference.
+ return PortableGroup::ObjectGroup::_duplicate (object_group);
+}
+
+CORBA::Object_ptr
+TAO_PG_ObjectGroupManager::get_member_ref (
+ PortableGroup::ObjectGroup_ptr object_group,
+ const PortableGroup::Location & loc
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound,
+ PortableGroup::MemberNotFound))
+{
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->lock_,
+ CORBA::Object::_nil ());
+
+ TAO_PG_ObjectGroup_Map_Entry * group_entry =
+ this->get_group_entry (object_group
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (PortableGroup::ObjectGroup::_nil ());
+
+ // This method assumes that it is faster to check for non-existence
+ // of an object group (and hence the member) at a given location,
+ // instead of existence of a member at a given location.
+
+ TAO_PG_ObjectGroup_Array * groups = 0;
+ if (this->location_map_.find (loc, groups) == 0
+ && this->member_already_present (*groups, group_entry))
+ {
+ TAO_PG_MemberInfo_Set & member_infos = group_entry->member_infos;
+
+ TAO_PG_MemberInfo_Set::iterator end = member_infos.end ();
+
+ // @todo If the object group contains a large number of members,
+ // this loop could take a while. Explore potentially
+ // faster containers for the list of PG_MemberInfos in the
+ // future.
+ for (TAO_PG_MemberInfo_Set::iterator i = member_infos.begin ();
+ i != end;
+ ++i)
+ if ((*i).location == loc)
+ return CORBA::Object::_duplicate ((*i).member.in ());
+ }
+
+ // No member of the given object group is present at the given
+ // location.
+ ACE_THROW_RETURN (PortableGroup::MemberNotFound (),
+ CORBA::Object::_nil ());
+}
+
+PortableGroup::ObjectGroup_ptr
+TAO_PG_ObjectGroupManager::get_object_group_ref_from_id (
+ PortableGroup::ObjectGroupId group_id
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((
+ CORBA::SystemException
+ , PortableGroup::ObjectGroupNotFound
+ ))
+{
+ //@@ If we change the PG's concept of ObjectGroupId from
+ // PortableServer::ObjectId to PortableGroup::ObjectGroupId, can
+ // just call TAO_PG_ObjectGroupManager::object_group() here.
+
+ TAO_PG_ObjectGroup_Map_Entry * group_entry = 0;
+ {
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->lock_,
+ PortableGroup::ObjectGroup::_nil ());
+
+ if (this->object_group_map_.find (ACE_U64_TO_U32 (group_id),
+ group_entry)
+ != 0)
+ {
+ ACE_THROW_RETURN (PortableGroup::ObjectGroupNotFound (),
+ PortableGroup::ObjectGroup::_nil ());
+ }
+ }
+
+ if (group_entry == 0)
+ {
+ ACE_THROW_RETURN (CORBA::INTERNAL (),
+ PortableGroup::ObjectGroup::_nil ());
+ }
+
+ return
+ PortableGroup::ObjectGroup::_duplicate (group_entry->object_group.in ());
+}
+
+PortableGroup::ObjectGroup_ptr
+TAO_PG_ObjectGroupManager::create_object_group (
+ CORBA::ULong group_id,
+ const PortableServer::ObjectId &oid,
+ const char * type_id,
+ const PortableGroup::Criteria & the_criteria
+ ACE_ENV_ARG_DECL)
+{
+ if (CORBA::is_nil (this->poa_.in ()))
+ ACE_THROW_RETURN (CORBA::INTERNAL (), CORBA::Object::_nil ());
+
+ // Create a reference for the ObjectGroup corresponding to the
+ // RepositoryId of the object being created.
+ CORBA::Object_var object_group =
+ this->poa_->create_reference_with_id (oid,
+ type_id
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (CORBA::Object::_nil ());
+
+ TAO_PG_ObjectGroup_Map_Entry * group_entry = 0;
+ ACE_NEW_THROW_EX (group_entry,
+ TAO_PG_ObjectGroup_Map_Entry,
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (CORBA::Object::_nil ());
+
+ auto_ptr<TAO_PG_ObjectGroup_Map_Entry> safe_group_entry (group_entry);
+
+ // Set the RepositoryId associated with the created ObjectGroup_Map
+ // entry.
+ group_entry->type_id = CORBA::string_dup (type_id);
+
+ group_entry->group_id = group_id;
+
+ group_entry->object_group = object_group;
+
+ CORBA::ULong len = the_criteria.length ();
+ group_entry->properties.length (len);
+ for (CORBA::ULong i = 0; i < len; ++i)
+ group_entry->properties[i] = the_criteria[i];
+
+ {
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->lock_,
+ 0);
+
+ if (this->object_group_map_.bind (oid, group_entry) != 0)
+ ACE_THROW_RETURN (PortableGroup::ObjectNotCreated (),
+ PortableGroup::ObjectGroup::_nil ());
+ }
+
+ (void) safe_group_entry.release ();
+
+ return object_group._retn ();
+}
+
+void
+TAO_PG_ObjectGroupManager::destroy_object_group (
+ const PortableServer::ObjectId & oid
+ ACE_ENV_ARG_DECL)
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
+
+ TAO_PG_ObjectGroup_Map_Entry * group_entry = 0;
+ if (this->object_group_map_.unbind (oid, group_entry) != 0)
+ ACE_THROW (PortableGroup::ObjectNotFound ());
+
+ delete group_entry;
+}
+
+char *
+TAO_PG_ObjectGroupManager::type_id (
+ PortableGroup::ObjectGroup_ptr object_group
+ ACE_ENV_ARG_DECL)
+{
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->lock_,
+ 0);
+
+ TAO_PG_ObjectGroup_Map_Entry * group_entry =
+ this->get_group_entry (object_group
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ return CORBA::string_dup (group_entry->type_id.in ());
+}
+
+PortableGroup::ObjectGroup_ptr
+TAO_PG_ObjectGroupManager::object_group (const PortableServer::ObjectId & oid)
+{
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->lock_,
+ PortableGroup::ObjectGroup::_nil ());
+
+ TAO_PG_ObjectGroup_Map_Entry * group_entry = 0;
+ if (this->object_group_map_.find (oid, group_entry) == 0)
+ return
+ PortableGroup::ObjectGroup::_duplicate (group_entry->object_group.in ());
+ else
+ 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 static_cast<CORBA::ULong> (group_entry->member_infos.size ());
+}
+
+void
+TAO_PG_ObjectGroupManager::poa (PortableServer::POA_ptr p)
+{
+ this->poa_ = PortableServer::POA::_duplicate (p);
+}
+
+
+PortableGroup::Properties *
+TAO_PG_ObjectGroupManager::get_properties (
+ PortableGroup::ObjectGroup_ptr object_group
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound))
+{
+ PortableGroup::Properties * properties = 0;
+ ACE_NEW_THROW_EX (properties,
+ PortableGroup::Properties,
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (0);
+
+ PortableGroup::Properties_var safe_properties = properties;
+
+ {
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->lock_,
+ 0);
+
+ TAO_PG_ObjectGroup_Map_Entry * group_entry =
+ this->get_group_entry (object_group
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ *properties = group_entry->properties;
+ }
+
+ return safe_properties._retn ();
+}
+
+TAO_PG_ObjectGroup_Map_Entry *
+TAO_PG_ObjectGroupManager::get_group_entry (
+ CORBA::Object_ptr object_group
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound))
+{
+ if (CORBA::is_nil (this->poa_.in ()))
+ ACE_THROW_RETURN (CORBA::INTERNAL (), 0);
+
+ PortableServer::ObjectId_var oid;
+ ACE_TRY
+ {
+ oid = this->poa_->reference_to_id (object_group
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ ACE_CATCH (PortableServer::POA::WrongAdapter, ex)
+ {
+ if (TAO_debug_level > 0)
+ ACE_PRINT_EXCEPTION (ex, "TAO_PG (%P|%t) Unexpected exception\n");
+
+ ACE_TRY_THROW (CORBA::INTERNAL ());
+ }
+ ACE_CATCH (PortableServer::POA::WrongPolicy, ex)
+ {
+ if (TAO_debug_level > 0)
+ ACE_PRINT_EXCEPTION (ex, "TAO_PG (%P|%t) Unexpected exception\n");
+
+ ACE_TRY_THROW (CORBA::INTERNAL ());
+ }
+ ACE_ENDTRY;
+ ACE_CHECK_RETURN (0);
+
+ TAO_PG_ObjectGroup_Map_Entry * group_entry = 0;
+ if (this->object_group_map_.find (oid.in (), group_entry) != 0)
+ ACE_THROW_RETURN (PortableGroup::ObjectGroupNotFound (),
+ 0);
+
+ return group_entry;
+}
+
+CORBA::Boolean
+TAO_PG_ObjectGroupManager::member_already_present (
+ const TAO_PG_ObjectGroup_Array &groups,
+ TAO_PG_ObjectGroup_Map_Entry * group_entry)
+{
+ // Multiple members from different object groups may reside at the
+ // same location. Iterate through the list to attempt to find a
+ // match.
+ size_t len = groups.size ();
+ for (size_t i = 0; i < len; ++i)
+ {
+ // It should be enough just to compare the group_entry pointers,
+ // but that seems brittle. Better to check a controlled value,
+ // like the ObjectGroupId.
+ if (groups[i]->group_id == group_entry->group_id)
+ {
+ // Member with given type ID exists at the given
+ // location.
+ return 1;
+ }
+ }
+
+ // No member with given type ID present at the given location.
+ return 0;
+}
+
+size_t
+TAO_PG_ObjectGroupManager::get_object_group_position (
+ const TAO_PG_ObjectGroup_Array &groups,
+ TAO_PG_ObjectGroup_Map_Entry * group_entry)
+{
+ // Multiple members from different object groups may reside at the
+ // same location. Iterate through the list to attempt to find a
+ // match.
+ size_t len = groups.size ();
+ for (size_t i = 0; i < len; ++i)
+ {
+ // It should be enough just to compare the group_entry pointers,
+ // but that seems brittle. Better to check a controlled value,
+ // like the ObjectGroupId.
+ if (groups[i]->group_id == group_entry->group_id)
+ {
+ // Member with given type ID exists at the given
+ // location.
+ return i;
+ }
+ }
+
+ // No member with given type ID present at the given location.
+ return 0;
+}
+
+CORBA::Boolean
+TAO_PG_ObjectGroupManager::valid_type_id (
+ PortableGroup::ObjectGroup_ptr object_group,
+ TAO_PG_ObjectGroup_Map_Entry * group_entry,
+ CORBA::Object_ptr member
+ ACE_ENV_ARG_DECL)
+{
+ // @todo Strategize this -- e.g. strict type checking.
+
+ if (CORBA::is_nil (member))
+ ACE_THROW_RETURN (CORBA::BAD_PARAM (), false);
+
+ // Before we can use this code, i.e. the reverse lock, the
+ // TAO_PG_ObjectGroup_Entry should be made so that it is reference
+ // counted. This is necessary since releasing the lock would
+ // allow other threads to destroy/unbind the object group entry.
+ // Another alternative is to simply attempt to reacquire the
+ // object group map entry once the lock is reacquired, which is
+ // easier to implement.
+
+ // Copy the type_id before releasing the lock to avoid a race
+ // condition.
+ CORBA::String_var type_id =
+ CORBA::string_dup (group_entry->type_id.in ());
+
+ CORBA::Boolean right_type_id = 0;
+ {
+ // Release the lock during the type_id check. No need to block
+ // other threads during the invocation.
+ ACE_Reverse_Lock<TAO_SYNCH_MUTEX> reverse_lock (this->lock_);
+
+ ACE_GUARD_RETURN (ACE_Reverse_Lock<TAO_SYNCH_MUTEX>,
+ reverse_guard,
+ reverse_lock,
+ right_type_id);
+
+ // 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.
+ right_type_id =
+ member->_is_a (type_id.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (right_type_id);
+ }
+
+ // Make sure the group entry still exists. It may have been
+ // destroyed by another thread.
+ group_entry = this->get_group_entry (object_group
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (right_type_id);
+
+ return right_type_id;
+}
+
+void
+TAO_PG_ObjectGroupManager::generic_factory (
+ TAO_PG_GenericFactory * generic_factory)
+{
+ this->generic_factory_ = generic_factory;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.h
new file mode 100644
index 00000000000..b78cc4028f3
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroupManager.h
@@ -0,0 +1,314 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_ObjectGroupManager.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_PG_OBJECT_GROUP_MANAGER_H
+#define TAO_PG_OBJECT_GROUP_MANAGER_H
+
+#include /**/ "ace/pre.h"
+
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+#include "orbsvcs/PortableGroupS.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroup/PG_ObjectGroup_Map.h"
+#include "orbsvcs/PortableGroup/PG_Location_Map.h"
+
+#include "tao/PortableServer/Key_Adapters.h"
+#include "tao/PortableServer/PortableServerC.h"
+
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// Forward declarations
+class TAO_PG_GenericFactory;
+
+
+/**
+ * @class TAO_PG_ObjectGroupManager
+ *
+ * @brief PortableGroup::ObjectGroupManager implementation.
+ *
+ * The ObjectGroupManager provides the interface necessary to
+ * facilitate application-controlled object group membership.
+ */
+class TAO_PortableGroup_Export TAO_PG_ObjectGroupManager
+ : public virtual POA_PortableGroup::ObjectGroupManager
+{
+public:
+
+ /// Constructor.
+ TAO_PG_ObjectGroupManager (void);
+
+ /// Destructor.
+ ~TAO_PG_ObjectGroupManager (void);
+
+ /**
+ * @name PortableGroup::ObjectGroupManager methods
+ *
+ * Methods required by the PortableGroup::ObjectGroupManager
+ * interface.
+ */
+ //@{
+
+ /// Create a member and add it to the given object group.
+ 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
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound,
+ PortableGroup::MemberAlreadyPresent,
+ PortableGroup::NoFactory,
+ PortableGroup::ObjectNotCreated,
+ PortableGroup::InvalidCriteria,
+ PortableGroup::CannotMeetCriteria));
+
+ /// Add an existing object to the ObjectGroup.
+ virtual PortableGroup::ObjectGroup_ptr add_member (
+ PortableGroup::ObjectGroup_ptr object_group,
+ const PortableGroup::Location & the_location,
+ CORBA::Object_ptr member
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound,
+ PortableGroup::MemberAlreadyPresent,
+ PortableGroup::ObjectNotAdded));
+
+ /**
+ * 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
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound,
+ PortableGroup::MemberNotFound));
+
+ /// Return the locations of the members in the given ObjectGroup.
+ virtual PortableGroup::Locations * locations_of_members (
+ PortableGroup::ObjectGroup_ptr object_group
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound));
+
+ /// Return the locations of the members in the given ObjectGroup.
+ virtual PortableGroup::ObjectGroups * groups_at_location (
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /// Return the ObjectGroupId for the given ObjectGroup.
+ /// @note Does this method make sense for load balanced objects?
+ virtual PortableGroup::ObjectGroupId get_object_group_id (
+ PortableGroup::ObjectGroup_ptr object_group
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound));
+
+ /// @note Does this method make sense for load balanced objects?
+ virtual PortableGroup::ObjectGroup_ptr get_object_group_ref (
+ PortableGroup::ObjectGroup_ptr object_group
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound));
+
+ /// Return the reference corresponding to the member of a given
+ /// ObjectGroup at the given location.
+ virtual CORBA::Object_ptr get_member_ref (
+ PortableGroup::ObjectGroup_ptr object_group,
+ const PortableGroup::Location & loc
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound,
+ PortableGroup::MemberNotFound));
+ /**
+ * TAO-specific extension.
+ * Return the ObjectGroup reference for the given ObjectGroupId.
+ */
+ virtual PortableGroup::ObjectGroup_ptr get_object_group_ref_from_id (
+ PortableGroup::ObjectGroupId group_id
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS
+ )
+ ACE_THROW_SPEC ((
+ CORBA::SystemException
+ , PortableGroup::ObjectGroupNotFound
+ ));
+
+ //@}
+
+ /// 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.
+ /**
+ * @note This method is used mainly by the
+ * GenericFactory::create_object() method.
+ */
+ PortableGroup::ObjectGroup_ptr create_object_group (
+ CORBA::ULong group_id,
+ const PortableServer::ObjectId &oid,
+ const char * type_id,
+ const PortableGroup::Criteria & the_criteria
+ ACE_ENV_ARG_DECL);
+
+ /// Destroy the object group corresponding to the given ObjectId.
+ /**
+ * @note This method is used mainly by the
+ * GenericFactory::delete_object() method.
+ */
+ void destroy_object_group (const PortableServer::ObjectId & oid
+ ACE_ENV_ARG_DECL);
+
+ /// Return the properties set when the object group was created, and
+ /// the dynamic properties that may have overridden them.
+ PortableGroup::Properties * get_properties (
+ PortableGroup::ObjectGroup_ptr object_group
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound));
+
+ /// Return the type_id for the given object group.
+ char * type_id (PortableGroup::ObjectGroup_ptr object_group
+ ACE_ENV_ARG_DECL);
+
+ /// Return the object group associated with the given ObjectId.
+ /**
+ * @return Returns PortableGroup::ObjectGroup::_nil() if no object
+ * group corresponding to the given ObjectId exists.
+ */
+ 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)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound));
+
+ /// 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 (
+ PortableGroup::ObjectGroup_ptr object_group
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound));
+
+
+ /// Check if a member resides at the location to which the group
+ /// array belongs to.
+ /**
+ * A member is actually represented by the object group to which it
+ * belongs. In this implementation, a pointer to a object group
+ * hash map entry is associated with a given a location.
+ */
+ CORBA::Boolean member_already_present (
+ const TAO_PG_ObjectGroup_Array & groups,
+ TAO_PG_ObjectGroup_Map_Entry * group_entry);
+
+ /// get the position of the object_group_map_entry
+ size_t get_object_group_position (
+ const TAO_PG_ObjectGroup_Array & groups,
+ TAO_PG_ObjectGroup_Map_Entry * group_entry);
+
+ /// Verify that the member type_id matches the object group type_id.
+ /**
+ * @todo Strategize this -- e.g. strict type checking.
+ */
+ CORBA::Boolean valid_type_id (
+ PortableGroup::ObjectGroup_ptr object_group,
+ TAO_PG_ObjectGroup_Map_Entry * group_entry,
+ CORBA::Object_ptr member
+ ACE_ENV_ARG_DECL);
+
+private:
+
+ /// Reference to the POA that created the object group references.
+ PortableServer::POA_var poa_;
+
+ /// The underlying table that contains all object group
+ /// information.
+ TAO_PG_ObjectGroup_Map object_group_map_;
+
+ /// Map that contains list of all members at a given location, in
+ /// 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_;
+
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PG_OBJECT_GROUP_MANAGER_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroup_Map.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroup_Map.h
new file mode 100644
index 00000000000..4673a79df0f
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroup_Map.h
@@ -0,0 +1,84 @@
+// -*- C++ -*-
+
+//=======================================================================
+/**
+ * @file PG_ObjectGroup_Map.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=======================================================================
+
+
+#ifndef TAO_PG_OBJECTGROUP_MAP_H
+#define TAO_PG_OBJECTGROUP_MAP_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroup/PG_MemberInfo.h"
+
+#include "orbsvcs/PortableGroupC.h"
+
+#include "tao/PortableServer/Key_Adapters.h"
+#include "tao/PortableServer/PortableServerC.h"
+
+#include "ace/Hash_Map_Manager_T.h"
+#include "ace/Null_Mutex.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class TAO_PG_ObjectGroup_Map_Entry
+ *
+ * @brief Value field of the ObjectGroup map.
+ */
+struct TAO_PG_ObjectGroup_Map_Entry
+{
+public:
+
+ /// The RepositoryId corresponding to all Members in the
+ /// ObjectGroup.
+ CORBA::String_var type_id;
+
+ /// This is the PortableGroup::ObjectGroupId.
+ /**
+ * The spec states that PortableGroup::ObjectGroupId is a
+ * CORBA::ULongLong. However, the over 4 billion group IDs that can
+ * be represented by a CORBA::ULong should be plenty for any
+ * application.
+ */
+ CORBA::ULong group_id;
+
+ /// Reference to the ObjectGroup.
+ PortableGroup::ObjectGroup_var object_group;
+
+ /// Unbounded set containing member references and all related
+ /// information for each member.
+ TAO_PG_MemberInfo_Set member_infos;
+
+ /// Properties used when creating this object group, in addition to
+ /// those set dynamically after the creation.
+ PortableGroup::Properties properties;
+
+};
+
+/// ObjectId hash map typedef.
+typedef ACE_Hash_Map_Manager_Ex<
+ PortableServer::ObjectId,
+ TAO_PG_ObjectGroup_Map_Entry *,
+ TAO_ObjectId_Hash,
+ ACE_Equal_To<PortableServer::ObjectId>,
+ ACE_Null_Mutex> TAO_PG_ObjectGroup_Map;
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PG_OBJECTGROUP_MAP_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Adapter_Factory.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Adapter_Factory.cpp
new file mode 100644
index 00000000000..f8545615ad6
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Adapter_Factory.cpp
@@ -0,0 +1,48 @@
+// $Id$
+
+#include "orbsvcs/PortableGroup/PG_Object_Adapter_Factory.h"
+#include "orbsvcs/PortableGroup/PG_Servant_Dispatcher.h"
+
+#include "tao/PortableServer/Object_Adapter.h"
+#include "tao/ORB_Core.h"
+
+ACE_RCSID (TAO_PortableGroup,
+ PG_Object_Adapter_Factory,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO_PG_Object_Adapter_Factory::TAO_PG_Object_Adapter_Factory (void)
+{
+}
+
+TAO_Adapter*
+TAO_PG_Object_Adapter_Factory::create (TAO_ORB_Core *orb_core)
+{
+ TAO_Object_Adapter *object_adapter = 0;
+ ACE_NEW_RETURN (object_adapter,
+ TAO_Object_Adapter (orb_core->server_factory ()->
+ active_object_map_creation_parameters (),
+ *orb_core),
+ 0);
+
+ // Create and register the RT servant dispatcher.
+ TAO_PG_Servant_Dispatcher *rt_servant_dispatcher = 0;
+ ACE_NEW_RETURN (rt_servant_dispatcher,
+ TAO_PG_Servant_Dispatcher,
+ 0);
+ object_adapter->servant_dispatcher (rt_servant_dispatcher);
+
+
+ return object_adapter;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+ACE_FACTORY_DEFINE (TAO_PortableGroup, TAO_PG_Object_Adapter_Factory)
+ACE_STATIC_SVC_DEFINE (TAO_PG_Object_Adapter_Factory,
+ ACE_TEXT ("TAO_GOA"),
+ ACE_SVC_OBJ_T,
+ &ACE_SVC_NAME (TAO_PG_Object_Adapter_Factory),
+ ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ,
+ 0)
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Adapter_Factory.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Adapter_Factory.h
new file mode 100644
index 00000000000..7edf4fe521e
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Adapter_Factory.h
@@ -0,0 +1,47 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Object_Adapter_Factory.h
+ *
+ * $Id$
+ *
+ * @author Johnny Willemsen
+ */
+// ===================================================================
+
+#ifndef TAO_PG_OBJECT_ADAPTER_FACTORY_H
+#define TAO_PG_OBJECT_ADAPTER_FACTORY_H
+#include /**/ "ace/pre.h"
+
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+
+#include "tao/PortableServer/Object_Adapter_Factory.h"
+#include "tao/orbconf.h"
+
+#include "ace/Service_Config.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class TAO_PortableGroup_Export TAO_PG_Object_Adapter_Factory : public TAO_Object_Adapter_Factory
+{
+public:
+ /// Constructor
+ TAO_PG_Object_Adapter_Factory (void);
+
+ /// Create adapter.
+ virtual TAO_Adapter *create (TAO_ORB_Core *orb_core);
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+ACE_STATIC_SVC_DECLARE (TAO_PG_Object_Adapter_Factory)
+ACE_FACTORY_DECLARE (TAO_PortableGroup, TAO_PG_Object_Adapter_Factory)
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PG_OBJECT_ADAPTER_FACTORY_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group.cpp
new file mode 100644
index 00000000000..09d492e76a0
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group.cpp
@@ -0,0 +1,896 @@
+// $Id$
+
+#include "orbsvcs/PortableGroup/PG_Object_Group.h"
+#include "orbsvcs/PortableGroup/PG_conf.h"
+
+#include "orbsvcs/PortableGroup/PG_Operators.h" // Borrow operator== on CosNaming::Name
+#include "orbsvcs/PortableGroup/PG_Utils.h"
+
+#include "tao/debug.h"
+
+#include "ace/Get_Opt.h"
+#include "ace/Vector_T.h"
+
+
+// Borland Developer Studio 2006 and earlier give a warning about comparing
+// signed and unsigned values in the minimum_polulate() and
+// initial_populate() warnings. The comparison uses a unsigned long and
+// unsigned short and it seems that the compiler promotes the unsigned
+// short of an int and this then gives the warning. Just for Borland
+// disabled the warning in this file.
+#if defined (__BORLANDC__) && (__BORLANDC__ <= 0x582)
+# pragma option push -w-csu
+# pragma nopushoptwarn
+# pragma nopackwarning
+#endif /* __BORLANDC__ && __BORLANDC__ <= 0x582 */
+
+#define TODO int todo;
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO::PG_Object_Group::MemberInfo::MemberInfo (
+ CORBA::Object_ptr member,
+ const PortableGroup::Location & location)
+ : member_ (CORBA::Object::_duplicate (member))
+ , factory_(PortableGroup::GenericFactory::_nil ())
+ , location_ (location)
+ , is_primary_ (0)
+{
+}
+
+TAO::PG_Object_Group::MemberInfo::MemberInfo (
+ CORBA::Object_ptr member,
+ const PortableGroup::Location & location,
+ PortableGroup::GenericFactory_ptr factory,
+ PortableGroup::GenericFactory::FactoryCreationId factory_id)
+ : member_ (CORBA::Object::_duplicate (member))
+ , factory_ (PortableGroup::GenericFactory::_duplicate (factory))
+ , factory_id_ (factory_id)
+ , location_ (location)
+ , is_primary_ (0)
+{
+}
+
+TAO::PG_Object_Group::MemberInfo::~MemberInfo (void)
+{
+ if( ! CORBA::is_nil (this->factory_.in()))
+ {
+ this->factory_->delete_object (this->factory_id_);
+ }
+}
+
+
+TAO::PG_Object_Group::PG_Object_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)
+ : internals_()
+ , orb_ (CORBA::ORB::_duplicate (orb))
+ , factory_registry_ (PortableGroup::FactoryRegistry::_duplicate (factory_registry))
+ , manipulator_ (manipulator)
+ , empty_ (1)
+ , role_ (type_id)
+ , type_id_ (CORBA::string_dup (type_id))
+ , tagged_component_ (tagged_component)
+ , reference_ (CORBA::Object::_duplicate(empty_group))
+ , members_ ()
+ , primary_location_(0)
+ , properties_ (the_criteria, type_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 ();
+}
+
+#if 0 // may want this again someday
+/////////////////////
+// q&d debug function
+static void
+dump_ior (const char * base,
+ const char * ext,
+ unsigned long version,
+ const char * iogr)
+{
+ char filename[1000];
+ ACE_OS::sprintf(filename, "%s_%lu.%s", base, version, ext );
+
+ FILE * iorfile = ACE_OS::fopen(filename, "w");
+ ACE_OS::fwrite (iogr, 1, ACE_OS::strlen(iogr), iorfile);
+ ACE_OS::fclose (iorfile);
+}
+#endif // may want this again someday
+
+PortableGroup::ObjectGroup_ptr
+TAO::PG_Object_Group::reference (void) const
+{
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->internals_,
+ PortableGroup::ObjectGroup::_nil ());
+ return PortableGroup::ObjectGroup::_duplicate (this->reference_);
+}
+
+void
+TAO::PG_Object_Group::get_group_specific_factories (
+ PortableGroup::FactoryInfos & result) const
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
+
+ // copy is needed to have some semblance of thread safeness.
+ // if performance is an issue avoid this method.
+ result = this->group_specific_factories_;
+}
+
+const PortableGroup::Location &
+TAO::PG_Object_Group::get_primary_location (void) const
+{
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->internals_,
+ this->primary_location_);
+ return this->primary_location_;
+}
+
+
+PortableGroup::ObjectGroup_ptr
+TAO::PG_Object_Group::add_member_to_iogr (CORBA::Object_ptr member
+ ACE_ENV_ARG_DECL)
+{
+ // assume internals is locked
+
+ PortableGroup::ObjectGroup_var result;
+
+ ////////////////////////////
+ // @@ HACK ALERT
+ // The PortableGroup::ObjectGroupManager creates an object reference
+ // containing a dummy entry so it will have a place to store the
+ // tagged group component. If this is the first entry, we need to
+ // remove that entry once we have a *real* member. This can be
+ // avoided when we get support for TAG_MULTIPLE_COMPONENTS. For
+ // now, we already have a copy of the tagGroupTagged component and
+ // we're going to use it below wen we increment the group version so
+ // we can clean out the dummy entry.
+ PortableGroup::ObjectGroup_var cleaned =
+ PortableGroup::ObjectGroup::_duplicate (this->reference_.in ());
+ if (this->empty_)
+ {
+ // remove the original profile. It's a dummy entry supplied by
+ // create_object.
+ cleaned =
+ this->manipulator_.remove_profiles (cleaned.in (),
+ this->reference_.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (PortableGroup::ObjectGroup::_nil());
+ this->empty_ = 0;
+ }
+
+ // create a list of references to be merged
+ TAO_IOP::TAO_IOR_Manipulation::IORList iors (2);
+ iors.length (2);
+ iors [0] = CORBA::Object::_duplicate (cleaned.in());
+ iors [1] = CORBA::Object::_duplicate (member);
+
+ // Now merge the list into one new IOGR
+ result =
+ this->manipulator_.merge_iors (iors ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (PortableGroup::ObjectGroup::_nil ());
+ return result._retn ();
+}
+
+void
+TAO::PG_Object_Group::add_member (const PortableGroup::Location & the_location,
+ CORBA::Object_ptr member
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectNotAdded))
+
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
+
+ /////////////////////////////////////////
+ // Convert the new member to a string IOR
+ // This keeps a clean IOR (not an IOGR!)
+ // while we add it to a group. We need a
+ // IORs, not IOGRs to send new IOGRs out
+ // to replicas.
+
+ CORBA::String_var member_ior_string =
+ orb_->object_to_string (member
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ PortableGroup::ObjectGroup_var new_reference =
+ add_member_to_iogr (member
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // Convert new member back to a (non group) ior.
+ CORBA::Object_var member_ior =
+ this->orb_->string_to_object (member_ior_string.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ MemberInfo * info = 0;
+ ACE_NEW_THROW_EX (info,
+ MemberInfo (member_ior.in (),
+ the_location),
+ CORBA::NO_MEMORY());
+
+ if (this->members_.bind (the_location, info) != 0)
+ {
+ // @@ Dale why this is a NO MEMORY exception?
+ ACE_THROW(CORBA::NO_MEMORY());
+ }
+
+ this->reference_ = new_reference; // note var-to-var assignment does
+ // a duplicate
+ if (this->increment_version ())
+ {
+ this->distribute_iogr (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+ else
+ {
+ ACE_THROW (PortableGroup::ObjectNotAdded ());
+ }
+
+ if (TAO_debug_level > 6)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT("PG (%P|%t) exit Object_Group add_member \n")));
+ }
+}
+
+int
+TAO::PG_Object_Group::set_primary_member (
+ TAO_IOP::TAO_IOR_Property * prop,
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::MemberNotFound))
+{
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->internals_,
+ 0);
+ int result = 1;
+ MemberInfo * info = 0;
+ if (this->members_.find (the_location, info) == 0)
+ {
+ int cleared = 0;
+ this->primary_location_ = the_location;
+ for (MemberMap_Iterator it = this->members_.begin();
+ !cleared && it != this->members_.end();
+ ++it)
+ {
+ cleared = (*it).int_id_->is_primary_;
+ (*it).int_id_->is_primary_ = 0;
+ }
+ info->is_primary_ = 1;
+
+ int set_ok =
+ this->manipulator_.set_primary (prop,
+ this->reference_.in (),
+ info->member_.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+ if (!set_ok)
+ {
+ if (TAO_debug_level > 3)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%T %n (%P|%t) - ")
+ ACE_TEXT ("Can't set primary in IOGR .\n")
+ ));
+ }
+//@@: ACE_THROW (FT::PrimaryNotSet());
+ result = 0;
+ }
+
+ if (result && this->increment_version ())
+ {
+ this->distribute_iogr (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+ }
+ else
+ {
+ if (TAO_debug_level > 3)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT("TAO-PG (%P|%t) - set_primary_location ")
+ ACE_TEXT("throwing PrimaryNotSet because increment")
+ ACE_TEXT("version failed.\n")
+ ));
+ }
+//@@: ACE_THROW (FT::PrimaryNotSet());
+ result = 0;
+ }
+ }
+ else
+ {
+ if (TAO_debug_level > 3)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TAO-PG (%P|%t) - set_primary_location ")
+ ACE_TEXT ("throwing MemberNotFound.\n")));
+ }
+ ACE_THROW_RETURN (PortableGroup::MemberNotFound(),
+ -1);
+ }
+
+ return result;
+}
+
+
+void
+TAO::PG_Object_Group::remove_member (
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ( (CORBA::SystemException,
+ PortableGroup::MemberNotFound))
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
+ MemberInfo * info = 0;
+ if (this->members_.unbind (the_location, info) == 0)
+ {
+ if (this->members_.current_size() > 0)
+ {
+ this->reference_ =
+ this->manipulator_.remove_profiles (this->reference_.in (),
+ info->member_.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+ else
+ {
+ empty_ = 1;
+ }
+
+ delete info;
+
+ if (the_location == this->primary_location_)
+ {
+ this->primary_location_.length(0);
+ }
+
+ if (this->increment_version ())
+ {
+ this->distribute_iogr (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+
+ }
+ else
+ {
+ if (TAO_debug_level > 6)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "TAO-PG (%P|%t) - "
+ "remove_member throwing MemberNotFound.\n"
+ ));
+ }
+ ACE_THROW (PortableGroup::MemberNotFound() );
+ }
+}
+
+
+PortableGroup::ObjectGroupId
+TAO::PG_Object_Group::get_object_group_id (void) const
+{
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->internals_,
+ 0);
+ return this->tagged_component_.object_group_id;
+}
+
+void
+TAO::PG_Object_Group::set_properties_dynamically (
+ const PortableGroup::Properties & overrides
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty))
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
+
+ this->properties_.decode (overrides ACE_ENV_ARG_PARAMETER);
+
+ //@@ int todo_override_rather_than_replace?
+}
+
+void
+TAO::PG_Object_Group::get_properties (
+ PortableGroup::Properties_var & result) const
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
+ this->properties_.export_properties(*result);
+}
+
+
+PortableGroup::TypeId
+TAO::PG_Object_Group::get_type_id (void) const
+{
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->internals_,
+ 0);
+ return CORBA::string_dup (this->type_id_);
+}
+
+
+///////////////////
+// Internal method
+
+int
+TAO::PG_Object_Group::increment_version (void)
+{
+ // assume internals is locked
+ int result = 0;
+ this->tagged_component_.object_group_ref_version += 1;
+ if (TAO_debug_level > 3)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%T %n (%P|%t) - Setting IOGR version to %u\n"),
+ static_cast<unsigned> (this->tagged_component_.object_group_ref_version)
+ ));
+ }
+
+ // Set the version
+ if (TAO::PG_Utils::set_tagged_component (this->reference_,
+ this->tagged_component_))
+ {
+ result = 1;
+ }
+ return result;
+}
+
+
+//////////////////
+// Internal method
+void
+TAO::PG_Object_Group::distribute_iogr (ACE_ENV_SINGLE_ARG_DECL)
+{
+ // assume internals is locked
+ CORBA::String_var iogr =
+ this->orb_->object_to_string (this->reference_.in()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+// size_t n_rep = 0; // for dump_ior below
+ for (MemberMap_Iterator it = this->members_.begin();
+ it != this->members_.end ();
+ ++it)
+ {
+ MemberInfo const * info = (*it).int_id_;
+ //
+ // Unchecked narrow means the member doesn't have to actually implement the TAO_UpdateObjectGroup interface
+ // PortableGroup::TAO_UpdateObjectGroup_var uog = PortableGroup::TAO_UpdateObjectGroup::_unchecked_narrow ( info->member_);
+ // but it doesn work: error message at replica is:
+ // TAO-FT (2996|976) - Wrong version information within the interceptor [1 | 0]
+ // TAO_Perfect_Hash_OpTable:find for operation 'tao_update_object_group' (length=23) failed
+ // back to using _narrow
+ PortableGroup::TAO_UpdateObjectGroup_var uog =
+ PortableGroup::TAO_UpdateObjectGroup::_narrow ( info->member_.in ());
+ if (!CORBA::is_nil (uog.in ()))
+ {
+ ACE_TRY_NEW_ENV
+ {
+ if (TAO_debug_level > 3)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "PG (%P|%t) - Object_Group pushing "
+ "IOGR to %s member: %s@%s.\n",
+ (info->is_primary_ ? "Primary" : "Backup"),
+ this->role_.c_str (),
+ static_cast<const char *> (info->location_[0].id)
+ ));
+ }
+ // dump_ior ("group", "iogr", this->tagged_component_.object_group_ref_version, iogr);
+ // CORBA::String_var replica_ior = this->orb_->object_to_string(uog.in() ACE_ENV_ARG_PARAMETER);
+ // dump_ior (info->location_[0].id, "ior", (this->tagged_component_.object_group_ref_version * 100) + n_rep++, replica_ior);
+ uog->tao_update_object_group (iogr.in (),
+ this->tagged_component_.object_group_ref_version,
+ info->is_primary_
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ ACE_CATCHANY
+ {
+ // we expect an exception
+ // tao_update_object_group is not a real method
+ }
+ ACE_ENDTRY;
+ }
+ else
+ {
+ ACE_ERROR ((LM_ERROR,
+ "TAO::PG_Object_Group::distribute iogr can't "
+ "narrow member reference to "
+ "PortableGroup::TAO_UpdateObjectGroup.\n"
+ ));
+ }
+ }
+}
+
+PortableGroup::Locations *
+TAO::PG_Object_Group::locations_of_members (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->internals_,
+ 0);
+
+ PortableGroup::Locations * result = 0;
+
+ size_t count = this->members_.current_size ();
+
+ ACE_NEW_THROW_EX (
+ result,
+ PortableGroup::Locations (count),
+ CORBA::NO_MEMORY() );
+ ACE_CHECK_RETURN (0);
+
+ result->length (count);
+
+ size_t pos = 0;
+ for (MemberMap_Iterator it = this->members_.begin();
+ it != this->members_.end();
+ ++it)
+ {
+ const PortableGroup::Location & location = (*it).ext_id_;
+ PortableGroup::Location & out = (*result)[pos];
+ out = location;
+ }
+ return result;
+}
+
+CORBA::Object_ptr
+TAO::PG_Object_Group::get_member_reference (
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((
+ CORBA::SystemException,
+ PortableGroup::MemberNotFound))
+{
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->internals_,
+ CORBA::Object::_nil ());
+
+ CORBA::Object_var result;
+
+ MemberInfo * info = 0;
+ if (this->members_.find (the_location, info) == 0)
+ {
+ result = CORBA::Object::_duplicate (info->member_.in ());
+ }
+ else
+ {
+ ACE_THROW_RETURN (PortableGroup::MemberNotFound(), result._retn ());
+ }
+ return result._retn ();
+}
+
+
+PortableGroup::MembershipStyleValue
+TAO::PG_Object_Group::get_membership_style (void) const
+{
+ PortableGroup::MembershipStyleValue membership_style = 0;
+ if (!TAO::find (properties_,
+ PortableGroup::PG_MEMBERSHIP_STYLE,
+ membership_style))
+ {
+ membership_style = TAO_PG_MEMBERSHIP_STYLE;
+ }
+ return membership_style;
+}
+
+
+PortableGroup::MinimumNumberMembersValue
+TAO::PG_Object_Group::get_minimum_number_members (void) const
+{
+ PortableGroup::MinimumNumberMembersValue minimum_number_members = 0;
+ if (!TAO::find (properties_,
+ PortableGroup::PG_MINIMUM_NUMBER_MEMBERS,
+ minimum_number_members))
+ {
+ minimum_number_members = TAO_PG_MINIMUM_NUMBER_MEMBERS;
+ }
+ return minimum_number_members;
+}
+
+PortableGroup::InitialNumberMembersValue
+TAO::PG_Object_Group::get_initial_number_members (void) const
+{
+ PortableGroup::InitialNumberMembersValue initial_number_members = 0;
+ if (!TAO::find (properties_,
+ PortableGroup::PG_INITIAL_NUMBER_MEMBERS,
+ initial_number_members))
+ {
+ initial_number_members = TAO_PG_INITIAL_NUMBER_MEMBERS;
+ }
+ return initial_number_members;
+}
+
+void
+TAO::PG_Object_Group::create_member (
+ const PortableGroup::Location & the_location,
+ const char * type_id,
+ const PortableGroup::Criteria & the_criteria
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ( (CORBA::SystemException,
+ PortableGroup::MemberAlreadyPresent,
+ PortableGroup::NoFactory,
+ PortableGroup::ObjectNotCreated,
+ PortableGroup::InvalidCriteria,
+ PortableGroup::CannotMeetCriteria))
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
+
+
+ if (0 != this->members_.find (the_location))
+ {
+ // @@ what if factories were passed as criteria?
+
+ CORBA::String_var factory_type;
+ PortableGroup::FactoryInfos_var factories =
+ this->factory_registry_->list_factories_by_role (
+ role_.c_str(),
+ factory_type.out ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // @@ what if factory_type != type_id != this->type_id_
+
+ int created = 0; // bool
+ CORBA::ULong factory_count = factories->length ();
+ for (CORBA::ULong factory_pos = 0;
+ ! created && factory_pos < factory_count;
+ ++factory_pos)
+ {
+ const PortableGroup::FactoryInfo & factory_info =
+ (*factories)[factory_pos];
+ if (factory_info.the_location == the_location)
+ {
+ // @@ should we merge the_criteria with
+ // factory_info.the_criteria?
+
+ PortableGroup::GenericFactory::FactoryCreationId_var fcid;
+ CORBA::Object_var member =
+ factory_info.the_factory->create_object (
+ type_id,
+ the_criteria,
+ fcid. out()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // convert the new member to a stringified IOR to avoid
+ // contamination with group info
+ CORBA::String_var member_ior_string =
+ orb_->object_to_string (member.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ PortableGroup::ObjectGroup_var new_reference =
+ this->add_member_to_iogr (member.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // Convert new member back to a (non group) ior.
+ CORBA::Object_var member_ior =
+ this->orb_->string_to_object (member_ior_string.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ MemberInfo * info = 0;
+ ACE_NEW_THROW_EX (info, MemberInfo(
+ member_ior.in(),
+ the_location,
+ factory_info.the_factory,
+ fcid.in ()),
+ CORBA::NO_MEMORY());
+ ACE_CHECK;
+
+ if (this->members_.bind (the_location, info) != 0)
+ {
+ ACE_THROW(CORBA::NO_MEMORY());
+ }
+
+ this->reference_ = new_reference; // note var-to-var
+ // assignment does a
+ // duplicate
+ if (this->increment_version ())
+ {
+ this->distribute_iogr (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+ created = 1;
+ }
+ }
+ if (! created)
+ {
+ ACE_THROW (PortableGroup::NoFactory ());
+ }
+ }
+ else
+ {
+ ACE_THROW (PortableGroup::MemberAlreadyPresent ());
+ }
+}
+
+void
+TAO::PG_Object_Group::create_members (size_t count ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::NoFactory))
+{
+ // assume internals is locked
+ // @@ what if factories were passed as criteria?
+
+ CORBA::String_var factory_type;
+ PortableGroup::FactoryInfos_var factories =
+ this->factory_registry_->list_factories_by_role (
+ role_.c_str(),
+ factory_type.out ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ CORBA::ULong factory_count = factories->length ();
+ if (factory_count > 0)
+ {
+ CORBA::ULong factory_pos = 0;
+ while (members_.current_size () < count && factory_pos < factory_count)
+ {
+ const PortableGroup::FactoryInfo & factory_info =
+ (*factories)[factory_pos];
+ const PortableGroup::Location & factory_location =
+ factory_info.the_location;
+ if (0 != this->members_.find (factory_location))
+ {
+ ///////////////////////////////////////////
+ // If a factory refuses to create a replica
+ // it's not fatal.
+ ACE_TRY_NEW_ENV
+ {
+ PortableGroup::GenericFactory::FactoryCreationId_var fcid;
+ CORBA::Object_var member =
+ factory_info.the_factory->create_object (
+ this->type_id_.in (),
+ factory_info.the_criteria,
+ fcid. out()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ // convert the new member to a stringified IOR to avoid
+ // contamination with group info
+ CORBA::String_var member_ior_string =
+ orb_->object_to_string (member.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ PortableGroup::ObjectGroup_var new_reference =
+ this->add_member_to_iogr (member.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ // Convert new member back to a (non group) ior.
+ CORBA::Object_var member_ior =
+ this->orb_->string_to_object (member_ior_string.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ MemberInfo * info = 0;
+ ACE_NEW_THROW_EX (info, MemberInfo(
+ member_ior.in(),
+ factory_location,
+ factory_info.the_factory,
+ fcid.in ()),
+ CORBA::NO_MEMORY());
+ ACE_TRY_CHECK;
+
+ if (this->members_.bind (factory_location, info) != 0)
+ {
+ ACE_TRY_THROW(CORBA::NO_MEMORY());
+ }
+ this->reference_ =
+ new_reference; // note var-to-var assignment does
+ // a duplicate
+ }
+ ACE_CATCHANY
+ {
+ // log, but otherwise ignore the errorf
+ if (TAO_debug_level > 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("PG (%P|%t) Replica Factory ")
+ ACE_TEXT ("@ %s refused create_object ")
+ ACE_TEXT ("request for type %s\n"),
+ static_cast<const char *> (factory_info.the_location[0].id),
+ static_cast<const char *> (this->type_id_.in ())
+ ));
+ }
+ }
+ ACE_ENDTRY;
+ }
+ }
+
+ if (this->increment_version ())
+ {
+ this->distribute_iogr (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+ }
+ else
+ {
+ ACE_THROW (PortableGroup::NoFactory());
+ }
+}
+
+void
+TAO::PG_Object_Group::initial_populate (ACE_ENV_SINGLE_ARG_DECL)
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
+
+ if (this->get_membership_style () == PortableGroup::MEMB_INF_CTRL)
+ {
+ PortableGroup::InitialNumberMembersValue initial_number_members =
+ this->get_initial_number_members ();
+
+ if (this->members_.current_size () < initial_number_members)
+ {
+ this->create_members (initial_number_members
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+ }
+}
+
+void
+TAO::PG_Object_Group::minimum_populate (ACE_ENV_SINGLE_ARG_DECL)
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
+
+ if ( this->get_membership_style () == PortableGroup::MEMB_INF_CTRL )
+ {
+ PortableGroup::MinimumNumberMembersValue minimum_number_members =
+ this->get_minimum_number_members ();
+ if (members_.current_size () < minimum_number_members)
+ {
+ this->create_members (minimum_number_members ACE_ENV_ARG_PARAMETER);
+ }
+ }
+}
+
+int
+TAO::PG_Object_Group::has_member_at (const PortableGroup::Location & location)
+{
+ return (0 == this->members_.find (location));
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+// Restore original compiler flags.
+#if defined (__BORLANDC__) && (__BORLANDC__ <= 0x582)
+# pragma option pop
+# pragma nopushoptwarn
+# pragma nopackwarning
+#endif /* __BORLANDC__ && __BORLANDC__ <= 0x582 */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group.h
new file mode 100644
index 00000000000..aaf4628cda3
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group.h
@@ -0,0 +1,382 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Object_Group.h
+ *
+ * $Id$
+ *
+ * Manage all information related to an object group.
+ * @@ Note: the above description is optimistic. The hope is to eventually
+ * @@ consolidate all information related to an object group into this object.
+ * @@ however at the moment GenericFactory, ObjectGroupManager, and
+ * FT_ReplicationManager have parallel collections of object group
+ * information.
+ *
+ * @author Dale Wilson <wilson_d@ociweb.com>
+ */
+//=============================================================================
+
+#ifndef TAO_PG_OBJECT_GROUP_H_
+#define TAO_PG_OBJECT_GROUP_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_Property_Set.h"
+#include "orbsvcs/PortableGroup/PG_Location_Hash.h"
+#include "orbsvcs/PortableGroup/PG_Location_Equal_To.h"
+#include "orbsvcs/PortableGroup/PG_Object_Group_Manipulator.h"
+#include "orbsvcs/PortableGroupC.h"
+#include "tao/PortableServer/PortableServer.h"
+#include "ace/Hash_Map_Manager_T.h"
+#include "ace/ACE.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/////////////////////
+// Forward references
+
+namespace TAO_IOP
+{
+ class TAO_IOR_Property;
+}
+
+////////////////
+// Class declarations
+namespace TAO
+{
+ /**
+ */
+ class TAO_PortableGroup_Export PG_Object_Group
+ {
+ // Information about an object group member
+ struct MemberInfo
+ {
+ /// Reference to the member.
+ CORBA::Object_var member_;
+
+ /// The factory that was used to create this object
+ /// nil if application created.
+ PortableGroup::GenericFactory_var factory_;
+
+ /// FactoryCreationId assigned to the member. Empty if application created
+ PortableGroup::GenericFactory::FactoryCreationId factory_id_;
+
+ /// Location where this member exists
+ PortableGroup::Location location_;
+
+
+ /// TRUE if this is primary member
+ CORBA::Boolean is_primary_;
+
+
+ ///////////////
+ // Methods
+
+ /// Construct an application-supplied member.
+ MemberInfo (CORBA::Object_ptr member, const PortableGroup::Location & location);
+
+ /// Construct a infrastructure-created member.
+ MemberInfo (
+ CORBA::Object_ptr member,
+ const PortableGroup::Location & location,
+ PortableGroup::GenericFactory_ptr factory,
+ PortableGroup::GenericFactory::FactoryCreationId factory_id);
+
+ /// Destructor
+ ~MemberInfo();
+ };
+
+ typedef TAO_SYNCH_MUTEX MemberMapMutex;
+ typedef ACE_Hash_Map_Manager_Ex <
+ PortableGroup::Location,
+ MemberInfo *,
+ TAO_PG_Location_Hash,
+ TAO_PG_Location_Equal_To,
+ MemberMapMutex> MemberMap;
+ typedef ACE_Hash_Map_Entry <PortableGroup::Location, MemberInfo *> MemberMap_Entry;
+ typedef ACE_Hash_Map_Iterator_Ex <
+ PortableGroup::Location,
+ MemberInfo *,
+ TAO_PG_Location_Hash,
+ TAO_PG_Location_Equal_To,
+ MemberMapMutex> MemberMap_Iterator;
+
+ /////////////////////
+ // Construct/Destruct
+ public:
+ /**
+ * @@TODO DOC
+ */
+ PG_Object_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);
+
+
+ /// Destructor
+ ~PG_Object_Group ();
+
+ /////////////////
+ // public methods
+
+ public:
+ /// return a duplicated reference to this group (IOGR)
+ PortableGroup::ObjectGroup_ptr reference()const;
+
+ /**
+ * Note the caller receives a copy of the factoryinfos in the result argument.
+ * inefficient, but thread safe.
+ */
+ void get_group_specific_factories (PortableGroup::FactoryInfos & result) const;
+
+ /**
+ * get location of primary member
+ */
+ const PortableGroup::Location & get_primary_location() const;
+
+ /**
+ * returns a duplicate
+ * caller must release
+ */
+ PortableGroup::TypeId get_type_id ()const;
+
+
+ /**
+ * @@TODO DOC
+ */
+ PortableGroup::MembershipStyleValue get_membership_style() const;
+
+ /**
+ * @@TODO DOC
+ */
+ PortableGroup::MinimumNumberMembersValue get_minimum_number_members () const;
+
+ /**
+ * @@TODO DOC
+ */
+ PortableGroup::InitialNumberMembersValue get_initial_number_members () const;
+
+
+
+ /**
+ * @@TODO DOC
+ */
+ void set_properties_dynamically (
+ const PortableGroup::Properties & overrides
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty));
+
+ /**
+ * @@TODO DOC
+ */
+ void get_properties (PortableGroup::Properties_var & result) const
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /**
+ * @@TODO DOC
+ */
+ 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 (
+ const PortableGroup::Location & the_location,
+ CORBA::Object_ptr member
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ( (CORBA::SystemException,
+ PortableGroup::ObjectNotAdded));
+
+ /**
+ * set the replica at the given location to be primary.
+ * Note: This should return void and throw FT::PrimaryNotSet
+ * but to avoid dependancies between PortableGroup and FaultTolerance
+ * it returns a boolean result. A false return means caller should
+ * throw FT::PrimaryNot_Set.
+ */
+ int set_primary_member (
+ TAO_IOP::TAO_IOR_Property * prop,
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((
+ CORBA::SystemException
+ , PortableGroup::MemberNotFound
+ ));
+
+ /**
+ * @@TODO DOC
+ */
+ void remove_member (
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ( (CORBA::SystemException,
+ PortableGroup::MemberNotFound));
+
+
+ /**
+ * @@TODO DOC
+ */
+ void create_member (
+ const PortableGroup::Location & the_location,
+ const char * type_id,
+ const PortableGroup::Criteria & the_criteria
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ( (CORBA::SystemException,
+ PortableGroup::MemberAlreadyPresent,
+ PortableGroup::NoFactory,
+ PortableGroup::ObjectNotCreated,
+ PortableGroup::InvalidCriteria,
+ PortableGroup::CannotMeetCriteria));
+
+ /**
+ * @@TODO DOC
+ */
+ PortableGroup::Locations * locations_of_members (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /**
+ * @@TODO DOC
+ */
+ CORBA::Object_ptr get_member_reference (
+ const PortableGroup::Location & the_location
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((
+ CORBA::SystemException,
+ PortableGroup::MemberNotFound));
+
+
+ /**
+ * @@TODO DOC
+ */
+ void initial_populate (ACE_ENV_SINGLE_ARG_DECL);
+
+ /**
+ * @@TODO DOC
+ */
+ void minimum_populate (ACE_ENV_SINGLE_ARG_DECL);
+
+
+ /**
+ * @@TODO DOC
+ */
+ int has_member_at (const PortableGroup::Location & location );
+
+ /////////////////////////
+ // Implementation methods
+ private:
+
+ int increment_version ();
+
+ void distribute_iogr (ACE_ENV_SINGLE_ARG_DECL);
+
+ PortableGroup::ObjectGroup_ptr add_member_to_iogr(CORBA::Object_ptr member ACE_ENV_ARG_DECL);
+
+
+ void create_members (size_t count ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((
+ CORBA::SystemException,
+ PortableGroup::NoFactory
+ ));
+
+
+ /////////////////////////
+ // Forbidden methods
+ private:
+ PG_Object_Group ();
+ PG_Object_Group (const PG_Object_Group & rhs);
+ PG_Object_Group & operator = (const PG_Object_Group & rhs);
+
+
+ /////////////////
+ // Static Methods
+ public:
+
+ ///////////////
+ // Static Data
+ private:
+
+ ///////////////
+ // Data Members
+ private:
+
+ /**
+ * Protect internal state.
+ */
+ mutable TAO_SYNCH_MUTEX internals_;
+
+ CORBA::ORB_var orb_;
+
+ /// Where to find the factories for replicas.
+ PortableGroup::FactoryRegistry_var factory_registry_;
+
+
+ // The object group manipulator
+ TAO::PG_Object_Group_Manipulator & manipulator_;
+
+ /// boolean true if empty group
+ int empty_;
+
+ ACE_CString role_;
+ PortableGroup::TypeId_var type_id_;
+
+ /**
+ * the GroupTaggedComponent that defines this group
+ * contains:
+ * GIOP::Version component_version;
+ * TAO::String_Manager group_domain_id;
+ * PortableGroup::ObjectGroupId object_group_id;
+ * PortableGroup::ObjectGroupRefVersion object_group_ref_version;
+ */
+ PortableGroup::TagGroupTaggedComponent tagged_component_;
+
+ /**
+ * the reference (IOGR) to this group
+ */
+ PortableGroup::ObjectGroup_var reference_;
+
+ /**
+ * The CORBA object id assigned to this object group
+ */
+ PortableServer::ObjectId_var object_id_;
+
+ // group members
+ MemberMap members_;
+
+ PortableGroup::Location primary_location_;
+
+ // Miscellaneous properties passed to create_object when this group
+ // was initially created. To be used to create new members.
+ TAO::PG_Property_Set properties_;
+
+ // Cached property information
+
+ PortableGroup::InitialNumberMembersValue initial_number_members_;
+ PortableGroup::MinimumNumberMembersValue minimum_number_members_;
+ PortableGroup::FactoryInfos group_specific_factories_;
+
+ };
+} // namespace TAO
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif // TAO_PG_OBJECT_GROUP_H_
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Manipulator.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Manipulator.cpp
new file mode 100644
index 00000000000..2fb57ae571a
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Manipulator.cpp
@@ -0,0 +1,190 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Object_Group_Manipulator.cpp
+ *
+ * $Id$
+ *
+ * @author Dale Wilson <wilson_d@ociweb.com>
+ */
+//=============================================================================
+
+#include "orbsvcs/PortableGroup/PG_Object_Group_Manipulator.h"
+#include "orbsvcs/PortableGroup/PG_Utils.h"
+
+#include "tao/debug.h"
+#include <ace/OS_NS_stdio.h>
+
+ACE_RCSID (PortableGroup,
+ PG_Object_Group_Manipulator,
+ "$Id$")
+
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO::PG_Object_Group_Manipulator::PG_Object_Group_Manipulator ()
+ : orb_ (CORBA::ORB::_nil ())
+ , poa_ (PortableServer::POA::_nil ())
+ , iorm_ ()
+ , lock_ogid_ ()
+ , next_ogid_ (1) // don't use ogid 0
+{
+}
+
+TAO::PG_Object_Group_Manipulator::~PG_Object_Group_Manipulator ()
+{
+}
+
+void TAO::PG_Object_Group_Manipulator::allocate_ogid (PortableGroup::ObjectGroupId & ogid)
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_ogid_);
+
+ // The numerical value used for the ObjectId increases
+ // monotonically.
+
+ ogid = this->next_ogid_;
+ this->next_ogid_ += 1;
+}
+
+PortableServer::ObjectId * TAO::PG_Object_Group_Manipulator::convert_ogid_to_oid (PortableGroup::ObjectGroupId ogid) const
+{
+ // 4294967295 -- Largest 32 bit unsigned integer
+ char oid_str[11];
+ ACE_OS::snprintf (oid_str, sizeof(oid_str),
+ "%lu",
+ static_cast<ACE_UINT32> (ogid));
+ oid_str[sizeof(oid_str) - 1] = '\0';
+
+ return PortableServer::string_to_ObjectId (oid_str);
+}
+
+PortableGroup::ObjectGroup_ptr
+TAO::PG_Object_Group_Manipulator::create_object_group (
+ const char * type_id,
+ const char * domain_id,
+ PortableGroup::ObjectGroupId & group_id
+ ACE_ENV_ARG_DECL)
+{
+ allocate_ogid(group_id);
+ PortableServer::ObjectId_var oid = convert_ogid_to_oid (group_id);
+
+ // Create a reference for the ObjectGroup
+ CORBA::Object_var object_group =
+ this->poa_->create_reference_with_id (oid.in(),
+ type_id
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (CORBA::Object::_nil ());
+
+ PortableGroup::TagGroupTaggedComponent tag_component;
+
+ tag_component.component_version.major = (CORBA::Octet) 1;
+ tag_component.component_version.minor = (CORBA::Octet) 0;
+ tag_component.group_domain_id = domain_id;
+ tag_component.object_group_id = group_id;
+ tag_component.object_group_ref_version = 0;
+
+ // Set the property
+ TAO::PG_Utils::set_tagged_component (object_group,
+ tag_component);
+ ACE_CHECK_RETURN (CORBA::Object::_nil ());
+
+ return object_group._retn ();
+}
+
+void
+TAO::PG_Object_Group_Manipulator::init (CORBA::ORB_ptr orb,
+ PortableServer::POA_ptr poa
+ ACE_ENV_ARG_DECL)
+{
+ ACE_ASSERT (CORBA::is_nil (this->orb_.in ()) && !CORBA::is_nil (orb));
+ this->orb_ = CORBA::ORB::_duplicate (orb);
+
+ ACE_ASSERT (CORBA::is_nil (this->poa_.in ()) && !CORBA::is_nil (poa));
+ this->poa_ = PortableServer::POA::_duplicate (poa);
+
+ // Get an object reference for the ORBs IORManipulation object!
+ CORBA::Object_var IORM = this->orb_->resolve_initial_references (
+ TAO_OBJID_IORMANIPULATION, 0 ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ this->iorm_ = TAO_IOP::TAO_IOR_Manipulation::_narrow (
+ IORM.in () ACE_ENV_ARG_PARAMETER);
+// ACE_CHECK;
+}
+
+int TAO::PG_Object_Group_Manipulator::set_primary (
+ TAO_IOP::TAO_IOR_Property * prop,
+ PortableGroup::ObjectGroup_ptr group,
+ CORBA::Object_ptr new_primary
+ ACE_ENV_ARG_DECL) const
+{
+ int sts = this->iorm_->is_primary_set (prop, group ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+ if (sts)
+ {
+ (void)this->iorm_->remove_primary_tag (prop, group ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+ }
+ /////note: iorm takes it's parameters in the "wrong" order for this call
+ return this->iorm_->set_primary (prop, new_primary, group ACE_ENV_ARG_PARAMETER);
+}
+
+PortableGroup::ObjectGroup_ptr TAO::PG_Object_Group_Manipulator::merge_iors(
+ TAO_IOP::TAO_IOR_Manipulation::IORList & list ACE_ENV_ARG_DECL) const
+{
+ return this->iorm_->merge_iors (list ACE_ENV_ARG_PARAMETER);
+}
+
+PortableGroup::ObjectGroup_ptr TAO::PG_Object_Group_Manipulator::remove_profiles(
+ PortableGroup::ObjectGroup_ptr group,
+ PortableGroup::ObjectGroup_ptr profile
+ ACE_ENV_ARG_DECL) const
+{
+ return this->iorm_->remove_profiles(group, profile ACE_ENV_ARG_PARAMETER);
+}
+
+void dump_membership (const char * label, PortableGroup::ObjectGroup_ptr member)
+{
+ ACE_UNUSED_ARG (label);
+ ACE_UNUSED_ARG (member);
+#if 0
+ PortableGroup::TagFTGroupTaggedComponent ft_tag_component;
+ TAO_FT_IOGR_Property prop (ft_tag_component);
+ if (this->iorm_->is_primary_set (&prop, member))
+ {
+ ACE_DEBUG ( (LM_DEBUG,
+ ACE_TEXT ("%T %n (%P|%t) - %s: PRIMARY member.\n"),
+ label
+ ));
+ }
+ else
+ {
+ ACE_DEBUG ( (LM_DEBUG,
+ ACE_TEXT ("%T %n (%P|%t) - %s: backup member.\n"),
+ label
+ ));
+ }
+
+ PortableGroup::TagGroupTaggedComponent tag_component;
+ if (TAO::PG_Utils::get_tagged_component (member, tag_component))
+ {
+ ACE_DEBUG ( (LM_DEBUG,
+ ACE_TEXT ("%T %n (%P|%t) - %s: Group: .")
+ ACE_TEXT (" version: %u\n"),
+
+ label,
+ tag_component.object_group_ref_version
+ ));
+ }
+ else
+ {
+ ACE_DEBUG ( (LM_DEBUG,
+ ACE_TEXT ("%T %n (%P|%t) - %s: No group information found.\n"),
+ label
+ ));
+ }
+#endif
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Manipulator.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Manipulator.h
new file mode 100644
index 00000000000..4397cbfe8e0
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Manipulator.h
@@ -0,0 +1,123 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Object_Group_Manipulator.h
+ *
+ * $Id$
+ *
+ * @author Dale Wilson <wilson_d@ociweb.com>
+ */
+//=============================================================================
+
+
+#ifndef TAO_PG_OBJECT_GROUP_MANIPULATOR_H
+#define TAO_PG_OBJECT_GROUP_MANIPULATOR_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/PortableGroupS.h"
+
+#include "tao/IORManipulation/IORManip_Loader.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace TAO
+{
+
+ /**
+ * @class TAO::PG_Object_Group_Manipulator
+ *
+ * @brief PortableGroup::ObjectGroupManager implementation.
+ *
+ * The ObjectGroupManager provides the interface necessary to
+ * facilitate application-controlled object group membership.
+ */
+ class TAO_PortableGroup_Export PG_Object_Group_Manipulator
+ {
+ public:
+
+ /// Constructor.
+ PG_Object_Group_Manipulator ();
+
+ /// Destructor.
+ ~PG_Object_Group_Manipulator ();
+
+ /**
+ * Initializes the group creator.
+ */
+ void init (CORBA::ORB_ptr orb,
+ PortableServer::POA_ptr poa
+ ACE_ENV_ARG_DECL);
+
+ /**
+ * Create an empty object group.
+ */
+ PortableGroup::ObjectGroup_ptr create_object_group (
+ const char * type_id,
+ const char * domain_id,
+ PortableGroup::ObjectGroupId & group_id
+ ACE_ENV_ARG_DECL);
+
+ PortableGroup::ObjectGroup_ptr remove_profiles (
+ PortableGroup::ObjectGroup_ptr group,
+ PortableGroup::ObjectGroup_ptr profile
+ ACE_ENV_ARG_DECL) const;
+
+ PortableGroup::ObjectGroup_ptr merge_iors (
+ TAO_IOP::TAO_IOR_Manipulation::IORList & iors
+ ACE_ENV_ARG_DECL) const;
+
+ int set_primary (
+ TAO_IOP::TAO_IOR_Property * prop,
+ PortableGroup::ObjectGroup_ptr reference,
+ CORBA::Object_ptr new_primary
+ ACE_ENV_ARG_DECL) const;
+
+ void dump_membership (const char * label,
+ PortableGroup::ObjectGroup_ptr member) const;
+
+ private:
+
+ /**
+ * Allocate an ogid for a new object group
+ */
+ void allocate_ogid (PortableGroup::ObjectGroupId & ogid);
+
+ /**
+ * convert numeric OGID to Sequence<Octet> oid
+ */
+ PortableServer::ObjectId *
+ convert_ogid_to_oid (PortableGroup::ObjectGroupId ogid) const;
+
+ private:
+
+ /// The orb
+ CORBA::ORB_var orb_;
+
+ /// Reference to the POA that created the object group references.
+ PortableServer::POA_var poa_;
+
+ /// The ORBs IORManipulation object
+ TAO_IOP::TAO_IOR_Manipulation_var iorm_;
+
+ /// Lock used to synchronize access to next_ogid_.
+ TAO_SYNCH_MUTEX lock_ogid_;
+
+ /// Next ogid to be allocated.
+ PortableGroup::ObjectGroupId next_ogid_;
+
+ };
+} //namespace TAO
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO::PG_OBJECT_GROUP_CREATOR_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Operators.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Operators.cpp
new file mode 100644
index 00000000000..9513dc724bb
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Operators.cpp
@@ -0,0 +1,33 @@
+#include "orbsvcs/PortableGroup/PG_Operators.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID (PortableGroup,
+ PG_Operators,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+bool
+operator== (const CosNaming::Name & lhs, const CosNaming::Name & rhs)
+{
+ const CORBA::ULong lhs_len = lhs.length ();
+ const CORBA::ULong rhs_len = rhs.length ();
+
+ if (lhs_len != rhs_len)
+ return false;
+
+ for (CORBA::ULong i = 0; i < lhs_len; ++i)
+ if (ACE_OS::strcmp (lhs[i].id.in (), rhs[i].id.in ()) != 0
+ || ACE_OS::strcmp (lhs[i].kind.in (), rhs[i].kind.in ()) != 0)
+ return false;
+
+ return true;
+}
+
+bool
+operator!= (const CosNaming::Name & lhs, const CosNaming::Name & rhs)
+{
+ return !(lhs == rhs);
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Operators.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Operators.h
new file mode 100644
index 00000000000..6218b5da005
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Operators.h
@@ -0,0 +1,50 @@
+// -*- C++ -*-
+
+
+//=============================================================================
+/**
+ * @file PG_Operators.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_PG_OPERATORS_H
+#define TAO_PG_OPERATORS_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/CosNamingC.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// Global CosNaming::Name equality operator.
+/**
+ * Used for checking equality of PortableGroup::Location and
+ * PortableGroup::Property variables.
+ */
+bool TAO_PortableGroup_Export operator== (const CosNaming::Name & lhs,
+ const CosNaming::Name & rhs);
+
+/// Global CosNaming::Name inequality operator.
+/**
+ * This simple implementation simply negates the result of the
+ * equality operator.
+ */
+bool TAO_PortableGroup_Export operator!= (const CosNaming::Name & lhs,
+ const CosNaming::Name & rhs);
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PG_OPERATORS_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Encoder.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Encoder.cpp
new file mode 100644
index 00000000000..de1fa1c7223
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Encoder.cpp
@@ -0,0 +1,67 @@
+//=============================================================================
+/**
+ * @file PG_Properties_Encoder.cpp
+ *
+ * $Id$
+ *
+ * This file implements classes to help manage the Properties
+ * defined in the Portable Object Group.
+ *
+ * @author Dale Wilson <wilson_d@ociweb.com>
+ */
+//=============================================================================
+#include "orbsvcs/PortableGroup/PG_Properties_Encoder.h"
+
+
+#if ! defined (__ACE_INLINE__)
+#include "orbsvcs/PortableGroup/PG_Properties_Encoder.inl"
+#endif /* ! __ACE_INLINE__ */
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+//////////
+// Properties_Encoder
+TAO_PG::Properties_Encoder::Properties_Encoder ()
+{
+}
+
+TAO_PG::Properties_Encoder::~Properties_Encoder ()
+{
+}
+
+
+void TAO_PG::Properties_Encoder::add (
+ const char * name,
+ const PortableGroup::Value & value)
+{
+ NamedValue nv(name, value);
+ values_.push_back(nv);
+}
+
+void TAO_PG::Properties_Encoder::encode (
+ PortableGroup::Properties * property_set) const
+{
+ ACE_ASSERT (property_set != 0);
+ size_t count = values_.size();
+ property_set->length(count);
+ for( size_t nItem = 0; nItem < count; ++nItem )
+ {
+ const NamedValue & nv = values_[nItem];
+ PortableGroup::Property & property = (*property_set)[nItem];
+ PortableGroup::Name & nsName = property.nam;
+ PortableGroup::Value & anyValue = property.val;
+ // assign the value
+ anyValue = (nv.value_);
+
+ // assign the name
+ // @@: This restricts the name to a single level with no "kind"
+ // @@: remove this restriction (?)
+ nsName.length(1);
+ CosNaming::NameComponent & nc = nsName[0];
+
+ nc.id = CORBA::string_dup (nv.name_.c_str());
+ // nc.kind defaults to empty. Leave it that way (for now)
+ }
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Encoder.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Encoder.h
new file mode 100644
index 00000000000..d1780105873
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Encoder.h
@@ -0,0 +1,101 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Properties_Encoder.h
+ *
+ * $Id$
+ *
+ * This file declares a class to help manage PortableGroup::Properties
+ *
+ * @author Dale Wilson <wilson_d@ociweb.com>
+ */
+//=============================================================================
+#ifndef TAO_PG_PROPERTIES_ENCODER_H
+#define TAO_PG_PROPERTIES_ENCODER_H
+
+#include /**/ "ace/pre.h"
+#include <ace/config-all.h>
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroupS.h"
+#include "orbsvcs/CosNamingC.h"
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+
+#include "ace/Vector_T.h"
+#include "ace/SString.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace TAO_PG
+{
+ /**
+ * A helper to assemble a set of properties into a PortableGroup::Properties structure.
+ *
+ * To use a Properties_Encoder:
+ * Create it.
+ * Add properties to it using the add method.
+ * Allocate a new PortableGroup::Properties.
+ * Use the encode method to transfer the properties into the
+ * PortableGroup::Properties.
+ */
+ class TAO_PortableGroup_Export Properties_Encoder
+ {
+ // Originally NamedValue was an ACE_Pair, but ACE_Pair allows operator ==
+ // (delegating to the member's operators ==.) Since CORBA::Any does
+ // not support operator ==, this confused gcc version 2.9-gnupro-98r2
+ // on LynxOS pfadev04 3.0.1 110298-G PowerPC
+ struct NamedValue
+ {
+ public:
+ ACE_CString name_;
+ PortableGroup::Value value_;
+ NamedValue ();
+ NamedValue (const ACE_CString & name, const PortableGroup::Value & value);
+ NamedValue (const NamedValue & rhs);
+ NamedValue & operator = (const NamedValue & rhs);
+ /// Meaningless method to keep ACE_Vector happy
+ bool operator == (const NamedValue &rhs) const;
+ /// Meaningless method to keep ACE_Vector happy
+ bool operator != (const NamedValue &rhs) const;
+ };
+ typedef ACE_Vector< NamedValue, 10 > NamedValueVec;
+
+ public:
+ /**
+ * Construct an empty set of properties.
+ */
+ Properties_Encoder ();
+
+ /// standard destructor
+ ~Properties_Encoder ();
+
+ /**
+ * add a name/value property to the Properties_Encoder.
+ */
+ void add (const char * name, const PortableGroup::Value & value);
+
+ /**
+ * Encode all properties in this Properties_Encoder into a PortableGroup::Properties.
+ *
+ */
+ void encode (PortableGroup::Properties * property_set) const;
+
+ private:
+ Properties_Encoder (const Properties_Encoder & rhs);
+ Properties_Encoder & operator = (const Properties_Encoder & rhs);
+ private:
+ NamedValueVec values_;
+ };
+
+} //namespace TAO_PG
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "orbsvcs/PortableGroup/PG_Properties_Encoder.inl"
+#endif /* __ACE_INLINE__ */
+#include /**/ "ace/post.h"
+#endif // TAO_PG_PROPERTIES_ENCODER_H
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Encoder.inl b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Encoder.inl
new file mode 100644
index 00000000000..aa64246f6a5
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Encoder.inl
@@ -0,0 +1,64 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Properties_Encoder.inl
+ *
+ * $Id$
+ *
+ * @author Dale Wilson <wilson_d@ociweb.com>
+ */
+//=============================================================================
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace TAO_PG
+{
+ ACE_INLINE
+ Properties_Encoder::NamedValue::NamedValue ()
+ {
+ }
+
+ ACE_INLINE
+ Properties_Encoder::NamedValue::NamedValue (const ACE_CString & name, const PortableGroup::Value & value)
+ : name_ (name)
+ , value_ (value)
+ {
+ }
+
+ ACE_INLINE
+ Properties_Encoder::NamedValue::NamedValue (const Properties_Encoder::NamedValue & rhs)
+ : name_ (rhs.name_)
+ , value_ (rhs.value_)
+ {
+ }
+
+ ACE_INLINE
+ Properties_Encoder::NamedValue &
+ Properties_Encoder::NamedValue::operator = (const Properties_Encoder::NamedValue & rhs)
+ {
+ if (this != &rhs)
+ {
+ this->name_ = rhs.name_;
+ this->value_ = rhs.value_;
+ }
+ return *this;
+ }
+
+ ACE_INLINE
+ bool
+ Properties_Encoder::NamedValue::operator == (const Properties_Encoder::NamedValue &rhs) const
+ {
+ return this->name_ == rhs.name_;
+ }
+
+ ACE_INLINE
+ bool
+ Properties_Encoder::NamedValue::operator != (const Properties_Encoder::NamedValue &rhs) const
+ {
+ return this->name_ != rhs.name_;
+ }
+
+} //namespace TAO_PG
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Support.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Support.cpp
new file mode 100644
index 00000000000..cc8d023d899
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Support.cpp
@@ -0,0 +1,151 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Properties_Support.cpp
+ *
+ * $Id$
+ *
+ * This file implements classes to help manage PortableGroup::Properties
+ *
+ * @author Dale Wilson <wilson_d@ociweb.com>
+ */
+//=============================================================================
+
+#include "orbsvcs/PortableGroup/PG_Properties_Support.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO::PG_Properties_Support::PG_Properties_Support ()
+{
+}
+
+TAO::PG_Properties_Support::~PG_Properties_Support ()
+{
+
+}
+
+void TAO::PG_Properties_Support::set_default_property (const char * name,
+ const PortableGroup::Value & value
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->default_properties_.set_property(name, value ACE_ENV_ARG_PARAMETER);
+}
+
+void TAO::PG_Properties_Support::set_default_properties (const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->default_properties_.decode (props ACE_ENV_ARG_PARAMETER);
+}
+
+PortableGroup::Properties *
+TAO::PG_Properties_Support::get_default_properties (
+ ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((
+ CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty))
+{
+ PortableGroup::Properties_var result;
+ ACE_NEW_THROW_EX ( result, PortableGroup::Properties(), CORBA::NO_MEMORY());
+ ACE_CHECK_RETURN (0);
+ this->default_properties_.export_properties (*result);
+ return result._retn ();
+}
+
+void TAO::PG_Properties_Support::remove_default_properties (
+ const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->default_properties_.remove (props);
+}
+
+void
+TAO::PG_Properties_Support::set_type_properties (
+ const char *type_id,
+ const PortableGroup::Properties & overrides
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ( (CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty))
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
+
+ TAO::PG_Property_Set * typeid_properties;
+ if ( 0 != this->properties_map_.find (type_id, typeid_properties))
+ {
+ ACE_NEW_THROW_EX (
+ typeid_properties,
+ TAO::PG_Property_Set (overrides, & this->default_properties_),
+ CORBA::NO_MEMORY());
+ this->properties_map_.bind (type_id, typeid_properties);
+ }
+ typeid_properties->clear ();
+ typeid_properties->decode (overrides ACE_ENV_ARG_PARAMETER);
+}
+
+PortableGroup::Properties *
+TAO::PG_Properties_Support::get_type_properties (
+ const char *type_id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ( (CORBA::SystemException))
+{
+ PortableGroup::Properties_var result;
+ ACE_NEW_THROW_EX (result, PortableGroup::Properties(), CORBA::NO_MEMORY ());
+
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->internals_, 0);
+
+ TAO::PG_Property_Set * typeid_properties = 0;
+ if ( 0 != this->properties_map_.find (type_id, typeid_properties))
+ {
+ typeid_properties->export_properties (*result);
+ }
+ return result._retn ();
+}
+
+void
+TAO::PG_Properties_Support::remove_type_properties (
+ const char *type_id,
+ const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ( (CORBA::SystemException))
+{
+ // NOTE: do not actually delete the properties for this type.
+ // There may be object groups depending on these.
+ // Reference counted pointers could be used to allow property sets
+ // for unused typeids to be deleted.
+
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
+
+ TAO::PG_Property_Set * typeid_properties = 0;
+ if ( 0 != this->properties_map_.find (type_id, typeid_properties))
+ {
+ typeid_properties->remove (props);
+ }
+}
+
+
+TAO::PG_Property_Set *
+TAO::PG_Properties_Support::find_typeid_properties (
+ const char *type_id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->internals_, 0);
+
+ TAO::PG_Property_Set * typeid_properties = 0;
+ if ( 0 != this->properties_map_.find (type_id, typeid_properties))
+ {
+ ACE_NEW_THROW_EX (
+ typeid_properties,
+ TAO::PG_Property_Set (& this->default_properties_),
+ CORBA::NO_MEMORY());
+ this->properties_map_.bind (type_id, typeid_properties);
+ }
+ return typeid_properties;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Support.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Support.h
new file mode 100644
index 00000000000..50e2f504ffd
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Properties_Support.h
@@ -0,0 +1,214 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Properties_Support.h
+ *
+ * $Id$
+ *
+ * This file declares classes to help manage the PortableGroup::Properties
+ * It serves roughly the same purpose as PG_PropertiesManager, but takes a
+ * different approach that suits the needs of FT CORBA.
+ * It would be possible to replace PG_PropertiesManager, or implement it in
+ * terms of PG_Properties_Support at some time in the future.
+ *
+ * @author Dale Wilson <wilson_d@ociweb.com>
+ */
+//=============================================================================
+#ifndef TAO_PG_PROPERTIES_SUPPORT_H
+#define TAO_PG_PROPERTIES_SUPPORT_H
+
+#include "orbsvcs/PortableGroup/PG_Property_Set.h"
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace TAO
+{
+ /**
+ * This Properties Support object manages Property Sets (TAO::PG_Property_Set).
+ *
+ * One set, default_properties_,
+ * acts as a "global" default set of properties.
+ *
+ * The collection, properties_map_, contains a set of properties for each
+ * PortableGroup::type_id. The default set acts as a "parent" for each of
+ * these type_id sets.
+ *
+ * Expected use: When an object group is created that implements the interface
+ * identified by type_id, the corresponding typed_id propery set acts as a
+ * parent to the Property set contained in the PG_Object_Group.
+ *
+ * This heirarchy of property sets provides the correct property behavior. A
+ * request for a propery to an ObjectGroup will be satisfied from:
+ * by the object group group property set, or
+ * the typed_id property set, or
+ * the default property set, or
+ * the request will fail..
+ *
+ * Note that changes to type_id or default properties will be visible
+ * immediately at the ObjectGroup level.
+ */
+
+ class TAO_PortableGroup_Export PG_Properties_Support
+ {
+ typedef ACE_Hash_Map_Manager<
+ ACE_CString,
+ ::TAO::PG_Property_Set *,
+ TAO_SYNCH_MUTEX> Properties_Map;
+ typedef ACE_Hash_Map_Iterator<
+ ACE_CString,
+ ::TAO::PG_Property_Set *,
+ TAO_SYNCH_MUTEX> Properties_Map_Iterator;
+
+ public:
+ PG_Properties_Support ();
+ ~PG_Properties_Support ();
+
+ /**
+ * Set a single default property.
+ * Overwriting any value previously set for that property.
+ * Leaving all other properties untouched.
+ * @param name the name of the property to set
+ * @value an Any containing the value.
+ */
+ void set_default_property (const char * name,
+ const PortableGroup::Value & value
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /**
+ * Update the default property set.
+ *
+ * Properties that appear in props are replaced in or added to the default
+ * property set. Properties that do not appear in props are unchanged.
+ *
+ * @param props the set of properties to update the defaults.
+ */
+ void set_default_properties (const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /**
+ * Export the default properties in PortableGroup::Properties format.
+ *
+ * This produces the properties in a format suitable for use across
+ * a CORBA interface.
+ * The caller owns the resulting Properties and must release it to avoid
+ * resource leaks.
+ * @returns a newly allocated PortableGroup::Properties.
+ */
+ PortableGroup::Properties * get_default_properties (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ( (CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty));
+
+ /**
+ * Undefine default properties that appear in props.
+ *
+ * Properties that are defined in props are removed from the default
+ * property set. Removal is done by name. The property values do not
+ * have to match. There is no penalty for attempting to remove a property
+ * that does not exist.
+ * @param props a set of propertys to be removed by name.
+ */
+ void remove_default_properties (
+ const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /**
+ * Override or define properties associated with a type_id.
+ *
+ * If a property set does not exist for type_id, a new one will be created.
+ * Any property included in overrides will be set or replaced in the type_id
+ * property set. Any property not in overrides will be unchanged.
+ *
+ * Contrary to the "throws" specification, this method does not attempt
+ * to validate the properties because doing so would unnecessarily constrain
+ * the uses to which this class could be put (although one could strategize the
+ * validation.)
+ */
+ void set_type_properties (
+ const char *type_id,
+ const PortableGroup::Properties & overrides
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((
+ CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty));
+
+ /**
+ * Export the property set in a PortableGroup::Properties format.
+ *
+ * This produces the properties associated with a type_id -- including
+ * any default properties that have not been overridden at the type_id level
+ * in a format suitable for use across a CORBA interface.
+ *
+ * The caller owns the resulting Properties and must release it to avoid
+ * resource leaks.
+ *
+ * Compare this method to find_typeid_properties which returns a pointer
+ * to the internal representation of the properties in TAO::PG_Property_Set
+ * format. This is more efficient, but suitable only for internal use.
+ *
+ * @param type_id identifies the set of properties to be exported.
+ * @returns a newly allocated PortableGroup::Properties that must be released by the caller.
+ */
+ PortableGroup::Properties * get_type_properties (
+ const char *type_id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ( (CORBA::SystemException));
+
+ /**
+ * Export the property set in a PortableGroup::Properties format.
+ *
+ * This method is intended to provide a parent
+ * for the property set in a newly-created Object Group of the given
+ * type_id.
+ *
+ * Callers who intend to send the property set across a CORBA interface
+ * should use the get_type_properties method.
+ *
+ * @param type_id identifies the set of properties to be found.
+ * @returns a pointer to a Property_Set owned by this Properties_Support object.
+ */
+ TAO::PG_Property_Set * find_typeid_properties (
+ const char *type_id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /**
+ * Undefine default properties that appear in props.
+ *
+ * Properties that are defined in props are removed from the type_id
+ * property set. Removal is done by name. The property values do not
+ * have to match. There is no penalty for attempting to remove a property
+ * that does not exist.
+ * @param props a set of propertys to be removed by name from the type_id set.
+ */
+ void remove_type_properties (
+ const char *type_id,
+ const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ( (CORBA::SystemException));
+
+ ///////////////
+ // Data Members
+ private:
+ /**
+ * Protect internal state.
+ */
+ TAO_SYNCH_MUTEX internals_;
+
+ /// The default property set.
+ TAO::PG_Property_Set default_properties_;
+
+ /// A collection of property sets indexed by type_id.
+ Properties_Map properties_map_;
+ };
+} //namespace TAO_PG
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#endif // TAO_PG_PROPERTIES_SUPPORT_H
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_PropertyManager.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_PropertyManager.cpp
new file mode 100644
index 00000000000..f6d9fb2a13c
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_PropertyManager.cpp
@@ -0,0 +1,368 @@
+// -*- C++ -*-
+
+#include "orbsvcs/PortableGroup/PG_PropertyManager.h"
+#include "orbsvcs/PortableGroup/PG_ObjectGroupManager.h"
+#include "orbsvcs/PortableGroup/PG_Property_Utils.h"
+
+#include "tao/ORB_Constants.h"
+
+#include "ace/SString.h"
+
+ACE_RCSID (PortableGroup,
+ PG_PropertyManager,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO_PG_PropertyManager::TAO_PG_PropertyManager (
+ TAO_PG_ObjectGroupManager & object_group_manager)
+ : object_group_manager_ (object_group_manager),
+ default_properties_ (),
+ type_properties_ (),
+ lock_ (),
+ property_validator_ ()
+{
+}
+
+
+void
+TAO_PG_PropertyManager::set_default_properties (
+ const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty))
+{
+ // First verify that the "Factories" property is not in the
+ // Properties sequence. According to the spec, it is not allowed to
+ // be set as part of the default properties.
+ PortableGroup::Name factories;
+ factories.length (1);
+ factories[0].id = CORBA::string_dup ("org.omg.PortableGroup.Factories");
+
+ CORBA::ULong len = props.length ();
+ for (CORBA::ULong i = 0; i < len; ++i)
+ {
+ PortableGroup::Property property = props[i];
+
+ if (property.nam == factories)
+ ACE_THROW (PortableGroup::InvalidProperty (property.nam,
+ property.val));
+ }
+
+ this->property_validator_.validate_property (props
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
+
+ this->default_properties_ = props;
+}
+
+
+PortableGroup::Properties *
+TAO_PG_PropertyManager::get_default_properties (
+ ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->lock_, 0);
+
+ PortableGroup::Properties * props = 0;
+ ACE_NEW_THROW_EX (props,
+ PortableGroup::Properties (this->default_properties_),
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (0);
+
+ return props;
+}
+
+
+void
+TAO_PG_PropertyManager::remove_default_properties (
+ const PortableGroup::Properties &props
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty))
+{
+ if (props.length () == 0)
+ return; // @@ Throw CORBA::BAD_PARAM instead?
+
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
+
+ this->remove_properties (props,
+ this->default_properties_
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+
+void
+TAO_PG_PropertyManager::set_type_properties (
+ const char * type_id,
+ const PortableGroup::Properties & overrides
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty))
+{
+ this->property_validator_.validate_property (overrides
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ CORBA::ULong num_overrides = overrides.length ();
+
+ if (num_overrides == 0)
+ return; // Throw CORBA::BAD_PARAM exception instead?
+
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
+
+ Type_Prop_Table::ENTRY * entry = 0;
+ if (this->type_properties_.find (type_id, entry) != 0)
+ ACE_THROW (CORBA::BAD_PARAM ());
+
+ PortableGroup::Properties & props = entry->int_id_;
+ props = overrides;
+}
+
+
+PortableGroup::Properties *
+TAO_PG_PropertyManager::get_type_properties (
+ const char * type_id
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->lock_, 0);
+
+
+ Type_Prop_Table::ENTRY * entry = 0;
+ PortableGroup::Properties * type_properties = 0;
+
+ if (this->type_properties_.find (type_id, entry) == 0)
+ type_properties = &entry->int_id_;
+
+ const CORBA::ULong def_props_len = this->default_properties_.length ();
+ const CORBA::ULong type_props_len =
+ (type_properties == 0 ? 0 : type_properties->length ());
+ const CORBA::ULong props_len =
+ (def_props_len > type_props_len ? def_props_len : type_props_len);
+
+ PortableGroup::Properties * tmp_properties = 0;
+ ACE_NEW_THROW_EX (tmp_properties,
+ PortableGroup::Properties (props_len),
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (0);
+
+ PortableGroup::Properties_var properties = tmp_properties;
+
+ // Set the length to the length of the largest of the two property
+ // sequences. The idea is to keep the cost of the incremental
+ // growth that may occur in TAO_PG::override_properties() to a
+ // minimum.
+ properties->length (props_len);
+
+ *tmp_properties = this->default_properties_;
+
+ if (type_properties != 0 && type_props_len > 0)
+ TAO_PG::override_properties (*type_properties, *tmp_properties);
+
+ return properties._retn ();
+}
+
+
+void
+TAO_PG_PropertyManager::remove_type_properties (
+ const char * type_id,
+ const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty))
+{
+ if (props.length () == 0)
+ return; // @@ Throw CORBA::BAD_PARAM instead?
+
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
+
+ Type_Prop_Table::ENTRY * entry = 0;
+ if (this->type_properties_.find (type_id, entry) != 0)
+ ACE_THROW (CORBA::BAD_PARAM ());
+
+ PortableGroup::Properties & type_properties = entry->int_id_;
+
+ this->remove_properties (props,
+ type_properties
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+
+void
+TAO_PG_PropertyManager::set_properties_dynamically (
+ PortableGroup::ObjectGroup_ptr /* object_group */,
+ const PortableGroup::Properties & /* overrides */
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty))
+{
+#if 0
+ // First verify that the "InitialNumberMembers" property is not in
+ // the Properties sequence. According to the spec, it is not
+ // allowed to be set as part of the default properties.
+ PortableGroup::Name factories;
+ factories.length (1);
+ factories[0].id =
+ CORBA::string_dup ("org.omg.PortableGroup.InitialNumberMembers");
+
+ CORBA::ULong len = props.length ();
+ for (CORBA::ULong i = 0; i < len; ++i)
+ {
+ PortableGroup::Property property = props[i];
+
+ if (property.nam == factories)
+ ACE_THROW (PortableGroup::InvalidProperty (property.nam,
+ property.val));
+ }
+
+ this->property_validator_.validate_property (overrides
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // @todo Set the properties in the object group map entry.
+#endif /* 0 */
+
+ ACE_THROW (CORBA::NO_IMPLEMENT ());
+}
+
+
+PortableGroup::Properties *
+TAO_PG_PropertyManager::get_properties (
+ PortableGroup::ObjectGroup_ptr object_group
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound))
+{
+ CORBA::ULong properties_len = 0;
+
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, property_map_guard, this->lock_, 0);
+
+ // @@ Race condition here!
+ PortableGroup::Properties_var dynamic_properties =
+ this->object_group_manager_.get_properties (object_group
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ CORBA::ULong dyn_props_len = dynamic_properties->length ();
+ if (dyn_props_len > properties_len)
+ properties_len = dyn_props_len;
+
+ CORBA::String_var type_id =
+ this->object_group_manager_.type_id (object_group
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ CORBA::ULong type_props_len = 0;
+ PortableGroup::Properties * type_properties = 0;
+ Type_Prop_Table::ENTRY * type_entry = 0;
+ if (this->type_properties_.find (type_id.in (), type_entry) == 0)
+ {
+ type_properties = &type_entry->int_id_;
+ type_props_len = type_properties->length ();
+
+ if (type_props_len > properties_len)
+ properties_len = type_props_len;
+ }
+
+ CORBA::ULong def_props_len = this->default_properties_.length ();
+ if (def_props_len > properties_len)
+ properties_len = def_props_len;
+
+ PortableGroup::Properties * tmp_properties = 0;
+ ACE_NEW_THROW_EX (tmp_properties,
+ PortableGroup::Properties (properties_len),
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (0);
+
+ PortableGroup::Properties_var properties = tmp_properties;
+
+ // Set the length to the length of the largest of the three property
+ // sequences. The idea is to keep the cost of the incremental
+ // growth that may occur in TAO_PG::override_properties() to a
+ // minimum.
+ properties->length (properties_len);
+
+ // Start out with a copy of the default properties.
+ *tmp_properties = this->default_properties_;
+
+ // Override default properties with type-specific properties.
+ if (type_properties != 0)
+ TAO_PG::override_properties (*type_properties, *tmp_properties);
+
+ // Now override with the dynamic (object group) properties.
+ TAO_PG::override_properties (dynamic_properties.in (), *tmp_properties);
+
+ return properties._retn ();
+}
+
+
+void
+TAO_PG_PropertyManager::remove_properties (
+ const PortableGroup::Properties & to_be_removed,
+ PortableGroup::Properties &properties
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty))
+{
+ const CORBA::ULong num_removed = to_be_removed.length ();
+ if (num_removed == 0)
+ return; // @@ Throw CORBA::BAD_PARAM instead?
+
+ const CORBA::ULong old_length = properties.length ();
+
+ const CORBA::ULong new_length = old_length - num_removed;
+
+ PortableGroup::Properties new_properties (new_length);
+ new_properties.length (new_length);
+
+ // @@ Slow O(n^2) operation. Switching to a faster container for
+ // the default properties might be a good idea at some point in
+ // the future.
+ CORBA::ULong n = 0;
+ for (CORBA::ULong i = 0; i < num_removed; ++i)
+ {
+ const CORBA::ULong old_n = n;
+ const PortableGroup::Property &remove = to_be_removed[i];
+
+ for (CORBA::ULong j = 0; j < old_length; ++j)
+ if (remove.nam != properties[j].nam)
+ new_properties[n++] = properties[j];
+
+ // The property to be removed doesn't exist in the current list
+ // of default properties.
+ if (n == old_n)
+ ACE_THROW (PortableGroup::InvalidProperty (remove.nam,
+ remove.val));
+ }
+
+ // All properties were successfully removed, and the remaining ones
+ // were placed in the "new_properties" variable. Now copy that
+ // variable.
+ properties = new_properties;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_PropertyManager.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_PropertyManager.h
new file mode 100644
index 00000000000..5d6c40fa063
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_PropertyManager.h
@@ -0,0 +1,192 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_PropertyManager.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+#ifndef TAO_PG_PROPERTY_MANAGER_H
+#define TAO_PG_PROPERTY_MANAGER_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroup/PG_Default_Property_Validator.h"
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+#include "orbsvcs/PortableGroupS.h"
+
+#include "ace/SString.h"
+#include "ace/Null_Mutex.h"
+#include "ace/Functor.h"
+#include "ace/Hash_Map_Manager_T.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// Forward declarations.
+class TAO_PG_ObjectGroupManager;
+
+/**
+ * @class TAO_PG_PropertyManager
+ *
+ * @brief Class that implements the PortableGroup::PropertyManager
+ * interface.
+ *
+ * Only the default and type-specific properties are housed in this
+ * class. The properties used at creation time of an object group and
+ * those set dynamically after object group creation are stored in the
+ * TAO_PG_ObjectGroup_Map_Entry structure. However, the
+ * PropertyManager is still used to manage those properties.
+ */
+class TAO_PortableGroup_Export TAO_PG_PropertyManager
+ : public virtual POA_PortableGroup::PropertyManager
+{
+public:
+
+ /// Constructor.
+ TAO_PG_PropertyManager (TAO_PG_ObjectGroupManager & object_group_manager);
+
+ /**
+ * @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
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty));
+
+ /// Get the default properties used by all object groups.
+ virtual PortableGroup::Properties * get_default_properties (
+ ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /// Remove default properties.
+ virtual void remove_default_properties (
+ const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty));
+
+ /// Set properties associated with a given Member type. These
+ /// properties override the default properties.
+ virtual void set_type_properties (
+ const char * type_id,
+ const PortableGroup::Properties & overrides
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty));
+
+ /**
+ * 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
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /// Remove the given properties associated with the Replica type ID.
+ virtual void remove_type_properties (
+ const char * type_id,
+ const PortableGroup::Properties & props
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty));
+
+ /**
+ * 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
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty));
+
+ /**
+ * 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
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::ObjectGroupNotFound));
+
+ //@}
+
+ /// Type-specific property hash map.
+ typedef ACE_Hash_Map_Manager_Ex<
+ ACE_CString,
+ PortableGroup::Properties,
+ ACE_Hash<ACE_CString>,
+ ACE_Equal_To<ACE_CString>,
+ ACE_Null_Mutex> Type_Prop_Table;
+
+private:
+
+ /// Remove properties "to_be_removed" from the given list of
+ /// properties.
+ void remove_properties (const PortableGroup::Properties & to_be_removed,
+ PortableGroup::Properties &properties
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableGroup::InvalidProperty,
+ PortableGroup::UnsupportedProperty));
+
+private:
+
+ /// Table that maps ObjectId to Object Group related information.
+ TAO_PG_ObjectGroupManager & object_group_manager_;
+
+ /// Default properties.
+ PortableGroup::Properties default_properties_;
+
+ /// Table of type-specific object group properties.
+ Type_Prop_Table type_properties_;
+
+ /// Lock used to synchronize access to the default properties and
+ /// the type-specific properties.
+ TAO_SYNCH_MUTEX lock_;
+
+ /// The property validator.
+ /**
+ * @todo Strategize the validator, or use template policies.
+ */
+ TAO_PG_Default_Property_Validator property_validator_;
+
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PG_PROPERTY_MANAGER_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Set.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Set.cpp
new file mode 100644
index 00000000000..e63ff905d9d
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Set.cpp
@@ -0,0 +1,360 @@
+//=============================================================================
+/**
+ * @file PG_Property_Set.cpp
+ *
+ * $Id$
+ *
+ * This file implements classes to help manage the Properties
+ * defined in the Portable Object Group.
+ *
+ * Note: this started as a simple helper class to make decoding sets of properties
+ * easier, but expanded to provide more general support for managing sets of properties.
+ *
+ * @author Dale Wilson <wilson_d@ociweb.com>
+ */
+//=============================================================================
+#include "orbsvcs/PortableGroup/PG_Property_Set.h"
+#include "tao/debug.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+//////////////////////
+// PG_Property_Set
+
+TAO::PG_Property_Set::PG_Property_Set()
+ : defaults_ (0)
+{
+}
+
+TAO::PG_Property_Set::PG_Property_Set (
+ const PortableGroup::Properties & property_set
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+ : defaults_ (0)
+{
+ this->decode (property_set ACE_ENV_ARG_PARAMETER);
+}
+
+TAO::PG_Property_Set::PG_Property_Set (
+ const PortableGroup::Properties & property_set,
+ PG_Property_Set * defaults
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+ : defaults_ (defaults)
+{
+ this->decode (property_set ACE_ENV_ARG_PARAMETER);
+}
+
+
+TAO::PG_Property_Set::PG_Property_Set (
+ PG_Property_Set * defaults)
+ : defaults_ (defaults)
+{
+}
+
+TAO::PG_Property_Set::~PG_Property_Set ()
+{
+ this->clear ();
+}
+
+void
+TAO::PG_Property_Set::decode (const PortableGroup::Properties & property_set
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
+
+ size_t count = property_set.length ();
+ for (size_t nItem = 0; nItem < count; ++nItem)
+ {
+ const PortableGroup::Property & property = property_set[nItem];
+ const CosNaming::Name & nsName = property.nam;
+ // note assumption one level name with no kind
+ // @@ TODO: fix this
+ const CosNaming::NameComponent & nc = nsName[0];
+
+ this->set_property (static_cast<const char *> (nc.id),
+ property.val
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+#if 0
+ ACE_CString name = static_cast<const char *> (nc.id);
+
+ const PortableGroup::Value * value_copy;
+ ACE_NEW_THROW_EX (value_copy,
+ PortableGroup::Value (property.val),
+ CORBA::NO_MEMORY ());
+ ACE_CHECK;
+
+ const PortableGroup::Value * replaced_value = 0;
+ if (0 == this->values_.rebind (name, value_copy, replaced_value))
+ {
+ if (0 != replaced_value)
+ {
+ delete replaced_value;
+ }
+ }
+ else
+ {
+ if (TAO_debug_level > 3)
+ {
+ ACE_ERROR ( (LM_ERROR,
+ "%n\n%T: Property_set: rebind failed.\n"
+ ));
+ }
+ // @@ should throw something here
+ ACE_THROW (CORBA::NO_MEMORY ());
+ }
+#endif
+ }
+}
+
+void TAO::PG_Property_Set::clear ()
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
+ for (ValueMapIterator it = this->values_.begin ();
+ it != this->values_.end ();
+ ++it)
+ {
+ delete (*it).int_id_;
+ }
+ this->values_.unbind_all ();
+}
+
+void TAO::PG_Property_Set::remove (const PortableGroup::Properties & property_set)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
+ size_t count = property_set.length ();
+ for (size_t nItem = 0; nItem < count; ++nItem)
+ {
+ const PortableGroup::Property & property = property_set[nItem];
+ const CosNaming::Name & nsName = property.nam;
+ // note assumption one level name with no kind
+ // @@ TODO: fix this
+ const CosNaming::NameComponent & nc = nsName[0];
+ ACE_CString name = static_cast<const char *> (nc.id);
+
+ const PortableGroup::Value * deleted_value;
+ if ( 0 == this->values_.unbind (name, deleted_value))
+ {
+ delete deleted_value;
+ }
+ else
+ {
+ // don't worry about it.
+ }
+ }
+}
+
+void TAO::PG_Property_Set::set_property (
+ const char * name,
+ const PortableGroup::Value & value
+ ACE_ENV_ARG_DECL)
+{
+ ACE_CString key (name);
+ PortableGroup::Value * value_copy;
+ ACE_NEW_THROW_EX (
+ value_copy, PortableGroup::Value (value),
+ CORBA::NO_MEMORY ());
+ ACE_CHECK;
+
+ const PortableGroup::Value * replaced_value = 0;
+ if (0 == this->values_.rebind (name, value_copy, replaced_value))
+ {
+ if (0 != replaced_value)
+ {
+ delete replaced_value;
+ }
+ }
+ else
+ {
+ if (TAO_debug_level > 3)
+ {
+ ACE_ERROR ( (LM_ERROR,
+ "%n\n%T: Property_set: rebind failed.\n"
+ ));
+ }
+ // @@ should throw something here
+ ACE_THROW (CORBA::NO_MEMORY ());
+ }
+}
+
+
+
+void TAO::PG_Property_Set::export_properties(PortableGroup::Properties & property_set) const
+{
+ ValueMap merged_values;
+ this->merge_properties (merged_values);
+
+ property_set.length (merged_values.current_size ());
+
+ size_t pos = 0;
+ for (ValueMapIterator it = merged_values.begin ();
+ it != merged_values.end ();
+ ++it)
+ {
+ const ACE_CString & name = (*it).ext_id_;
+ const PortableGroup::Value * value = (*it).int_id_;
+
+ PortableGroup::Property & property = property_set[pos];
+ CosNaming::Name & nsName = property.nam;
+ //@@ note assumption: single level name, no kind
+ nsName.length(1);
+ CosNaming::NameComponent & nc = nsName[0];
+ nc.id = CORBA::string_dup (name.c_str ());
+ PortableGroup::Value & val = property.val;
+ val = *value; // NOTE: Any assignment does a deep copy
+ ++pos;
+ }
+ ACE_ASSERT (pos == property_set.length ());
+}
+
+void TAO::PG_Property_Set::merge_properties (ValueMap & merged_values) const
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->internals_);
+ if (0 != this->defaults_)
+ {
+ this->defaults_->merge_properties (merged_values);
+ }
+ // note AFICT ACE_Hash_Map does not support const iterators, hence the const cast.
+ ValueMap & mutable_values = const_cast<ValueMap &> (this->values_);
+ for (ValueMapIterator it = mutable_values.begin ();
+ it != mutable_values.end ();
+ ++it)
+ {
+ merged_values.rebind ( (*it).ext_id_, (*it).int_id_);
+ }
+}
+
+
+
+int TAO::PG_Property_Set::find (
+ const ACE_CString & key,
+ const PortableGroup::Value *& pValue) const
+{
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->internals_, 0);
+ int found = (0 == this->values_.find (key, pValue));
+ if (! found)
+ {
+ if (0 != this->defaults_)
+ {
+ found = this->defaults_->find (key, pValue);
+ }
+ }
+ return found;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+//#define PG_PS_UNIT_TEST
+#ifdef PG_PS_UNIT_TEST
+#include "orbsvcs/PortableGroup/PG_Properties_Encoder.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+int TAO_PG::test_encode_decode ()
+{
+ int result = 1;
+ static const long testLong = 123456L;
+ static const char * testLongKey = "MyLong";
+
+ static const char * testString = "Now is the time for all good people.";
+ static const char * testStringKey = "plover";
+
+ static const double testDouble = 3.1415;
+ static const char * testDoubleKey = "pi";
+
+ PortableGroup::Properties_var property_set = new PortableGroup::Properties;
+ //scope encoder to be sure its gone before decoding
+ {
+ TAO_PG::Encoder encoder;
+ PortableGroup::Value value;
+ value <<= (CORBA::Long) testLong;
+ encoder.add (testLongKey, value);
+
+ value <<= testString;
+ encoder.add (testStringKey, value);
+
+ value <<= (CORBA::Double) testDouble;
+ encoder.add (testDoubleKey, value);
+
+ encoder.encode (property_set);
+ }
+
+ TAO::PG_Property_Set decoder (property_set);
+
+ CORBA::Long longResult = 0;
+ if (find (decoder, testLongKey, longResult) )
+ {
+ if (longResult != testLong)
+ {
+ ACE_ERROR ( (LM_ERROR,
+ "%n\n%T: %s = %d expecting %d\n",
+ testLongKey,
+ (int)longResult,
+ (int)testLong
+ ));
+ result = 0;
+ }
+ }
+ else
+ {
+ ACE_ERROR ( (LM_ERROR,
+ "%n\n%T: Can't find value for %s\n", testLongKey
+ ));
+ result = 0;
+ }
+
+ const char * stringResult = "";
+ if (find (decoder, testStringKey, stringResult))
+ {
+ if (0 != ACE_OS::strcmp (testString, stringResult))
+ {
+ ACE_ERROR ( (LM_ERROR,
+ "%n\n%T: %s = \"%s\" expecting \"%s\"\n",
+ testStringKey,
+ (int)stringResult,
+ (int)testString
+ ));
+ result = 0;
+ }
+ }
+ else
+ {
+ ACE_ERROR ( (LM_ERROR,
+ "%n\n%T: Can't find value for %s\n", testStringKey
+ ));
+ result = 0;
+ }
+
+
+ CORBA::Double doubleResult = 0.0;
+ if (find (decoder, testDoubleKey, doubleResult))
+ {
+ if (doubleResult != testDouble)
+ {
+ ACE_ERROR ( (LM_ERROR,
+ "%n\n%T: %s = \"%f\" expecting \"%f\"\n",
+ testDoubleKey,
+ doubleResult,
+ testDouble
+ ));
+ result = 0;
+ }
+ }
+ else
+ {
+ ACE_ERROR ( (LM_ERROR,
+ "%n\n%T: Can't find value for %s\n", testDoubleKey
+ ));
+ result = 0;
+ }
+
+ return result;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#endif // PG_PS_UNIT_TEST
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Set.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Set.h
new file mode 100644
index 00000000000..44aae869da7
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Set.h
@@ -0,0 +1,200 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Property_Set.h
+ *
+ * $Id$
+ *
+ * This file declares classes to help manage the Properties
+ * defined in the Portable Object Group.
+ *
+ * Note: this started as a simple helper class to make decoding sets of properties
+ * easier, but expanded to provide more general support for managing sets of properties.
+ *
+ * A more appropriate name would be PG_Properties_Set. Maybe this can be changed someday.
+ *
+ * @author Dale Wilson <wilson_d@ociweb.com>
+ */
+//=============================================================================
+#ifndef TAO_PG_PROPERTY_SET
+#define TAO_PG_PROPERTY_SET
+#include /**/ "ace/pre.h"
+
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+#include "orbsvcs/PortableGroupS.h"
+#include "orbsvcs/CosNamingC.h"
+#include "ace/Hash_Map_Manager.h"
+#include "ace/SString.h"
+#include "ace/Null_Mutex.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace TAO
+{
+
+ /**
+ * The PG_Property_Set captures the set of properties from a
+ * PortableGroup::Properties structure in a more usable format (a
+ * hash map), and provides methods for operating on these properties.
+ *
+ * It supports "chains" of property sets to implement default value semantics.
+ * If a requested property is not found in this set, the default set(s) are searched.
+ * Thus, any property found at this level overrides the defaults.
+ *
+ * See: PG_Properties_Support for more details on use of this object.
+ *
+ * A PG_Property_Set may also be used for it's original purpose as a stand-alone
+ * helper class for extracting values from PortableGroup::Properties.
+ */
+
+ class TAO_PortableGroup_Export PG_Property_Set
+ {
+ typedef ACE_Hash_Map_Manager<
+ ACE_CString,
+ const PortableGroup::Value *,
+ ACE_SYNCH_NULL_MUTEX> ValueMap;
+ typedef ACE_Hash_Map_Iterator<
+ ACE_CString,
+ const PortableGroup::Value *,
+ ACE_SYNCH_NULL_MUTEX> ValueMapIterator;
+
+ public:
+
+ /**
+ * constructor: empty set with no defaults.
+ */
+ PG_Property_Set (void);
+
+ /**
+ * constructor
+ * @param property_set the properties to be decoded
+ */
+ PG_Property_Set (const PortableGroup::Properties & property_set
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /**
+ * constructor with defaults
+ * @param property_set the properties to be decoded
+ * @param defaults a propert set decoder that supplies default values.
+ */
+ PG_Property_Set (const PortableGroup::Properties & property_set,
+ PG_Property_Set * defaults
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /**
+ * constructor with defaults, but no properties (yet)
+ * (note this is not a copy constructor)
+ * @param defaults a propert set decoder that supplies default values.
+ */
+ PG_Property_Set (PG_Property_Set * defaults);
+
+
+ ~PG_Property_Set ();
+
+ /**
+ * general purpose find. returns a pointer to an Any
+ * if templated methods were available:
+ * template <typename TYPE >
+ * int find (const ACE_CString & key, TYPE & value) const;
+ * instead, see global function below
+ * @param key the (simple) name of the property
+ * @param pValue an out parameter to receive a pointer to the Any containing the value
+ * @returns boolean true if found
+ */
+ int find (const ACE_CString & key, const PortableGroup::Value *& pValue)const;
+
+
+ /**
+ * Decode additional properties
+ * Duplicate values replace previous values.
+ * @param property_set the properties to be decoded
+ */
+ void decode (const PortableGroup::Properties & property_set ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /**
+ * Clear properties
+ * Does not clear default properties.
+ */
+ void clear ();
+
+ void remove (const PortableGroup::Properties & property_set)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /**
+ * set or replace a single property
+ */
+ void set_property (
+ const char * name,
+ const PortableGroup::Value & value
+ ACE_ENV_ARG_DECL);
+
+
+ /**
+ * Export the properties to a PortableGroup::Properties
+ *
+ * This method is intended to be used to implement the PropertyManager::get_*_properties
+ * methods. If you want to access the properties for any purpose other than exporting
+ * them across a CORBA interface, it is much more efficient to use the find interface.
+ *
+ */
+ void export_properties(PortableGroup::Properties & property_set) const;
+
+ /////////////////////////
+ // Implementation Methods
+ private:
+ /**
+ * populate a ValueMap with the properties known to this decoder
+ * including but overriding default values
+ */
+ void merge_properties (ValueMap & merged_values) const;
+
+ ////////////////////
+ // Forbidden methods
+ private:
+ PG_Property_Set(const PG_Property_Set & rhs);
+ PG_Property_Set & operator = (const PG_Property_Set & rhs);
+
+ ///////////////
+ // Data Members
+ private:
+
+ /**
+ * Protect internal state.
+ */
+ mutable TAO_SYNCH_MUTEX internals_;
+
+ ValueMap values_;
+ /**
+ * a parent to another property decoder that provides default values
+ * these can be chained indefinitely.
+ * @todo reference counted pointers would be a good idea here.
+ */
+ PG_Property_Set * defaults_;
+ };
+
+
+#ifdef PG_PS_UNIT_TEST
+
+ /**
+ * unit test: encode and decode properties.
+ * Initialize CORBA before calling this function.
+ * Success is silent, failure prints on cerr.
+ * @returns 1 if test passed; 0 if test failed.
+ */
+ int test_encode_decode();
+#endif // PG_PS_UNIT_TEST
+} //namespace TAO
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+////////////////////////////////////
+// include templated helper function
+#include "orbsvcs/PortableGroup/PG_Property_Set_Find.h"
+
+#include /**/ "ace/post.h"
+
+#endif // TAO_PG_PROPERTY_SET
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Set_Find.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Set_Find.h
new file mode 100644
index 00000000000..6f68524d8ac
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Set_Find.h
@@ -0,0 +1,55 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Property_Set_Find.h
+ *
+ * $Id$
+ *
+ * This is a companion function for the properties docoder
+ * to work around compilers that don't support templated methods.
+ *
+ * @author Dale Wilson <wilson_d@ociweb.com>
+ */
+//=============================================================================
+#ifndef TAO_PG_PROPERTY_SET_FIND_H
+#define TAO_PG_PROPERTY_SET_FIND_H
+#include /**/ "ace/pre.h"
+#include <ace/ACE.h>
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+
+#include "ace/Hash_Map_Manager.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace TAO
+{
+ /**
+ * Find a value in a TAO::PG_Property_Set.
+ * This is a work-around for the lack of
+ * templated methods.
+ */
+ template <typename TYPE>
+ int find (const PG_Property_Set & decoder, const ACE_CString & key, TYPE & value)
+ {
+ int result = 0;
+ PortableGroup::Value const * any;
+ if ( decoder.find (key, any))
+ {
+ result = ((*any) >>= value);
+ }
+ return result;
+ }
+
+} //namespace TAO
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif // TAO_PG_PROPERTY_SET_FIND_H
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Utils.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Utils.cpp
new file mode 100644
index 00000000000..897facce517
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Utils.cpp
@@ -0,0 +1,82 @@
+#include "orbsvcs/PortableGroup/PG_Property_Utils.h"
+#include "orbsvcs/PortableGroup/PG_Operators.h"
+
+ACE_RCSID (PortableGroup,
+ PG_Property_Utils,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+CORBA::Boolean
+TAO_PG::get_property_value (const PortableGroup::Name & property_name,
+ const PortableGroup::Properties & properties,
+ PortableGroup::Value & property_value)
+{
+ const CORBA::ULong len = properties.length ();
+ for (CORBA::ULong i = 0; i < len; ++i)
+ {
+ const PortableGroup::Property & property = properties[i];
+ if (property.nam == property_name)
+ {
+ property_value = property.val;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void
+TAO_PG::override_properties (
+ const PortableGroup::Properties & overrides,
+ PortableGroup::Properties &properties)
+{
+ const CORBA::ULong num_overrides = overrides.length ();
+ if (num_overrides == 0)
+ return;
+
+ const CORBA::ULong old_length = properties.length ();
+
+ const CORBA::ULong new_length =
+ (num_overrides > old_length ? num_overrides : old_length);
+
+ // Increase the length wholesale as much as possible. The idea is
+ // to keep the cost of the incremental growth that may occur below
+ // to a minimum.
+ properties.length (new_length);
+
+ // @@ Slow O(n^2) operation. Note that it may be slower than O(n^2)
+ // if the length of the property sequence must be increased
+ // on-the-fly due to the allocations and copies incurred by such
+ // an operation.
+ for (CORBA::ULong i = 0; i < num_overrides; ++i)
+ {
+ const PortableGroup::Property &override = overrides[i];
+
+ CORBA::ULong j = 0;
+ for ( ; j < old_length; ++j)
+ if (properties[j].nam == override.nam)
+ {
+ properties[j].val = override.val;
+ break;
+ }
+
+ // No property to override. Append the override.
+ if (j == old_length)
+ {
+ // @@ Slow incremental growth! In order to set the length
+ // only once, i.e. a priori, instead of multiple times a
+ // searches in the override list and the property list
+ // must be performed to determine how many additional
+ // properties from the override list must be appended to
+ // the properties list. Depending on the size of each
+ // list, such an operation may be just as slow as this
+ // operation.
+ const CORBA::ULong current_length = properties.length ();
+ properties.length (current_length + 1);
+ properties[current_length] = override;
+ }
+ }
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Utils.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Utils.h
new file mode 100644
index 00000000000..8e8395f2bc6
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Property_Utils.h
@@ -0,0 +1,57 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Property_Utils.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_PG_PROPERTY_UTILS_H
+#define TAO_PG_PROPERTY_UTILS_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+#include "orbsvcs/PortableGroupC.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace TAO_PG
+{
+ /// Retrieve the value of the given property from the given property
+ /// list.
+ /**
+ * @return true if successful, false otherwise
+ */
+ TAO_PortableGroup_Export CORBA::Boolean get_property_value (
+ const PortableGroup::Name & property_name,
+ const PortableGroup::Properties & properties,
+ PortableGroup::Value & property_value);
+
+ /// Override properties in the "properties" sequence with those in
+ /// the "overrides" sequence.
+ /**
+ * If no property is overridden, the override in question will be
+ * appended to the "properties" list.
+ */
+ TAO_PortableGroup_Export void override_properties (
+ const PortableGroup::Properties & overrides,
+ PortableGroup::Properties &properties);
+
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* TAO_PG_PROPERTY_UTILS_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Servant_Dispatcher.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Servant_Dispatcher.cpp
new file mode 100644
index 00000000000..4b3504795e2
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Servant_Dispatcher.cpp
@@ -0,0 +1,70 @@
+// $Id$
+
+#include "orbsvcs/PortableGroup/GOA.h"
+#include "orbsvcs/PortableGroup/PG_Servant_Dispatcher.h"
+
+ACE_RCSID(PortableGroup,
+ PG_Servant_Dispatcher,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO_PG_Servant_Dispatcher::~TAO_PG_Servant_Dispatcher (void)
+{
+}
+
+TAO_Root_POA *
+TAO_PG_Servant_Dispatcher::create_Root_POA (const ACE_CString &name,
+ PortableServer::POAManager_ptr poa_manager,
+ const TAO_POA_Policy_Set &policies,
+ ACE_Lock &lock,
+ TAO_SYNCH_MUTEX &thread_lock,
+ TAO_ORB_Core &orb_core,
+ TAO_Object_Adapter *object_adapter
+ ACE_ENV_ARG_DECL)
+{
+ TAO_Root_POA *poa = 0;
+
+ ACE_NEW_THROW_EX (poa,
+ TAO_GOA (name,
+ poa_manager,
+ policies,
+ 0,
+ lock,
+ thread_lock,
+ orb_core,
+ object_adapter
+ ACE_ENV_ARG_PARAMETER),
+ CORBA::NO_MEMORY ());
+ ACE_CHECK_RETURN (0);
+
+ return poa;
+}
+
+void
+TAO_PG_Servant_Dispatcher::pre_invoke_remote_request (
+ TAO_Root_POA &,
+ CORBA::Short,
+ TAO_ServerRequest &,
+ TAO::Portable_Server::Servant_Upcall::Pre_Invoke_State &
+ ACE_ENV_ARG_DECL_NOT_USED)
+{
+}
+
+void
+TAO_PG_Servant_Dispatcher::pre_invoke_collocated_request (
+ TAO_Root_POA &,
+ CORBA::Short,
+ TAO::Portable_Server::Servant_Upcall::Pre_Invoke_State &
+ ACE_ENV_ARG_DECL_NOT_USED)
+{
+}
+
+void
+TAO_PG_Servant_Dispatcher::post_invoke (
+ TAO_Root_POA &,
+ TAO::Portable_Server::Servant_Upcall::Pre_Invoke_State &)
+{
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Servant_Dispatcher.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Servant_Dispatcher.h
new file mode 100644
index 00000000000..a5718c240cc
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Servant_Dispatcher.h
@@ -0,0 +1,72 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Servant_Dispatcher.h
+ *
+ * $Id$
+ *
+ * @author Johnny Willemsen <jwillemsen@remedy.nl>
+ */
+//=============================================================================
+
+#ifndef TAO_PG_SERVANT_DISPATCHER_H
+#define TAO_PG_SERVANT_DISPATCHER_H
+#include /**/ "ace/pre.h"
+
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+#include "tao/PortableServer/Servant_Dispatcher.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class TAO_PG_Servant_Dispatcher
+ *
+ * @brief Concrete instantiation of the Servant_Dispatcher strategy.
+ *
+ * This class just calls _dispatch on the servant_upcall. No extra
+ * processing is done or needed.
+ *
+ */
+class TAO_PortableGroup_Export TAO_PG_Servant_Dispatcher
+ : public TAO_Servant_Dispatcher
+{
+public:
+ virtual ~TAO_PG_Servant_Dispatcher (void);
+
+ /// Pre_invoke remote request.
+ void pre_invoke_remote_request (TAO_Root_POA &poa,
+ CORBA::Short servant_priority,
+ TAO_ServerRequest &req,
+ TAO::Portable_Server::Servant_Upcall::Pre_Invoke_State &pre_invoke_state
+ ACE_ENV_ARG_DECL);
+
+ /// Pre_invoke collocated request.
+ void pre_invoke_collocated_request (TAO_Root_POA &poa,
+ CORBA::Short servant_priority,
+ TAO::Portable_Server::Servant_Upcall::Pre_Invoke_State &pre_invoke_state
+ ACE_ENV_ARG_DECL);
+
+ /// Post_invoke request.
+ void post_invoke (TAO_Root_POA &poa,
+ TAO::Portable_Server::Servant_Upcall::Pre_Invoke_State &pre_invoke_state);
+
+ /// Factory method for creating new POA's.
+ TAO_Root_POA *create_Root_POA (const ACE_CString &name,
+ PortableServer::POAManager_ptr poa_manager,
+ const TAO_POA_Policy_Set &policies,
+ ACE_Lock &lock,
+ TAO_SYNCH_MUTEX &thread_lock,
+ TAO_ORB_Core &orb_core,
+ TAO_Object_Adapter *object_adapter
+ ACE_ENV_ARG_DECL);
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* TAO_PG_SERVANT_DISPATCHER_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Utils.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Utils.cpp
new file mode 100644
index 00000000000..a57079ffea8
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Utils.cpp
@@ -0,0 +1,176 @@
+#include "orbsvcs/PortableGroup/PG_Utils.h"
+
+#include "tao/MProfile.h"
+#include "tao/Profile.h"
+#include "tao/Stub.h"
+#include "tao/Tagged_Components.h"
+#include "tao/CDR.h"
+
+#include "ace/OS_NS_string.h"
+
+
+ACE_RCSID (PortableGroup,
+ PG_Utils,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace TAO
+{
+ /*static*/ CORBA::Boolean
+ PG_Utils::set_tagged_component (
+ PortableGroup::ObjectGroup *&ior,
+ PortableGroup::TagGroupTaggedComponent &tg)
+ {
+ if (ior->_stubobj () == 0)
+ return 0;
+
+ // We need to apply the property for every profile in the IOR
+ TAO_MProfile &tmp_pfiles =
+ ior->_stubobj ()->base_profiles ();
+
+ // Create the output CDR stream
+ TAO_OutputCDR cdr;
+
+ IOP::TaggedComponent tagged_components;
+ tagged_components.tag = IOP::TAG_FT_GROUP;
+
+ // Encode the property in to the tagged_components
+ CORBA::Boolean retval =
+ PG_Utils::encode_properties (cdr,
+ tg);
+
+ if (retval == 0)
+ return retval;
+
+ // Get the length of the CDR stream
+ CORBA::ULong length = static_cast<CORBA::ULong> (cdr.total_length ());
+
+ // Set the length
+ tagged_components.component_data.length (length);
+
+ // Get the pointer to the underlying buffer
+ CORBA::Octet *buf =
+ tagged_components.component_data.get_buffer ();
+
+ for (const ACE_Message_Block *i = cdr.begin ();
+ i != 0;
+ i = i->cont ())
+ {
+
+ ACE_OS::memcpy (buf, i->rd_ptr (), i->length ());
+ buf += i->length ();
+ }
+ const IOP::TaggedComponent &tmp_tc = tagged_components;
+
+ // Get the profile count.
+ CORBA::ULong count =
+ ior->_stubobj ()->base_profiles ().profile_count ();
+
+ // Go through every profile and set the TaggedComponent field
+ for (CORBA::ULong p_idx = 0; p_idx < count ; ++p_idx)
+ {
+ // Get the tagged components in the profile
+ TAO_Tagged_Components &tag_comp =
+ tmp_pfiles.get_profile (p_idx)->tagged_components ();
+
+ // Finally set the <tagged_component> in the
+ // <TAO_Tagged_Component>
+ tag_comp.set_component (tmp_tc);
+ }
+
+ // Success
+ return 1;
+ }
+
+ /*static*/ CORBA::Boolean
+ PG_Utils::get_tagged_component (
+ PortableGroup::ObjectGroup *&ior,
+ PortableGroup::TagGroupTaggedComponent &tg)
+ {
+ if (ior->_stubobj () == 0)
+ return 0;
+
+ TAO_MProfile &mprofile =
+ ior->_stubobj ()->base_profiles ();
+
+ // Looking for a tagged component with a TAG_FT_GROUP flag.
+ IOP::TaggedComponent tc;
+ tc.tag = IOP::TAG_FT_GROUP;
+
+ CORBA::ULong count =
+ mprofile.profile_count ();
+
+ for (CORBA::ULong i = 0;
+ i < count;
+ i++)
+ {
+
+ // Get the Tagged Components
+ const TAO_Tagged_Components &pfile_tagged =
+ mprofile.get_profile (i)->tagged_components ();
+
+ // Look for the primary
+ if (pfile_tagged.get_component (tc) == 1)
+ {
+ TAO_InputCDR cdr (reinterpret_cast<const char*> (tc.component_data.get_buffer ()),
+ tc.component_data.length ());
+
+ CORBA::Boolean byte_order;
+
+ cdr >> ACE_InputCDR::to_boolean (byte_order);
+
+ if (!cdr.good_bit ())
+ return 0;
+
+ cdr.reset_byte_order (static_cast<int> (byte_order));
+
+ cdr >> tg;
+
+ if (cdr.good_bit ())
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+ CORBA::Boolean
+ PG_Utils::encode_properties (
+ TAO_OutputCDR &cdr,
+ PortableGroup::TagGroupTaggedComponent &tg)
+ {
+ cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER);
+
+ if (!cdr.good_bit ())
+ return 0;
+
+ // the version info
+ cdr << tg.component_version;
+
+ if (!cdr.good_bit ())
+ return 0;
+
+ // the domain id
+ cdr << tg.group_domain_id.in ();
+
+ if (!cdr.good_bit ())
+ return 0;
+
+ // Object group id
+ cdr << tg.object_group_id;
+
+ if (!cdr.good_bit ())
+ return 0;
+
+ // Object group reference version
+ cdr << tg.object_group_ref_version;
+
+ if (!cdr.good_bit ())
+ return 0;
+
+ return cdr.good_bit ();
+ }
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Utils.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Utils.h
new file mode 100644
index 00000000000..5552f38c3a3
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Utils.h
@@ -0,0 +1,59 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_Utils.h
+ *
+ * $Id$
+ *
+ * Utility methods
+ *
+ * @author Balachandran Natarajan <bala@dre.vanderbilt.edu>
+ */
+//=============================================================================
+#ifndef TAO_PORTABLEGROUP_UTILS_H
+#define TAO_PORTABLEGROUP_UTILS_H
+#include /**/ "ace/pre.h"
+
+#include "orbsvcs/PortableGroupC.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace TAO
+{
+ /**
+ * @class PG_Utils
+ *
+ * @brief Simple utility class
+ */
+ class TAO_PortableGroup_Export PG_Utils
+ {
+ public:
+
+ /// Set tagged component for the object group
+ static CORBA::Boolean set_tagged_component (
+ PortableGroup::ObjectGroup *&ior,
+ PortableGroup::TagGroupTaggedComponent &t);
+
+ /// Get tagged component for the object group
+ static CORBA::Boolean get_tagged_component (
+ PortableGroup::ObjectGroup *&ior,
+ PortableGroup::TagGroupTaggedComponent &t);
+
+ private:
+ static CORBA::Boolean encode_properties (
+ TAO_OutputCDR &cdr,
+ PortableGroup::TagGroupTaggedComponent &tg);
+ };
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /*TAO_PORTABLEGROUP_UTILS_H*/
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_conf.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_conf.h
new file mode 100644
index 00000000000..7f993ad8f71
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_conf.h
@@ -0,0 +1,64 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PG_conf.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_PG_CONF_H
+#define TAO_PG_CONF_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroupC.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+#ifndef TAO_PG_MAX_OBJECT_GROUPS // @@ why create arbitrary limits?
+/// The maximum number of object groups to be managed by the
+/// ObjectGroupManager. This number is also equal to the number of
+/// factory sets managed by the GenericFactory.
+const size_t TAO_PG_MAX_OBJECT_GROUPS = 1024;
+#endif /* TAO_PG_MAX_NUMBER_OF_OBJECT_GROUPS */
+
+#ifndef TAO_PG_MAX_LOCATIONS // @@ why create arbitrary limits?
+/// The maximum number of locations to be managed by the
+/// ObjectGroupManager.
+const size_t TAO_PG_MAX_LOCATIONS = 1024;
+#endif /* TAO_PG_MAX_LOCATIONS */
+
+#ifndef TAO_PG_MEMBERSHIP_STYLE
+/// The default object group membership style.
+const PortableGroup::MembershipStyleValue TAO_PG_MEMBERSHIP_STYLE =
+ PortableGroup::MEMB_INF_CTRL;
+#endif /* TAO_PG_INITIAL_NUMBER_MEMBERS */
+
+#ifndef TAO_PG_INITIAL_NUMBER_MEMBERS
+/// The default initial number of object group members.
+const PortableGroup::InitialNumberMembersValue TAO_PG_INITIAL_NUMBER_MEMBERS =
+ 2;
+#endif /* TAO_PG_INITIAL_NUMBER_MEMBERS */
+
+#ifndef TAO_PG_MINIMUM_NUMBER_MEMBERS
+/// The default minimum number of object group members.
+const PortableGroup::MinimumNumberMembersValue TAO_PG_MINIMUM_NUMBER_MEMBERS =
+ TAO_PG_INITIAL_NUMBER_MEMBERS;
+#endif /* TAO_PG_MINIMUM_NUMBER_MEMBERS */
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PG_CONF_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Acceptor_Registry.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Acceptor_Registry.cpp
new file mode 100644
index 00000000000..a22594ca04b
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Acceptor_Registry.cpp
@@ -0,0 +1,191 @@
+// $Id$
+
+#include "orbsvcs/PortableGroup/PortableGroup_Acceptor_Registry.h"
+#include "tao/ORB_Core.h"
+#include "tao/Profile.h"
+#include "tao/Protocol_Factory.h"
+#include "tao/GIOP_Message_State.h"
+#include "tao/debug.h"
+#include "tao/Endpoint.h"
+#include "tao/Thread_Lane_Resources.h"
+#include "tao/Leader_Follower.h"
+
+ACE_RCSID (PortableGroup,
+ PortableGroup_Acceptor_Registry,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO_PortableGroup_Acceptor_Registry::TAO_PortableGroup_Acceptor_Registry (void)
+{
+}
+
+TAO_PortableGroup_Acceptor_Registry::~TAO_PortableGroup_Acceptor_Registry (void)
+{
+ // Free the memory for the endpoints.
+ Entry *entry;
+ Acceptor_Registry_Iterator iter (this->registry_);
+
+ while (iter.next (entry))
+ {
+ delete entry->endpoint;
+ delete entry->acceptor;
+ iter.advance ();
+ }
+}
+
+
+void
+TAO_PortableGroup_Acceptor_Registry::open (const TAO_Profile* profile,
+ TAO_ORB_Core &orb_core
+ ACE_ENV_ARG_DECL)
+{
+ Entry *entry;
+
+ if (this->find (profile, entry) == 1)
+ {
+ // Found it. Increment the reference count.
+ ++entry->cnt;
+ }
+ else
+ {
+ // Not found. Open a new acceptor.
+
+ // Now get the list of available protocol factories.
+ TAO_ProtocolFactorySetItor end =
+ orb_core.protocol_factories ()->end ();
+
+ // int found = 0;
+ // If usable protocol (factory) is found then this will be
+ // set equal to 1.
+
+ for (TAO_ProtocolFactorySetItor factory =
+ orb_core.protocol_factories ()->begin ();
+ factory != end;
+ ++factory)
+ {
+ if ((*factory)->factory ()->tag () == profile->tag ())
+ {
+ this->open_i (profile,
+ orb_core,
+ factory
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // found = 1; // A usable protocol was found.
+ }
+ else
+ continue;
+ }
+ }
+}
+
+#define MAX_ADDR_LENGTH (32)
+
+void
+TAO_PortableGroup_Acceptor_Registry::open_i (const TAO_Profile* profile,
+ TAO_ORB_Core &orb_core,
+ TAO_ProtocolFactorySetItor &factory
+ ACE_ENV_ARG_DECL)
+{
+ TAO_Acceptor *acceptor = (*factory)->factory ()->make_acceptor ();
+
+ if (acceptor != 0)
+ {
+ // Extract the desired endpoint/protocol version if one
+ // exists.
+ const TAO_GIOP_Message_Version &version = profile->version ();
+ char buffer [MAX_ADDR_LENGTH];
+
+ // Removed the constness of profile. We're not changing
+ // anything, but need to call a nonconst function.
+ TAO_Profile* nc_profile = const_cast<TAO_Profile *> (profile);
+ nc_profile->endpoint ()->addr_to_string (buffer, MAX_ADDR_LENGTH);
+
+ if (acceptor->open (&orb_core,
+ orb_core.lane_resources ().leader_follower ().reactor(),
+ version.major,
+ version.minor,
+ buffer,
+ 0) == -1)
+ {
+ delete acceptor;
+
+ if (TAO_debug_level > 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("TAO (%P|%t) ")
+ ACE_TEXT ("unable to open acceptor ")
+ ACE_TEXT ("for <%s>%p\n"),
+ buffer,
+ ""));
+
+ ACE_THROW (CORBA::BAD_PARAM (
+ CORBA::SystemException::_tao_minor_code (
+ TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE,
+ EINVAL),
+ CORBA::COMPLETED_NO));
+ }
+
+ // Add acceptor to list.
+ Entry tmp_entry;
+ tmp_entry.acceptor = acceptor;
+ tmp_entry.endpoint = nc_profile->endpoint ()->duplicate ();
+ tmp_entry.cnt = 1;
+
+ if (this->registry_.enqueue_tail (tmp_entry) == -1)
+ {
+ delete acceptor;
+
+ if (TAO_debug_level > 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("TAO (%P|%t) ")
+ ACE_TEXT ("unable to add acceptor to registry")
+ ACE_TEXT ("for <%s>%p\n"),
+ buffer,
+ ""));
+
+ ACE_THROW (CORBA::BAD_PARAM (
+ CORBA::SystemException::_tao_minor_code (
+ TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE,
+ EINVAL),
+ CORBA::COMPLETED_NO));
+ }
+ }
+ else
+ {
+ if (TAO_debug_level > 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("TAO (%P|%t) ")
+ ACE_TEXT ("unable to create acceptor ")
+ ));
+
+ ACE_THROW (CORBA::BAD_PARAM (
+ CORBA::SystemException::_tao_minor_code (
+ TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE,
+ EINVAL),
+ CORBA::COMPLETED_NO));
+ }
+}
+
+int
+TAO_PortableGroup_Acceptor_Registry::find (const TAO_Profile* profile,
+ Entry *&entry)
+{
+ Acceptor_Registry_Iterator iter (this->registry_);
+
+ while (iter.next (entry))
+ {
+ // Since the endpoint routine is nonconst, need to
+ // cast away the constness even though we're not
+ // changing anything.
+ TAO_Profile *nc_profile = const_cast<TAO_Profile *> (profile);
+ if (entry->endpoint->is_equivalent (nc_profile->endpoint ()))
+ return 1;
+
+ iter.advance ();
+ }
+
+ return 0;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Acceptor_Registry.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Acceptor_Registry.h
new file mode 100644
index 00000000000..1ecc90efa4d
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Acceptor_Registry.h
@@ -0,0 +1,117 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PortableGroup_Acceptor_Registry.h
+ *
+ * $Id$
+ *
+ * Registry for dynamically created acceptors.
+ *
+ * @author Frank Hunleth <fhunleth@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef TAO_PORTABLEGROUP_ACCEPTOR_REGISTRY_H
+#define TAO_PORTABLEGROUP_ACCEPTOR_REGISTRY_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/Unbounded_Queue.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/CORBA_macros.h"
+
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+
+#include "tao/Transport_Acceptor.h"
+#include "tao/Resource_Factory.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class TAO_Profile;
+
+namespace CORBA
+{
+ class Environment;
+}
+
+/**
+ * @class TAO_PortableGroup_Acceptor_Registry
+ *
+ * @brief .
+ *
+ * There is one TAO_PortableGroup_Acceptor_Registry per ORB_Core.
+ */
+class TAO_PortableGroup_Export TAO_PortableGroup_Acceptor_Registry
+{
+public:
+
+ /**
+ * @struct Entry
+ *
+ * @brief Value field of the portable group acceptor registry.
+ */
+ struct Entry
+ {
+ /// Pointer to the acceptor for this GroupId.
+ TAO_Acceptor *acceptor;
+
+ /// Cached endpoint that the acceptor is listening on.
+ TAO_Endpoint *endpoint;
+
+ /// Count of times that this GroupId has been opened.
+ int cnt;
+ };
+
+
+ // = Initialization and termination methods.
+ /// Default constructor.
+ TAO_PortableGroup_Acceptor_Registry (void);
+
+ /// Default destructor.
+ ~TAO_PortableGroup_Acceptor_Registry (void);
+
+ /// Open an acceptor based on a tagged profile.
+ void open (const TAO_Profile* profile,
+ TAO_ORB_Core &orb_core
+ ACE_ENV_ARG_DECL);
+
+ /// Close all open acceptors.
+ int close_all (void);
+
+ typedef ACE_Unbounded_Queue<Entry> Acceptor_Registry;
+ typedef ACE_Unbounded_Queue_Iterator<Entry> Acceptor_Registry_Iterator;
+
+protected:
+
+ /// Helper function to open a group acceptor.
+ void open_i (const TAO_Profile* profile,
+ TAO_ORB_Core &orb_core,
+ TAO_ProtocolFactorySetItor &factory
+ ACE_ENV_ARG_DECL);
+
+ /// Find an acceptor by using a profile.
+ int find (const TAO_Profile* profile,
+ Entry *&entry);
+
+private:
+
+ // The acceptor registry should not be copied.
+ TAO_PortableGroup_Acceptor_Registry (
+ const TAO_PortableGroup_Acceptor_Registry&);
+ void operator= (const TAO_PortableGroup_Acceptor_Registry&);
+
+private:
+ /// List of acceptors that are currently open.
+ Acceptor_Registry registry_;
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PORTABLEGROUP_ACCEPTOR_REGISTRY_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Loader.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Loader.cpp
new file mode 100644
index 00000000000..2878d3db9a6
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Loader.cpp
@@ -0,0 +1,83 @@
+// $Id$
+
+#include "orbsvcs/PortableGroup/PortableGroup_Loader.h"
+#include "orbsvcs/PortableGroup/PG_Object_Adapter_Factory.h"
+#include "orbsvcs/PortableGroup/PortableGroup_ORBInitializer.h"
+#include "ace/Dynamic_Service.h"
+#include "tao/ORB_Core.h"
+#include "tao/ORBInitializer_Registry.h"
+
+ACE_RCSID (PortableGroup,
+ PortableGroup_Loader,
+ "$Id$")
+
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO_PortableGroup_Loader::TAO_PortableGroup_Loader (void)
+{
+}
+
+int
+TAO_PortableGroup_Loader::init (int /*argc*/,
+ char* /*argv*/ [])
+{
+ ACE_TRACE ("TAO_PortableGroup_Loader::init");
+ // Register the ORB initializer.
+ ACE_TRY_NEW_ENV
+ {
+ PortableInterceptor::ORBInitializer_ptr temp_orb_initializer =
+ PortableInterceptor::ORBInitializer::_nil ();
+ PortableInterceptor::ORBInitializer_var orb_initializer;
+
+ /// Register the Portablegroup ORBInitializer.
+ ACE_NEW_THROW_EX (temp_orb_initializer,
+ TAO_PortableGroup_ORBInitializer (),
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_TRY_CHECK;
+ orb_initializer = temp_orb_initializer;
+
+ PortableInterceptor::register_orb_initializer (orb_initializer.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ ACE_CATCHANY
+ {
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,
+ "Unexpected exception caught while initializing the PortableGroup:");
+ return 1;
+ }
+ ACE_ENDTRY;
+
+ return 0;
+}
+
+int
+TAO_PortableGroup_Loader::Initializer (void)
+{
+ ACE_Service_Config::process_directive (ace_svc_desc_TAO_PortableGroup_Loader);
+ TAO_PortableGroup_Loader *tmp =
+ ACE_Dynamic_Service<TAO_PortableGroup_Loader>::instance (
+ "PortableGroup_Loader");
+
+ if (tmp != 0)
+ {
+ return tmp->init (0, 0);
+ }
+
+ return -1;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+ACE_STATIC_SVC_DEFINE (TAO_PortableGroup_Loader,
+ ACE_TEXT ("PortableGroup_Loader"),
+ ACE_SVC_OBJ_T,
+ &ACE_SVC_NAME (TAO_PortableGroup_Loader),
+ ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ,
+ 0)
+ACE_FACTORY_DEFINE (TAO_PortableGroup, TAO_PortableGroup_Loader)
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Loader.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Loader.h
new file mode 100644
index 00000000000..7dac70972c2
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Loader.h
@@ -0,0 +1,68 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PortableGroup_Loader.h
+ *
+ * $Id$
+ *
+ * Loads and initializes the PortableGroup extensions to TAO.
+ *
+ * @author Frank Hunleth <fhunleth@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef TAO_PORTABLEGROUP_LOADER_H
+#define TAO_PORTABLEGROUP_LOADER_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 "tao/Versioned_Namespace.h"
+
+#include "ace/Service_Config.h"
+#include "ace/Service_Object.h"
+
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class TAO_PortableGroup_Adapter
+ *
+ * @brief TAO_PortableGroup_Adapter.
+ *
+ * This class acts as a facade for the PortableGroup library to the
+ * ORB.
+ */
+class TAO_PortableGroup_Export TAO_PortableGroup_Loader
+ : public ACE_Service_Object
+{
+public:
+ /// Constructor.
+ TAO_PortableGroup_Loader (void);
+
+ /// Initialize the PortableGroup loader hooks.
+ virtual int init (int argc,
+ char *[]);
+
+ /// Used to force the initialization of the ORB code.
+ static int Initializer (void);
+};
+
+static int
+TAO_Requires_PortableGroup_Initializer =
+ TAO_PortableGroup_Loader::Initializer ();
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+ACE_STATIC_SVC_DECLARE (TAO_PortableGroup_Loader)
+ACE_FACTORY_DECLARE (TAO_PortableGroup, TAO_PortableGroup_Loader)
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PORTABLEGROUP_LOADER_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_ORBInitializer.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_ORBInitializer.cpp
new file mode 100644
index 00000000000..870c6b75e59
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_ORBInitializer.cpp
@@ -0,0 +1,71 @@
+// $Id$
+
+#include "orbsvcs/PortableGroup/PortableGroup_ORBInitializer.h"
+#include "orbsvcs/PortableGroup/PortableGroup_Request_Dispatcher.h"
+
+#include "tao/Exception.h"
+#include "tao/ORB_Core.h"
+#include "tao/PI/ORBInitInfo.h"
+#include "tao/debug.h"
+
+ACE_RCSID (PortableGroup,
+ PortableGroup_ORBInitializer,
+ "$Id$")
+
+static const char pg_poa_factory_name[] = "TAO_GOA";
+static const char pg_poa_factory_directive[] = ACE_DYNAMIC_SERVICE_DIRECTIVE(
+ "TAO_GOA", "TAO_PortableGroup", "_make_TAO_PG_Object_Adapter_Factory", "");
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+TAO_PortableGroup_ORBInitializer::pre_init (
+ PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ // Narrow to a TAO_ORBInitInfo object to get access to the
+ // orb_core() TAO extension.
+ TAO_ORBInitInfo_var tao_info = TAO_ORBInitInfo::_narrow (info
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ if (CORBA::is_nil (tao_info.in ()))
+ {
+ if (TAO_debug_level > 0)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) PortableGroup_ORBInitializer::pre_init:\n"
+ "(%P|%t) Unable to narrow "
+ "\"PortableInterceptor::ORBInitInfo_ptr\" to\n"
+ "(%P|%t) \"TAO_ORBInitInfo_ptr.\"\n"));
+
+ ACE_THROW (CORBA::INTERNAL ());
+ }
+
+ // Set a new request dispatcher in the ORB.
+ PortableGroup_Request_Dispatcher *rd = 0;
+ ACE_NEW_THROW_EX (rd,
+ PortableGroup_Request_Dispatcher (),
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK;
+
+ tao_info->orb_core ()->request_dispatcher (rd);
+
+ // If the application resolves the root POA, make sure we load the PG POA.
+ TAO_ORB_Core::set_poa_factory (pg_poa_factory_name,
+ pg_poa_factory_directive);
+}
+
+void
+TAO_PortableGroup_ORBInitializer::post_init (
+ PortableInterceptor::ORBInitInfo_ptr
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_ORBInitializer.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_ORBInitializer.h
new file mode 100644
index 00000000000..56f730edd59
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_ORBInitializer.h
@@ -0,0 +1,61 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PortableGroup_ORBInitializer.h
+ *
+ * $Id$
+ *
+ * @author Frank Hunleth <fhunleth@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_PORTABLEGROUP_ORB_INITIALIZER_H
+#define TAO_PORTABLEGROUP_ORB_INITIALIZER_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 "tao/PI/PI.h"
+#include "tao/LocalObject.h"
+
+// This is to remove "inherits via dominance" warnings from MSVC.
+// MSVC is being a little too paranoid.
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:4250)
+#endif /* _MSC_VER */
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// PortableGroup ORB initializer.
+class TAO_PortableGroup_Export TAO_PortableGroup_ORBInitializer :
+ public virtual PortableInterceptor::ORBInitializer,
+ public virtual TAO_Local_RefCounted_Object
+{
+public:
+ virtual void pre_init (PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual void post_init (PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif /* _MSC_VER */
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PORTABLEGROUP_ORB_INITIALIZER_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Request_Dispatcher.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Request_Dispatcher.cpp
new file mode 100644
index 00000000000..ae3fbe2d941
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Request_Dispatcher.cpp
@@ -0,0 +1,61 @@
+// $Id$
+
+#include "orbsvcs/PortableGroup/UIPMC_Profile.h"
+#include "orbsvcs/PortableGroup/PortableGroup_Request_Dispatcher.h"
+#include "orbsvcs/PortableGroup/PortableGroup_Loader.h"
+
+#include "tao/TAO_Server_Request.h"
+#include "tao/ORB_Core.h"
+
+ACE_RCSID (PortableGroup,
+ PortableGroup_Request_Dispatcher,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+PortableGroup_Request_Dispatcher::~PortableGroup_Request_Dispatcher (void)
+{
+}
+
+void
+PortableGroup_Request_Dispatcher::dispatch (TAO_ORB_Core *orb_core,
+ TAO_ServerRequest &request,
+ CORBA::Object_out forward_to
+ ACE_ENV_ARG_DECL)
+{
+ // Check if the request contains a tagged profile
+ if (request.profile ().discriminator () == GIOP::ProfileAddr)
+ {
+ // Get the IOP::Tagged profile.
+ const IOP::TaggedProfile &tagged_profile =
+ request.profile ().tagged_profile ();
+ PortableGroup::TagGroupTaggedComponent group;
+
+ // Extract a Group ID from the profile if it exists.
+ int result = TAO_UIPMC_Profile::extract_group_component (tagged_profile,
+ group);
+ if (result == 0)
+ {
+ // Got a group. Dispatch based on the group ID
+ this->group_map_.dispatch (&group,
+ orb_core,
+ request,
+ forward_to
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ return;
+ }
+
+ // Else, fall through and dispatch based on object key like normal.
+ }
+
+ // Dispatch based on object key.
+ orb_core->adapter_registry ()->dispatch (request.object_key (),
+ request,
+ forward_to
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Request_Dispatcher.h b/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Request_Dispatcher.h
new file mode 100644
index 00000000000..fb6ae13e934
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PortableGroup_Request_Dispatcher.h
@@ -0,0 +1,70 @@
+//-*- C++ -*-
+
+//=============================================================================
+/**
+ * @file PortableGroup_Request_Dispatcher.h
+ *
+ * $Id$
+ *
+ * A class that strategizes the request dispatching procedure.
+ *
+ * @author Frank Hunleth <fhunleth@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_PORTABLEGROUP_REQUEST_DISPATCHER_H
+#define TAO_PORTABLEGROUP_REQUEST_DISPATCHER_H
+
+#include /**/ "ace/pre.h"
+
+#include "tao/Request_Dispatcher.h"
+
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+#include "orbsvcs/PortableGroup/Portable_Group_Map.h"
+#include "orbsvcs/PortableGroup/PortableGroup_Acceptor_Registry.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declarations.
+class TAO_PortableGroup_Loader;
+
+/**
+ * @class PortableGroup_Request_Dispatcher
+ *
+ * @brief A class that strategizes the request dispatching procedure.
+ *
+ */
+class TAO_PortableGroup_Export PortableGroup_Request_Dispatcher
+ : public TAO_Request_Dispatcher
+{
+ friend class TAO_GOA;
+
+public:
+
+ /// Destructor.
+ virtual ~PortableGroup_Request_Dispatcher (void);
+
+ /**
+ * Dispatch a request.
+ */
+ virtual void dispatch (TAO_ORB_Core *orb_core,
+ TAO_ServerRequest &request,
+ CORBA::Object_out forward_to
+ ACE_ENV_ARG_DECL);
+
+private:
+
+ /// Hash map containing the GroupId->ObjectKey mappings.
+ TAO_Portable_Group_Map group_map_;
+
+ /// Registry for all of the group (multicast) acceptors.
+ TAO_PortableGroup_Acceptor_Registry acceptor_registry_;
+
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_PORTABLEGROUP_REQUEST_DISPATCHER_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/Portable_Group_Map.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/Portable_Group_Map.cpp
new file mode 100644
index 00000000000..73745a4460b
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/Portable_Group_Map.cpp
@@ -0,0 +1,180 @@
+// $Id$
+
+#include "orbsvcs/PortableGroup/Portable_Group_Map.h"
+#include "tao/ORB_Core.h"
+#include "tao/TAO_Server_Request.h"
+#include "tao/CDR.h"
+
+ACE_RCSID (PortableGroup,
+ Portable_Group_Map,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/// Constructor.
+TAO_Portable_Group_Map::TAO_Portable_Group_Map ()
+{
+}
+
+/// Destructor.
+TAO_Portable_Group_Map::~TAO_Portable_Group_Map (void)
+{
+ for (Iterator i = this->map_.begin ();
+ i != this->map_.end ();
+ ++i)
+ {
+ // Deallocate the id.
+ delete (*i).ext_id_;
+
+ // Delete the chain of Map_Entries.
+ Map_Entry *entry = (*i).int_id_;
+ while (entry)
+ {
+ Map_Entry *next = entry->next;
+ delete entry;
+ entry = next;
+ }
+
+ }
+
+ this->map_.close ();
+}
+
+
+void
+TAO_Portable_Group_Map::add_groupid_objectkey_pair (
+ PortableGroup::TagGroupTaggedComponent *group_id,
+ const TAO::ObjectKey &key
+ ACE_ENV_ARG_DECL
+ )
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX,
+ guard,
+ this->lock_);
+
+ Map_Entry *new_entry;
+
+ // We take ownership of the group_id memory. Be sure we don't
+ // forget about it.
+ PortableGroup::TagGroupTaggedComponent_var safe_group = group_id;
+
+ ACE_NEW_THROW_EX (new_entry,
+ Map_Entry (),
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK;
+
+ // Fill out the entry.
+ new_entry->key = key;
+
+ // First, check if the GroupId is already in the map.
+ Map_Entry *entry;
+ if (this->map_.find (group_id,
+ entry) == 0)
+ {
+ // Add the object key to the list of object keys serviced by this GroupId.
+ new_entry->next = entry->next;
+ entry->next = new_entry;
+ }
+ else
+ {
+ new_entry->next = 0;
+
+ // Add the
+ int result =
+ this->map_.bind (group_id,
+ new_entry);
+
+ if (result != 0)
+ {
+ delete new_entry;
+ ACE_THROW (CORBA::INTERNAL ());
+ }
+
+ // Transfer ownership of group_id to the map.
+ (void) safe_group._retn ();
+ }
+}
+
+void
+TAO_Portable_Group_Map::remove_groupid_objectkey_pair (const PortableGroup::TagGroupTaggedComponent* /*group_id*/,
+ const TAO::ObjectKey &/*key*/
+ ACE_ENV_ARG_DECL_NOT_USED)
+{
+
+}
+
+
+void
+TAO_Portable_Group_Map::dispatch (PortableGroup::TagGroupTaggedComponent* group_id,
+ TAO_ORB_Core *orb_core,
+ TAO_ServerRequest &request,
+ CORBA::Object_out forward_to
+ ACE_ENV_ARG_DECL)
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX,
+ guard,
+ this->lock_);
+
+ // Look up the GroupId.
+ Map_Entry *entry = 0;
+ if (this->map_.find (group_id,
+ entry) == 0)
+ {
+
+ // Save the read pointer in the message block since
+ // every time we dispatch the request, we need to
+ // reset it so that the request demarshals correctly.
+ TAO_InputCDR *tao_in = request.incoming ();
+ ACE_Message_Block *msgblk =
+ const_cast<ACE_Message_Block *> (tao_in->start ());
+ char *read_ptr = msgblk->rd_ptr ();
+
+ // Iterate through the list of ObjectKeys.
+ while (entry)
+ {
+ orb_core->adapter_registry ()->dispatch (entry->key,
+ request,
+ forward_to
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ // Reset the read pointer in the message block.
+ msgblk->rd_ptr (read_ptr);
+ entry = entry->next;
+ }
+ }
+}
+
+u_long
+TAO_GroupId_Hash::operator () (const PortableGroup::TagGroupTaggedComponent *id) const
+{
+ u_long hash =
+ ACE::hash_pjw ((const char *) id->group_domain_id,
+ ACE_OS::strlen ((const char *) id->group_domain_id));
+
+ // Truncate the object_group_id in half for the has.
+ // Divide by one so that the ACE_U_LongLong representation
+ // will automatically cast down to a u_long
+ hash += (u_long) (id->object_group_id / 1);
+
+ hash += id->object_group_ref_version;
+
+ return hash;
+}
+
+int
+TAO_GroupId_Equal_To::operator () (
+ const PortableGroup::TagGroupTaggedComponent *lhs,
+ const PortableGroup::TagGroupTaggedComponent *rhs) const
+{
+ return
+ ACE_OS::strcmp (lhs->group_domain_id, rhs->group_domain_id) == 0
+ && lhs->object_group_id == rhs->object_group_id
+ && lhs->object_group_ref_version == rhs->object_group_ref_version;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/Portable_Group_Map.h b/TAO/orbsvcs/orbsvcs/PortableGroup/Portable_Group_Map.h
new file mode 100644
index 00000000000..c6c69ae9e11
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/Portable_Group_Map.h
@@ -0,0 +1,139 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Portable_Group_Map.h
+ *
+ * $Id$
+ *
+ * @author Frank Hunleth <fhunleth@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef TAO_PORTABLE_GROUP_MAP_H
+#define TAO_PORTABLE_GROUP_MAP_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 "tao/Object_KeyC.h"
+
+#include "ace/Null_Mutex.h"
+#include "ace/Hash_Map_Manager_T.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class TAO_ServerRequest;
+
+/**
+ * @class TAO_GroupId_Hash
+ *
+ * @brief Hashing class for Group Ids.
+ *
+ * Define the hash() method for Group Ids.
+ */
+class TAO_PortableGroup_Export TAO_GroupId_Hash
+{
+public:
+
+ /// Returns hash value.
+ u_long operator () (const PortableGroup::TagGroupTaggedComponent *id) const;
+};
+
+/**
+ * @class TAO_GroupId_Equal_To
+ *
+ * @brief Hashing class for Group Ids.
+ *
+ * Define the Equal_To () method for Object Ids.
+ */
+class TAO_PortableGroup_Export TAO_GroupId_Equal_To
+{
+public:
+
+ /// Returns 1 if equal.
+ int operator () (const PortableGroup::TagGroupTaggedComponent *lhs,
+ const PortableGroup::TagGroupTaggedComponent *rhs) const;
+};
+
+/**
+ * @class TAO_Portable_Group_Map
+ *
+ * @brief Map of GroupIds to ObjectKeys.
+ */
+class TAO_PortableGroup_Export TAO_Portable_Group_Map
+{
+public:
+
+ /**
+ * @struct Map_Entry
+ *
+ * @brief Value field of the portable group map.
+ */
+ struct Map_Entry
+ {
+ /// The key.
+ TAO::ObjectKey key;
+
+ /// next ObjectKey in the group.
+ struct Map_Entry *next;
+ };
+
+ /// Constructor.
+ TAO_Portable_Group_Map ();
+
+ /// Destructor.
+ ~TAO_Portable_Group_Map (void);
+
+ /// Add a GroupId->ObjectKey mapping to the map.
+ /// This function takes ownership of the memory pointed to be group_id
+ void add_groupid_objectkey_pair (PortableGroup::TagGroupTaggedComponent *group_id,
+ const TAO::ObjectKey &key
+ ACE_ENV_ARG_DECL);
+
+
+ /// Remove a GroupId->ObjectKey mapping from the map.
+ void remove_groupid_objectkey_pair (const PortableGroup::TagGroupTaggedComponent* group_id,
+ const TAO::ObjectKey &key
+ ACE_ENV_ARG_DECL);
+
+ /// Dispatch a request to all of the ObjectIds that belong to
+ /// the specified group.
+ void dispatch (PortableGroup::TagGroupTaggedComponent* group_id,
+ TAO_ORB_Core *orb_core,
+ TAO_ServerRequest &request,
+ CORBA::Object_out forward_to
+ ACE_ENV_ARG_DECL);
+
+ /// Id hash map.
+ typedef ACE_Hash_Map_Manager_Ex<
+ PortableGroup::TagGroupTaggedComponent *,
+ Map_Entry *,
+ TAO_GroupId_Hash,
+ TAO_GroupId_Equal_To,
+ ACE_Null_Mutex> GroupId_Table;
+ typedef GroupId_Table::iterator Iterator;
+
+protected:
+ /// Lock used to synchronize access to map_.
+ TAO_SYNCH_MUTEX lock_;
+
+ /// Id map.
+ GroupId_Table map_;
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+//#if defined (__ACE_INLINE__)
+//# include "Portable_Group_Map.i"
+//#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* TAO_PORTABLE_GROUP_MAP_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/README b/TAO/orbsvcs/orbsvcs/PortableGroup/README
new file mode 100644
index 00000000000..7faf4cd6e46
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/README
@@ -0,0 +1,43 @@
+$Id$
+
+This directory contains an implementation of the MIOP specification
+for TAO. This currently includes:
+
+ . The UIPMC (Unreliable IP multicast) Pluggable Protocol
+ . The PortableGroup extensions to the POA
+ . Request dispatch hooks to TAO to dispatch based on GroupID
+
+For examples on how to use MIOP, see $TAO_ROOT/orbsvcs/tests/Miop.
+
+Compilation Note:
+
+The PortableGroup library requires the CosNaming library due to references
+to it in the IDL from the MIOP specification. It is not really used in
+actual implementation.
+
+Implementation Notes:
+
+The current MIOP implementation is usable, but not complete according
+to the final MIOP specification. The following are current limitations:
+
+ 1. MIOP packet reassembly. This limits requests to about 5-6K in length
+ depending on the platform. Miop packet segmentation is available,
+ but not completely tested.
+
+ 2. Disassociating a group reference from a servant is not implemented.
+ If interested in fixing this, be aware of the race conditions if a
+ servant disassociates during an upcall. The TAO event services all
+ have code to handle this issue.
+
+ 3. Clients must call _unchecked_narrow to narrow any group references
+ since a multicast group manager isn't supported yet (and UIPMC does
+ not support twoway invocations)
+
+ 4. TAO does not have a multicast group manager, so groups must be
+ assigned by creating a MIOP CORBALOC formatted reference. See
+ the tests or the MIOP specification for example group references.
+
+ 5. TAO does not have a multicast gateway implementation, so using MIOP
+ is currently limited to networks that natively support multicast
+
+
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.cpp
new file mode 100644
index 00000000000..1b3377b9f19
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.cpp
@@ -0,0 +1,354 @@
+// This may look like C, but it's really -*- C++ -*-
+//
+// $Id$
+
+#include "orbsvcs/PortableGroup/UIPMC_Profile.h"
+#include "orbsvcs/PortableGroup/UIPMC_Acceptor.h"
+
+#include "tao/MProfile.h"
+#include "tao/ORB_Core.h"
+#include "tao/debug.h"
+#include "tao/Protocols_Hooks.h"
+#include "tao/ORB_Constants.h"
+
+#include "ace/Auto_Ptr.h"
+#include "ace/os_include/os_netdb.h"
+
+#if !defined(__ACE_INLINE__)
+#include "orbsvcs/PortableGroup/UIPMC_Acceptor.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (PortableGroup,
+ UIPMC_Acceptor,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO_UIPMC_Acceptor::TAO_UIPMC_Acceptor (CORBA::Boolean /*flag*/)
+ : TAO_Acceptor (IOP::TAG_UIPMC),
+ addrs_ (0),
+ hosts_ (0),
+ endpoint_count_ (0),
+ version_ (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR),
+ orb_core_ (0),
+ connection_handler_ (0)
+{
+}
+
+TAO_UIPMC_Acceptor::~TAO_UIPMC_Acceptor (void)
+{
+ // Make sure we are closed before we start destroying the
+ // strategies.
+ this->close ();
+
+ delete [] this->addrs_;
+
+ for (size_t i = 0; i < this->endpoint_count_; ++i)
+ CORBA::string_free (this->hosts_[i]);
+
+ delete [] this->hosts_;
+}
+
+int
+TAO_UIPMC_Acceptor::create_profile (const TAO::ObjectKey &,
+ TAO_MProfile &,
+ CORBA::Short)
+{
+ // The standard mechanism for adding profiles to object references
+ // for each pluggable protocol doesn't apply to UIPMC profiles, so
+ // this function just returns success without doing anything. The
+ // appropiate mechanism for getting UIPMC profiles is to call the
+ // multicast group manager to get a Group reference. Invocations
+ // sent to this group reference will be dispatched to the servants
+ // that belong to that group.
+ return 0;
+}
+
+int
+TAO_UIPMC_Acceptor::is_collocated (const TAO_Endpoint *)
+{
+ // @@ Not clear how
+ // to best handle collation. For example, one servant could
+ // be collocated, but we still need to send the request out on
+ // the network to see if there are any other servants in the
+ // group.
+ return 0; // Not collocated
+}
+
+int
+TAO_UIPMC_Acceptor::close (void)
+{
+ return 0;
+}
+
+int
+TAO_UIPMC_Acceptor::open (TAO_ORB_Core *orb_core,
+ ACE_Reactor *reactor,
+ int major,
+ int minor,
+ const char *address,
+ const char *options)
+{
+ this->orb_core_ = orb_core;
+
+ if (this->hosts_ != 0)
+ {
+ // The hostname cache has already been set!
+ // This is bad mojo, i.e. an internal TAO error.
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("TAO (%P|%t) ")
+ ACE_TEXT ("UIPMC_Acceptor::open - ")
+ ACE_TEXT ("hostname already set\n\n")),
+ -1);
+ }
+
+ if (address == 0)
+ return -1;
+
+ if (major >=0 && minor >= 0)
+ this->version_.set_version (static_cast<CORBA::Octet> (major),
+ static_cast<CORBA::Octet> (minor));
+ // Parse options
+ if (this->parse_options (options) == -1)
+ return -1;
+
+ ACE_INET_Addr addr;
+
+ const char *port_separator_loc = ACE_OS::strchr (address, ':');
+ const char *specified_hostname = 0;
+ char tmp_host[MAXHOSTNAMELEN + 1];
+
+ // Both host and port have to be specified.
+ if (addr.set (address) != 0)
+ return -1;
+
+ // Extract out just the host part of the address.
+ size_t len = port_separator_loc - address;
+ ACE_OS::memcpy (tmp_host, address, len);
+ tmp_host[len] = '\0';
+
+ specified_hostname = tmp_host;
+
+ this->endpoint_count_ = 1; // Only one hostname to store
+
+ ACE_NEW_RETURN (this->addrs_,
+ ACE_INET_Addr[this->endpoint_count_],
+ -1);
+
+ ACE_NEW_RETURN (this->hosts_,
+ char *[this->endpoint_count_],
+ -1);
+
+ this->hosts_[0] = 0;
+
+ if (this->hostname (orb_core,
+ addr,
+ this->hosts_[0],
+ specified_hostname) != 0)
+ return -1;
+
+ // Copy the addr. The port is (re)set in
+ // TAO_UIPMC_Acceptor::open_i().
+ if (this->addrs_[0].set (addr) != 0)
+ return -1;
+
+ return this->open_i (addr,
+ reactor);
+}
+
+int
+TAO_UIPMC_Acceptor::open_default (TAO_ORB_Core *,
+ ACE_Reactor *,
+ int,
+ int,
+ const char *)
+{
+ // There is no such thing as a default multicast listen
+ // port. The mechanism for choosing these ports is done
+ // when creating the group ids. (I.e. not here).
+ return -1;
+}
+
+int
+TAO_UIPMC_Acceptor::open_i (const ACE_INET_Addr& addr,
+ ACE_Reactor *reactor)
+{
+ ACE_NEW_RETURN (this->connection_handler_,
+ TAO_UIPMC_Connection_Handler (this->orb_core_),
+ -1);
+
+ this->connection_handler_->local_addr (addr);
+ this->connection_handler_->open_server ();
+
+ int result =
+ reactor->register_handler (this->connection_handler_,
+ ACE_Event_Handler::READ_MASK);
+ if (result == -1)
+ return result;
+
+ // Connection handler ownership now belongs to the Reactor.
+ this->connection_handler_->remove_reference ();
+
+ // Set the port for each addr. If there is more than one network
+ // interface then the endpoint created on each interface will be on
+ // the same port. This is how a wildcard socket bind() is supposed
+ // to work.
+ u_short port = addr.get_port_number ();
+ for (size_t j = 0; j < this->endpoint_count_; ++j)
+ this->addrs_[j].set_port_number (port, 1);
+
+ if (TAO_debug_level > 5)
+ {
+ for (size_t i = 0; i < this->endpoint_count_; ++i)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\nTAO (%P|%t) UIPMC_Acceptor::open_i - ")
+ ACE_TEXT ("listening on: <%s:%u>\n"),
+ this->hosts_[i],
+ this->addrs_[i].get_port_number ()));
+ }
+ }
+
+ return 0;
+}
+
+int
+TAO_UIPMC_Acceptor::hostname (TAO_ORB_Core *,
+ ACE_INET_Addr &addr,
+ char *&host,
+ const char *)
+{
+ // Only have dotted decimal addresses for multicast.
+ return this->dotted_decimal_address (addr, host);
+}
+
+int
+TAO_UIPMC_Acceptor::dotted_decimal_address (ACE_INET_Addr &addr,
+ char *&host)
+{
+ const char *tmp = addr.get_host_addr ();
+ if (tmp == 0)
+ {
+ if (TAO_debug_level > 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\n\nTAO (%P|%t) ")
+ ACE_TEXT ("UIPMC_Acceptor::dotted_decimal_address ")
+ ACE_TEXT ("- %p\n\n"),
+ ACE_TEXT ("cannot determine hostname")));
+ return -1;
+ }
+
+ host = CORBA::string_dup (tmp);
+ return 0;
+}
+
+CORBA::ULong
+TAO_UIPMC_Acceptor::endpoint_count (void)
+{
+ return this->endpoint_count_;
+}
+
+int
+TAO_UIPMC_Acceptor::object_key (IOP::TaggedProfile &,
+ TAO::ObjectKey &)
+{
+ // No object key to extract. Just return success.
+ return 1;
+}
+
+
+int
+TAO_UIPMC_Acceptor::parse_options (const char *str)
+{
+ if (str == 0)
+ return 0; // No options to parse. Not a problem.
+
+ // Use an option format similar to the one used for CGI scripts in
+ // HTTP URLs.
+ // e.g.: option1=foo&option2=bar
+
+ ACE_CString options (str);
+
+ size_t len = options.length ();
+
+ const char option_delimiter = '&';
+
+ // Count the number of options.
+
+ CORBA::ULong option_count = 1;
+ // Number of endpoints in the string (initialized to 1).
+
+ // Only check for endpoints after the protocol specification and
+ // before the object key.
+ for (size_t i = 0; i < len; ++i)
+ if (options[i] == option_delimiter)
+ ++option_count;
+
+ // The idea behind the following loop is to split the options into
+ // (option, name) pairs.
+ // For example,
+ // `option1=foo&option2=bar'
+ // will be parsed into:
+ // `option1=foo'
+ // `option2=bar'
+
+ ACE_CString::size_type begin = 0;
+ ACE_CString::size_type end = 0;
+
+ for (CORBA::ULong j = 0; j < option_count; ++j)
+ {
+ if (j < option_count - 1)
+ end = options.find (option_delimiter, begin);
+ else
+ end = len;
+
+ if (end == begin)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("TAO (%P|%t) Zero length UIPMC option.\n")),
+ -1);
+ else if (end != ACE_CString::npos)
+ {
+ ACE_CString opt = options.substring (begin, end);
+
+ ACE_CString::size_type const slot = opt.find ("=");
+
+ if (slot == len - 1
+ || slot == ACE_CString::npos)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("TAO (%P|%t) UIPMC option <%s> is ")
+ ACE_TEXT ("missing a value.\n"),
+ opt.c_str ()),
+ -1);
+
+ ACE_CString name = opt.substring (0, slot);
+ ACE_CString value = opt.substring (slot + 1);
+
+ if (name.length () == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("TAO (%P|%t) Zero length UIPMC ")
+ ACE_TEXT ("option name.\n")),
+ -1);
+
+ if (name == "priority")
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("TAO (%P|%t) Invalid UIPMC endpoint format: ")
+ ACE_TEXT ("endpoint priorities no longer supported. \n"),
+ value.c_str ()),
+ -1);
+ }
+ else
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("TAO (%P|%t) Invalid UIPMC option: <%s>\n"),
+ name.c_str ()),
+ -1);
+
+ begin = end + 1;
+ }
+ else
+ break; // No other options.
+ }
+ return 0;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.h b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.h
new file mode 100644
index 00000000000..6c783e885c1
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.h
@@ -0,0 +1,160 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file UIPMC_Acceptor.h
+ *
+ * $Id$
+ *
+ * MIOP specific acceptor processing
+ *
+ * @author Frank Hunleth <fhunleth@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef TAO_UIPMC_ACCEPTOR_H
+#define TAO_UIPMC_ACCEPTOR_H
+
+#include /**/ "ace/pre.h"
+
+#include "orbsvcs/PortableGroup/UIPMC_Connection_Handler.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "tao/Transport_Acceptor.h"
+#include "tao/Acceptor_Impl.h"
+#include "tao/GIOP_Message_State.h"
+
+#include "ace/Acceptor.h"
+#include "ace/SOCK_Acceptor.h"
+
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// TAO UIPMC_Acceptor concrete call defination
+
+/**
+ * @class TAO_UIPMC_Acceptor
+ *
+ * @brief TAO_UIPMC_Acceptor
+ *
+ * The UIPMC-specific bridge class for the concrete acceptor.
+ */
+class TAO_PortableGroup_Export TAO_UIPMC_Acceptor : public TAO_Acceptor
+{
+public:
+ /// Constructor.
+ TAO_UIPMC_Acceptor (CORBA::Boolean flag = 0);
+
+ /// Destructor.
+ ~TAO_UIPMC_Acceptor (void);
+
+ /// @@ Helper method for the implementation repository, should go
+ /// away
+ const ACE_INET_Addr& address (void) const;
+
+ /// Returns the array of endpoints in this acceptor
+ const ACE_INET_Addr *endpoints (void);
+
+ /**
+ * The TAO_Acceptor methods, check the documentation in
+ * Pluggable.h for details.
+ */
+ virtual int open (TAO_ORB_Core *orb_core,
+ ACE_Reactor *reactor,
+ int version_major,
+ int version_minor,
+ const char *address,
+ const char *options = 0);
+ virtual int open_default (TAO_ORB_Core *orb_core,
+ ACE_Reactor *reactor,
+ int version_major,
+ int version_minor,
+ const char *options = 0);
+ virtual int close (void);
+ virtual int create_profile (const TAO::ObjectKey &object_key,
+ TAO_MProfile &mprofile,
+ CORBA::Short priority);
+ virtual int is_collocated (const TAO_Endpoint *endpoint);
+ virtual CORBA::ULong endpoint_count (void);
+
+ virtual int object_key (IOP::TaggedProfile &profile,
+ TAO::ObjectKey &key);
+
+ /**
+ * Set the host name for the given addr.
+ * A hostname may be forced by using specified_hostname. This
+ * is useful if the given address corresponds to more than one
+ * hostname and the desired one cannot be determined in any
+ * other way.
+ */
+ int hostname (TAO_ORB_Core *orb_core,
+ ACE_INET_Addr &addr,
+ char *&host,
+ const char *specified_hostname = 0);
+
+ /**
+ * Set the host name for the given address using the dotted decimal
+ * format.
+ */
+ int dotted_decimal_address (ACE_INET_Addr &addr,
+ char *&host);
+
+protected:
+
+ /**
+ * Implement the common part of the open*() methods. This method is
+ * virtual to allow a derived class implementation to be invoked
+ * instead.
+ */
+ virtual int open_i (const ACE_INET_Addr &addr,
+ ACE_Reactor *reactor);
+
+ /// Parse protocol specific options.
+ virtual int parse_options (const char *options);
+
+protected:
+
+ /// Array of ACE_INET_Addr instances, each one corresponding to a
+ /// given network interface.
+ ACE_INET_Addr *addrs_;
+
+ /**
+ * Cache the information about the endpoints serviced by this
+ * acceptor.
+ * There may in fact be multiple hostnames for this endpoint. For
+ * example, if the IP address is INADDR_ANY (0.0.0.0) then there
+ * will be possibly a different hostname for each interface.
+ */
+ char **hosts_;
+
+ /// The number of host names cached in the hosts_ array (equivalent
+ /// to the number of endpoints opened by this Acceptor).
+ CORBA::ULong endpoint_count_;
+
+ /**
+ * The GIOP version for this endpoint
+ * @@ Theoretically this shouldn't be here!! We need to look at a
+ * way to move this out
+ */
+ TAO_GIOP_Message_Version version_;
+
+ /// ORB Core.
+ TAO_ORB_Core *orb_core_;
+
+private:
+
+ TAO_UIPMC_Connection_Handler *connection_handler_;
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#if defined(__ACE_INLINE__)
+#include "orbsvcs/PortableGroup/UIPMC_Acceptor.i"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* TAO_UIPMC_ACCEPTOR_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.i b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.i
new file mode 100644
index 00000000000..ec296d0f9b6
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.i
@@ -0,0 +1,29 @@
+// -*- C++ -*-
+//
+// $Id$
+
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE const ACE_INET_Addr&
+TAO_UIPMC_Acceptor::address (void) const
+{
+ ACE_ASSERT (this->addrs_ != 0);
+
+ // @@ This is busted.
+ // The Implementation Repository will have to start supporting
+ // IORs with multiple profiles. For now, we just return the
+ // first addr.
+ // -Ossama
+ return this->addrs_[0];
+}
+
+ACE_INLINE const ACE_INET_Addr *
+TAO_UIPMC_Acceptor::endpoints (void)
+{
+ ACE_ASSERT (this->addrs_ != 0);
+
+ return this->addrs_;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.cpp
new file mode 100644
index 00000000000..df2fbd006c7
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.cpp
@@ -0,0 +1,267 @@
+// This may look like C, but it's really -*- C++ -*-
+//
+// $Id$
+
+
+#include "orbsvcs/PortableGroup/UIPMC_Connection_Handler.h"
+#include "orbsvcs/PortableGroup/UIPMC_Transport.h"
+#include "orbsvcs/PortableGroup/UIPMC_Endpoint.h"
+
+#include "tao/Timeprobe.h"
+#include "tao/debug.h"
+#include "tao/ORB_Core.h"
+#include "tao/ORB.h"
+#include "tao/CDR.h"
+#include "tao/Server_Strategy_Factory.h"
+#include "tao/Transport_Cache_Manager.h"
+#include "tao/Thread_Lane_Resources.h"
+#include "tao/Base_Transport_Property.h"
+#include "tao/Resume_Handle.h"
+
+
+ACE_RCSID(PortableGroup,
+ UIPMC_Connection_Handler,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO_UIPMC_Connection_Handler::TAO_UIPMC_Connection_Handler (ACE_Thread_Manager *t)
+ : TAO_UIPMC_SVC_HANDLER (t, 0 , 0),
+ TAO_Connection_Handler (0),
+ udp_socket_ (ACE_sap_any_cast (ACE_INET_Addr &)),
+ mcast_socket_ (),
+ using_mcast_ (0)
+{
+ // This constructor should *never* get called, it is just here to
+ // make the compiler happy: the default implementation of the
+ // Creation_Strategy requires a constructor with that signature, we
+ // don't use that implementation, but some (most?) compilers
+ // instantiate it anyway.
+ ACE_ASSERT (0);
+}
+
+
+TAO_UIPMC_Connection_Handler::TAO_UIPMC_Connection_Handler (TAO_ORB_Core *orb_core)
+ : TAO_UIPMC_SVC_HANDLER (orb_core->thr_mgr (), 0, 0),
+ TAO_Connection_Handler (orb_core),
+ udp_socket_ (ACE_sap_any_cast (ACE_INET_Addr &)),
+ mcast_socket_ (),
+ using_mcast_ (0)
+{
+ TAO_UIPMC_Transport* specific_transport = 0;
+ ACE_NEW(specific_transport,
+ TAO_UIPMC_Transport(this, orb_core, 0));
+
+ // store this pointer (indirectly increment ref count)
+ this->transport (specific_transport);
+}
+
+
+TAO_UIPMC_Connection_Handler::~TAO_UIPMC_Connection_Handler (void)
+{
+ if (this->using_mcast_)
+ {
+ // Closing a multicast socket automatically unsubscribes us from
+ // the multicast group.
+ this->mcast_socket_.close ();
+ }
+ else
+ this->udp_socket_.close ();
+
+ delete this->transport ();
+}
+
+ACE_HANDLE
+TAO_UIPMC_Connection_Handler::get_handle (void) const
+{
+ if (this->using_mcast_)
+ return this->mcast_socket_.get_handle ();
+ else
+ return this->udp_socket_.get_handle ();
+}
+
+const ACE_INET_Addr &
+TAO_UIPMC_Connection_Handler::addr (void)
+{
+ return this->addr_;
+}
+
+
+void
+TAO_UIPMC_Connection_Handler::addr (const ACE_INET_Addr &addr)
+{
+ this->addr_ = addr;
+}
+
+
+const ACE_INET_Addr &
+TAO_UIPMC_Connection_Handler::local_addr (void)
+{
+ return local_addr_;
+}
+
+
+void
+TAO_UIPMC_Connection_Handler::local_addr (const ACE_INET_Addr &addr)
+{
+ local_addr_ = addr;
+}
+
+
+const ACE_SOCK_Dgram &
+TAO_UIPMC_Connection_Handler::dgram (void)
+{
+ return this->udp_socket_;
+}
+
+const ACE_SOCK_Dgram_Mcast &
+TAO_UIPMC_Connection_Handler::mcast_dgram (void)
+{
+ return this->mcast_socket_;
+}
+
+
+int
+TAO_UIPMC_Connection_Handler::open_handler (void *v)
+{
+ return this->open (v);
+}
+
+int
+TAO_UIPMC_Connection_Handler::open (void*)
+{
+ this->udp_socket_.open (this->local_addr_);
+
+ if(TAO_debug_level > 5)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT("TAO (%P|%t) TAO_UIPMC_Connection_Handler::open, ")
+ ACE_TEXT("listening on: <%s:%u>\n"),
+ this->local_addr_.get_host_addr (),
+ this->local_addr_.get_port_number ()));
+ }
+
+ this->using_mcast_ = 0;
+
+ // Set that the transport is now connected, if fails we return -1
+ // Use C-style cast b/c otherwise we get warnings on lots of
+ // compilers
+ if (!this->transport ()->post_open ((size_t) this->udp_socket_.get_handle ()))
+ return -1;
+
+ return 0;
+}
+
+int
+TAO_UIPMC_Connection_Handler::open_server (void)
+{
+ this->mcast_socket_.join (this->local_addr_);
+ if( TAO_debug_level > 5)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT("TAO (%P|%t) TAO_UIPMC_Connection_Handler::open_server, ")
+ ACE_TEXT("subcribed to multicast group at %s:%d\n"),
+ this->local_addr_.get_host_addr (),
+ this->local_addr_.get_port_number ()
+ ));
+ }
+
+ this->transport ()->id ((size_t) this->mcast_socket_.get_handle ());
+ this->using_mcast_ = 1;
+
+ return 0;
+}
+
+int
+TAO_UIPMC_Connection_Handler::resume_handler (void)
+{
+ return ACE_Event_Handler::ACE_APPLICATION_RESUMES_HANDLER;
+}
+
+int
+TAO_UIPMC_Connection_Handler::close_connection (void)
+{
+ return this->close_connection_eh (this);
+}
+
+int
+TAO_UIPMC_Connection_Handler::handle_input (ACE_HANDLE h)
+{
+ return this->handle_input_eh (h, this);
+}
+
+int
+TAO_UIPMC_Connection_Handler::handle_output (ACE_HANDLE handle)
+{
+ int result =
+ this->handle_output_eh (handle, this);
+
+ if (result == -1)
+ {
+ this->close_connection ();
+ return 0;
+ }
+
+ return result;
+}
+
+int
+TAO_UIPMC_Connection_Handler::handle_timeout (const ACE_Time_Value &,
+ const void *)
+{
+ // We don't use this upcall for I/O. This is only used by the
+ // Connector to indicate that the connection timedout. Therefore,
+ // we should call close().
+ return this->close ();
+}
+
+int
+TAO_UIPMC_Connection_Handler::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ // No asserts here since the handler is registered with the Reactor
+ // and the handler ownership is given to the Reactor. When the
+ // Reactor closes, it will call handle_close() on the handler. It
+ // is however important to overwrite handle_close() to do nothing
+ // since the base class does too much.
+ return 0;
+}
+
+int
+TAO_UIPMC_Connection_Handler::close (u_long)
+{
+ this->state_changed (TAO_LF_Event::LFS_CONNECTION_CLOSED,
+ this->orb_core ()->leader_follower ());
+ this->transport ()->remove_reference ();
+ return 0;
+}
+
+int
+TAO_UIPMC_Connection_Handler::release_os_resources (void)
+{
+ return this->peer().close ();
+}
+
+int
+TAO_UIPMC_Connection_Handler::add_transport_to_cache (void)
+{
+ ACE_INET_Addr addr;
+
+ // This function is called by the acceptor to add this
+ // transport to the transport cache. This is really
+ // important for proper shutdown. The address used
+ // is irrelevent, since UIPMC is connectionless.
+
+ // Construct a UIPMC_Endpoint object.
+ TAO_UIPMC_Endpoint endpoint (addr);
+
+ // Construct a property object
+ TAO_Base_Transport_Property prop (&endpoint);
+
+ // Add the handler to Cache
+ return this->orb_core ()->lane_resources ()
+ .transport_cache ().cache_transport (&prop,
+ this->transport ());
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.h b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.h
new file mode 100644
index 00000000000..51153c2d196
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.h
@@ -0,0 +1,149 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file UIPMC_Connection_Handler.h
+ *
+ * $Id$
+ *
+ * @author Frank Hunleth <fhunleth@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef TAO_UIPMC_CONNECTION_HANDLER_H
+#define TAO_UIPMC_CONNECTION_HANDLER_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/PortableGroup/UIPMC_Transport.h"
+
+#include "tao/Wait_Strategy.h"
+#include "tao/Connection_Handler.h"
+
+#include "ace/Acceptor.h"
+#include "ace/Reactor.h"
+#include "ace/SOCK_Dgram_Mcast.h"
+#include "ace/SOCK_Dgram.h"
+
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward Decls
+class TAO_Pluggable_Messaging;
+
+// ****************************************************************
+
+/**
+ * @class TAO_UIPMC_Connection_Handler
+ *
+ * @brief Handles requests on a single connection.
+ *
+ * The Connection handler which is common for the Acceptor and
+ * the Connector
+ */
+class TAO_PortableGroup_Export TAO_UIPMC_Connection_Handler :
+ public TAO_UIPMC_SVC_HANDLER,
+ public TAO_Connection_Handler
+{
+
+public:
+
+ TAO_UIPMC_Connection_Handler (ACE_Thread_Manager* t = 0);
+
+ /// Constructor. <arg> parameter is used by the Acceptor to pass the
+ /// protocol configuration properties for this connection.
+ TAO_UIPMC_Connection_Handler (TAO_ORB_Core *orb_core);
+
+
+ /// Destructor.
+ ~TAO_UIPMC_Connection_Handler (void);
+
+ //@{
+ /** @name Connection Handler overloads
+ */
+ virtual int open_handler (void *v);
+ //@}
+
+ // @@ Frank: Similar to open, but called on server
+ virtual int open_server (void);
+
+ /// Close called by the Acceptor or Connector when connection
+ /// establishment fails.
+ int close (u_long = 0);
+
+ //@{
+ /** @name Event Handler overloads
+ */
+ virtual int resume_handler (void);
+ virtual int close_connection (void);
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_output (ACE_HANDLE);
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask);
+ virtual int handle_timeout (const ACE_Time_Value &current_time,
+ const void *act = 0);
+ virtual int open (void *);
+ //@}
+
+ /// Add ourselves to Cache.
+ int add_transport_to_cache (void);
+
+ // UIPMC Additions - Begin
+ ACE_HANDLE get_handle (void) const;
+
+ const ACE_INET_Addr &addr (void);
+
+ void addr (const ACE_INET_Addr &addr);
+
+ const ACE_INET_Addr &local_addr (void);
+
+ void local_addr (const ACE_INET_Addr &addr);
+
+ const ACE_INET_Addr &server_addr (void);
+
+ void server_addr (const ACE_INET_Addr &addr);
+
+ const ACE_SOCK_Dgram &dgram (void);
+
+ const ACE_SOCK_Dgram_Mcast &mcast_dgram (void);
+ // UIPMC Additions - End
+
+protected:
+
+ // UIPMC Additions - Begin
+
+ /// Client side UDP socket (send only).
+ ACE_SOCK_Dgram udp_socket_;
+
+ /// Server side Mcast UDP socket (receive only).
+ ACE_SOCK_Dgram_Mcast mcast_socket_;
+
+ /// Flag that specifies whether multicast is in use or not.
+ CORBA::Boolean using_mcast_;
+
+ // This is always the remote address
+ ACE_INET_Addr addr_;
+
+ // This is always the local address for the connector
+ ACE_INET_Addr local_addr_;
+
+ // UIPMC Additions - End
+
+ //@{
+ /**
+ * @name TAO_Connection Handler overloads
+ */
+ virtual int release_os_resources (void);
+ //@}
+
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* TAO_UIPMC_CONNECTION_HANDLER_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connector.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connector.cpp
new file mode 100644
index 00000000000..30f909e93e4
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connector.cpp
@@ -0,0 +1,215 @@
+// $Id$
+
+#include "orbsvcs/PortableGroup/UIPMC_Profile.h"
+#include "orbsvcs/PortableGroup/UIPMC_Connector.h"
+
+#include "tao/debug.h"
+#include "tao/ORB_Core.h"
+#include "tao/Environment.h"
+#include "tao/Base_Transport_Property.h"
+#include "tao/Protocols_Hooks.h"
+
+#include "ace/Connector.h"
+#include "ace/OS_NS_strings.h"
+
+ACE_RCSID (PortableGroup,
+ UIPMC_Connector, "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO_UIPMC_Connector::TAO_UIPMC_Connector (CORBA::Boolean)
+ : TAO_Connector (IOP::TAG_UIPMC)
+{
+}
+
+TAO_UIPMC_Connector::~TAO_UIPMC_Connector (void)
+{
+}
+
+int
+TAO_UIPMC_Connector::open (TAO_ORB_Core *orb_core)
+{
+ this->orb_core (orb_core);
+
+ // For the sake of uniformity do
+ if (this->create_connect_strategy () == -1)
+ return -1;
+
+ // @@ Michael: We do not use traditional connection management.
+
+ return 0;
+}
+
+int
+TAO_UIPMC_Connector::close (void)
+{
+ SvcHandlerIterator iter (svc_handler_table_);
+
+ while (!iter.done ())
+ {
+ (*iter).int_id_->remove_reference ();
+ iter++;
+ }
+
+ return 0;
+}
+
+int
+TAO_UIPMC_Connector::set_validate_endpoint (TAO_Endpoint *endpoint)
+{
+ if (endpoint->tag () != IOP::TAG_UIPMC)
+ return -1;
+
+ TAO_UIPMC_Endpoint *uipmc_endpoint =
+ dynamic_cast<TAO_UIPMC_Endpoint *> (endpoint );
+
+ if (uipmc_endpoint == 0)
+ return -1;
+
+ const ACE_INET_Addr &remote_address =
+ uipmc_endpoint->object_addr ();
+
+ // Verify that the remote ACE_INET_Addr was initialized properly.
+ // Failure can occur if hostname lookup failed when initializing the
+ // remote ACE_INET_Addr.
+ if (remote_address.get_type () != AF_INET)
+ {
+ if (TAO_debug_level > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TAO (%P|%t) UIPMC connection failed.\n")
+ ACE_TEXT ("TAO (%P|%t) This is most likely ")
+ ACE_TEXT ("due to a hostname lookup ")
+ ACE_TEXT ("failure.\n")));
+ }
+
+ return -1;
+ }
+
+ return 0;
+}
+
+TAO_Transport *
+TAO_UIPMC_Connector::make_connection (TAO::Profile_Transport_Resolver *,
+ TAO_Transport_Descriptor_Interface &desc,
+ ACE_Time_Value *)
+{
+ TAO_UIPMC_Endpoint *uipmc_endpoint =
+ dynamic_cast<TAO_UIPMC_Endpoint *> (desc.endpoint ());
+
+ if (uipmc_endpoint == 0)
+ return 0;
+
+ const ACE_INET_Addr &remote_address =
+ uipmc_endpoint->object_addr ();
+
+ TAO_UIPMC_Connection_Handler *svc_handler = 0;
+
+ if (this->svc_handler_table_.find (remote_address, svc_handler) == -1)
+ {
+ TAO_UIPMC_Connection_Handler *svc_handler_i = 0;
+ ACE_NEW_RETURN (svc_handler_i,
+ TAO_UIPMC_Connection_Handler (this->orb_core ()),
+ 0);
+
+ svc_handler_i->local_addr (ACE_sap_any_cast (ACE_INET_Addr &));
+ svc_handler_i->addr (remote_address);
+
+ svc_handler_i->open (0);
+
+ svc_handler_table_.bind (remote_address,
+ svc_handler_i);
+ svc_handler = svc_handler_i;
+
+ if (TAO_debug_level > 2)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) UIPMC_Connector::make_connection, ")
+ ACE_TEXT ("new connection on HANDLE %d\n"),
+ svc_handler->get_handle ()));
+ }
+
+ // @@ Michael: We do not use traditional connection management.
+ svc_handler->add_reference ();
+
+ return svc_handler->transport ();
+}
+
+
+TAO_Profile *
+TAO_UIPMC_Connector::create_profile (TAO_InputCDR& cdr)
+{
+ TAO_Profile *pfile;
+ ACE_NEW_RETURN (pfile,
+ TAO_UIPMC_Profile (this->orb_core ()),
+ 0);
+
+ int r = pfile->decode (cdr);
+ if (r == -1)
+ {
+ pfile->_decr_refcnt ();
+ pfile = 0;
+ }
+
+ return pfile;
+}
+
+TAO_Profile *
+TAO_UIPMC_Connector::make_profile (ACE_ENV_SINGLE_ARG_DECL)
+{
+ // The endpoint should be of the form:
+ // N.n@host:port/object_key
+ // or:
+ // host:port/object_key
+
+ TAO_Profile *profile = 0;
+ ACE_NEW_THROW_EX (profile,
+ TAO_UIPMC_Profile (this->orb_core ()),
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (0);
+
+ return profile;
+}
+
+int
+TAO_UIPMC_Connector::check_prefix (const char *endpoint)
+{
+ // Check for a valid string
+ if (!endpoint || !*endpoint)
+ return -1; // Failure
+
+ static const char protocol[] = "miop";
+ static size_t const len = sizeof (protocol) - 1;
+
+ size_t const slot = ACE_OS::strchr (endpoint, ':') - endpoint;
+
+ // Check for the proper prefix in the IOR. If the proper prefix
+ // isn't in the IOR then it is not an IOR we can use.
+ if (slot == len
+ && ACE_OS::strncasecmp (endpoint, protocol, len) == 0)
+ return 0;
+
+ return -1;
+ // Failure: not a MIOP IOR
+ // DO NOT throw an exception here.
+}
+
+char
+TAO_UIPMC_Connector::object_key_delimiter (void) const
+{
+ return TAO_UIPMC_Profile::object_key_delimiter_;
+}
+
+int
+TAO_UIPMC_Connector::cancel_svc_handler (
+ TAO_Connection_Handler * /* svc_handler */)
+{
+ // Noop
+ return 0;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connector.h b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connector.h
new file mode 100644
index 00000000000..43357053bd2
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connector.h
@@ -0,0 +1,99 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file UIPMC_Connector.h
+ *
+ * $Id$
+ *
+ * MIOP specific connector processing.
+ *
+ * @author Frank Hunleth <fhunleth@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef TAO_UIPMC_CONNECTOR_H
+#define TAO_UIPMC_CONNECTOR_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/PortableGroup/UIPMC_Connection_Handler.h"
+
+#include "tao/Transport_Connector.h"
+#include "ace/Null_Mutex.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// ****************************************************************
+
+/**
+ * @class TAO_UIPMC_Connector
+ *
+ * @brief UIPMC-specific Connector bridge for pluggable protocols.
+ *
+ * Concrete instance of the TAO_Connector class. Responsible
+ * for establishing a connection with a server and is called from the
+ * Connector_Registory.
+ */
+class TAO_PortableGroup_Export TAO_UIPMC_Connector : public TAO_Connector
+{
+public:
+ // = Initialization and termination methods.
+ /// Constructor.
+ TAO_UIPMC_Connector (CORBA::Boolean flag = 0);
+
+ /// Destructor.
+ ~TAO_UIPMC_Connector (void);
+
+ // = The TAO_Connector methods, please check the documentation on
+ // Transport_Connector.h
+ int open (TAO_ORB_Core *orb_core);
+ int close (void);
+ TAO_Profile *create_profile (TAO_InputCDR& cdr);
+
+ virtual int check_prefix (const char *endpoint);
+
+ virtual char object_key_delimiter (void) const;
+
+protected:
+ /// = More TAO_Connector methods, please check the documentation on
+ /// Transport_Connector.h
+ int set_validate_endpoint (TAO_Endpoint *endpoint);
+
+ TAO_Transport *make_connection (TAO::Profile_Transport_Resolver *r,
+ TAO_Transport_Descriptor_Interface &desc,
+ ACE_Time_Value *timeout = 0);
+
+ virtual TAO_Profile * make_profile (ACE_ENV_SINGLE_ARG_DECL);
+
+ /// Cancel the passed cvs handler from the connector
+ virtual int cancel_svc_handler (TAO_Connection_Handler * svc_handler);
+
+private:
+ // @@ Michael: UDP Addition
+ ACE_Hash_Map_Manager_Ex < ACE_INET_Addr,
+ TAO_UIPMC_Connection_Handler *,
+ ACE_Hash < ACE_INET_Addr >,
+ ACE_Equal_To < ACE_INET_Addr >,
+ ACE_Null_Mutex >
+ svc_handler_table_;
+
+ typedef ACE_Hash_Map_Iterator_Ex < ACE_INET_Addr,
+ TAO_UIPMC_Connection_Handler *,
+ ACE_Hash < ACE_INET_Addr >,
+ ACE_Equal_To < ACE_INET_Addr >,
+ ACE_Null_Mutex >
+ SvcHandlerIterator;
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_UIPMC_CONNECTOR_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Endpoint.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Endpoint.cpp
new file mode 100644
index 00000000000..056cfd741b6
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Endpoint.cpp
@@ -0,0 +1,150 @@
+// $Id$
+
+#include "orbsvcs/PortableGroup/UIPMC_Endpoint.h"
+#include "orbsvcs/PortableGroup/UIPMC_Profile.h"
+
+#include "tao/debug.h"
+#include "ace/Guard_T.h"
+#include "tao/ORB_Constants.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_Memory.h"
+
+ACE_RCSID (tao,
+ UIPMC_Endpoint,
+ "$Id$")
+
+
+#if !defined (__ACE_INLINE__)
+# include "orbsvcs/PortableGroup/UIPMC_Endpoint.i"
+#endif /* __ACE_INLINE__ */
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO_UIPMC_Endpoint::TAO_UIPMC_Endpoint (void)
+ : TAO_Endpoint (IOP::TAG_UIPMC),
+ object_addr_ (),
+ next_ (0)
+{
+}
+
+
+TAO_UIPMC_Endpoint::TAO_UIPMC_Endpoint (const ACE_INET_Addr &addr)
+ : TAO_Endpoint (IOP::TAG_UIPMC),
+ object_addr_ (addr),
+ next_ (0)
+{
+ this->object_addr (addr);
+}
+
+TAO_UIPMC_Endpoint::TAO_UIPMC_Endpoint (const CORBA::Octet class_d_address[4],
+ CORBA::UShort port)
+ : TAO_Endpoint (IOP::TAG_UIPMC),
+ port_ (port),
+ next_ (0)
+{
+ for (int i = 0; i<4; i++)
+ this->class_d_address_[i] = class_d_address[i];
+
+ this->update_object_addr ();
+}
+
+
+TAO_UIPMC_Endpoint::~TAO_UIPMC_Endpoint (void)
+{
+
+}
+
+void
+TAO_UIPMC_Endpoint::object_addr (const ACE_INET_Addr &addr)
+{
+ this->port_ = addr.get_port_number();
+ this->uint_ip_addr (addr.get_ip_address ());
+
+ this->object_addr_.set (addr);
+}
+
+const char *
+TAO_UIPMC_Endpoint::get_host_addr (void) const
+{
+ return this->object_addr_.get_host_addr ();
+}
+
+
+int
+TAO_UIPMC_Endpoint::addr_to_string (char *buffer, size_t length)
+{
+ size_t actual_len =
+ 15 // chars in dotted decimal addr
+ + sizeof (':') // delimiter
+ + 5 // max port
+ + sizeof ('\0');
+
+ if (length < actual_len)
+ return -1;
+
+ ACE_OS::sprintf (buffer, "%d.%d.%d.%d:%d",
+ this->class_d_address_[0],
+ this->class_d_address_[1],
+ this->class_d_address_[2],
+ this->class_d_address_[3],
+ this->port_);
+
+ return 0;
+}
+
+TAO_Endpoint *
+TAO_UIPMC_Endpoint::next (void)
+{
+ return this->next_;
+}
+
+TAO_Endpoint *
+TAO_UIPMC_Endpoint::duplicate (void)
+{
+ TAO_UIPMC_Endpoint *endpoint = 0;
+
+ ACE_NEW_RETURN (endpoint,
+ TAO_UIPMC_Endpoint (this->object_addr_),
+ 0);
+
+ return endpoint;
+}
+
+CORBA::Boolean
+TAO_UIPMC_Endpoint::is_equivalent (const TAO_Endpoint *other_endpoint)
+{
+ TAO_Endpoint *endpt = const_cast<TAO_Endpoint *> (other_endpoint);
+
+ TAO_UIPMC_Endpoint *endpoint = dynamic_cast<TAO_UIPMC_Endpoint *> (endpt);
+ if (endpoint == 0)
+ return 0;
+
+ return
+ this->port_ == endpoint->port_
+ && ACE_OS::memcmp (this->class_d_address_, endpoint->class_d_address_, 4) == 0;
+}
+
+CORBA::ULong
+TAO_UIPMC_Endpoint::hash (void)
+{
+ if (this->hash_val_ != 0)
+ return this->hash_val_;
+
+ {
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ guard,
+ this->addr_lookup_lock_,
+ this->hash_val_);
+ // .. DCL
+ if (this->hash_val_ != 0)
+ return this->hash_val_;
+
+ this->hash_val_ =
+ this->uint_ip_addr () + this->port_;
+ }
+
+ return this->hash_val_;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Endpoint.h b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Endpoint.h
new file mode 100644
index 00000000000..3c137d6c9ef
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Endpoint.h
@@ -0,0 +1,129 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file UIPMC_Endpoint.h
+ *
+ * $Id$
+ *
+ * UIPMC implementation of PP Framework Endpoint interface.
+ *
+ * @author Frank Hunleth <fhunleth@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef TAO_UIPMC_ENDPOINT_H
+#define TAO_UIPMC_ENDPOINT_H
+
+#include /**/ "ace/pre.h"
+
+#include "tao/Endpoint.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/INET_Addr.h"
+
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class TAO_UIPMC_Endpoint
+ *
+ * @brief TAO_UIPMC_Endpoint
+ *
+ * UIPMC-specific implementation of PP Framework Endpoint interface.
+ */
+class TAO_PortableGroup_Export TAO_UIPMC_Endpoint : public TAO_Endpoint
+{
+public:
+ // = Initialization and termination methods.
+
+ /// Default constructor.
+ TAO_UIPMC_Endpoint (void);
+
+ /// Constructor.
+ TAO_UIPMC_Endpoint (const ACE_INET_Addr &addr);
+
+ /// Constructor. @@ Frank - deprecate this.
+ TAO_UIPMC_Endpoint (const CORBA::Octet class_d_address[4],
+ CORBA::UShort port);
+
+ /// Destructor.
+ ~TAO_UIPMC_Endpoint (void);
+
+ // = Implementation of abstract TAO_Endpoint methods. See
+ // Endpoint.h for their documentation.
+
+ virtual TAO_Endpoint *next (void);
+ virtual int addr_to_string (char *buffer, size_t length);
+
+ /// Makes a copy of <this>
+ virtual TAO_Endpoint *duplicate (void);
+
+ /// Return true if this endpoint is equivalent to <other_endpoint>. Two
+ /// endpoints are equivalent iff their port and host are the same.
+ CORBA::Boolean is_equivalent (const TAO_Endpoint *other_endpoint);
+
+ /// Return a hash value for this object.
+ CORBA::ULong hash (void);
+
+ // Allocates memory and returns a copy of <this>
+
+ // = UIPMC_Endpoint-specific methods.
+
+ /// Return a reference to the <object_addr>.
+ const ACE_INET_Addr &object_addr (void) const;
+
+ /// Set the IP multicast address and port.
+ void object_addr (const ACE_INET_Addr &addr);
+
+ /// Return a pointer to the stringified host address (not including the
+ /// port). This class retains ownership of the address memory.
+ const char *get_host_addr (void) const;
+
+ /// Return the port number.
+ CORBA::UShort port (void) const;
+
+ /// Set the port number.
+ CORBA::UShort port (CORBA::UShort p); //@@ Frank - deprecate this.
+
+ //TAO_UIPMC_Connection_Handler *&hint (void);
+ // Access to our <hint_>.
+
+
+private:
+
+ /// Helper methods for getting and setting the IP address.
+ ACE_UINT32 uint_ip_addr (void) const;
+ void uint_ip_addr (ACE_UINT32 ip_addr);
+
+ /// Helper method to update the cached object address.
+ void update_object_addr (void);
+
+ /// IP Multicast address. @@ Frank - deprecate this.
+ CORBA::Octet class_d_address_[4];
+
+ /// UDP port number. @@ Frank - deprecate this.
+ CORBA::UShort port_;
+
+ /// Cached instance of <ACE_INET_Addr> for use in making
+ /// invocations, etc.
+ ACE_INET_Addr object_addr_;
+
+ /// UIPMC Endpoints can be stringed into a list. Return the next
+ /// endpoint in the list, if any.
+ TAO_UIPMC_Endpoint *next_;
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+# include "orbsvcs/PortableGroup/UIPMC_Endpoint.i"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_UIPMC_PROFILE_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Endpoint.i b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Endpoint.i
new file mode 100644
index 00000000000..7d91cc4d459
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Endpoint.i
@@ -0,0 +1,52 @@
+// -*- C++ -*-
+//
+// $Id$
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_INLINE const ACE_INET_Addr &
+TAO_UIPMC_Endpoint::object_addr (void) const
+{
+ return this->object_addr_;
+}
+
+
+ACE_INLINE CORBA::UShort
+TAO_UIPMC_Endpoint::port (void) const
+{
+ return this->port_;
+}
+
+ACE_INLINE CORBA::UShort
+TAO_UIPMC_Endpoint::port (CORBA::UShort p)
+{
+ return this->port_ = p;
+}
+
+
+ACE_INLINE ACE_UINT32
+TAO_UIPMC_Endpoint::uint_ip_addr (void) const
+{
+ return (((ACE_UINT32)this->class_d_address_[0] << 24) |
+ ((ACE_UINT32)this->class_d_address_[1] << 16) |
+ ((ACE_UINT32)this->class_d_address_[2] << 8) |
+ ((ACE_UINT32)this->class_d_address_[3]));
+}
+
+ACE_INLINE void
+TAO_UIPMC_Endpoint::uint_ip_addr (ACE_UINT32 ip_addr)
+{
+ this->class_d_address_[0] = (CORBA::Char)(ip_addr >> 24);
+ this->class_d_address_[1] = (CORBA::Char)((ip_addr >> 16) & 0xff);
+ this->class_d_address_[2] = (CORBA::Char)((ip_addr >> 8) & 0xff);
+ this->class_d_address_[3] = (CORBA::Char)(ip_addr & 0xff);
+}
+
+ACE_INLINE void
+TAO_UIPMC_Endpoint::update_object_addr (void)
+{
+ this->object_addr_.set (this->port_,
+ this->uint_ip_addr ());
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.cpp
new file mode 100644
index 00000000000..3a16a9f9793
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.cpp
@@ -0,0 +1,99 @@
+// $Id$
+
+#include "orbsvcs/PortableGroup/UIPMC_Factory.h"
+#include "orbsvcs/PortableGroup/UIPMC_Acceptor.h"
+#include "orbsvcs/PortableGroup/UIPMC_Connector.h"
+#include "ace/OS_NS_strings.h"
+#include "tao/ORB_Constants.h"
+
+ACE_RCSID (PortableGroup,
+ UIPMC_Factory,
+ "$Id$")
+
+static const char the_prefix[] = "uipmc";
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO_UIPMC_Protocol_Factory::TAO_UIPMC_Protocol_Factory (void)
+ : TAO_Protocol_Factory (IOP::TAG_UIPMC),
+ major_ (TAO_DEF_GIOP_MAJOR),
+ minor_ (TAO_DEF_GIOP_MINOR)
+{
+}
+
+TAO_UIPMC_Protocol_Factory::~TAO_UIPMC_Protocol_Factory (void)
+{
+}
+
+int
+TAO_UIPMC_Protocol_Factory::match_prefix (const ACE_CString &prefix)
+{
+ // Check for the proper prefix for this protocol.
+ return (ACE_OS::strcasecmp (prefix.c_str (), ::the_prefix) == 0);
+}
+
+const char *
+TAO_UIPMC_Protocol_Factory::prefix (void) const
+{
+ return ::the_prefix;
+}
+
+char
+TAO_UIPMC_Protocol_Factory::options_delimiter (void) const
+{
+ return '/';
+}
+
+TAO_Acceptor *
+TAO_UIPMC_Protocol_Factory::make_acceptor (void)
+{
+ TAO_Acceptor *acceptor = 0;
+
+ ACE_NEW_RETURN (acceptor,
+ TAO_UIPMC_Acceptor,
+ 0);
+
+ return acceptor;
+}
+
+int
+TAO_UIPMC_Protocol_Factory::init (int /* argc */,
+ char* /* argv */ [])
+{
+ return 0;
+}
+
+TAO_Connector *
+TAO_UIPMC_Protocol_Factory::make_connector (void)
+{
+ TAO_Connector *connector = 0;
+
+ ACE_NEW_RETURN (connector,
+ TAO_UIPMC_Connector,
+ 0);
+ return connector;
+}
+
+int
+TAO_UIPMC_Protocol_Factory::requires_explicit_endpoint (void) const
+{
+ // A multicast endpoint can't be picked automatically in the
+ // pluggable protocol framework. It must be determined from
+ // the UIPMC profile that has the group reference. This information
+ // is either specified by the user or generated by the
+ // multicast group manager or other UIPMC profile generation
+ // interface.
+ return 1;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+ACE_STATIC_SVC_DEFINE (TAO_UIPMC_Protocol_Factory,
+ ACE_TEXT ("UIPMC_Factory"),
+ ACE_SVC_OBJ_T,
+ &ACE_SVC_NAME (TAO_UIPMC_Protocol_Factory),
+ ACE_Service_Type::DELETE_THIS |
+ ACE_Service_Type::DELETE_OBJ,
+ 0)
+
+ACE_FACTORY_DEFINE (TAO_PortableGroup, TAO_UIPMC_Protocol_Factory)
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.h b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.h
new file mode 100644
index 00000000000..8b7ab75adf2
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.h
@@ -0,0 +1,72 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file UIPMC_Factory.h
+ *
+ * $Id$
+ *
+ * @author Frank Hunleth <fhunleth@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef TAO_UIPMC_FACTORY_H
+#define TAO_UIPMC_FACTORY_H
+
+#include /**/ "ace/pre.h"
+
+#include "tao/Protocol_Factory.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Config.h"
+
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class TAO_Acceptor;
+class TAO_Connector;
+
+class TAO_PortableGroup_Export TAO_UIPMC_Protocol_Factory : public TAO_Protocol_Factory
+{
+public:
+ TAO_UIPMC_Protocol_Factory (void);
+ virtual ~TAO_UIPMC_Protocol_Factory (void);
+
+ // = Service Configurator hooks.
+ /// Dynamic linking hook
+ virtual int init (int argc, char* argv[]);
+
+ /// Verify prefix is a match
+ virtual int match_prefix (const ACE_CString &prefix);
+
+ /// Returns the prefix used by the protocol.
+ virtual const char *prefix (void) const;
+
+ /// Return the character used to mark where an endpoint ends and
+ /// where its options begin.
+ virtual char options_delimiter (void) const;
+
+ // = Check Protocol_Factory.h for a description of these methods.
+ virtual TAO_Acceptor *make_acceptor (void);
+ virtual TAO_Connector *make_connector (void);
+ virtual int requires_explicit_endpoint (void) const;
+
+private:
+ /// Changing the version number can be used to provide backwards
+ /// compatibility with old clients.
+ int major_;
+ int minor_;
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+ACE_STATIC_SVC_DECLARE (TAO_UIPMC_Protocol_Factory)
+ACE_FACTORY_DECLARE (TAO_PortableGroup, TAO_UIPMC_Protocol_Factory)
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO_UIPMC_FACTORY_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Message_Block_Data_Iterator.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Message_Block_Data_Iterator.cpp
new file mode 100644
index 00000000000..4e3d4173fcf
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Message_Block_Data_Iterator.cpp
@@ -0,0 +1,89 @@
+// $Id$
+
+#include "orbsvcs/PortableGroup/UIPMC_Message_Block_Data_Iterator.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+UIPMC_Message_Block_Data_Iterator::UIPMC_Message_Block_Data_Iterator (iovec *iov, int iovcnt) :
+ iov_ (iov),
+ iovcnt_ (iovcnt),
+ iov_ptr_ (0),
+ iov_index_ (0),
+ iov_len_left_ (0),
+ state_ (INTER_BLOCK)
+{
+}
+
+size_t
+UIPMC_Message_Block_Data_Iterator::next_block (size_t max_length,
+ iovec &block)
+{
+ if (this->state_ == INTER_BLOCK)
+ {
+ // Check that there are some iovec buffers left.
+ if (this->iov_index_ >= this->iovcnt_)
+ return 0;
+
+
+ size_t current_iov_len =
+ this->iov_[this->iov_index_].iov_len;
+
+ if (current_iov_len <= max_length)
+ {
+ // Return the full data portion.
+ block.iov_len = static_cast<u_long> (current_iov_len);
+ block.iov_base = this->iov_[this->iov_index_].iov_base;
+
+ // Go to the next block.
+ this->iov_index_++;
+
+ return current_iov_len;
+ }
+ else
+ {
+ // Let the caller use the first part of this
+ // message block.
+ block.iov_len = static_cast<u_long> (max_length);
+ block.iov_base = this->iov_[this->iov_index_].iov_base;
+
+ // Break up the block.
+ this->iov_len_left_ = current_iov_len - max_length;
+ this->iov_ptr_ =
+ reinterpret_cast<char *> (reinterpret_cast<char *> (block.iov_base)
+ + max_length);
+ this->state_ = INTRA_BLOCK;
+
+ return max_length;
+ }
+ }
+ else
+ {
+ // Currently scanning a split block.
+ if (this->iov_len_left_ <= max_length)
+ {
+ // Return everything that's left in the block.
+ block.iov_len = static_cast<u_long> (this->iov_len_left_);
+ block.iov_base = this->iov_ptr_;
+
+ // Go to the next block.
+ this->iov_index_++;
+
+ // Update the state.
+ this->state_ = INTER_BLOCK;
+
+ return this->iov_len_left_;
+ }
+ else
+ {
+ // Split a little more off the block.
+ block.iov_len = static_cast<u_long> (this->iov_len_left_);
+ block.iov_base = this->iov_ptr_;
+
+ this->iov_len_left_ -= max_length;
+ this->iov_ptr_ += max_length;
+ return max_length;
+ }
+ }
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Message_Block_Data_Iterator.h b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Message_Block_Data_Iterator.h
new file mode 100644
index 00000000000..0378e1aac7c
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Message_Block_Data_Iterator.h
@@ -0,0 +1,70 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file UIPMC_Message_Block_Data_Iterator.h
+ *
+ * $Id$
+ *
+ * @author Frank Hunleth <frank@hunleth.com>
+ */
+//=============================================================================
+
+#ifndef TAO_UIPMC_MESSAGE_BLOCK_DATA_ITERATOR_H
+#define TAO_UIPMC_MESSAGE_BLOCK_DATA_ITERATOR_H
+#include /**/ "ace/pre.h"
+
+#include "ace/os_include/sys/os_uio.h"
+#include "ace/os_include/os_stddef.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "tao/Versioned_Namespace.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class UIPMC_Message_Block_Data_Iterator
+ *
+ * @brief This is a help class for iterating through ACE_Message_Blocks and to
+ * segment them into MIOP packets.
+ */
+class UIPMC_Message_Block_Data_Iterator
+{
+public:
+ /// Constructor
+ UIPMC_Message_Block_Data_Iterator (iovec *iov, int iovcnt);
+
+ /// Get the next data block that has a size less than or equal
+ /// to max_length. Return the length of the block returned.
+ size_t next_block (size_t max_length,
+ iovec &block);
+
+private:
+ enum State
+ {
+ INTER_BLOCK,
+ INTRA_BLOCK
+ };
+
+ iovec *iov_;
+ int iovcnt_;
+
+ // Point internal to a message block, if we have to split one up.
+ char *iov_ptr_;
+ int iov_index_;
+
+ // Length used in a split message block.
+ size_t iov_len_left_;
+
+ // Current message iterator state.
+ State state_;
+
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* TAO_UIPMC_MESSAGE_BLOCK_DATA_ITERATOR_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Profile.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Profile.cpp
new file mode 100644
index 00000000000..d242aef76a1
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Profile.cpp
@@ -0,0 +1,800 @@
+// $Id$
+
+#include "orbsvcs/PortableGroup/UIPMC_Profile.h"
+#include "orbsvcs/PortableGroup/miopconf.h"
+#include "tao/CDR.h"
+#include "tao/Environment.h"
+#include "tao/ORB.h"
+#include "tao/ORB_Core.h"
+#include "tao/debug.h"
+#include "tao/target_specification.h"
+#include "ace/os_include/os_ctype.h"
+
+#include "orbsvcs/miopC.h"
+#include "orbsvcs/PortableGroupC.h"
+
+ACE_RCSID (PortableGroup,
+ UIPMC_Profile,
+ "$Id$")
+
+static const char the_prefix[] = "uipmc";
+
+// UIPMC doesn't support object keys, so send profiles by default in the GIOP 1.2 target
+// specification.
+static const CORBA::Short default_addressing_mode_ = TAO_Target_Specification::Profile_Addr;
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+const char TAO_UIPMC_Profile::object_key_delimiter_ = '/';
+
+char
+TAO_UIPMC_Profile::object_key_delimiter (void) const
+{
+ return TAO_UIPMC_Profile::object_key_delimiter_;
+}
+
+
+TAO_UIPMC_Profile::TAO_UIPMC_Profile (TAO_ORB_Core *orb_core)
+ : TAO_Profile (IOP::TAG_UIPMC,
+ orb_core,
+ TAO_GIOP_Message_Version (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR)),
+ endpoint_ (),
+ count_ (1),
+ tagged_profile_ ()
+{
+ addressing_mode_ = default_addressing_mode_;
+}
+
+TAO_UIPMC_Profile::TAO_UIPMC_Profile (const ACE_INET_Addr &addr,
+ TAO_ORB_Core *orb_core)
+ : TAO_Profile (IOP::TAG_UIPMC,
+ orb_core,
+ TAO_GIOP_Message_Version (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR)),
+ endpoint_ (addr),
+ count_ (1),
+ tagged_profile_ ()
+{
+ addressing_mode_ = default_addressing_mode_;
+}
+
+TAO_UIPMC_Profile::TAO_UIPMC_Profile (const CORBA::Octet class_d_address[4],
+ CORBA::UShort port,
+ TAO_ORB_Core *orb_core)
+ : TAO_Profile (IOP::TAG_UIPMC,
+ orb_core,
+ TAO_GIOP_Message_Version (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR)),
+ endpoint_ (class_d_address, port),
+ count_ (1),
+ tagged_profile_ ()
+{
+ addressing_mode_ = default_addressing_mode_;
+}
+
+/*
+
+TAO_UIPMC_Profile::TAO_UIPMC_Profile (const char *string,
+ TAO_ORB_Core *orb_core
+ ACE_ENV_ARG_DECL)
+ : TAO_Profile (TAO_TAG_UIPMC_PROFILE,
+ orb_core,
+ TAO_GIOP_Message_Version (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR)),
+ endpoint_ (),
+ count_ (1),
+ tagged_profile_ ()
+{
+ this->add_group_component ();
+ this->parse_string (string ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ addressing_mode_ = default_addressing_mode_;
+}
+
+TAO_UIPMC_Profile::TAO_UIPMC_Profile (TAO_ORB_Core *orb_core)
+ : TAO_Profile (TAO_TAG_UIPMC_PROFILE,
+ orb_core,
+ TAO_GIOP_Message_Version (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR)),
+ endpoint_ (),
+ count_ (1),
+ tagged_profile_ ()
+{
+ addressing_mode_ = default_addressing_mode_;
+}
+*/
+
+TAO_UIPMC_Profile::~TAO_UIPMC_Profile (void)
+{
+}
+
+int
+TAO_UIPMC_Profile::decode (TAO_InputCDR& cdr)
+{
+ // The following is a selective reproduction of TAO_Profile::decode
+
+ CORBA::ULong encap_len = cdr.length ();
+
+ // Read and verify major, minor versions, ignoring profiles
+ // whose versions we don't understand.
+ if (!(cdr.read_octet (this->version_.major)
+ && this->version_.major == TAO_DEF_GIOP_MAJOR
+ && cdr.read_octet (this->version_.minor)
+ && this->version_.minor <= TAO_DEF_GIOP_MINOR))
+ {
+ if (TAO_debug_level > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TAO (%P|%t) - Profile::decode - v%d.%d\n"),
+ this->version_.major,
+ this->version_.minor));
+ }
+
+ return -1;
+ }
+
+ // Transport specific details
+ if (this->decode_profile (cdr) < 0)
+ {
+ return -1;
+ }
+
+ // UIPMC profiles must have tagged components.
+ if (this->tagged_components_.decode (cdr) == 0)
+ {
+ return -1;
+ }
+
+ if (cdr.length () != 0 && TAO_debug_level)
+ {
+ // If there is extra data in the profile we are supposed to
+ // ignore it, but print a warning just in case...
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%d bytes out of %d left after profile data\n"),
+ cdr.length (),
+ encap_len));
+ }
+
+ // We don't call ::decode_endpoints because it is implemented
+ // as ACE_NOTSUP_RETURN (-1) for this profile
+
+ return 1;
+}
+
+int
+TAO_UIPMC_Profile::decode_endpoints (void)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+TAO_UIPMC_Profile::decode_profile (TAO_InputCDR& cdr)
+{
+ CORBA::UShort port = 0;
+ ACE_CString address;
+ if (!(cdr.read_string (address)
+ && cdr.read_ushort (port)))
+ {
+ if (TAO_debug_level > 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TAO (%P|%t) UIPMC_Profile::decode - ")
+ ACE_TEXT ("Couldn't unmarshal address and port!\n")));
+ return -1;
+ }
+
+ if (cdr.good_bit ())
+ {
+ // If everything was successful, update the endpoint's address
+ // and port with the new data.
+ ACE_INET_Addr addr (port, address.c_str ());
+ this->endpoint_.object_addr (addr);
+ return 1;
+ }
+
+ return -1;
+}
+
+void
+TAO_UIPMC_Profile::parse_string (const char *string
+ ACE_ENV_ARG_DECL)
+{
+ this->parse_string_i (string
+ ACE_ENV_ARG_PARAMETER);
+}
+
+void
+TAO_UIPMC_Profile::parse_string_i (const char *string
+ ACE_ENV_ARG_DECL)
+{
+ // Remove the "N.n@" version prefix, if it exists, and verify the
+ // version is one that we accept.
+
+ // Check for MIOP version
+ if (isdigit (string [0]) &&
+ string[1] == '.' &&
+ isdigit (string [2]) &&
+ string[3] == '@')
+ {
+ if (string[0] != '1' ||
+ string[2] != '0')
+ {
+ ACE_THROW (CORBA::INV_OBJREF (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ EINVAL),
+ CORBA::COMPLETED_NO));
+ }
+
+ string += 4;
+ // Skip over the "N.n@"
+ }
+
+ // UIPMC profiles always use GIOP 1.2
+ this->version_.set_version (1, 2);
+
+ //
+ // Parse the group_id.
+ //
+
+ // Parse the group component version.
+ if (isdigit (string [0]) &&
+ string[1] == '.' &&
+ isdigit (string [2]) &&
+ string[3] == '-')
+ {
+ CORBA::Char major;
+ CORBA::Char minor;
+
+ major = (char) (string [0] - '0');
+ minor = (char) (string [2] - '0');
+
+ // Verify that a supported version of MIOP is specified.
+ if (major != TAO_DEF_MIOP_MAJOR ||
+ minor > TAO_DEF_MIOP_MINOR)
+ {
+ ACE_THROW (CORBA::INV_OBJREF (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ EINVAL),
+ CORBA::COMPLETED_NO));
+ }
+
+ // Skip over "N.n-"
+ string += 4;
+ }
+ else
+ {
+ // The group component version is mandatory.
+ ACE_THROW (CORBA::INV_OBJREF (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ EINVAL),
+ CORBA::COMPLETED_NO));
+ }
+
+ // Parse the group_domain_id.
+ // The Domain ID is terminated with a '-'.
+
+ // Wrap the string in a ACE_CString
+ ACE_CString ace_str (string, 0, 0);
+
+ // Look for the group domain delimitor.
+ ACE_CString::size_type pos = ace_str.find ('-');
+
+ if (pos == ACE_CString::npos)
+ {
+ // The group_domain_id is mandatory, so throw an
+ // exception if it isn't found.
+ ACE_THROW (CORBA::INV_OBJREF (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ EINVAL),
+ CORBA::COMPLETED_NO));
+ }
+
+ // Save the group_domain_id.
+ ACE_CString group_domain_id = ace_str.substring (0, pos);
+
+ // Parse the group_id.
+ // The group_id is terminated with a '-' or a '/'.
+
+ // Skip past the last '-'.
+ ++pos;
+ ACE_CString::size_type end_pos = ace_str.find ('-',pos);
+
+ CORBA::Boolean parse_group_ref_version_flag = 0;
+
+ if (end_pos != ACE_CString::npos)
+ {
+ // String was terminated by a '-', so there's a group
+ // reference version to be parsed.
+ parse_group_ref_version_flag = 1;
+ }
+ else
+ {
+ // Look for a slash as the separator.
+ end_pos = ace_str.find ('/', pos);
+
+ if (end_pos == ACE_CString::npos)
+ {
+ // The Group ID is mandatory, so throw an exception.
+ ACE_THROW (CORBA::INV_OBJREF (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ EINVAL),
+ CORBA::COMPLETED_NO));
+ }
+ }
+
+ // Get the domain_id.
+ ACE_CString str_domain_id = ace_str.substring (pos, end_pos - pos);
+
+ // Convert the domain_id into numerical form.
+ // @@ group_id is actually 64 bits, but strtoul only can parse 32 bits.
+ // @@ Need a 64 bit strtoul...
+ PortableGroup::ObjectGroupId group_id =
+ ACE_OS::strtoul (str_domain_id.c_str (), 0, 10);
+
+ PortableGroup::ObjectGroupRefVersion ref_version = 0;
+ if (parse_group_ref_version_flag)
+ {
+ // Try to find the group version. It is terminated by a '/'.
+ pos = end_pos + 1;
+ end_pos = ace_str.find ('/', pos);
+ if (end_pos == ACE_CString::npos)
+ {
+ // The group version was expected but not found,
+ // so throw an exception.
+ ACE_THROW (CORBA::INV_OBJREF (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ EINVAL),
+ CORBA::COMPLETED_NO));
+ }
+
+ ACE_CString str_group_ref_ver = ace_str.substring (pos, end_pos - pos);
+
+ ref_version =
+ ACE_OS::strtoul (str_group_ref_ver.c_str (), 0, 10);
+ }
+
+ // Parse the group multicast address.
+ // The multicast address is terminated by a ':'.
+ pos = end_pos + 1;
+ end_pos = ace_str.find (':', pos);
+
+ if (end_pos == ACE_CString::npos)
+ {
+ // The multicast address is mandatory, so throw an exception,
+ // since it wasn't found.
+ ACE_THROW (CORBA::INV_OBJREF (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ EINVAL),
+ CORBA::COMPLETED_NO));
+ }
+
+ ACE_CString mcast_addr = ace_str.substring (pos, end_pos - pos);
+
+ // Parse the multicast port number.
+
+ // First check that there's something left in the string.
+ pos = end_pos + 1;
+ if (ace_str[pos] == '\0')
+ {
+ // The multicast port is mandatory, so throw an exception,
+ // since it wasn't found.
+ ACE_THROW (CORBA::INV_OBJREF (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ EINVAL),
+ CORBA::COMPLETED_NO));
+ }
+
+ CORBA::UShort mcast_port =
+ static_cast<CORBA::UShort> (ACE_OS::strtoul (ace_str.c_str () + pos, 0, 10));
+
+ //
+ // Finally, set all of the fields of the profile.
+ //
+
+ ACE_INET_Addr addr (mcast_port, mcast_addr.c_str ());
+ this->endpoint_.object_addr (addr);
+
+ this->set_group_info (group_domain_id.c_str (),
+ group_id,
+ ref_version);
+
+}
+
+CORBA::Boolean
+TAO_UIPMC_Profile::do_is_equivalent (const TAO_Profile *other_profile)
+{
+ const TAO_UIPMC_Profile *op =
+ dynamic_cast<const TAO_UIPMC_Profile *> (other_profile);
+
+ if (op == 0)
+ return 0;
+
+ return this->endpoint_.is_equivalent (&op->endpoint_);
+}
+
+CORBA::ULong
+TAO_UIPMC_Profile::hash (CORBA::ULong max
+ ACE_ENV_ARG_DECL_NOT_USED)
+{
+ // Get the hashvalue for all endpoints.
+ CORBA::ULong hashval = this->endpoint_.hash ();
+
+ hashval += this->version_.minor;
+ hashval += this->tag ();
+
+ return hashval % max;
+}
+
+TAO_Endpoint*
+TAO_UIPMC_Profile::endpoint (void)
+{
+ return &this->endpoint_;
+}
+
+int
+TAO_UIPMC_Profile::encode_endpoints (void)
+{
+ return 1;
+}
+
+CORBA::ULong
+TAO_UIPMC_Profile::endpoint_count (void) const
+{
+ return 1;
+}
+
+char *
+TAO_UIPMC_Profile::to_string (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+{
+ // @@ Frank: Update to pull out GroupID information...
+
+ size_t buflen = (ACE_OS::strlen (::the_prefix) +
+ 3 /* "loc" */ +
+ 1 /* colon separator */ +
+ 2 /* double-slash separator */ +
+ 1 /* major version */ +
+ 1 /* decimal point */ +
+ 1 /* minor version */ +
+ 1 /* `@' character */ +
+ 15 /* dotted decimal IPv4 address */ +
+ 1 /* colon separator */ +
+ 5 /* port number */);
+
+ char * buf = CORBA::string_alloc (static_cast<CORBA::ULong> (buflen));
+
+ ACE_OS::sprintf (buf,
+ "corbaloc:%s://1.0@%s:%d",
+ ::the_prefix,
+ this->endpoint_.get_host_addr (),
+ this->endpoint_.port ());
+ return buf;
+}
+
+const char *
+TAO_UIPMC_Profile::prefix (void)
+{
+ return ::the_prefix;
+}
+
+IOP::TaggedProfile &
+TAO_UIPMC_Profile::create_tagged_profile (void)
+{
+ // Check whether we have already created the TaggedProfile
+ if (this->tagged_profile_.profile_data.length () == 0)
+ {
+ // As we have not created we will now create the TaggedProfile
+ this->tagged_profile_.tag = IOP::TAG_UIPMC;
+
+ // Create the encapsulation....
+ TAO_OutputCDR encap;
+
+ // Create the profile body
+ this->create_profile_body (encap);
+
+ CORBA::ULong length =
+ static_cast<CORBA::ULong> (encap.total_length ());
+
+#if (TAO_NO_COPY_OCTET_SEQUENCES == 1)
+ // Place the message block in to the Sequence of Octets that we
+ // have
+ this->tagged_profile_.profile_data.replace (length,
+ encap.begin ());
+#else
+ this->tagged_profile_.profile_data.length (length);
+ CORBA::Octet *buffer =
+ this->tagged_profile_.profile_data.get_buffer ();
+ for (const ACE_Message_Block *i = encap.begin ();
+ i != encap.end ();
+ i = i->next ())
+ {
+ ACE_OS::memcpy (buffer, i->rd_ptr (), i->length ());
+ buffer += i->length ();
+ }
+#endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */
+ }
+
+ return this->tagged_profile_;
+}
+
+void
+TAO_UIPMC_Profile::create_profile_body (TAO_OutputCDR &encap) const
+{
+ encap.write_octet (TAO_ENCAP_BYTE_ORDER);
+
+ // The GIOP version
+ // Note: Only GIOP 1.2 and above are supported currently for MIOP.
+ encap.write_octet (this->version_.major);
+ encap.write_octet (this->version_.minor);
+
+ // Address.
+ encap.write_string (this->endpoint_.get_host_addr ());
+
+ // Port number.
+ encap.write_ushort (this->endpoint_.port ());
+
+ // UIPMC is only supported by versions of GIOP that have tagged components,
+ // so unconditionally encode the components.
+ this->tagged_components ().encode (encap);
+}
+
+/*
+int
+TAO_UIPMC_Profile::decode_endpoints (void)
+{
+ IOP::TaggedComponent tagged_component;
+ tagged_component.tag = TAO_TAG_ENDPOINTS;
+
+ if (this->tagged_components_.get_component (tagged_component))
+ {
+ const CORBA::Octet *buf =
+ tagged_component.component_data.get_buffer ();
+
+ TAO_InputCDR in_cdr (reinterpret_cast<const char*> (buf),
+ tagged_component.component_data.length ());
+
+ // Extract the Byte Order.
+ CORBA::Boolean byte_order;
+ if ((in_cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
+ return -1;
+ in_cdr.reset_byte_order (static_cast<int> (byte_order));
+
+ // Extract endpoints sequence.
+ TAO_UIPMCEndpointSequence endpoints;
+
+ if ((in_cdr >> endpoints) == 0)
+ return -1;
+
+ // Get the priority of the first endpoint (head of the list.
+ // It's other data is extracted as part of the standard profile
+ // decoding.
+ this->endpoint_.priority (endpoints[0].priority);
+
+ // Use information extracted from the tagged component to
+ // populate the profile. Skip the first endpoint, since it is
+ // always extracted through standard profile body. Also, begin
+ // from the end of the sequence to preserve endpoint order,
+ // since <add_endpoint> method reverses the order of endpoints
+ // in the list.
+ for (CORBA::ULong i = endpoints.length () - 1;
+ i > 0;
+ --i)
+ {
+ TAO_UIPMC_Endpoint *endpoint = 0;
+ ACE_NEW_RETURN (endpoint,
+ TAO_UIPMC_Endpoint (endpoints[i].host,
+ endpoints[i].port,
+ endpoints[i].priority),
+ -1);
+
+ this->add_endpoint (endpoint);
+ }
+ }
+
+ return 0;
+}
+*/
+
+void
+TAO_UIPMC_Profile::set_group_info (const char *domain_id,
+ PortableGroup::ObjectGroupId group_id,
+ PortableGroup::ObjectGroupRefVersion ref_version)
+{
+ // First, record the group information.
+ this->group_domain_id_.set (domain_id);
+ this->group_id_ = group_id;
+ this->ref_version_ = ref_version;
+
+ // Update the cached version of the group component.
+ this->update_cached_group_component ();
+}
+
+void
+TAO_UIPMC_Profile::update_cached_group_component (void)
+{
+ PortableGroup::TagGroupTaggedComponent group;
+
+ // Encode the data structure.
+ group.component_version.major = TAO_DEF_MIOP_MAJOR;
+ group.component_version.minor = TAO_DEF_MIOP_MINOR;
+
+ group.group_domain_id = CORBA::string_dup (this->group_domain_id_.c_str ());
+ group.object_group_id = this->group_id_;
+ group.object_group_ref_version = this->ref_version_;
+
+ TAO_OutputCDR out_cdr;
+
+ // Write the byte order.
+ out_cdr << ACE_OutputCDR::from_boolean (ACE_CDR_BYTE_ORDER);
+
+ // Write the group information.
+ if ((out_cdr << group) == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Error marshaling group component!"));
+ return;
+ }
+
+ size_t length = out_cdr.total_length ();
+
+ IOP::TaggedComponent tagged_component;
+ tagged_component.tag = IOP::TAG_GROUP;
+ tagged_component.component_data.length (static_cast<CORBA::ULong> (length));
+ CORBA::Octet *buf =
+ tagged_component.component_data.get_buffer ();
+
+ for (const ACE_Message_Block *iterator = out_cdr.begin ();
+ iterator != 0;
+ iterator = iterator->cont ())
+ {
+ size_t i_length = iterator->length ();
+ ACE_OS::memcpy (buf, iterator->rd_ptr (), i_length);
+
+ buf += i_length;
+ }
+
+ // Add component with encoded endpoint data to this profile's
+ // TaggedComponents.
+ this->tagged_components_.set_component (tagged_component);
+}
+
+void
+TAO_UIPMC_Profile::request_target_specifier (
+ TAO_Target_Specification &target_spec,
+ TAO_Target_Specification::TAO_Target_Address required_type
+ ACE_ENV_ARG_DECL)
+{
+ // Fill out the target specifier based on the required type.
+ switch (required_type)
+ {
+ case TAO_Target_Specification::Profile_Addr:
+
+ // Only using a profile as the target specifier is supported
+ // at this time. Object keys are strictly not supported since
+ // UIPMC profiles do not have object keys.
+ target_spec.target_specifier (
+ this->create_tagged_profile ());
+ break;
+
+ case TAO_Target_Specification::Key_Addr:
+ case TAO_Target_Specification::Reference_Addr:
+ default:
+ // Unsupported or unknown required type. Throw an exception.
+ ACE_THROW (CORBA::MARSHAL ());
+ }
+}
+
+int
+TAO_UIPMC_Profile::supports_multicast (void) const
+{
+ // Yes! We support multicast!
+ return 1;
+}
+
+void
+TAO_UIPMC_Profile::addressing_mode (CORBA::Short addr_mode
+ ACE_ENV_ARG_DECL)
+{
+ // ** See race condition note about addressing mode in Profile.h **
+ switch (addr_mode)
+ {
+ case TAO_Target_Specification::Profile_Addr:
+ case TAO_Target_Specification::Reference_Addr:
+ this->addressing_mode_ = addr_mode;
+ break;
+
+ case TAO_Target_Specification::Key_Addr:
+ // There is no object key, so it is not supported.
+
+ default:
+ ACE_THROW (CORBA::BAD_PARAM (
+ CORBA::SystemException::_tao_minor_code (
+ TAO::VMCID,
+ EINVAL),
+ CORBA::COMPLETED_NO));
+ }
+}
+
+int
+TAO_UIPMC_Profile::extract_group_component (const IOP::TaggedProfile &profile,
+ PortableGroup::TagGroupTaggedComponent &group)
+{
+ // Create the decoding stream from the encapsulation in the buffer,
+//#if (TAO_NO_COPY_OCTET_SEQUENCES == 1)
+// TAO_InputCDR cdr (profile.profile_data.mb ());
+//#else
+ TAO_InputCDR cdr (reinterpret_cast<const char*> (profile.profile_data.get_buffer ()),
+ profile.profile_data.length ());
+//#endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */
+
+ // Extract the Byte Order.
+ CORBA::Boolean byte_order;
+ if ((cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
+ return -1;
+ cdr.reset_byte_order (static_cast<int> (byte_order));
+
+ // Read and verify major, minor versions, ignoring UIPMC profiles
+ // whose versions we don't understand.
+ CORBA::Octet major;
+ CORBA::Octet minor = CORBA::Octet();
+
+ // Read the version. We just read it here. We don't*do any*
+ // processing.
+ if (!(cdr.read_octet (major)
+ && cdr.read_octet (minor)))
+ {
+ if (TAO_debug_level > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TAO (%P|%t) UIPMC_Profile::extract_group_component - v%d.%d\n"),
+ major,
+ minor));
+ }
+ return -1;
+ }
+
+ // Decode the endpoint.
+ ACE_CString address;
+ CORBA::UShort port;
+
+ if (!(cdr.read_string (address)
+ && cdr.read_ushort (port)))
+ {
+ if (TAO_debug_level > 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TAO (%P|%t) UIPMC_Profile::extract_group_component - Couldn't unmarshal address and port!\n")));
+ return -1;
+ }
+
+ TAO_Tagged_Components tagged_components;
+ if (tagged_components.decode (cdr) == 0)
+ return -1;
+
+ IOP::TaggedComponent tagged_component;
+ tagged_component.tag = IOP::TAG_GROUP;
+
+ // Try to find it.
+ if (tagged_components.get_component (tagged_component) == 0)
+ return -1;
+
+ // Found it.
+ const CORBA::Octet *buf =
+ tagged_component.component_data.get_buffer ();
+
+ TAO_InputCDR in_cdr (reinterpret_cast<const char*> (buf),
+ tagged_component.component_data.length ());
+
+ // Extract the Byte Order.
+ if ((in_cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
+ return -1;
+ in_cdr.reset_byte_order (static_cast<int> (byte_order));
+
+ if ((in_cdr >> group) == 0)
+ return -1;
+
+ return 0;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Profile.h b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Profile.h
new file mode 100644
index 00000000000..a6f8846eeb5
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Profile.h
@@ -0,0 +1,165 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file UIPMC_Profile.h
+ *
+ * $Id$
+ *
+ * UIPMC profile specific processing
+ *
+ * @author Frank Hunleth <fhunleth@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef TAO_UIPMC_PROFILE_H
+#define TAO_UIPMC_PROFILE_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/PortableGroup/UIPMC_Endpoint.h"
+
+#include "orbsvcs/PortableGroupC.h"
+
+#include "tao/Object_KeyC.h"
+#include "tao/target_specification.h"
+#include "tao/Profile.h"
+
+#include "ace/SString.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// TAO UIPMC_Profile concrete Profile definitions
+/**
+ * @class TAO_UIPMC_Profile
+ *
+ * @brief This class defines the protocol specific attributes required
+ * for locating ORBs over a TCP/IP network.
+ *
+ * This class defines the UIPMC profile as specified in the CORBA
+ * specification.
+ *
+ * @NOTE: This class inherits the ObjectKey from TAO_Profile which may
+ * not be needed at all! But lets punt on this for the timebeing.
+ */
+class TAO_PortableGroup_Export TAO_UIPMC_Profile : public TAO_Profile
+{
+public:
+ /// The object key delimiter that UIPMC uses or expects.
+ static const char object_key_delimiter_;
+ virtual char object_key_delimiter (void) const;
+
+ /// Return the char string prefix.
+ static const char *prefix (void);
+
+ /// Profile constructor, default. Used when the profile contents
+ /// are not yet known or when it is being decoded from an IOR.
+ TAO_UIPMC_Profile (TAO_ORB_Core *orb_core);
+
+ /// Profile constructor, same as above except the object_key has
+ /// already been marshaled.
+ TAO_UIPMC_Profile (const ACE_INET_Addr &addr,
+ TAO_ORB_Core *orb_core);
+
+ /// Profile constructor.
+ TAO_UIPMC_Profile (const CORBA::Octet class_d_address[4],
+ CORBA::UShort port,
+ TAO_ORB_Core *orb_core);
+
+ /// Create object using a string ior.
+ TAO_UIPMC_Profile (const char *string,
+ TAO_ORB_Core *orb_core
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS);
+
+ /// Destructor is to be called only through <_decr_refcnt>.
+ ~TAO_UIPMC_Profile (void);
+
+ /// Template methods. Please see tao/Profile.h for documentation.
+
+ /// N.B. We have to override the TAO_Profile default decode because
+ /// in UIPMC there is no object key marshalled and we do not implement
+ /// a useable ::decode_endpoints
+ virtual int decode (TAO_InputCDR& cdr);
+ virtual void parse_string (const char *string
+ ACE_ENV_ARG_DECL);
+ virtual char * to_string (ACE_ENV_SINGLE_ARG_DECL);
+ virtual int encode_endpoints (void);
+ virtual TAO_Endpoint *endpoint (void);
+ virtual CORBA::ULong endpoint_count (void) const;
+ virtual CORBA::ULong hash (CORBA::ULong max
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS);
+ virtual IOP::TaggedProfile &create_tagged_profile (void);
+ virtual void request_target_specifier (
+ TAO_Target_Specification &target_spec,
+ TAO_Target_Specification::TAO_Target_Address r
+ ACE_ENV_ARG_DECL);
+ virtual int supports_multicast (void) const;
+ virtual void addressing_mode (CORBA::Short addr_mode
+ ACE_ENV_ARG_DECL);
+ static int extract_group_component (const IOP::TaggedProfile &profile,
+ PortableGroup::TagGroupTaggedComponent &group);
+
+ /// Add the mandatory group component to this profile.
+ void set_group_info (const char *domain_id,
+ PortableGroup::ObjectGroupId group_id,
+ PortableGroup::ObjectGroupRefVersion ref_version);
+
+
+protected:
+ /// Template methods, please see documentation in tao/Profile.h
+ virtual int decode_profile (TAO_InputCDR& cdr);
+ virtual int decode_endpoints (void);
+ virtual void parse_string_i (const char *
+ ACE_ENV_ARG_DECL);
+ virtual void create_profile_body (TAO_OutputCDR &cdr) const;
+ virtual CORBA::Boolean do_is_equivalent (const TAO_Profile *other_profile);
+ virtual void update_cached_group_component (void);
+
+protected:
+
+ /**
+ * Head of this profile's list of endpoints. This endpoint is not
+ * dynamically allocated because a profile always contains at least
+ * one endpoint.
+ *
+ * Currently, a profile contains more than one endpoint, i.e.,
+ * list contains more than just the head, only when RTCORBA is enabled.
+ * However, in the near future, this will be used in nonRT
+ * mode as well, e.g., to support TAG_ALTERNATE_IIOP_ADDRESS
+ * feature.
+ * Addressing info of the default endpoint, i.e., head of the list,
+ * is transmitted using standard UIPMC ProfileBody components. See
+ * <encode_endpoints> method documentation above for how the rest of
+ * the endpoint list is transmitted.
+ */
+ TAO_UIPMC_Endpoint endpoint_;
+
+ /// Number of endpoints in the list headed by <endpoint_>.
+ CORBA::ULong count_;
+
+private:
+
+ /// Cached version of our tagged profile.
+ IOP::TaggedProfile tagged_profile_;
+
+ /// Group Domain ID.
+ ACE_CString group_domain_id_;
+
+ /// Our group ID within the group domain.
+ PortableGroup::ObjectGroupId group_id_;
+
+ /// The group reference's version.
+ PortableGroup::ObjectGroupRefVersion ref_version_;
+
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* TAO_UIPMC_PROFILE_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.cpp
new file mode 100644
index 00000000000..32c3b149dcb
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.cpp
@@ -0,0 +1,613 @@
+// $Id$
+
+#include "orbsvcs/PortableGroup/UIPMC_Profile.h"
+#include "orbsvcs/PortableGroup/UIPMC_Transport.h"
+#include "orbsvcs/PortableGroup/UIPMC_Connection_Handler.h"
+#include "orbsvcs/PortableGroup/UIPMC_Message_Block_Data_Iterator.h"
+#include "orbsvcs/PortableGroup/UIPMC_Acceptor.h"
+#include "orbsvcs/PortableGroup/UIPMC_Wait_Never.h"
+
+#include "tao/Acceptor_Registry.h"
+#include "tao/operation_details.h"
+#include "tao/Timeprobe.h"
+#include "tao/CDR.h"
+#include "tao/Transport_Mux_Strategy.h"
+#include "tao/Wait_Strategy.h"
+#include "tao/Stub.h"
+#include "tao/ORB_Core.h"
+#include "tao/debug.h"
+#include "tao/Resume_Handle.h"
+#include "tao/GIOP_Message_Base.h"
+#include "tao/GIOP_Message_Lite.h"
+
+ACE_RCSID (PortableGroup,
+ UIPMC_Transport,
+ "$Id$")
+
+
+// Local MIOP Definitions:
+
+// Note: We currently support packet fragmentation on transmit, but
+// do not support reassembly.
+
+// Limit the number of fragments that we can divide a message
+// into.
+#define MIOP_MAX_FRAGMENTS (1)
+#define MIOP_MAX_HEADER_SIZE (272) // See MIOP Spec. Must be a multiple of 8.
+#define MIOP_MAX_DGRAM_SIZE (ACE_MAX_DGRAM_SIZE)
+
+#define MIOP_MAGIC_OFFSET (0)
+#define MIOP_VERSION_OFFSET (4)
+#define MIOP_FLAGS_OFFSET (5)
+#define MIOP_PACKET_LENGTH_OFFSET (6)
+#define MIOP_PACKET_NUMBER_OFFSET (8)
+#define MIOP_NUMBER_OF_PACKETS_OFFSET (12)
+#define MIOP_ID_LENGTH_OFFSET (16)
+#define MIOP_MIN_LENGTH_ID (0)
+#define MIOP_MAX_LENGTH_ID (252)
+#define MIOP_ID_DEFAULT_LENGTH (12)
+#define MIOP_ID_CONTENT_OFFSET (20)
+#define MIOP_HEADER_PADDING (0) // The ID field needs to be padded to
+ // a multiple of 8 bytes.
+#define MIOP_HEADER_SIZE (MIOP_ID_CONTENT_OFFSET \
+ + MIOP_ID_DEFAULT_LENGTH \
+ + MIOP_HEADER_PADDING)
+#define MIOP_MIN_HEADER_SIZE (MIOP_ID_CONTENT_OFFSET \
+ + MIOP_MIN_LENGTH_ID \
+ + (8 - MIOP_MIN_LENGTH_ID) /* padding */)
+
+static const CORBA::Octet miop_magic[4] = { 0x4d, 0x49, 0x4f, 0x50 }; // 'M', 'I', 'O', 'P'
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+struct MIOP_Packet
+{
+ iovec iov[ACE_IOV_MAX];
+ int iovcnt;
+ int length;
+};
+
+
+TAO_UIPMC_Transport::TAO_UIPMC_Transport (TAO_UIPMC_Connection_Handler *handler,
+ TAO_ORB_Core *orb_core,
+ CORBA::Boolean /*flag*/)
+ : TAO_Transport (IOP::TAG_UIPMC,
+ orb_core)
+ , connection_handler_ (handler)
+ , messaging_object_ (0)
+{
+ // Use the normal GIOP object
+ ACE_NEW (this->messaging_object_,
+ TAO_GIOP_Message_Base (orb_core,
+ this,
+ MIOP_MAX_DGRAM_SIZE));
+
+ // Replace the default wait strategy with our own
+ // since we don't support waiting on anything.
+ delete this->ws_;
+ ACE_NEW (this->ws_,
+ TAO_UIPMC_Wait_Never (this));
+}
+
+TAO_UIPMC_Transport::~TAO_UIPMC_Transport (void)
+{
+ delete this->messaging_object_;
+}
+
+ACE_Event_Handler *
+TAO_UIPMC_Transport::event_handler_i (void)
+{
+ return this->connection_handler_;
+}
+
+TAO_Connection_Handler *
+TAO_UIPMC_Transport::connection_handler_i (void)
+{
+ return this->connection_handler_;
+}
+
+TAO_Pluggable_Messaging *
+TAO_UIPMC_Transport::messaging_object (void)
+{
+ return this->messaging_object_;
+}
+
+
+void
+TAO_UIPMC_Transport::write_unique_id (TAO_OutputCDR &miop_hdr, unsigned long unique)
+{
+ // We currently construct a unique ID for each MIOP message by
+ // concatenating the address of the buffer to a counter. We may
+ // also need to use a MAC address or something more unique to
+ // fully comply with the MIOP specification.
+
+ static unsigned long counter = 1; // Don't worry about race conditions on counter,
+ // since buffer addresses can't be the same if
+ // this is being called simultaneously.
+
+ CORBA::Octet unique_id[MIOP_ID_DEFAULT_LENGTH];
+
+ unique_id[0] = static_cast<CORBA::Octet> (unique & 0xff);
+ unique_id[1] = static_cast<CORBA::Octet> ((unique & 0xff00) >> 8);
+ unique_id[2] = static_cast<CORBA::Octet> ((unique & 0xff0000) >> 16);
+ unique_id[3] = static_cast<CORBA::Octet> ((unique & 0xff000000) >> 24);
+
+ unique_id[4] = static_cast<CORBA::Octet> (counter & 0xff);
+ unique_id[5] = static_cast<CORBA::Octet> ((counter & 0xff00) >> 8);
+ unique_id[6] = static_cast<CORBA::Octet> ((counter & 0xff0000) >> 16);
+ unique_id[7] = static_cast<CORBA::Octet> ((counter & 0xff000000) >> 24);
+
+ unique_id[8] = 0;
+ unique_id[9] = 0;
+ unique_id[10] = 0;
+ unique_id[11] = 0;
+
+ miop_hdr.write_ulong (MIOP_ID_DEFAULT_LENGTH);
+ miop_hdr.write_octet_array (unique_id, MIOP_ID_DEFAULT_LENGTH);
+}
+
+ssize_t
+TAO_UIPMC_Transport::send (iovec *iov, int iovcnt,
+ size_t &bytes_transferred,
+ const ACE_Time_Value *)
+{
+ const ACE_INET_Addr &addr = this->connection_handler_->addr ();
+ bytes_transferred = 0;
+
+ // Calculate the bytes to send. This value is only used for
+ // error conditions to fake a good return. We do this for
+ // semantic consistency with DIOP, and since errors aren't
+ // handled correctly from send_i (our fault). If these
+ // semantics are not desirable, the error handling problems
+ // that need to be fixed can be found in
+ // UIPMC_Connection_Handler::decr_refcount which will need to
+ // deregister the connection handler from the UIPMC_Connector
+ // cache.
+ ssize_t bytes_to_send = 0;
+ for (int i = 0; i < iovcnt; i++)
+ bytes_to_send += iov[i].iov_len;
+
+ MIOP_Packet fragments[MIOP_MAX_FRAGMENTS];
+ MIOP_Packet *current_fragment;
+ int num_fragments = 1;
+
+ UIPMC_Message_Block_Data_Iterator mb_iter (iov, iovcnt);
+
+ // Initialize the first fragment
+ current_fragment = &fragments[0];
+ current_fragment->iovcnt = 1; // The MIOP Header
+ current_fragment->length = MIOP_HEADER_SIZE;
+
+ // Go through all of the message blocks.
+ while (mb_iter.next_block (MIOP_MAX_DGRAM_SIZE - current_fragment->length,
+ current_fragment->iov[current_fragment->iovcnt]))
+ {
+ // Increment the length and iovcnt.
+ current_fragment->length += current_fragment->iov[current_fragment->iovcnt].iov_len;
+ current_fragment->iovcnt++;
+
+ // Check if we've filled up this fragment or if we've run out of
+ // iov entries.
+ if (current_fragment->length == MIOP_MAX_DGRAM_SIZE ||
+ current_fragment->iovcnt == ACE_IOV_MAX)
+ {
+ // Make a new fragment.
+ num_fragments++;
+
+ // Check if too many fragments
+ if (num_fragments > MIOP_MAX_FRAGMENTS)
+ {
+ // This is an error as we do not send more.
+ // Silently drop the message but log an error.
+
+ // Pluggable_Messaging::transport_message only
+ // cares if it gets -1 or 0 so we can return a
+ // partial length and it will think all has gone
+ // well.
+ if (TAO_debug_level > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\n\nTAO (%P|%t) ")
+ ACE_TEXT ("UIPMC_Transport::send_i ")
+ ACE_TEXT ("Message of size %d needs too many MIOP fragments (max is %d).\n")
+ ACE_TEXT ("You may be able to increase ACE_MAX_DGRAM_SIZE.\n"),
+ bytes_to_send,
+ MIOP_MAX_FRAGMENTS));
+ }
+
+ // Pretend it is o.k. See note by bytes_to_send calculation.
+ bytes_transferred = bytes_to_send;
+ return 1;
+ }
+
+ // Otherwise, initialize another fragment.
+ current_fragment++;
+ current_fragment->iovcnt = 1; // The MIOP Header
+ current_fragment->length = MIOP_HEADER_SIZE;
+ }
+ }
+
+ // Build a generic MIOP Header.
+
+ // Allocate space on the stack for the header (add 8 to account for
+ // the possibility of adjusting for alignment).
+ char header_buffer[MIOP_HEADER_SIZE + 8];
+ TAO_OutputCDR miop_hdr (header_buffer, MIOP_HEADER_SIZE + 8);
+
+ miop_hdr.write_octet_array (miop_magic, 4); // Magic
+ miop_hdr.write_octet (0x10); // Version
+ CORBA::Octet *flags_field = reinterpret_cast<CORBA::Octet *> (miop_hdr.current ()->wr_ptr ());
+
+ // Write flags octet:
+ // Bit Description
+ // 0 Endian
+ // 1 Stop message flag (Assigned later)
+ // 2 - 7 Set to 0
+ miop_hdr.write_octet (TAO_ENCAP_BYTE_ORDER); // Flags
+
+ // Packet Length
+ // NOTE: We can save pointers and write them later without byte swapping since
+ // in CORBA, the sender chooses the endian.
+ CORBA::UShort *packet_length = reinterpret_cast<CORBA::UShort *> (miop_hdr.current ()->wr_ptr ());
+ miop_hdr.write_short (0);
+
+ // Packet number
+ CORBA::ULong *packet_number = reinterpret_cast<CORBA::ULong *> (miop_hdr.current ()->wr_ptr ());
+ miop_hdr.write_ulong (0);
+
+ // Number of packets field
+ miop_hdr.write_ulong (num_fragments);
+
+ // UniqueId
+ ptrdiff_t unique_id = reinterpret_cast<ptrdiff_t> (iov);
+ this->write_unique_id (miop_hdr,
+ static_cast<unsigned long> (unique_id));
+
+ // Send the buffers.
+ current_fragment = &fragments[0];
+ while (num_fragments > 0 &&
+ current_fragment->iovcnt > 1)
+ {
+ // Fill in the packet length header field.
+ *packet_length = static_cast<CORBA::UShort> (current_fragment->length);
+
+ // If this is the last fragment, set the stop message flag.
+ if (num_fragments == 1)
+ {
+ *flags_field |= 0x02;
+ }
+
+ // Setup the MIOP header in the iov list.
+ current_fragment->iov[0].iov_base = miop_hdr.current ()->rd_ptr ();
+ current_fragment->iov[0].iov_len = MIOP_HEADER_SIZE;
+
+ // Send the fragment. - Need to check for errors!!
+ ssize_t rc = this->connection_handler_->dgram ().send (current_fragment->iov,
+ current_fragment->iovcnt,
+ addr);
+
+ if (rc <= 0)
+ {
+ if (TAO_debug_level > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\n\nTAO (%P|%t) ")
+ ACE_TEXT ("UIPMC_Transport::send")
+ ACE_TEXT (" %p\n\n"),
+ ACE_TEXT ("Error returned from transport:")));
+ }
+
+ // Pretend it is o.k. See note by bytes_to_send calculation.
+ bytes_transferred = bytes_to_send;
+ return 1;
+ }
+
+ // Increment the number of bytes transferred, but don't
+ // count the MIOP header that we added.
+ bytes_transferred += rc - MIOP_HEADER_SIZE;
+
+ if (TAO_debug_level > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "TAO_UIPMC_Transport::send_i: sent %d bytes to %s:%d\n",
+ rc,
+ addr.get_host_addr (),
+ addr.get_port_number ()));
+ }
+
+ // Go to the next fragment.
+ (*packet_number)++;
+ ++current_fragment;
+ --num_fragments;
+ }
+
+ // Return total bytes transferred.
+ return bytes_transferred;
+}
+
+
+ssize_t
+TAO_UIPMC_Transport::recv (char *buf,
+ size_t len,
+ const ACE_Time_Value * /*max_wait_time*/)
+{
+ ACE_INET_Addr from_addr;
+
+ ssize_t n = this->connection_handler_->mcast_dgram ().recv (buf,
+ len,
+ from_addr);
+ if (TAO_debug_level > 5)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "TAO_UIPMC_Transport::recv_i: received %d bytes from %s:%d\n",
+ n,
+ from_addr.get_host_addr (),
+ from_addr.get_port_number ()));
+ }
+
+ // Make sure that we at least have a MIOP header.
+ if (n < MIOP_MIN_HEADER_SIZE)
+ {
+ if (TAO_debug_level > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "TAO_UIPMC_Transport::recv_i: packet of size %d is too small from %s:%d\n",
+ n,
+ from_addr.get_host_addr (),
+ from_addr.get_port_number ()));
+ }
+ return 0;
+ }
+
+ // Check for MIOP magic bytes.
+ if (buf[MIOP_MAGIC_OFFSET] != miop_magic [0] ||
+ buf[MIOP_MAGIC_OFFSET + 1] != miop_magic [1] ||
+ buf[MIOP_MAGIC_OFFSET + 2] != miop_magic [2] ||
+ buf[MIOP_MAGIC_OFFSET + 3] != miop_magic [3])
+ {
+ if (TAO_debug_level > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "TAO_UIPMC_Transport::recv_i: UIPMC packet didn't contain magic bytes.\n"));
+ }
+
+ return 0;
+ }
+
+ // Retrieve the byte order.
+ // 0 = Big endian
+ // 1 = Small endian
+ CORBA::Octet byte_order = buf[MIOP_FLAGS_OFFSET] & 0x01;
+
+ // Ignore the header version, other flags, packet length and number of packets.
+
+ // Get the length of the ID.
+ CORBA::ULong id_length;
+#if !defined (ACE_DISABLE_SWAP_ON_READ)
+ if (byte_order == ACE_CDR_BYTE_ORDER)
+ {
+ id_length = *reinterpret_cast<ACE_CDR::ULong*> (&buf[MIOP_ID_LENGTH_OFFSET]);
+ }
+ else
+ {
+ ACE_CDR::swap_4 (&buf[MIOP_ID_LENGTH_OFFSET],
+ reinterpret_cast<char*> (&id_length));
+ }
+#else
+ id_length = *reinterpret_cast<ACE_CDR::ULong*> (&buf[MIOP_ID_LENGTH_OFFSET]);
+#endif /* ACE_DISABLE_SWAP_ON_READ */
+
+ // Make sure that the length field is legal.
+ if (id_length > MIOP_MAX_LENGTH_ID ||
+ static_cast<ssize_t> (MIOP_ID_CONTENT_OFFSET + id_length) > n)
+ {
+ if (TAO_debug_level > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "TAO_UIPMC_Transport::recv_i: Invalid ID length.\n"));
+ }
+
+ return 0;
+ }
+
+ // Trim off the header for now.
+ ssize_t miop_header_size = (MIOP_ID_CONTENT_OFFSET + id_length + 7) & ~0x7;
+ if (miop_header_size > n)
+ {
+ if (TAO_debug_level > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "TAO_UIPMC_Transport::recv_i: MIOP packet not large enough for padding.\n"));
+ }
+
+ return 0;
+ }
+
+ n -= miop_header_size;
+ ACE_OS::memmove (buf, buf + miop_header_size, n);
+
+ return n;
+}
+
+int
+TAO_UIPMC_Transport::handle_input (TAO_Resume_Handle &rh,
+ ACE_Time_Value *max_wait_time,
+ int /*block*/)
+{
+ // If there are no messages then we can go ahead to read from the
+ // handle for further reading..
+
+ // The buffer on the stack which will be used to hold the input
+ // messages
+ char buf [MIOP_MAX_DGRAM_SIZE];
+
+#if defined (ACE_INITIALIZE_MEMORY_BEFORE_USE)
+ (void) ACE_OS::memset (buf,
+ '\0',
+ sizeof buf);
+#endif /* ACE_INITIALIZE_MEMORY_BEFORE_USE */
+
+ // Create a data block
+ ACE_Data_Block db (sizeof (buf),
+ ACE_Message_Block::MB_DATA,
+ buf,
+ this->orb_core_->input_cdr_buffer_allocator (),
+ this->orb_core_->locking_strategy (),
+ ACE_Message_Block::DONT_DELETE,
+ this->orb_core_->input_cdr_dblock_allocator ());
+
+ // Create a message block
+ ACE_Message_Block message_block (&db,
+ ACE_Message_Block::DONT_DELETE,
+ this->orb_core_->input_cdr_msgblock_allocator ());
+
+
+ // Align the message block
+ ACE_CDR::mb_align (&message_block);
+
+
+ // Read the message into the message block that we have created on
+ // the stack.
+ ssize_t n = this->recv (message_block.rd_ptr (),
+ message_block.space (),
+ max_wait_time);
+
+ // If there is an error return to the reactor..
+ if (n <= 0)
+ {
+ if (TAO_debug_level)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TAO: (%P|%t|%N|%l) recv returned error on transport %d after fault %p\n"),
+ this->id (),
+ ACE_TEXT ("handle_input_i ()\n")));
+ }
+
+ if (n == -1)
+ this->tms_->connection_closed ();
+
+ return n;
+ }
+
+ // Set the write pointer in the stack buffer.
+ message_block.wr_ptr (n);
+
+
+ // Make a node of the message block..
+ TAO_Queued_Data qd (&message_block);
+ size_t mesg_length;
+
+ // Parse the incoming message for validity. The check needs to be
+ // performed by the messaging objects.
+ if (this->messaging_object ()->parse_next_message (message_block,
+ qd,
+ mesg_length) == -1)
+ {
+ if (TAO_debug_level)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TAO: (%P|%t|%N|%l) handle_input failed on transport %d after fault\n"),
+ this->id () ));
+ }
+
+ return -1;
+ }
+
+ if (message_block.length () > mesg_length)
+ {
+ if (TAO_debug_level)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TAO: (%P|%t|%N|%l) handle_input failed on transport %d after fault\n"),
+ this->id () ));
+ }
+
+ return -1;
+ }
+
+ // NOTE: We are not performing any queueing nor any checking for
+ // missing data. We are assuming that ALL the data would be got in a
+ // single read.
+
+ // Process the message
+ return this->process_parsed_messages (&qd, rh);
+}
+
+int
+TAO_UIPMC_Transport::register_handler (void)
+{
+ // We never register register the handler with the reactor
+ // as we never need to be informed about any incoming data,
+ // assuming we only use one-ways.
+ // If we would register and ICMP Messages would arrive, e.g
+ // due to a not reachable server, we would get informed - as this
+ // disturbs the general MIOP assumptions of not being
+ // interested in any network failures, we ignore ICMP messages.
+ return 0;
+}
+
+int
+TAO_UIPMC_Transport::send_request (TAO_Stub *stub,
+ TAO_ORB_Core *orb_core,
+ TAO_OutputCDR &stream,
+ int message_semantics,
+ ACE_Time_Value *max_wait_time)
+{
+ if (this->ws_->sending_request (orb_core,
+ message_semantics) == -1)
+ return -1;
+
+ if (this->send_message (stream,
+ stub,
+ message_semantics,
+ max_wait_time) == -1)
+
+ return -1;
+
+ return 0;
+}
+
+int
+TAO_UIPMC_Transport::send_message (TAO_OutputCDR &stream,
+ TAO_Stub *stub,
+ int message_semantics,
+ ACE_Time_Value *max_wait_time)
+{
+ // Format the message in the stream first
+ if (this->messaging_object_->format_message (stream) != 0)
+ return -1;
+
+ // Strictly speaking, should not need to loop here because the
+ // socket never gets set to a nonblocking mode ... some Linux
+ // versions seem to need it though. Leaving it costs little.
+
+ // This guarantees to send all data (bytes) or return an error.
+ ssize_t n = this->send_message_shared (stub,
+ message_semantics,
+ stream.begin (),
+ max_wait_time);
+
+ if (n == -1)
+ {
+ if (TAO_debug_level)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TAO: (%P|%t|%N|%l) closing transport %d after fault %p\n"),
+ this->id (),
+ ACE_TEXT ("send_message ()\n")));
+
+ return -1;
+ }
+
+ return 1;
+}
+
+int
+TAO_UIPMC_Transport::messaging_init (CORBA::Octet major,
+ CORBA::Octet minor)
+{
+ this->messaging_object_->init (major,
+ minor);
+ return 1;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.h b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.h
new file mode 100644
index 00000000000..634b85c0b1a
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.h
@@ -0,0 +1,131 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file UIPMC_Transport.h
+ *
+ * $Id$
+ *
+ * @author Frank Hunleth <fhunleth@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef TAO_UIPMC_TRANSPORT_H
+#define TAO_UIPMC_TRANSPORT_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 "tao/Transport.h"
+
+#include "ace/SOCK_Stream.h"
+#include "ace/Svc_Handler.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward decls.
+class TAO_UIPMC_Connection_Handler;
+class TAO_ORB_Core;
+class TAO_Operation_Details;
+class TAO_Pluggable_Messaging;
+class TAO_Acceptor;
+
+// Service Handler for this transport
+typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
+ TAO_UIPMC_SVC_HANDLER;
+
+#if defined ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION_EXPORT
+template class TAO_PortableGroup_Export ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>;
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION_EXPORT */
+
+/**
+ * @class TAO_UIPMC_Transport
+ *
+ * @brief Specialization of the base TAO_Transport class to handle the
+ * MIOP protocol.
+ */
+class TAO_PortableGroup_Export TAO_UIPMC_Transport : public TAO_Transport
+{
+public:
+
+ /// Constructor.
+ TAO_UIPMC_Transport (TAO_UIPMC_Connection_Handler *handler,
+ TAO_ORB_Core *orb_core,
+ CORBA::Boolean flag);
+
+ /// Default destructor.
+ ~TAO_UIPMC_Transport (void);
+
+ /// Look for the documentation in Transport.h.
+ virtual int handle_input (TAO_Resume_Handle &rh,
+ ACE_Time_Value *max_wait_time = 0,
+ int block = 0);
+protected:
+ /** @name Overridden Template Methods
+ *
+ * These are implementations of template methods declared by TAO_Transport.
+ */
+ //@{
+
+ virtual ACE_Event_Handler * event_handler_i (void);
+ virtual TAO_Connection_Handler *connection_handler_i (void);
+ virtual TAO_Pluggable_Messaging *messaging_object (void);
+
+ /// Write the complete Message_Block chain to the connection.
+ virtual ssize_t send (iovec *iov, int iovcnt,
+ size_t &bytes_transferred,
+ const ACE_Time_Value *max_wait_time);
+
+
+ /// Read len bytes from into buf.
+ virtual ssize_t recv (char *buf,
+ size_t len,
+ const ACE_Time_Value *s = 0);
+
+ virtual int register_handler (void);
+
+public:
+ /// @@TODO: These methods IMHO should have more meaningful
+ /// names. The names seem to indicate nothing.
+ virtual int send_request (TAO_Stub *stub,
+ TAO_ORB_Core *orb_core,
+ TAO_OutputCDR &stream,
+ int message_semantics,
+ ACE_Time_Value *max_wait_time);
+
+ virtual int send_message (TAO_OutputCDR &stream,
+ TAO_Stub *stub = 0,
+ int message_semantics = TAO_Transport::TAO_TWOWAY_REQUEST,
+ ACE_Time_Value *max_time_wait = 0);
+
+ /// Initialising the messaging object
+ virtual int messaging_init (CORBA::Octet major,
+ CORBA::Octet minor);
+
+ //@}
+
+private:
+ /// Process the message that we have read.
+ int process_message (void);
+
+ /// Construct and write a unique ID to the MIOP header.
+ void write_unique_id (TAO_OutputCDR &miop_hdr, unsigned long unique);
+
+private:
+
+ /// The connection service handler used for accessing lower layer
+ /// communication protocols.
+ TAO_UIPMC_Connection_Handler *connection_handler_;
+
+ /// Our messaging object.
+ TAO_Pluggable_Messaging *messaging_object_;
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* TAO_UIPMC_TRANSPORT_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Wait_Never.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Wait_Never.cpp
new file mode 100644
index 00000000000..0e1a0f1bc89
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Wait_Never.cpp
@@ -0,0 +1,53 @@
+// $Id$
+
+#include "orbsvcs/PortableGroup/UIPMC_Wait_Never.h"
+#include "tao/ORB_Core.h"
+#include "tao/Transport.h"
+#include "tao/debug.h"
+
+ACE_RCSID(tao, Wait_On_Leader_Follower, "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+TAO_UIPMC_Wait_Never::TAO_UIPMC_Wait_Never (TAO_Transport *transport)
+ : TAO_Wait_Strategy (transport)
+{
+}
+
+TAO_UIPMC_Wait_Never::~TAO_UIPMC_Wait_Never (void)
+{
+}
+
+int
+TAO_UIPMC_Wait_Never::register_handler (void)
+{
+ return -1;
+}
+
+bool
+TAO_UIPMC_Wait_Never::non_blocking (void) const
+{
+ return true;
+}
+
+bool
+TAO_UIPMC_Wait_Never::can_process_upcalls (void) const
+{
+ return true;
+}
+
+int
+TAO_UIPMC_Wait_Never::sending_request (TAO_ORB_Core *,
+ int)
+{
+ return 0;
+}
+
+int
+TAO_UIPMC_Wait_Never::wait (ACE_Time_Value *,
+ TAO_Synch_Reply_Dispatcher &)
+{
+ return -1;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Wait_Never.h b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Wait_Never.h
new file mode 100644
index 00000000000..9f39cd77b91
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Wait_Never.h
@@ -0,0 +1,58 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file UIPMC_Wait_Never.h
+ *
+ * $Id$
+ *
+ * @author Frank Hunleth <fhunleth@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_UIPMC_WAIT_NEVER_H
+#define TAO_UIPMC_WAIT_NEVER_H
+#include /**/ "ace/pre.h"
+
+#include "tao/Wait_Strategy.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/PortableGroup/portablegroup_export.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class TAO_UIPMC_Wait_Never
+ *
+ * @brief Since two-ways are not supported by UIPMC and more
+ * generally, anything that requires waiting isn't supported, so
+ * return error if anyone tries to do this.
+ */
+class TAO_PortableGroup_Export TAO_UIPMC_Wait_Never : public TAO_Wait_Strategy
+{
+
+public:
+ /// Constructor.
+ TAO_UIPMC_Wait_Never (TAO_Transport *transport);
+
+ /// Destructor.
+ virtual ~TAO_UIPMC_Wait_Never (void);
+
+ // = Documented in TAO_Wait_Strategy.
+ virtual int sending_request (TAO_ORB_Core *orb_core,
+ int two_way);
+ virtual int wait (ACE_Time_Value *max_wait_time,
+ TAO_Synch_Reply_Dispatcher &rd);
+ virtual int register_handler (void);
+ virtual bool non_blocking (void) const;
+ virtual bool can_process_upcalls (void) const;
+};
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+#endif /* TAO_UIPMC_WAIT_NEVER_H */
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/miopconf.h b/TAO/orbsvcs/orbsvcs/PortableGroup/miopconf.h
new file mode 100644
index 00000000000..44db690f7b2
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/miopconf.h
@@ -0,0 +1,41 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file miopconf.h
+ *
+ * $Id$
+ *
+ * Build configuration file.
+ *
+ * @author Copyright 1995 by Sun Microsystems, Inc.
+ * @author Chris Cleeland
+ * @author Douglas C. Schmidt
+ */
+//=============================================================================
+
+#ifndef TAO_MIOPCONF_H
+#define TAO_MIOPCONF_H
+#include /**/ "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// This is the version of the MIOP spec that TAO supports. The
+// exact usage of the version has not been emphasized. But TAO should
+// get a TaggedComponents for a group with this version number. So, for
+// the present, we do a sanity check for our version and raise an error on
+// a mismatch.
+
+#if !defined (TAO_DEF_MIOP_MAJOR)
+#define TAO_DEF_MIOP_MAJOR 1
+#endif /* TAO_DEF_MIOP_MAJOR */
+#if !defined (TAO_DEF_MIOP_MINOR)
+#define TAO_DEF_MIOP_MINOR 0
+#endif /* TAO_DEF_MIOP_MINOR */
+
+#include /**/ "ace/post.h"
+#endif /*TAO_MIOPCONF_H*/
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/portablegroup_export.h b/TAO/orbsvcs/orbsvcs/PortableGroup/portablegroup_export.h
new file mode 100644
index 00000000000..15494956536
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/portablegroup_export.h
@@ -0,0 +1,40 @@
+
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by generate_export_file.pl
+// ------------------------------
+#ifndef TAO_PORTABLEGROUP_EXPORT_H
+#define TAO_PORTABLEGROUP_EXPORT_H
+
+#include "ace/config-all.h"
+
+#if defined (TAO_AS_STATIC_LIBS)
+# if !defined (TAO_PORTABLEGROUP_HAS_DLL)
+# define TAO_PORTABLEGROUP_HAS_DLL 0
+# endif /* ! TAO_PORTABLEGROUP_HAS_DLL */
+#else
+# if !defined (TAO_PORTABLEGROUP_HAS_DLL)
+# define TAO_PORTABLEGROUP_HAS_DLL 1
+# endif /* ! TAO_PORTABLEGROUP_HAS_DLL */
+#endif
+
+#if defined (TAO_PORTABLEGROUP_HAS_DLL) && (TAO_PORTABLEGROUP_HAS_DLL == 1)
+# if defined (TAO_PORTABLEGROUP_BUILD_DLL)
+# define TAO_PortableGroup_Export ACE_Proper_Export_Flag
+# define TAO_PORTABLEGROUP_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define TAO_PORTABLEGROUP_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else /* TAO_PORTABLEGROUP_BUILD_DLL */
+# define TAO_PortableGroup_Export ACE_Proper_Import_Flag
+# define TAO_PORTABLEGROUP_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define TAO_PORTABLEGROUP_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* TAO_PORTABLEGROUP_BUILD_DLL */
+#else /* TAO_PORTABLEGROUP_HAS_DLL == 1 */
+# define TAO_PortableGroup_Export
+# define TAO_PORTABLEGROUP_SINGLETON_DECLARATION(T)
+# define TAO_PORTABLEGROUP_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* TAO_PORTABLEGROUP_HAS_DLL == 1 */
+
+#endif /* TAO_PORTABLEGROUP_EXPORT_H */
+
+// End of auto generated file.