00001 #include "orbsvcs/PortableGroup/PG_GenericFactory.h"
00002 #include "orbsvcs/PortableGroup/PG_MemberInfo.h"
00003 #include "orbsvcs/PortableGroup/PG_ObjectGroupManager.h"
00004 #include "orbsvcs/PortableGroup/PG_PropertyManager.h"
00005 #include "orbsvcs/PortableGroup/PG_Property_Utils.h"
00006 #include "orbsvcs/PortableGroup/PG_conf.h"
00007
00008 #include "ace/OS_NS_stdio.h"
00009
00010 #include "tao/ORB_Constants.h"
00011
00012 ACE_RCSID (PortableGroup,
00013 PG_GenericFactory,
00014 "$Id: PG_GenericFactory.cpp 77001 2007-02-12 07:54:49Z johnnyw $")
00015
00016
00017 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00018
00019 TAO_PG_GenericFactory::TAO_PG_GenericFactory (
00020 TAO_PG_ObjectGroupManager & object_group_manager,
00021 TAO_PG_PropertyManager & property_manager)
00022 : poa_ (),
00023 object_group_manager_ (object_group_manager),
00024 property_manager_ (property_manager),
00025 factory_map_ (TAO_PG_MAX_OBJECT_GROUPS),
00026 next_fcid_ (0),
00027 lock_ ()
00028 {
00029 this->object_group_manager_.generic_factory (this);
00030 }
00031
00032 TAO_PG_GenericFactory::~TAO_PG_GenericFactory (void)
00033 {
00034
00035 TAO_PG_Factory_Map::iterator end = this->factory_map_.end ();
00036 for (TAO_PG_Factory_Map::iterator i = this->factory_map_.begin ();
00037 i != end;
00038 ++i)
00039 {
00040 TAO_PG_Factory_Set & factory_set = (*i).int_id_;
00041
00042 try
00043 {
00044 this->delete_object_i (factory_set,
00045 1 );
00046 }
00047 catch (const CORBA::Exception&)
00048 {
00049
00050 }
00051 }
00052
00053 (void) this->factory_map_.close ();
00054 }
00055
00056 CORBA::Object_ptr
00057 TAO_PG_GenericFactory::create_object (
00058 const char * type_id,
00059 const PortableGroup::Criteria & the_criteria,
00060 PortableGroup::GenericFactory::FactoryCreationId_out factory_creation_id)
00061 {
00062 PortableGroup::Properties_var properties =
00063 this->property_manager_.get_type_properties (type_id);
00064
00065 PortableGroup::MembershipStyleValue membership_style =
00066 TAO_PG_MEMBERSHIP_STYLE;
00067 PortableGroup::FactoriesValue factory_infos(0);
00068
00069 PortableGroup::InitialNumberMembersValue initial_number_members =
00070 TAO_PG_INITIAL_NUMBER_MEMBERS;
00071 PortableGroup::MinimumNumberMembersValue minimum_number_members =
00072 TAO_PG_MINIMUM_NUMBER_MEMBERS;
00073
00074
00075
00076 this->process_criteria (type_id,
00077 the_criteria,
00078 membership_style,
00079 factory_infos,
00080 initial_number_members,
00081 minimum_number_members);
00082
00083 CORBA::ULong fcid = 0;
00084
00085 {
00086 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
00087 guard,
00088 this->lock_,
00089 CORBA::Object::_nil ());
00090
00091
00092 fcid = this->next_fcid_;
00093
00094
00095
00096 while (this->factory_map_.find (this->next_fcid_) == 0)
00097 {
00098 this->next_fcid_++;
00099
00100
00101
00102
00103
00104
00105 if (this->next_fcid_ == fcid)
00106 throw PortableGroup::ObjectNotCreated ();
00107 }
00108
00109
00110
00111 fcid = this->next_fcid_;
00112 }
00113
00114
00115
00116 PortableServer::ObjectId_var oid;
00117 this->get_ObjectId (fcid, oid.out ());
00118
00119 PortableGroup::ObjectGroup_var object_group =
00120 this->object_group_manager_.create_object_group (fcid,
00121 oid.in (),
00122 type_id,
00123 the_criteria);
00124
00125 TAO_PG_Factory_Set factory_set;
00126
00127 const CORBA::ULong factory_infos_count = factory_infos.length ();
00128
00129 try
00130 {
00131 if (factory_infos_count > 0
00132 && membership_style == PortableGroup::MEMB_INF_CTRL)
00133 {
00134 this->populate_object_group (object_group.in (),
00135 type_id,
00136 factory_infos,
00137 initial_number_members,
00138 factory_set);
00139
00140 if (this->factory_map_.bind (fcid, factory_set) != 0)
00141 throw PortableGroup::ObjectNotCreated ();
00142
00143 }
00144
00145
00146 PortableGroup::GenericFactory::FactoryCreationId * tmp = 0;
00147 ACE_NEW_THROW_EX (tmp,
00148 PortableGroup::GenericFactory::FactoryCreationId,
00149 CORBA::NO_MEMORY (
00150 CORBA::SystemException::_tao_minor_code (
00151 TAO::VMCID,
00152 ENOMEM),
00153 CORBA::COMPLETED_NO));
00154
00155 factory_creation_id = tmp;
00156
00157 *tmp <<= fcid;
00158 }
00159 catch (const CORBA::Exception&)
00160 {
00161 this->delete_object_i (factory_set,
00162 1 );
00163
00164 this->object_group_manager_.destroy_object_group (oid.in ());
00165
00166 throw;
00167 }
00168
00169 {
00170 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
00171 guard,
00172 this->lock_,
00173 CORBA::Object::_nil ());
00174
00175
00176
00177 this->next_fcid_++;
00178 }
00179
00180 return object_group._retn ();
00181 }
00182
00183 void
00184 TAO_PG_GenericFactory::delete_object (
00185 const PortableGroup::GenericFactory::FactoryCreationId &
00186 factory_creation_id)
00187 {
00188 CORBA::ULong fcid = 0;
00189
00190 if (factory_creation_id >>= fcid)
00191 {
00192
00193
00194
00195 ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
00196
00197
00198
00199 TAO_PG_Factory_Map::ENTRY *entry = 0;
00200 if (this->factory_map_.find (fcid, entry) == 0)
00201 {
00202 TAO_PG_Factory_Set & factory_set = entry->int_id_;
00203
00204 this->delete_object_i (factory_set,
00205 0 );
00206
00207 if (this->factory_map_.unbind (fcid) != 0)
00208 throw CORBA::INTERNAL ();
00209 }
00210 }
00211 else
00212 throw PortableGroup::ObjectNotFound ();
00213
00214
00215
00216
00217
00218 PortableServer::ObjectId_var oid;
00219 this->get_ObjectId (fcid, oid.out ());
00220
00221
00222 this->object_group_manager_.destroy_object_group (
00223 oid.in ());
00224 }
00225
00226 void
00227 TAO_PG_GenericFactory::delete_object_i (TAO_PG_Factory_Set & factory_set,
00228 CORBA::Boolean ignore_exceptions)
00229 {
00230 const size_t len = factory_set.size ();
00231
00232 size_t ilen = len;
00233 for (size_t i = 0; i != len; ++i)
00234 {
00235
00236
00237
00238 --ilen;
00239
00240 TAO_PG_Factory_Node & factory_node = factory_set[ilen];
00241
00242 PortableGroup::GenericFactory_ptr factory =
00243 factory_node.factory_info.the_factory.in ();
00244 const PortableGroup::GenericFactory::FactoryCreationId & member_fcid =
00245 factory_node.factory_creation_id.in ();
00246
00247 try
00248 {
00249 factory->delete_object (member_fcid);
00250 }
00251 catch (const CORBA::Exception&)
00252 {
00253
00254
00255
00256
00257
00258
00259 if (!ignore_exceptions)
00260 throw;
00261 }
00262
00263
00264
00265
00266
00267
00268 factory_set.size (ilen);
00269 }
00270 }
00271
00272 void
00273 TAO_PG_GenericFactory::delete_member (
00274 CORBA::ULong group_id,
00275 const PortableGroup::Location & location)
00276 {
00277 ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
00278
00279
00280
00281 TAO_PG_Factory_Map::ENTRY *entry = 0;
00282 if (this->factory_map_.find (group_id, entry) == 0)
00283 {
00284 TAO_PG_Factory_Set & factory_set = entry->int_id_;
00285
00286 const size_t len = factory_set.size ();
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 for (size_t i = 0; i < len; ++i)
00298 {
00299 TAO_PG_Factory_Node & node = factory_set[i];
00300 PortableGroup::FactoryInfo & info = node.factory_info;
00301
00302 if (info.the_location == location)
00303 {
00304 info.the_factory->delete_object (node.factory_creation_id.in ());
00305
00306
00307
00308 if (len > 1)
00309 {
00310
00311
00312
00313 const size_t new_len = len - 1;
00314 node = factory_set[new_len];
00315 factory_set.size (new_len);
00316 }
00317 else
00318 {
00319
00320
00321 factory_set.size (0);
00322 }
00323
00324 return;
00325 }
00326 }
00327 }
00328 }
00329
00330 void
00331 TAO_PG_GenericFactory::poa (PortableServer::POA_ptr p)
00332 {
00333 ACE_ASSERT (CORBA::is_nil (this->poa_.in ())
00334 && !CORBA::is_nil (p));
00335
00336 this->poa_ = PortableServer::POA::_duplicate (p);
00337 }
00338
00339 void
00340 TAO_PG_GenericFactory::populate_object_group (
00341 PortableGroup::ObjectGroup_ptr object_group,
00342 const char * type_id,
00343 const PortableGroup::FactoryInfos & factory_infos,
00344 PortableGroup::InitialNumberMembersValue initial_number_members,
00345 TAO_PG_Factory_Set & factory_set)
00346 {
00347 CORBA::ULong factory_infos_count = factory_infos.length ();
00348 factory_set.size (factory_infos_count);
00349
00350 for (CORBA::ULong j = 0; j < factory_infos_count; ++j)
00351 {
00352 TAO_PG_Factory_Node & factory_node = factory_set[j];
00353
00354 const PortableGroup::FactoryInfo &factory_info = factory_infos[j];
00355
00356 if (j < static_cast<CORBA::ULong> (initial_number_members))
00357 {
00358 PortableGroup::GenericFactory_ptr factory =
00359 factory_info.the_factory.in ();
00360
00361 if (CORBA::is_nil (factory))
00362 {
00363
00364 throw PortableGroup::NoFactory (
00365 factory_info.the_location,
00366 type_id);
00367 }
00368
00369
00370
00371 const CORBA::Boolean propagate_member_already_present = 0;
00372
00373 factory_node.factory_creation_id =
00374 this->create_member (object_group,
00375 factory_info,
00376 type_id,
00377 propagate_member_already_present);
00378 }
00379
00380 factory_node.factory_info = factory_info;
00381 }
00382 }
00383
00384 void
00385 TAO_PG_GenericFactory::get_ObjectId (
00386 CORBA::ULong fcid,
00387 PortableServer::ObjectId_out oid)
00388 {
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 const size_t MAX_OID_LEN = 14;
00410
00411 char oid_str[MAX_OID_LEN] = { 0 };
00412 ACE_OS::sprintf (oid_str,
00413 "%ul",
00414 fcid);
00415
00416 oid = PortableServer::string_to_ObjectId (oid_str);
00417 }
00418
00419 void
00420 TAO_PG_GenericFactory::process_criteria (
00421 const char * type_id,
00422 const PortableGroup::Criteria & criteria,
00423 PortableGroup::MembershipStyleValue & membership_style,
00424 PortableGroup::FactoriesValue & factory_infos,
00425 PortableGroup::InitialNumberMembersValue & initial_number_members,
00426 PortableGroup::MinimumNumberMembersValue & minimum_number_members)
00427 {
00428
00429 PortableGroup::Properties_var props =
00430 this->property_manager_.get_type_properties (type_id);
00431
00432
00433 TAO_PG::override_properties (criteria, props.inout ());
00434
00435 PortableGroup::Criteria unmet_criteria;
00436 unmet_criteria.length (4);
00437
00438
00439
00440 CORBA::ULong uc = 0;
00441
00442 PortableGroup::Name name (1);
00443 name.length (1);
00444
00445 PortableGroup::Value value;
00446 PortableGroup::Value value1;
00447 PortableGroup::Value value2;
00448 PortableGroup::Value value3;
00449
00450
00451 name[0].id = CORBA::string_dup ("org.omg.PortableGroup.MembershipStyle");
00452 if (TAO_PG::get_property_value (name, props.in (), value)
00453 && (!(value >>= membership_style)
00454 || (membership_style != PortableGroup::MEMB_APP_CTRL
00455 && membership_style != PortableGroup::MEMB_INF_CTRL)))
00456 {
00457
00458
00459 throw PortableGroup::InvalidProperty (name, value);
00460 }
00461
00462
00463 const PortableGroup::FactoryInfos * factory_infos_tmp = 0;
00464 name[0].id = CORBA::string_dup ("org.omg.PortableGroup.Factories");
00465 if (TAO_PG::get_property_value (name, props.in (), value1)
00466 && !(value1 >>= factory_infos_tmp))
00467 {
00468
00469
00470 throw PortableGroup::InvalidProperty (name, value1);
00471 }
00472
00473 const CORBA::ULong factory_infos_count =
00474 (factory_infos_tmp == 0 ? 0 : factory_infos_tmp->length ());
00475
00476
00477 name[0].id =
00478 CORBA::string_dup ("org.omg.PortableGroup.InitialNumberMembers");
00479 if (TAO_PG::get_property_value (name, props.in (), value2)
00480 && !(value2 >>= initial_number_members))
00481 {
00482
00483
00484 throw PortableGroup::InvalidProperty (name, value2);
00485 }
00486
00487 if (membership_style == PortableGroup::MEMB_INF_CTRL)
00488 {
00489
00490
00491
00492
00493 if (factory_infos_count < static_cast<CORBA::ULong> (initial_number_members))
00494 {
00495 unmet_criteria[uc].nam = name;
00496 unmet_criteria[uc++].val = value2;
00497 }
00498 }
00499
00500
00501 name[0].id =
00502 CORBA::string_dup ("org.omg.PortableGroup.MinimumNumberMembers");
00503 if (TAO_PG::get_property_value (name, props.in (), value3)
00504 && !(value3 >>= minimum_number_members))
00505 {
00506
00507
00508 throw PortableGroup::InvalidProperty (name, value3);
00509 }
00510
00511
00512
00513
00514
00515
00516
00517
00518 if (membership_style == PortableGroup::MEMB_INF_CTRL)
00519 {
00520 if (minimum_number_members < initial_number_members
00521 || static_cast<CORBA::ULong> (minimum_number_members) > factory_infos_count)
00522 {
00523 unmet_criteria[uc].nam = name;
00524 unmet_criteria[uc++].val = value3;
00525 }
00526 else if (factory_infos_tmp != 0)
00527 {
00528 factory_infos.length (factory_infos_count);
00529 factory_infos = *factory_infos_tmp;
00530 }
00531 }
00532
00533 if (uc > 0)
00534 {
00535
00536
00537
00538
00539 unmet_criteria.length (uc);
00540
00541 throw PortableGroup::CannotMeetCriteria (unmet_criteria);
00542 }
00543 }
00544
00545 void
00546 TAO_PG_GenericFactory::check_minimum_number_members (
00547 PortableGroup::ObjectGroup_ptr object_group,
00548 CORBA::ULong group_id,
00549 const char * type_id)
00550 {
00551
00552
00553
00554
00555
00556
00557 TAO_PG_Factory_Map::ENTRY *entry = 0;
00558 if (this->factory_map_.find (group_id, entry) != 0)
00559 return;
00560
00561 TAO_PG_Factory_Set & factory_set = entry->int_id_;
00562
00563 PortableGroup::Properties_var props =
00564 this->property_manager_.get_properties (object_group);
00565
00566 PortableGroup::Name name (1);
00567 name.length (1);
00568
00569 PortableGroup::Value value;
00570
00571
00572 name[0].id =
00573 CORBA::string_dup ("org.omg.PortableGroup.MinimumNumberMembers");
00574
00575 PortableGroup::MinimumNumberMembersValue minimum_number_members;
00576
00577 if (TAO_PG::get_property_value (name, props.in (), value))
00578 {
00579 if (!(value >>= minimum_number_members))
00580 {
00581
00582
00583 throw CORBA::INTERNAL ();
00584 }
00585
00586 const CORBA::ULong count =
00587 this->object_group_manager_.member_count (object_group);
00588
00589 if (count >= static_cast<CORBA::ULong> (minimum_number_members))
00590 return;
00591
00592 const CORBA::ULong gap =
00593 static_cast<CORBA::ULong> (minimum_number_members) - count;
00594
00595 CORBA::ULong creation_count = 0;
00596
00597 const size_t len = factory_set.size ();
00598
00599 static const PortableGroup::GenericFactory::FactoryCreationId *
00600 nil_fcid = 0;
00601
00602 for (size_t i = 0; i < len; ++i)
00603 {
00604 TAO_PG_Factory_Node & node = factory_set[i];
00605
00606 PortableGroup::GenericFactory::FactoryCreationId * const tmp_fcid =
00607 node.factory_creation_id;
00608
00609
00610
00611 if (tmp_fcid != nil_fcid)
00612 continue;
00613
00614 try
00615 {
00616 const CORBA::Boolean propagate_member_already_present = 1;
00617
00618 node.factory_creation_id =
00619 this->create_member (object_group,
00620 node.factory_info,
00621 type_id,
00622 propagate_member_already_present);
00623
00624 ++creation_count;
00625
00626
00627
00628 if (gap == creation_count)
00629 return;
00630 }
00631 catch (const PortableGroup::MemberAlreadyPresent&)
00632 {
00633
00634 }
00635 }
00636
00637
00638
00639
00640 }
00641 }
00642
00643 PortableGroup::GenericFactory::FactoryCreationId *
00644 TAO_PG_GenericFactory::create_member (
00645 PortableGroup::ObjectGroup_ptr object_group,
00646 const PortableGroup::FactoryInfo & factory_info,
00647 const char * type_id,
00648 const CORBA::Boolean propagate_member_already_present)
00649 {
00650 PortableGroup::GenericFactory::FactoryCreationId_var fcid;
00651
00652 CORBA::Object_var member =
00653 factory_info.the_factory->create_object (type_id,
00654 factory_info.the_criteria,
00655 fcid.out ());
00656
00657 try
00658 {
00659
00660
00661
00662
00663
00664
00665
00666
00667 CORBA::Boolean right_type_id =
00668 member->_is_a (type_id);
00669
00670
00671 if (!right_type_id)
00672 {
00673
00674
00675 factory_info.the_factory->delete_object (fcid.in ());
00676
00677 throw PortableGroup::NoFactory (factory_info.the_location, type_id);
00678 }
00679
00680 this->object_group_manager_._tao_add_member (
00681 object_group,
00682 factory_info.the_location,
00683 member.in (),
00684 type_id,
00685 propagate_member_already_present);
00686 }
00687 catch (const CORBA::Exception&)
00688 {
00689
00690
00691
00692 if (!CORBA::is_nil (member.in ()))
00693 {
00694 factory_info.the_factory->delete_object (fcid.in ());
00695 }
00696
00697 throw;
00698 }
00699
00700 return fcid._retn ();
00701 }
00702
00703 TAO_END_VERSIONED_NAMESPACE_DECL