diff options
author | William R. Otte <wotte@dre.vanderbilt.edu> | 2006-07-24 15:50:21 +0000 |
---|---|---|
committer | William R. Otte <wotte@dre.vanderbilt.edu> | 2006-07-24 15:50:21 +0000 |
commit | 3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c (patch) | |
tree | 197c810e5f5bce17b1233a7cb8d7b50c0bcd25e2 /TAO/orbsvcs/orbsvcs/PortableGroup | |
parent | 6b846cf03c0bcbd8c276cb0af61a181e5f98eaae (diff) | |
download | ATCD-3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c.tar.gz |
Repo restructuring
Diffstat (limited to 'TAO/orbsvcs/orbsvcs/PortableGroup')
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 ¤t_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. |