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 87872 2009-12-02 18:25:48Z dai_y $")
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 try {
00305 info.the_factory->delete_object (node.factory_creation_id.in ());
00306 }
00307 catch (const CORBA::Exception& ex)
00308 {
00309
00310
00311
00312 if (TAO_debug_level > 0)
00313 {
00314 ex._tao_print_exception ("TAO_PG_GenericFactory::delete_member \n");
00315 }
00316 }
00317
00318
00319
00320 if (len > 1)
00321 {
00322
00323
00324
00325 const size_t new_len = len - 1;
00326 node = factory_set[new_len];
00327 factory_set.size (new_len);
00328 }
00329 else
00330 {
00331
00332
00333 factory_set.size (0);
00334 }
00335
00336 return;
00337 }
00338 }
00339 }
00340 }
00341
00342 void
00343 TAO_PG_GenericFactory::poa (PortableServer::POA_ptr p)
00344 {
00345 ACE_ASSERT (CORBA::is_nil (this->poa_.in ())
00346 && !CORBA::is_nil (p));
00347
00348 this->poa_ = PortableServer::POA::_duplicate (p);
00349 }
00350
00351 void
00352 TAO_PG_GenericFactory::populate_object_group (
00353 PortableGroup::ObjectGroup_ptr object_group,
00354 const char * type_id,
00355 const PortableGroup::FactoryInfos & factory_infos,
00356 PortableGroup::InitialNumberMembersValue initial_number_members,
00357 TAO_PG_Factory_Set & factory_set)
00358 {
00359 CORBA::ULong factory_infos_count = factory_infos.length ();
00360 factory_set.size (factory_infos_count);
00361
00362 for (CORBA::ULong j = 0; j < factory_infos_count; ++j)
00363 {
00364 TAO_PG_Factory_Node & factory_node = factory_set[j];
00365
00366 const PortableGroup::FactoryInfo &factory_info = factory_infos[j];
00367
00368 if (j < static_cast<CORBA::ULong> (initial_number_members))
00369 {
00370 PortableGroup::GenericFactory_ptr factory =
00371 factory_info.the_factory.in ();
00372
00373 if (CORBA::is_nil (factory))
00374 {
00375
00376 throw PortableGroup::NoFactory (
00377 factory_info.the_location,
00378 type_id);
00379 }
00380
00381
00382
00383 const CORBA::Boolean propagate_member_already_present = 0;
00384
00385 factory_node.factory_creation_id =
00386 this->create_member (object_group,
00387 factory_info,
00388 type_id,
00389 propagate_member_already_present);
00390 }
00391
00392 factory_node.factory_info = factory_info;
00393 }
00394 }
00395
00396 void
00397 TAO_PG_GenericFactory::get_ObjectId (
00398 CORBA::ULong fcid,
00399 PortableServer::ObjectId_out oid)
00400 {
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 const size_t MAX_OID_LEN = 14;
00422
00423 char oid_str[MAX_OID_LEN] = { 0 };
00424 ACE_OS::sprintf (oid_str,
00425 "%ul",
00426 fcid);
00427
00428 oid = PortableServer::string_to_ObjectId (oid_str);
00429 }
00430
00431 void
00432 TAO_PG_GenericFactory::process_criteria (
00433 const char * type_id,
00434 const PortableGroup::Criteria & criteria,
00435 PortableGroup::MembershipStyleValue & membership_style,
00436 PortableGroup::FactoriesValue & factory_infos,
00437 PortableGroup::InitialNumberMembersValue & initial_number_members,
00438 PortableGroup::MinimumNumberMembersValue & minimum_number_members)
00439 {
00440
00441 PortableGroup::Properties_var props =
00442 this->property_manager_.get_type_properties (type_id);
00443
00444
00445 TAO_PG::override_properties (criteria, props.inout ());
00446
00447 PortableGroup::Criteria unmet_criteria;
00448 unmet_criteria.length (4);
00449
00450
00451
00452 CORBA::ULong uc = 0;
00453
00454 PortableGroup::Name name (1);
00455 name.length (1);
00456
00457 PortableGroup::Value value;
00458 PortableGroup::Value value1;
00459 PortableGroup::Value value2;
00460 PortableGroup::Value value3;
00461
00462
00463 name[0].id = CORBA::string_dup ("org.omg.PortableGroup.MembershipStyle");
00464 if (TAO_PG::get_property_value (name, props.in (), value)
00465 && (!(value >>= membership_style)
00466 || (membership_style != PortableGroup::MEMB_APP_CTRL
00467 && membership_style != PortableGroup::MEMB_INF_CTRL)))
00468 {
00469
00470
00471 throw PortableGroup::InvalidProperty (name, value);
00472 }
00473
00474
00475 const PortableGroup::FactoryInfos * factory_infos_tmp = 0;
00476 name[0].id = CORBA::string_dup ("org.omg.PortableGroup.Factories");
00477 if (TAO_PG::get_property_value (name, props.in (), value1)
00478 && !(value1 >>= factory_infos_tmp))
00479 {
00480
00481
00482 throw PortableGroup::InvalidProperty (name, value1);
00483 }
00484
00485 const CORBA::ULong factory_infos_count =
00486 (factory_infos_tmp == 0 ? 0 : factory_infos_tmp->length ());
00487
00488
00489 name[0].id =
00490 CORBA::string_dup ("org.omg.PortableGroup.InitialNumberMembers");
00491 if (TAO_PG::get_property_value (name, props.in (), value2)
00492 && !(value2 >>= initial_number_members))
00493 {
00494
00495
00496 throw PortableGroup::InvalidProperty (name, value2);
00497 }
00498
00499 if (membership_style == PortableGroup::MEMB_INF_CTRL)
00500 {
00501
00502
00503
00504
00505 if (factory_infos_count < static_cast<CORBA::ULong> (initial_number_members))
00506 {
00507 unmet_criteria[uc].nam = name;
00508 unmet_criteria[uc++].val = value2;
00509 }
00510 }
00511
00512
00513 name[0].id =
00514 CORBA::string_dup ("org.omg.PortableGroup.MinimumNumberMembers");
00515 if (TAO_PG::get_property_value (name, props.in (), value3)
00516 && !(value3 >>= minimum_number_members))
00517 {
00518
00519
00520 throw PortableGroup::InvalidProperty (name, value3);
00521 }
00522
00523
00524
00525
00526
00527
00528
00529
00530 if (membership_style == PortableGroup::MEMB_INF_CTRL)
00531 {
00532 if (minimum_number_members < initial_number_members
00533 || static_cast<CORBA::ULong> (minimum_number_members) > factory_infos_count)
00534 {
00535 unmet_criteria[uc].nam = name;
00536 unmet_criteria[uc++].val = value3;
00537 }
00538 else if (factory_infos_tmp != 0)
00539 {
00540 factory_infos.length (factory_infos_count);
00541 factory_infos = *factory_infos_tmp;
00542 }
00543 }
00544
00545 if (uc > 0)
00546 {
00547
00548
00549
00550
00551 unmet_criteria.length (uc);
00552
00553 throw PortableGroup::CannotMeetCriteria (unmet_criteria);
00554 }
00555 }
00556
00557 void
00558 TAO_PG_GenericFactory::check_minimum_number_members (
00559 PortableGroup::ObjectGroup_ptr object_group,
00560 CORBA::ULong group_id,
00561 const char * type_id)
00562 {
00563
00564
00565
00566
00567
00568
00569 TAO_PG_Factory_Map::ENTRY *entry = 0;
00570 if (this->factory_map_.find (group_id, entry) != 0)
00571 return;
00572
00573 TAO_PG_Factory_Set & factory_set = entry->int_id_;
00574
00575 PortableGroup::Properties_var props =
00576 this->property_manager_.get_properties (object_group);
00577
00578 PortableGroup::Name name (1);
00579 name.length (1);
00580
00581 PortableGroup::Value value;
00582
00583
00584 name[0].id =
00585 CORBA::string_dup ("org.omg.PortableGroup.MinimumNumberMembers");
00586
00587 PortableGroup::MinimumNumberMembersValue minimum_number_members;
00588
00589 if (TAO_PG::get_property_value (name, props.in (), value))
00590 {
00591 if (!(value >>= minimum_number_members))
00592 {
00593
00594
00595 throw CORBA::INTERNAL ();
00596 }
00597
00598 const CORBA::ULong count =
00599 this->object_group_manager_.member_count (object_group);
00600
00601 if (count >= static_cast<CORBA::ULong> (minimum_number_members))
00602 return;
00603
00604 const CORBA::ULong gap =
00605 static_cast<CORBA::ULong> (minimum_number_members) - count;
00606
00607 CORBA::ULong creation_count = 0;
00608
00609 const size_t len = factory_set.size ();
00610
00611 static const PortableGroup::GenericFactory::FactoryCreationId *
00612 nil_fcid = 0;
00613
00614 for (size_t i = 0; i < len; ++i)
00615 {
00616 TAO_PG_Factory_Node & node = factory_set[i];
00617
00618 PortableGroup::GenericFactory::FactoryCreationId * const tmp_fcid =
00619 node.factory_creation_id;
00620
00621
00622
00623 if (tmp_fcid != nil_fcid)
00624 continue;
00625
00626 try
00627 {
00628 const CORBA::Boolean propagate_member_already_present = 1;
00629
00630 node.factory_creation_id =
00631 this->create_member (object_group,
00632 node.factory_info,
00633 type_id,
00634 propagate_member_already_present);
00635
00636 ++creation_count;
00637
00638
00639
00640 if (gap == creation_count)
00641 return;
00642 }
00643 catch (const PortableGroup::MemberAlreadyPresent&)
00644 {
00645
00646 }
00647 }
00648
00649
00650
00651
00652 }
00653 }
00654
00655 PortableGroup::GenericFactory::FactoryCreationId *
00656 TAO_PG_GenericFactory::create_member (
00657 PortableGroup::ObjectGroup_ptr object_group,
00658 const PortableGroup::FactoryInfo & factory_info,
00659 const char * type_id,
00660 const CORBA::Boolean propagate_member_already_present)
00661 {
00662 PortableGroup::GenericFactory::FactoryCreationId_var fcid;
00663
00664 CORBA::Object_var member =
00665 factory_info.the_factory->create_object (type_id,
00666 factory_info.the_criteria,
00667 fcid.out ());
00668
00669 try
00670 {
00671
00672
00673
00674
00675
00676
00677
00678
00679 CORBA::Boolean right_type_id =
00680 member->_is_a (type_id);
00681
00682
00683 if (!right_type_id)
00684 {
00685
00686
00687 factory_info.the_factory->delete_object (fcid.in ());
00688
00689 throw PortableGroup::NoFactory (factory_info.the_location, type_id);
00690 }
00691
00692 this->object_group_manager_._tao_add_member (
00693 object_group,
00694 factory_info.the_location,
00695 member.in (),
00696 type_id,
00697 propagate_member_already_present);
00698 }
00699 catch (const CORBA::Exception&)
00700 {
00701
00702
00703
00704 if (!CORBA::is_nil (member.in ()))
00705 {
00706 factory_info.the_factory->delete_object (fcid.in ());
00707 }
00708
00709 throw;
00710 }
00711
00712 return fcid._retn ();
00713 }
00714
00715 TAO_END_VERSIONED_NAMESPACE_DECL