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_("")
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, ACE_TCHAR * argv[])
00068 {
00069 ACE_Get_Opt get_opts (argc, argv, ACE_TEXT("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_ = ACE_TEXT_ALWAYS_CHAR(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_.length () != 0)
00147 {
00148 this->naming_context_->unbind (this_name_);
00149 this->ns_name_ = "";
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 if (this->ior_output_file_ != 0)
00220 {
00221 this->identity_ = "file:";
00222 this->identity_ += ACE_TEXT_ALWAYS_CHAR(this->ior_output_file_);
00223 result = write_ior_file (this->ior_output_file_,
00224 this->ior_.in ());
00225 }
00226
00227 if (this->ns_name_.length () != 0)
00228 {
00229 this->identity_ = "name:";
00230 this->identity_ += this->ns_name_;
00231
00232 CORBA::Object_var naming_obj =
00233 this->orb_->resolve_initial_references ("NameService");
00234
00235 if (CORBA::is_nil(naming_obj.in ())){
00236 ACE_ERROR_RETURN ((LM_ERROR,
00237 "%T %n (%P|%t) Unable to find the Naming Service\n"),
00238 1);
00239 }
00240
00241 this->naming_context_ =
00242 CosNaming::NamingContext::_narrow (naming_obj.in ());
00243
00244 this->this_name_.length (1);
00245 this->this_name_[0].id = CORBA::string_dup (this->ns_name_.c_str ());
00246
00247 this->naming_context_->rebind (this->this_name_, this->this_obj_.in()
00248 );
00249 }
00250
00251 return result;
00252 }
00253
00254
00255 ::PortableGroup::FactoryRegistry_ptr TAO::PG_FactoryRegistry::reference()
00256 {
00257
00258 return ::PortableGroup::FactoryRegistry::_narrow(this->this_obj_.in ());
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 TAO::PG_FactoryRegistry::RoleInfo::RoleInfo(size_t estimated_number_entries)
00277 : infos_(estimated_number_entries)
00278 {
00279 }
00280
00281
00282 void TAO::PG_FactoryRegistry::register_factory (
00283 const char * role,
00284 const char * type_id,
00285 const PortableGroup::FactoryInfo & factory_info
00286 )
00287 {
00288 METHOD_ENTRY(TAO::PG_FactoryRegistry::register_factory);
00289
00290 RoleInfo * role_info = 0;
00291 auto_ptr<RoleInfo> safe_entry;
00292 if (this->registry_.find(role, role_info) != 0)
00293 {
00294 ACE_DEBUG(( LM_DEBUG,
00295 "%s: adding new role: %s:%s\n",
00296 this->identity_.c_str(), role, type_id));
00297
00298
00299
00300
00301 ACE_NEW_THROW_EX (role_info,
00302 RoleInfo(5),
00303 CORBA::NO_MEMORY());
00304
00305 ACE_AUTO_PTR_RESET (safe_entry, role_info, RoleInfo);
00306 role_info->type_id_ = type_id;
00307 }
00308 else
00309 {
00310 if (role_info->type_id_ != type_id)
00311 {
00312 throw PortableGroup::TypeConflict();
00313 }
00314 }
00315
00316 PortableGroup::FactoryInfos & infos = role_info->infos_;;
00317 size_t length = infos.length();
00318 for (size_t nInfo = 0; nInfo < length; ++nInfo)
00319 {
00320 PortableGroup::FactoryInfo & info = infos[nInfo];
00321 if (info.the_location == factory_info.the_location)
00322 {
00323 ACE_ERROR(( LM_ERROR,
00324 "%s: Attempt to register duplicate location %s for role: %s\n" ,
00325 this->identity_.c_str(),
00326 static_cast<const char *> (info.the_location[0].id),
00327 role));
00328 throw PortableGroup::MemberAlreadyPresent();
00329 }
00330 }
00331
00332 infos.length(length + 1);
00333 infos[length] = factory_info;
00334
00335 if (safe_entry.get() != 0)
00336 {
00337 this->registry_.bind(role, safe_entry.release());
00338 }
00339
00340 ACE_DEBUG(( LM_DEBUG,
00341 "%s: Added factory: [%d] %s@%s\n",
00342 this->identity_.c_str(),
00343 static_cast<int> (length + 1),
00344 role,
00345 static_cast<const char *> (factory_info.the_location[0].id)
00346 ));
00347
00348 METHOD_RETURN(TAO::PG_FactoryRegistry::register_factory);
00349 }
00350
00351 void TAO::PG_FactoryRegistry::unregister_factory (
00352 const char * role,
00353 const PortableGroup::Location & location
00354 )
00355 {
00356 METHOD_ENTRY(TAO::PG_FactoryRegistry::unregister_factory);
00357
00358 RoleInfo * role_info = 0;
00359 if (this->registry_.find(role, role_info) == 0)
00360 {
00361 PortableGroup::FactoryInfos & infos = role_info->infos_;
00362 int found = 0;
00363 size_t length = infos.length();
00364 for (size_t nInfo = 0; !found && nInfo < length; ++nInfo)
00365 {
00366 PortableGroup::FactoryInfo & info = infos[nInfo];
00367 if (info.the_location == location)
00368 {
00369 found = 1;
00370
00371 ACE_ERROR(( LM_INFO,
00372 "%s: Unregistering factory %s@%s\n",
00373 this->identity_.c_str(),
00374 role,
00375 static_cast<const char *> (location[0].id)
00376 ));
00377 if (length > 1)
00378 {
00379
00380 if (nInfo + 1 < length)
00381 {
00382
00383 infos[nInfo] = infos[length - 1];
00384 nInfo = length -1;
00385 }
00386 infos.length(nInfo);
00387 }
00388 else
00389 {
00390 ACE_ASSERT ( length == 1 );
00391 if (this->registry_.unbind (role) == 0)
00392 {
00393 ACE_DEBUG(( LM_INFO,
00394 "%s: No more factories registered for %s\n",
00395 this->identity_.c_str(),
00396 role
00397 ));
00398 delete role_info;
00399 }
00400 else
00401 {
00402 ACE_ERROR ((LM_ERROR,
00403 "%s: LOGIC ERROR AT " __FILE__ " (%d): Entry to be deleted disappeared\n",
00404 this->identity_.c_str(),
00405 __LINE__));
00406 }
00407 }
00408 }
00409 }
00410 }
00411 else
00412 {
00413 ACE_ERROR(( LM_ERROR,
00414 "%s, Attempt to unregister factory for unknown role %s\n",
00415 this->identity_.c_str(),
00416 role
00417 ));
00418 throw PortableGroup::MemberNotFound();
00419 }
00420
00421
00422
00423
00424 if (registry_.current_size() == 0 && quit_state_ == LIVE)
00425 {
00426 ACE_ERROR(( LM_INFO,
00427 "%s is idle\n",
00428 identity()
00429 ));
00430 if (quit_on_idle_)
00431 {
00432 this->poa_->deactivate_object (this->object_id_.in ());
00433 quit_state_ = DEACTIVATED;
00434 }
00435 }
00436
00437 METHOD_RETURN(TAO::PG_FactoryRegistry::unregister_factory);
00438 }
00439
00440 void TAO::PG_FactoryRegistry::unregister_factory_by_role (
00441 const char * role
00442 )
00443 {
00444 METHOD_ENTRY(TAO::PG_FactoryRegistry::unregister_factory_by_role);
00445
00446 RoleInfo * role_info = 0;
00447 if (this->registry_.unbind(role, role_info) == 0)
00448 {
00449 ACE_DEBUG(( LM_DEBUG,
00450 "%s: Unregistering all factories for role %s\n",
00451 this->identity_.c_str(),
00452 role
00453 ));
00454
00455 delete role_info;
00456 }
00457 else
00458 {
00459 ACE_ERROR(( LM_INFO,
00460 "%s: Unregister_factory_by_role: unknown role: %s\n",
00461 this->identity_.c_str(),
00462 role
00463 ));
00464 }
00465
00466
00467
00468
00469 if (registry_.current_size() == 0 && quit_state_ == LIVE)
00470 {
00471 ACE_ERROR(( LM_INFO,
00472 "%s is idle\n",
00473 identity()
00474 ));
00475 if (quit_on_idle_)
00476 {
00477 this->poa_->deactivate_object (this->object_id_.in ());
00478 quit_state_ = DEACTIVATED;
00479 }
00480 }
00481
00482 METHOD_RETURN(TAO::PG_FactoryRegistry::unregister_factory_by_role);
00483 }
00484
00485 void TAO::PG_FactoryRegistry::unregister_factory_by_location (
00486 const PortableGroup::Location & location
00487 )
00488 {
00489 METHOD_ENTRY(TAO::PG_FactoryRegistry::unregister_factory_by_location);
00490
00491
00492
00493 ACE_Vector<ACE_CString> emptyRoles;
00494
00495
00496 for (RegistryType_Iterator it = this->registry_.begin();
00497 it != this->registry_.end();
00498 ++it)
00499 {
00500 RegistryType_Entry & entry = *it;
00501 ACE_CString & role = entry.ext_id_;
00502 RoleInfo * role_info = entry.int_id_;
00503
00504 PortableGroup::FactoryInfos & infos = role_info->infos_;
00505
00506
00507 int found = 0;
00508 size_t length = infos.length();
00509 for (size_t nInfo = 0; !found && nInfo < length; ++nInfo)
00510 {
00511 PortableGroup::FactoryInfo & info = infos[nInfo];
00512 if (info.the_location == location)
00513 {
00514
00515 ACE_ERROR((LM_INFO,
00516 "%s: Unregister_factory_by_location: Removing: [%d] %s@%s\n",
00517 this->identity_.c_str(),
00518 static_cast<int> (nInfo),
00519 role.c_str(),
00520 static_cast<const char *> (location[0].id)
00521 ));
00522 found = 1;
00523 if (length > 1)
00524 {
00525 while (nInfo + 1 < length)
00526 {
00527 ACE_ERROR((LM_INFO,
00528 "%s: Unregister_factory_by_location: Move: [%d] %s to [%d]\n",
00529 this->identity_.c_str(),
00530 (int)nInfo + 1, role.c_str(), (int)nInfo
00531 ));
00532 infos[nInfo] = infos[nInfo + 1];
00533 nInfo += 1;
00534 }
00535 ACE_ERROR((LM_INFO,
00536 "%s: unregister_factory_by_location: New length [%d] %s\n",
00537 this->identity_.c_str(),
00538 (int)nInfo, role.c_str()
00539 ));
00540 infos.length(nInfo);
00541 }
00542 else
00543 {
00544 ACE_ERROR((LM_INFO,
00545 "%s: Removed all entries for %s\n",
00546 this->identity_.c_str(),
00547 role.c_str()
00548 ));
00549 ACE_ASSERT ( length == 1 );
00550
00551 emptyRoles.push_back(entry.ext_id_);
00552 }
00553 }
00554 }
00555 }
00556
00557
00558
00559 for (size_t nRole = 0; nRole < emptyRoles.size(); ++nRole)
00560 {
00561 ACE_ERROR((LM_INFO,
00562 "%s: Remove role %s\n",
00563 this->identity_.c_str(),
00564 emptyRoles[nRole].c_str()
00565 ));
00566 RoleInfo * role_info;
00567 if (this->registry_.unbind(emptyRoles[nRole], role_info) == 0)
00568 {
00569 delete role_info;
00570 }
00571 else
00572 {
00573 ACE_ERROR ((LM_ERROR,
00574 "%s: LOGIC ERROR AT " __FILE__ " (%d): Role to be deleted disappeared\n",
00575 this->identity_.c_str(),
00576 __LINE__));
00577 }
00578 }
00579
00580
00581 if (registry_.current_size() == 0 && quit_state_ == LIVE)
00582 {
00583 ACE_ERROR(( LM_INFO,
00584 "%s is idle\n",
00585 identity()
00586 ));
00587 if (quit_on_idle_)
00588 {
00589 this->poa_->deactivate_object (this->object_id_.in ());
00590 quit_state_ = DEACTIVATED;
00591 }
00592 }
00593
00594 METHOD_RETURN(TAO::PG_FactoryRegistry::unregister_factory_by_location);
00595 }
00596
00597 ::PortableGroup::FactoryInfos * TAO::PG_FactoryRegistry::list_factories_by_role (
00598 const char * role,
00599 CORBA::String_out type_id
00600 )
00601 {
00602 METHOD_ENTRY(TAO::PG_FactoryRegistry::list_factories_by_role);
00603
00604
00605 PortableGroup::FactoryInfos_var result = 0;
00606 ACE_NEW_THROW_EX (result, ::PortableGroup::FactoryInfos(),
00607 CORBA::NO_MEMORY (TAO::VMCID, CORBA::COMPLETED_NO));
00608
00609
00610 RoleInfo * role_info = 0;
00611 if (this->registry_.find(role, role_info) == 0)
00612 {
00613 type_id = CORBA::string_dup(role_info->type_id_.c_str());
00614 (*result) = role_info->infos_;
00615 }
00616 else
00617 {
00618 type_id = CORBA::string_dup("");
00619 ACE_ERROR(( LM_INFO,
00620 "%s: list_factories_by_role: unknown role %s\n",
00621 this->identity_.c_str(),
00622 role
00623 ));
00624 }
00625 METHOD_RETURN(TAO::PG_FactoryRegistry::list_factories_by_role) result._retn();
00626 }
00627
00628 ::PortableGroup::FactoryInfos * TAO::PG_FactoryRegistry::list_factories_by_location (
00629 const PortableGroup::Location & location
00630 )
00631 {
00632 METHOD_ENTRY(TAO::PG_FactoryRegistry::list_factories_by_location);
00633 ::PortableGroup::FactoryInfos_var result;
00634 ACE_NEW_THROW_EX (result, ::PortableGroup::FactoryInfos(this->registry_.current_size()),
00635 CORBA::NO_MEMORY (TAO::VMCID, CORBA::COMPLETED_NO));
00636
00637
00638 size_t result_length = 0;
00639
00640
00641 for (RegistryType_Iterator it = this->registry_.begin();
00642 it != this->registry_.end();
00643 ++it)
00644 {
00645 RegistryType_Entry & entry = *it;
00646 RoleInfo * role_info = entry.int_id_;
00647
00648 PortableGroup::FactoryInfos & found_infos = role_info->infos_;
00649
00650 int found = 0;
00651 size_t length = found_infos.length();
00652 for (size_t nInfo = 0; !found && nInfo < length; ++nInfo)
00653 {
00654 PortableGroup::FactoryInfo & info = found_infos[nInfo];
00655 if (info.the_location == location)
00656 {
00657 found = 1;
00658 result_length += 1;
00659 result->length(result_length);
00660 (*result)[result_length-1] = info;
00661 }
00662 }
00663 }
00664
00665 METHOD_RETURN(TAO::PG_FactoryRegistry::list_factories_by_location) result._retn();
00666 }
00667
00668
00669
00670
00671 int TAO::PG_FactoryRegistry::write_ior_file(const ACE_TCHAR * outputFile, const char * ior)
00672 {
00673 int result = -1;
00674 FILE* out = ACE_OS::fopen (outputFile, "w");
00675 if (out)
00676 {
00677 ACE_OS::fprintf (out, "%s", ior);
00678 ACE_OS::fclose (out);
00679 result = 0;
00680 }
00681 else
00682 {
00683 ACE_ERROR ((LM_ERROR,
00684 "Open failed for %s\n", outputFile
00685 ));
00686 }
00687 return result;
00688 }
00689
00690 TAO_END_VERSIONED_NAMESPACE_DECL