📄 pg_genericfactory.cpp
字号:
#include "PG_GenericFactory.h"
#include "PG_MemberInfo.h"
#include "PG_ObjectGroupManager.h"
#include "PG_PropertyManager.h"
#include "PG_Property_Utils.h"
#include "PG_conf.h"
#include "ace/OS_NS_stdio.h"
#include "tao/ORB_Constants.h"
ACE_RCSID (PortableGroup,
PG_GenericFactory,
"PG_GenericFactory.cpp,v 1.21 2003/12/22 01:44:38 wilson_d Exp")
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_DEFAULT_MINOR_CODE,
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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -