00001
00002
00003
00004 #include "orbsvcs/PortableGroup/PG_FactoryRegistry.h"
00005
00006 #include "ace/Get_Opt.h"
00007 #include "ace/Vector_T.h"
00008 #include "ace/OS_NS_stdio.h"
00009 #include "ace/OS_NS_unistd.h"
00010 #include "ace/Auto_Ptr.h"
00011 #include "tao/debug.h"
00012 #include "tao/ORB_Constants.h"
00013 #include "tao/PortableServer/POAManagerC.h"
00014 #include "orbsvcs/PortableGroup/PG_Operators.h"
00015
00016 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00017
00018
00019
00020 #define METHOD_ENTRY(name) \
00021 if (TAO_debug_level <= 6){} else \
00022 ACE_DEBUG (( LM_DEBUG, \
00023 "Enter %s\n", #name \
00024 ))
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #define METHOD_RETURN(name) \
00038 if (TAO_debug_level <= 6){} else \
00039 ACE_DEBUG (( LM_DEBUG, \
00040 "Leave %s\n", #name \
00041 )); \
00042 return
00043
00044 TAO::PG_FactoryRegistry::PG_FactoryRegistry (const char * name)
00045 : identity_(name)
00046 , orb_ (0)
00047 , poa_ (0)
00048 , object_id_ (0)
00049 , this_obj_ (0)
00050 , ior_output_file_(0)
00051 , ns_name_(0)
00052 , naming_context_(0)
00053 , this_name_(1)
00054 , quit_on_idle_(0)
00055 , quit_state_(LIVE)
00056 , linger_(0)
00057 {
00058 }
00059
00060 TAO::PG_FactoryRegistry::~PG_FactoryRegistry (void)
00061 {
00062 }
00063
00064
00065
00066
00067 int TAO::PG_FactoryRegistry::parse_args (int argc, char * argv[])
00068 {
00069 ACE_Get_Opt get_opts (argc, argv, "o:n:q");
00070 int c;
00071
00072 while ((c = get_opts ()) != -1)
00073 {
00074 switch (c)
00075 {
00076 case 'o':
00077 {
00078 this->ior_output_file_ = get_opts.opt_arg ();
00079 break;
00080 }
00081 case 'n':
00082 {
00083 this->ns_name_ = get_opts.opt_arg();
00084 break;
00085 }
00086 case 'q':
00087 {
00088 this->quit_on_idle_ = 1;
00089 break;
00090 }
00091
00092 case '?':
00093
00094 default:
00095 ACE_ERROR_RETURN ((LM_ERROR,
00096 "usage: %s"
00097 " -o <registry ior file>"
00098 " -n <name to use to register with name service>"
00099 " -q{uit on idle}"
00100 "\n",
00101 argv [0]),
00102 -1);
00103 break;
00104 }
00105 }
00106
00107 return 0;
00108 }
00109
00110 const char * TAO::PG_FactoryRegistry::identity () const
00111 {
00112 return this->identity_.c_str();
00113 }
00114
00115 void TAO::PG_FactoryRegistry::_remove_ref (void)
00116 {
00117 this->quit_state_ = GONE;
00118 }
00119
00120 int TAO::PG_FactoryRegistry::idle (int & result)
00121 {
00122 result = 0;
00123 int quit = 0;
00124 if (this->quit_state_ == GONE)
00125 {
00126 if (linger_ < 2)
00127 {
00128 ++linger_;
00129 }
00130 else
00131 {
00132 quit = 1;
00133 }
00134 }
00135 return quit;
00136 }
00137
00138
00139 int TAO::PG_FactoryRegistry::fini (void)
00140 {
00141 if (this->ior_output_file_ != 0)
00142 {
00143 ACE_OS::unlink (this->ior_output_file_);
00144 this->ior_output_file_ = 0;
00145 }
00146 if (this->ns_name_ != 0)
00147 {
00148 this->naming_context_->unbind (this_name_);
00149 this->ns_name_ = 0;
00150 }
00151 return 0;
00152 }
00153
00154
00155 void TAO::PG_FactoryRegistry::init (CORBA::ORB_ptr orb, PortableServer::POA_ptr poa)
00156 {
00157 ACE_ASSERT (CORBA::is_nil (this->orb_.in ()));
00158 ACE_ASSERT (CORBA::is_nil (this->poa_.in ()));
00159 this->orb_ = CORBA::ORB::_duplicate (orb);
00160 this->poa_ = PortableServer::POA::_duplicate (poa);
00161 ACE_ASSERT ( ! CORBA::is_nil (this->orb_.in ()));
00162 ACE_ASSERT ( ! CORBA::is_nil (this->poa_.in ()));
00163
00164
00165 this->object_id_ = this->poa_->activate_object (this);
00166
00167
00168 this->this_obj_ =
00169 this->poa_->id_to_reference (object_id_.in ());
00170
00171
00172 this->ior_ = this->orb_->object_to_string (this->this_obj_.in ());
00173
00174 }
00175
00176 int TAO::PG_FactoryRegistry::init (CORBA::ORB_ptr orb)
00177 {
00178 int result = 0;
00179
00180 this->orb_ = CORBA::ORB::_duplicate (orb);
00181
00182
00183 CORBA::Object_var poa_object =
00184 this->orb_->resolve_initial_references (TAO_OBJID_ROOTPOA);
00185
00186 if (CORBA::is_nil (poa_object.in ()))
00187 ACE_ERROR_RETURN ((LM_ERROR,
00188 ACE_TEXT (" (%P|%t) Unable to initialize the POA.\n")),
00189 -1);
00190
00191
00192 this->poa_ =
00193 PortableServer::POA::_narrow (poa_object.in ());
00194
00195
00196 if (CORBA::is_nil (this->poa_.in()))
00197 {
00198 ACE_ERROR_RETURN ((LM_ERROR,
00199 ACE_TEXT (" (%P|%t) Unable to narrow the POA.\n")),
00200 -1);
00201 }
00202
00203 PortableServer::POAManager_var poa_manager =
00204 this->poa_->the_POAManager ();
00205
00206 poa_manager->activate ();
00207
00208
00209 this->object_id_ = this->poa_->activate_object (this);
00210
00211
00212 this->this_obj_ =
00213 this->poa_->id_to_reference (object_id_.in ());
00214
00215
00216
00217 this->ior_ = this->orb_->object_to_string (this->this_obj_.in ());
00218
00219
00220 if (this->ior_output_file_ != 0)
00221 {
00222 this->identity_ = "file:";
00223 this->identity_ += this->ior_output_file_;
00224 result = write_ior_file (this->ior_output_file_,
00225 this->ior_.in ());
00226 }
00227
00228 if (this->ns_name_ != 0)
00229 {
00230 this->identity_ = "name:";
00231 this->identity_ += this->ns_name_;
00232
00233 CORBA::Object_var naming_obj =
00234 this->orb_->resolve_initial_references ("NameService");
00235
00236 if (CORBA::is_nil(naming_obj.in ())){
00237 ACE_ERROR_RETURN ((LM_ERROR,
00238 "%T %n (%P|%t) Unable to find the Naming Service\n"),
00239 1);
00240 }
00241
00242 this->naming_context_ =
00243 CosNaming::NamingContext::_narrow (naming_obj.in ());
00244
00245 this->this_name_.length (1);
00246 this->this_name_[0].id = CORBA::string_dup (this->ns_name_);
00247
00248 this->naming_context_->rebind (this->this_name_, this->this_obj_.in()
00249 );
00250 }
00251
00252 return result;
00253 }
00254
00255
00256 ::PortableGroup::FactoryRegistry_ptr TAO::PG_FactoryRegistry::reference()
00257 {
00258
00259 return ::PortableGroup::FactoryRegistry::_narrow(this->this_obj_.in ());
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 TAO::PG_FactoryRegistry::RoleInfo::RoleInfo(size_t estimated_number_entries)
00278 : infos_(estimated_number_entries)
00279 {
00280 }
00281
00282
00283 void TAO::PG_FactoryRegistry::register_factory (
00284 const char * role,
00285 const char * type_id,
00286 const PortableGroup::FactoryInfo & factory_info
00287 )
00288 {
00289 METHOD_ENTRY(TAO::PG_FactoryRegistry::register_factory);
00290
00291 RoleInfo * role_info = 0;
00292 auto_ptr<RoleInfo> safe_entry;
00293 if (this->registry_.find(role, role_info) != 0)
00294 {
00295 ACE_DEBUG(( LM_DEBUG,
00296 "%s: adding new role: %s:%s\n",
00297 this->identity_.c_str(), role, type_id));
00298
00299
00300
00301
00302 ACE_NEW_THROW_EX (role_info,
00303 RoleInfo(5),
00304 CORBA::NO_MEMORY());
00305
00306 ACE_AUTO_PTR_RESET (safe_entry, role_info, RoleInfo);
00307 role_info->type_id_ = type_id;
00308 }
00309 else
00310 {
00311 if (role_info->type_id_ != type_id)
00312 {
00313 throw PortableGroup::TypeConflict();
00314 }
00315 }
00316
00317 PortableGroup::FactoryInfos & infos = role_info->infos_;;
00318 size_t length = infos.length();
00319 for (size_t nInfo = 0; nInfo < length; ++nInfo)
00320 {
00321 PortableGroup::FactoryInfo & info = infos[nInfo];
00322 if (info.the_location == factory_info.the_location)
00323 {
00324 ACE_ERROR(( LM_ERROR,
00325 "%s: Attempt to register duplicate location %s for role: %s\n" ,
00326 this->identity_.c_str(),
00327 static_cast<const char *> (info.the_location[0].id),
00328 role));
00329 throw PortableGroup::MemberAlreadyPresent();
00330 }
00331 }
00332
00333 infos.length(length + 1);
00334 infos[length] = factory_info;
00335
00336 if (safe_entry.get() != 0)
00337 {
00338 this->registry_.bind(role, safe_entry.release());
00339 }
00340
00341 ACE_DEBUG(( LM_DEBUG,
00342 "%s: Added factory: [%d] %s@%s \n",
00343 this->identity_.c_str(),
00344 static_cast<int> (length + 1),
00345 role,
00346 static_cast<const char *> (factory_info.the_location[0].id)
00347 ));
00348
00349 METHOD_RETURN(TAO::PG_FactoryRegistry::register_factory);
00350 }
00351
00352 void TAO::PG_FactoryRegistry::unregister_factory (
00353 const char * role,
00354 const PortableGroup::Location & location
00355 )
00356 {
00357 METHOD_ENTRY(TAO::PG_FactoryRegistry::unregister_factory);
00358
00359 RoleInfo * role_info = 0;
00360 if (this->registry_.find(role, role_info) == 0)
00361 {
00362 PortableGroup::FactoryInfos & infos = role_info->infos_;
00363 int found = 0;
00364 size_t length = infos.length();
00365 for (size_t nInfo = 0; !found && nInfo < length; ++nInfo)
00366 {
00367 PortableGroup::FactoryInfo & info = infos[nInfo];
00368 if (info.the_location == location)
00369 {
00370 found = 1;
00371
00372 ACE_ERROR(( LM_INFO,
00373 "%s: Unregistering factory %s@%s\n",
00374 this->identity_.c_str(),
00375 role,
00376 static_cast<const char *> (location[0].id)
00377 ));
00378 if (length > 1)
00379 {
00380
00381 if (nInfo + 1 < length)
00382 {
00383
00384 infos[nInfo] = infos[length - 1];
00385 nInfo = length -1;
00386 }
00387 infos.length(nInfo);
00388 }
00389 else
00390 {
00391 ACE_ASSERT ( length == 1 );
00392 if (this->registry_.unbind (role) == 0)
00393 {
00394 ACE_DEBUG(( LM_INFO,
00395 "%s: No more factories registered for %s\n",
00396 this->identity_.c_str(),
00397 role
00398 ));
00399 delete role_info;
00400 }
00401 else
00402 {
00403 ACE_ERROR ((LM_ERROR,
00404 "%s: LOGIC ERROR AT " __FILE__ " (%d): Entry to be deleted disappeared\n",
00405 this->identity_.c_str(),
00406 __LINE__));
00407 }
00408 }
00409 }
00410 }
00411 }
00412 else
00413 {
00414 ACE_ERROR(( LM_ERROR,
00415 "%s, Attempt to unregister factory for unknown role %s\n",
00416 this->identity_.c_str(),
00417 role
00418 ));
00419 throw PortableGroup::MemberNotFound();
00420 }
00421
00422
00423
00424
00425 if (registry_.current_size() == 0 && quit_state_ == LIVE)
00426 {
00427 ACE_ERROR(( LM_INFO,
00428 "%s is idle\n",
00429 identity()
00430 ));
00431 if (quit_on_idle_)
00432 {
00433 this->poa_->deactivate_object (this->object_id_.in ());
00434 quit_state_ = DEACTIVATED;
00435 }
00436 }
00437
00438 METHOD_RETURN(TAO::PG_FactoryRegistry::unregister_factory);
00439 }
00440
00441 void TAO::PG_FactoryRegistry::unregister_factory_by_role (
00442 const char * role
00443 )
00444 {
00445 METHOD_ENTRY(TAO::PG_FactoryRegistry::unregister_factory_by_role);
00446
00447 RoleInfo * role_info = 0;
00448 if (this->registry_.unbind(role, role_info) == 0)
00449 {
00450 ACE_DEBUG(( LM_DEBUG,
00451 "%s: Unregistering all factories for role %s\n",
00452 this->identity_.c_str(),
00453 role
00454 ));
00455
00456 delete role_info;
00457 }
00458 else
00459 {
00460 ACE_ERROR(( LM_INFO,
00461 "%s: Unregister_factory_by_role: unknown role: %s\n",
00462 this->identity_.c_str(),
00463 role
00464 ));
00465 }
00466
00467
00468
00469
00470 if (registry_.current_size() == 0 && quit_state_ == LIVE)
00471 {
00472 ACE_ERROR(( LM_INFO,
00473 "%s is idle\n",
00474 identity()
00475 ));
00476 if (quit_on_idle_)
00477 {
00478 this->poa_->deactivate_object (this->object_id_.in ());
00479 quit_state_ = DEACTIVATED;
00480 }
00481 }
00482
00483 METHOD_RETURN(TAO::PG_FactoryRegistry::unregister_factory_by_role);
00484 }
00485
00486 void TAO::PG_FactoryRegistry::unregister_factory_by_location (
00487 const PortableGroup::Location & location
00488 )
00489 {
00490 METHOD_ENTRY(TAO::PG_FactoryRegistry::unregister_factory_by_location);
00491
00492
00493
00494 ACE_Vector<ACE_CString> emptyRoles;
00495
00496
00497 for (RegistryType_Iterator it = this->registry_.begin();
00498 it != this->registry_.end();
00499 ++it)
00500 {
00501 RegistryType_Entry & entry = *it;
00502 ACE_CString & role = entry.ext_id_;
00503 RoleInfo * role_info = entry.int_id_;
00504
00505 PortableGroup::FactoryInfos & infos = role_info->infos_;
00506
00507
00508 int found = 0;
00509 size_t length = infos.length();
00510 for (size_t nInfo = 0; !found && nInfo < length; ++nInfo)
00511 {
00512 PortableGroup::FactoryInfo & info = infos[nInfo];
00513 if (info.the_location == location)
00514 {
00515
00516 ACE_ERROR((LM_INFO,
00517 "%s: Unregister_factory_by_location: Removing: [%d] %s@%s\n",
00518 this->identity_.c_str(),
00519 static_cast<int> (nInfo),
00520 role.c_str(),
00521 static_cast<const char *> (location[0].id)
00522 ));
00523 found = 1;
00524 if (length > 1)
00525 {
00526 while (nInfo + 1 < length)
00527 {
00528 ACE_ERROR((LM_INFO,
00529 "%s: Unregister_factory_by_location: Move: [%d] %s to [%d]\n",
00530 this->identity_.c_str(),
00531 (int)nInfo + 1, role.c_str(), (int)nInfo
00532 ));
00533 infos[nInfo] = infos[nInfo + 1];
00534 nInfo += 1;
00535 }
00536 ACE_ERROR((LM_INFO,
00537 "%s: unregister_factory_by_location: New length [%d] %s\n",
00538 this->identity_.c_str(),
00539 (int)nInfo, role.c_str()
00540 ));
00541 infos.length(nInfo);
00542 }
00543 else
00544 {
00545 ACE_ERROR((LM_INFO,
00546 "%s: Removed all entries for %s\n",
00547 this->identity_.c_str(),
00548 role.c_str()
00549 ));
00550 ACE_ASSERT ( length == 1 );
00551
00552 emptyRoles.push_back(entry.ext_id_);
00553 }
00554 }
00555 }
00556 }
00557
00558
00559
00560 for (size_t nRole = 0; nRole < emptyRoles.size(); ++nRole)
00561 {
00562 ACE_ERROR((LM_INFO,
00563 "%s: Remove role %s\n",
00564 this->identity_.c_str(),
00565 emptyRoles[nRole].c_str()
00566 ));
00567 RoleInfo * role_info;
00568 if (this->registry_.unbind(emptyRoles[nRole], role_info) == 0)
00569 {
00570 delete role_info;
00571 }
00572 else
00573 {
00574 ACE_ERROR ((LM_ERROR,
00575 "%s: LOGIC ERROR AT " __FILE__ " (%d): Role to be deleted disappeared\n",
00576 this->identity_.c_str(),
00577 __LINE__));
00578 }
00579 }
00580
00581
00582 if (registry_.current_size() == 0 && quit_state_ == LIVE)
00583 {
00584 ACE_ERROR(( LM_INFO,
00585 "%s is idle\n",
00586 identity()
00587 ));
00588 if (quit_on_idle_)
00589 {
00590 this->poa_->deactivate_object (this->object_id_.in ());
00591 quit_state_ = DEACTIVATED;
00592 }
00593 }
00594
00595 METHOD_RETURN(TAO::PG_FactoryRegistry::unregister_factory_by_location);
00596 }
00597
00598 ::PortableGroup::FactoryInfos * TAO::PG_FactoryRegistry::list_factories_by_role (
00599 const char * role,
00600 CORBA::String_out type_id
00601 )
00602 {
00603 METHOD_ENTRY(TAO::PG_FactoryRegistry::list_factories_by_role);
00604
00605
00606 PortableGroup::FactoryInfos_var result = 0;
00607 ACE_NEW_THROW_EX (result, ::PortableGroup::FactoryInfos(),
00608 CORBA::NO_MEMORY (TAO::VMCID, CORBA::COMPLETED_NO));
00609
00610
00611 RoleInfo * role_info = 0;
00612 if (this->registry_.find(role, role_info) == 0)
00613 {
00614 type_id = CORBA::string_dup(role_info->type_id_.c_str());
00615 (*result) = role_info->infos_;
00616 }
00617 else
00618 {
00619 type_id = CORBA::string_dup("");
00620 ACE_ERROR(( LM_INFO,
00621 "%s: list_factories_by_role: unknown role %s\n",
00622 this->identity_.c_str(),
00623 role
00624 ));
00625 }
00626 METHOD_RETURN(TAO::PG_FactoryRegistry::list_factories_by_role) result._retn();
00627 }
00628
00629 ::PortableGroup::FactoryInfos * TAO::PG_FactoryRegistry::list_factories_by_location (
00630 const PortableGroup::Location & location
00631 )
00632 {
00633 METHOD_ENTRY(TAO::PG_FactoryRegistry::list_factories_by_location);
00634 ::PortableGroup::FactoryInfos_var result;
00635 ACE_NEW_THROW_EX (result, ::PortableGroup::FactoryInfos(this->registry_.current_size()),
00636 CORBA::NO_MEMORY (TAO::VMCID, CORBA::COMPLETED_NO));
00637
00638
00639 size_t result_length = 0;
00640
00641
00642 for (RegistryType_Iterator it = this->registry_.begin();
00643 it != this->registry_.end();
00644 ++it)
00645 {
00646 RegistryType_Entry & entry = *it;
00647 RoleInfo * role_info = entry.int_id_;
00648
00649 PortableGroup::FactoryInfos & found_infos = role_info->infos_;
00650
00651 int found = 0;
00652 size_t length = found_infos.length();
00653 for (size_t nInfo = 0; !found && nInfo < length; ++nInfo)
00654 {
00655 PortableGroup::FactoryInfo & info = found_infos[nInfo];
00656 if (info.the_location == location)
00657 {
00658 found = 1;
00659 result_length += 1;
00660 result->length(result_length);
00661 (*result)[result_length-1] = info;
00662 }
00663 }
00664 }
00665
00666 METHOD_RETURN(TAO::PG_FactoryRegistry::list_factories_by_location) result._retn();
00667 }
00668
00669
00670
00671
00672 int TAO::PG_FactoryRegistry::write_ior_file(const char * outputFile, const char * ior)
00673 {
00674 int result = -1;
00675 FILE* out = ACE_OS::fopen (outputFile, "w");
00676 if (out)
00677 {
00678 ACE_OS::fprintf (out, "%s", ior);
00679 ACE_OS::fclose (out);
00680 result = 0;
00681 }
00682 else
00683 {
00684 ACE_ERROR ((LM_ERROR,
00685 "Open failed for %s\n", outputFile
00686 ));
00687 }
00688 return result;
00689 }
00690
00691 TAO_END_VERSIONED_NAMESPACE_DECL