PG_FactoryRegistry.cpp

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 // $Id: PG_FactoryRegistry.cpp 77001 2007-02-12 07:54:49Z johnnyw $
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" // operator == on CosNaming::Name
00015 
00016 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00017 
00018 // Use this macro at the beginning of CORBA methods
00019 // to aid in debugging.
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 // Use this macro to return from CORBA methods
00027 // to aid in debugging.  Note that you can specify
00028 // the return value after the macro, for example:
00029 // METHOD_RETURN(Plugh::plover) xyzzy; is equivalent
00030 // to return xyzzy;
00031 // METHOD_RETURN(Plugh::troll); is equivalent to
00032 // return;
00033 // WARNING: THIS GENERATES TWO STATEMENTS!!! THE FOLLOWING
00034 // will not do what you want it to:
00035 //  if (cave_is_closing) METHOD_RETURN(Plugh::pirate) aarrggh;
00036 // Moral:  Always use braces.
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 /* value goes here */
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 // PG_FactoryRegistry public, non-CORBA methods
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         // fall thru
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   // Indicates sucessful parsing of the command line
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   // Register with the POA.
00165   this->object_id_ = this->poa_->activate_object (this);
00166 
00167   // find my identity as a corba object
00168   this->this_obj_ =
00169     this->poa_->id_to_reference (object_id_.in ());
00170 
00171   // and create a ior string
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   // Use the ROOT POA for now
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   // Get the POA object.
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   // Register with the POA.
00209   this->object_id_ = this->poa_->activate_object (this);
00210 
00211   // find my identity as a corba object
00212   this->this_obj_ =
00213     this->poa_->id_to_reference (object_id_.in ());
00214 
00215 
00216   // and create a ior string
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()  //CORBA::Object::_duplicate(this_obj)
00249                             );
00250   }
00251 
00252   return result;
00253 }
00254 
00255 
00256 ::PortableGroup::FactoryRegistry_ptr TAO::PG_FactoryRegistry::reference()
00257 {
00258   // narrow and duplicate
00259   return ::PortableGroup::FactoryRegistry::_narrow(this->this_obj_.in ());
00260 }
00261 
00262 
00263 //////////////////////////////////////////
00264 // PG_FactoryRegistry CORBA methods
00265 
00266 /* Reference:info
00267   typedef CosNaming::Name Name;
00268   typedef Name Location;
00269   struct FactoryInfo {
00270     GenericFactory the_factory;
00271     Location the_location;
00272     Criteria the_criteria;
00273   };
00274   typedef sequence<FactoryInfo> FactoryInfos;
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       // Note the 5.  It's a guess about the number of factories
00300       // that might exist for any particular role object.
00301       // todo: make it a parameter.
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           // if this is not the last entry
00381           if (nInfo + 1 < length)
00382           {
00383             // move last entry into newly-emptied slot
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   // request complete
00424   // check quit-on-idle
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     // delete the entire set of factories for this location.
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   // Function complete
00469   // check quit options
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   // a vector of roles that need to be deleted.
00494   ACE_Vector<ACE_CString> emptyRoles;
00495 
00496   // iterate through the registery
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     // ACE_ERROR((LM_INFO,  "unregister_factory_by_location: Checking role %s\n", role.c_str()  ));
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           // remember entries to be deleted
00552           emptyRoles.push_back(entry.ext_id_);
00553         }
00554       }
00555     }
00556   }
00557 
00558   // now remove any roles that became empty
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   // If all types are gone...
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   // allocate stucture to be returned.
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   // iterate through the registery
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     // iterate through the entry for this type
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 // Implementation methods
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

Generated on Sun Jan 27 16:22:30 2008 for TAO_PortableGroup by doxygen 1.3.6