Service_Gestalt.cpp

Go to the documentation of this file.
00001 // Service_Gestalt.cpp,v 4.18 2006/06/22 05:34:51 jeliazkov_i Exp
00002 
00003 #include "ace/Svc_Conf.h"
00004 #include "ace/Get_Opt.h"
00005 #include "ace/ARGV.h"
00006 #include "ace/Malloc.h"
00007 #include "ace/Service_Manager.h"
00008 #include "ace/Service_Types.h"
00009 #include "ace/Containers.h"
00010 #include "ace/Auto_Ptr.h"
00011 #include "ace/Reactor.h"
00012 #include "ace/Thread_Manager.h"
00013 #include "ace/DLL.h"
00014 #include "ace/XML_Svc_Conf.h"
00015 #include "ace/SString.h"
00016 
00017 #ifndef ACE_LACKS_UNIX_SIGNALS
00018 # include "ace/Signal.h"
00019 #endif  /* !ACE_LACKS_UNIX_SIGNALS */
00020 
00021 #include "ace/OS_NS_stdio.h"
00022 #include "ace/OS_NS_string.h"
00023 #include "ace/OS_NS_time.h"
00024 #include "ace/OS_NS_unistd.h"
00025 #include "ace/OS_NS_sys_stat.h"
00026 
00027 #include "ace/TSS_T.h"
00028 #include "ace/Service_Gestalt.h"
00029 
00030 #include "ace/Svc_Conf_Param.h"
00031 
00032 ACE_RCSID (ace,
00033            Service_Gestalt,
00034            "Service_Gestalt.cpp,v 4.18 2006/06/22 05:34:51 jeliazkov_i Exp")
00035 
00036   ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00037 
00038 // This is here, in the implementation, because it depends on the ACE_DLL type,
00039 // which would be unnecessary to introduuce all over the place, had we declared
00040 // this in the header file.
00041 
00042 // A forward service declaration guard. Used to declare a Service Type with a
00043 // specific name in a Service Repository, which may later be replaced by the
00044 // "real" Service Type. The only application is in the implementation of
00045 // ACE_Service_Gestalt::initialize (), hence the declaration scoping in
00046 // this file.
00047 class ACE_Service_Type_Forward_Declaration_Guard
00048 {
00049 public:
00050   ACE_Service_Type_Forward_Declaration_Guard (ACE_Service_Repository *r,
00051                                               ACE_TCHAR const *name);
00052 
00053   ~ACE_Service_Type_Forward_Declaration_Guard (void);
00054 
00055 private:
00056   const ACE_DLL dummy_dll_;
00057   ACE_Service_Repository *repo_;
00058   ACE_TCHAR const * const name_;
00059   ACE_Service_Type const * dummy_;
00060 };
00061 
00062 ACE_Service_Type_Forward_Declaration_Guard::ACE_Service_Type_Forward_Declaration_Guard
00063   (ACE_Service_Repository *r, const ACE_TCHAR *name)
00064     : repo_ (r)
00065     , name_ (name)
00066 {
00067   ACE_ASSERT (this->repo_ != 0); // No repository specified?
00068   ACE_ASSERT (this->name_ != 0); // No name?
00069 
00070   ACE_NEW_NORETURN (this->dummy_, // Allocate the forward declaration ...
00071                     ACE_Service_Type (this->name_,  // ... use the same name
00072                                       0,            // ... inactive
00073                                       this->dummy_dll_, // ... bogus ACE_DLL
00074                                       0));              // ... no type_impl
00075 
00076   ACE_ASSERT (this->dummy_ != 0); // No memory?
00077 
00078   if(ACE::debug ())
00079     ACE_DEBUG ((LM_DEBUG,
00080                 ACE_LIB_TEXT ("(%P|%t) FWDCL::start, repo=%@, \'%s\' ")
00081                 ACE_LIB_TEXT ("- type=%@ (impl=(nil))\n"),
00082                 this->repo_,
00083                 this->name_,
00084                 this->dummy_));
00085 
00086   // Note that the dummy_'s memory can disaper between invoking
00087   // the ctor and dtor, if the expected "real" dynamic service is
00088   // inserted in the repository.
00089   this->repo_->insert (this->dummy_);
00090 }
00091 
00092 ACE_Service_Type_Forward_Declaration_Guard::~ACE_Service_Type_Forward_Declaration_Guard (void)
00093 {
00094   const ACE_Service_Type *tmp = 0;
00095 
00096   // Lookup without ignoring suspended services. Making sure
00097   // not to ignore any inactive services, since those may be forward
00098   // declarations
00099   int ret = this->repo_->find (this->name_, &tmp, 0);
00100 
00101   // We inserted it (as inactive), so we expect to find it, right?
00102   if (ret < 0 && ret != -2)
00103     {
00104       if(ACE::debug ())
00105         ACE_ERROR ((LM_WARNING,
00106                     ACE_LIB_TEXT ("(%P|%t) FWDCL::end - Failed (%d) to find %s\n"),
00107                     ret, this->name_));
00108       return;
00109     }
00110 
00111   if (tmp != 0 && tmp->type () != 0)
00112     {
00113       // Something has registered a proper (non-forward-decl) service with
00114       // the same name as our dummy. The ACE_Service_Gestalt::insert() modifies
00115       // the memory for the previous ACE_Service_Type instance. It has in fact
00116       // taken ownership and deleted the instance when it replaced it with the
00117       // actual implementation, so nothing is left to do. We are hereby giving
00118       // up any ownership claims.
00119       this->dummy_ = 0;
00120 
00121       if(ACE::debug ())
00122         {
00123           ACE_DEBUG ((LM_DEBUG,
00124                       ACE_LIB_TEXT ("(%P|%t) FWDCL::end, repo=%@ - ")
00125                       ACE_LIB_TEXT ("Found different decl - "),
00126                       this->repo_,
00127                       this->name_));
00128           tmp->dump ();
00129         }
00130 
00131     }
00132   else
00133     {
00134       if(ACE::debug ())
00135         {
00136           ACE_DEBUG ((LM_DEBUG,
00137                       ACE_LIB_TEXT ("(%P|%t) FWDCL::end, repo=%@ - ")
00138                       ACE_LIB_TEXT ("Removing incomplete decl - "),
00139                       this->repo_,
00140                       this->name_));
00141           this->dummy_->dump ();
00142         }
00143 
00144       // The (dummy) forward declaration is still there and is
00145       // the same, which means that no actual declaration was
00146       // provided inside the guarded scope. Therefore, the forward
00147       // declaration is no longer necessary.
00148       if (this->repo_->remove (this->name_,
00149                                const_cast< ACE_Service_Type**> (&this->dummy_)) == 0)
00150         {
00151           delete this->dummy_;
00152         }
00153       else
00154         {
00155           if(ACE::debug ())
00156             {
00157               ACE_ERROR ((LM_ERROR,
00158                           ACE_LIB_TEXT ("(%P|%t) FWDCL::end, repo=%@ - ")
00159                           ACE_LIB_TEXT ("Failed to remove incomplete decl"),
00160                           this->repo_,
00161                           this->name_));
00162               this->dummy_->dump ();
00163             }
00164         }
00165     }
00166 
00167   // Clean up
00168   this->dummy_ = 0;
00169   this->repo_ = 0;
00170 }
00171 
00172 
00173 
00174 // ----------------------------------------
00175 
00176 ACE_Service_Gestalt::Processed_Static_Svc::
00177 Processed_Static_Svc (const ACE_Static_Svc_Descriptor *assd)
00178   :name_(0),
00179    assd_(assd)
00180 {
00181   ACE_NEW_NORETURN (name_, ACE_TCHAR[ACE_OS::strlen(assd->name_)+1]);
00182   ACE_OS::strcpy(name_,assd->name_);
00183   if (ACE::debug ())
00184     ACE_DEBUG ((LM_DEBUG,
00185                 ACE_LIB_TEXT ("(%P|%t) PSS::ctor -  name = %s\n"),
00186                 name_));
00187 }
00188 
00189 ACE_Service_Gestalt::Processed_Static_Svc::
00190 ~Processed_Static_Svc (void)
00191 {
00192   if (ACE::debug ())
00193     ACE_DEBUG ((LM_DEBUG,
00194                 ACE_LIB_TEXT ("(%P|%t) PSS::dtor -  name = %s\n"),
00195                 name_));
00196 
00197   delete [] name_;
00198 }
00199 
00200 // ----------------------------------------
00201 
00202 ACE_Service_Gestalt::~ACE_Service_Gestalt (void)
00203 {
00204   ACE_ASSERT (this->repo_ != 0);
00205 
00206   if (this->svc_repo_is_owned_)
00207     delete this->repo_;
00208   delete this->static_svcs_;
00209   // Delete the dynamically allocated static_svcs instance.
00210   if (ACE::debug ())
00211     ACE_DEBUG ((LM_DEBUG,
00212                 ACE_LIB_TEXT ("(%P|%t) SG::dtor - this=%@, pss = %@\n"),
00213                 this, this->processed_static_svcs_));
00214 
00215   if (this->processed_static_svcs_ &&
00216       !this->processed_static_svcs_->is_empty())
00217     {
00218       Processed_Static_Svc **pss = 0;
00219       for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_);
00220            iter.next (pss) != 0;
00221            iter.advance ())
00222         {
00223           delete *pss;
00224         }
00225     }
00226   delete this->processed_static_svcs_;
00227 }
00228 
00229 ACE_Service_Gestalt::ACE_Service_Gestalt (size_t size,
00230                                           bool svc_repo_is_owned,
00231                                           bool no_static_svcs)
00232   : svc_repo_is_owned_ (svc_repo_is_owned)
00233   , is_opened_ (0)
00234   , logger_key_ (ACE_DEFAULT_LOGGER_KEY)
00235   , no_static_svcs_ (no_static_svcs)
00236   , svc_queue_ (0)
00237   , svc_conf_file_queue_ (0)
00238 {
00239   if (svc_repo_is_owned)
00240     ACE_NEW_NORETURN (this->repo_,
00241                       ACE_Service_Repository (size));
00242   else
00243       this->repo_ =
00244         ACE_Service_Repository::instance (size);
00245 
00246   ACE_NEW_NORETURN (this->static_svcs_,
00247                     ACE_STATIC_SVCS);
00248 
00249   this->processed_static_svcs_ = 0;
00250 
00251   if (ACE::debug ())
00252     ACE_DEBUG ((LM_DEBUG,
00253                 ACE_LIB_TEXT ("(%P|%t) SG::ctor - this = %@, pss = %@\n"),
00254                 this, this->processed_static_svcs_));
00255 }
00256 
00257 // Add the default statically-linked services to the Service
00258 // Repository.
00259 
00260 int
00261 ACE_Service_Gestalt::load_static_svcs (void)
00262 {
00263   ACE_TRACE ("ACE_Service_Gestalt::load_static_svcs");
00264 
00265   if (this->static_svcs_ == 0)
00266     return 0; // Nothing to do
00267 
00268   ACE_Static_Svc_Descriptor **ssdp = 0;
00269   for (ACE_STATIC_SVCS_ITERATOR iter (*this->static_svcs_);
00270        iter.next (ssdp) != 0;
00271        iter.advance ())
00272     {
00273       ACE_Static_Svc_Descriptor *ssd = *ssdp;
00274 
00275       if (this->process_directive (*ssd, 1) == -1)
00276         return -1;
00277     }
00278   return 0;
00279 
00280 } /* load_static_svcs () */
00281 
00282 
00283 
00284 /// Find a static service descriptor by name
00285 
00286 int
00287 ACE_Service_Gestalt::find_static_svc_descriptor (const ACE_TCHAR* name,
00288                                                  ACE_Static_Svc_Descriptor **ssd) const
00289 {
00290   ACE_TRACE ("ACE_Service_Gestalt::find_static_svc_descriptor");
00291 
00292   if (this->static_svcs_ == 0)
00293     return -1;
00294 
00295   ACE_Static_Svc_Descriptor **ssdp = 0;
00296   for (ACE_STATIC_SVCS_ITERATOR iter ( *this->static_svcs_);
00297        iter.next (ssdp) != 0;
00298        iter.advance ())
00299     {
00300       if (ACE_OS::strcmp ((*ssdp)->name_, name) == 0)
00301         {
00302           if (ssd != 0)
00303             *ssd = *ssdp;
00304 
00305           return 0;
00306         }
00307     }
00308 
00309   return -1;
00310 }
00311 
00312 const ACE_Static_Svc_Descriptor*
00313 ACE_Service_Gestalt::find_processed_static_svc (const ACE_TCHAR* name)
00314 {
00315   Processed_Static_Svc **pss = 0;
00316   for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_);
00317        iter.next (pss) != 0;
00318        iter.advance ())
00319     {
00320       if (ACE_OS::strcmp ((*pss)->name_, name) == 0)
00321         return (*pss)->assd_;
00322     }
00323   return 0;
00324 }
00325 
00326 void
00327 ACE_Service_Gestalt::add_processed_static_svc
00328   (const ACE_Static_Svc_Descriptor *assd)
00329 {
00330   if (this->processed_static_svcs_ == 0)
00331     ACE_NEW (this->processed_static_svcs_,
00332              ACE_PROCESSED_STATIC_SVCS);
00333 
00334   Processed_Static_Svc **pss = 0;
00335   for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_);
00336        iter.next (pss) != 0;
00337        iter.advance ())
00338     {
00339       if (ACE_OS::strcmp ((*pss)->name_, assd->name_) == 0)
00340         {
00341           (*pss)->assd_ = assd;
00342           return;
00343         }
00344     }
00345   Processed_Static_Svc *tmp = 0;
00346   ACE_NEW (tmp,Processed_Static_Svc(assd));
00347   this->processed_static_svcs_->insert(tmp);
00348 }
00349 
00350 int
00351 ACE_Service_Gestalt::insert (ACE_Static_Svc_Descriptor *stsd)
00352 {
00353   if (ACE::debug () > 1)
00354     {
00355       // If called during static initialization ACE_Log_Msg may not have
00356       // been initialized yet, so use printf intead.
00357       ACE_OS::fprintf (stderr,
00358            "// (%d|0) SG::insert"
00359            " repo=%p, name=%s - queuing a Static_Svc_Descriptor:"
00360            " active=%d, repo opened=%d.\n",
00361            ACE_OS::getpid (),
00362            this->repo_,
00363            stsd->name_,
00364            stsd->active_,
00365            this->is_opened_);
00366     }
00367 
00368   // Inserting a service after teh Gestalt has been opened makes it
00369   // impossible to activate it later. Perhaps open came too soon?
00370   //ACE_ASSERT (this->is_opened_ == 0);
00371 
00372   return this->static_svcs_->insert (stsd);
00373 }
00374 
00375 
00376 ACE_ALLOC_HOOK_DEFINE (ACE_Service_Gestalt)
00377 
00378 
00379   void
00380 ACE_Service_Gestalt::dump (void) const
00381 {
00382 #if defined (ACE_HAS_DUMP)
00383   ACE_TRACE ("ACE_Service_Gestalt::dump");
00384 #endif /* ACE_HAS_DUMP */
00385 }
00386 
00387 
00388 
00389 ACE_ALLOC_HOOK_DEFINE (ACE_Service_Type_Factory)
00390 
00391 ACE_Service_Type_Factory::ACE_Service_Type_Factory (ACE_TCHAR const *name,
00392                                                     int type,
00393                                                     ACE_Location_Node *location,
00394                                                     int active)
00395   : name_ (name)
00396   , type_ (type)
00397   , location_ (location)
00398   , is_active_ (active)
00399 {
00400 }
00401 
00402 
00403 ACE_Service_Type_Factory::~ACE_Service_Type_Factory (void)
00404 {
00405 }
00406 
00407 
00408 ACE_Service_Type *
00409 ACE_Service_Type_Factory::make_service_type (ACE_Service_Gestalt *cfg) const
00410 {
00411   ACE_TRACE ("ACE_Service_Type_Factory::make_service_type");
00412 
00413   u_int flags = ACE_Service_Type::DELETE_THIS
00414     | (this->location_->dispose () == 0 ? 0 : ACE_Service_Type::DELETE_OBJ);
00415 
00416   ACE_Service_Object_Exterminator gobbler = 0;
00417 
00418   int yyerrno = 0;
00419   void *sym = this->location_->symbol (cfg, yyerrno, &gobbler);
00420 
00421   if (sym != 0)
00422     {
00423       ACE_Service_Type_Impl *stp
00424         = ACE_Service_Config::create_service_type_impl (this->name (),
00425                                                         this->type_,
00426                                                         sym,
00427                                                         flags,
00428                                                         gobbler);
00429       if (stp == 0)
00430         ++yyerrno;
00431 
00432       ACE_Service_Type *tmp = 0;
00433       ACE_NEW_RETURN (tmp,
00434                       ACE_Service_Type (this->name (),
00435                                         stp,
00436                                         this->location_->dll (),
00437                                         this->is_active_),
00438                       0);
00439       return tmp;
00440     }
00441   else
00442     {
00443 #ifndef ACE_NLOGGING
00444       ACE_ERROR ((LM_ERROR,
00445                   ACE_LIB_TEXT ("(%P|%t) Unable to find service \'%s\'\n"),
00446                   this->name ()));
00447 #endif
00448       ++yyerrno;
00449       return 0;
00450     }
00451 }
00452 
00453 ACE_TCHAR const*
00454 ACE_Service_Type_Factory::name (void) const
00455 {
00456   return name_.c_str ();
00457 }
00458 
00459 
00460 ///
00461 
00462 int
00463 ACE_Service_Gestalt::initialize (const ACE_TCHAR *svc_name,
00464                                  const ACE_TCHAR *parameters)
00465 {
00466   ACE_TRACE ("ACE_Service_Gestalt_Base::initialize (repo)");
00467   ACE_ARGV args (parameters);
00468 
00469 #ifndef ACE_NLOGGING
00470   if (ACE::debug () > 1)
00471     {
00472       ACE_DEBUG ((LM_DEBUG,
00473                   ACE_LIB_TEXT ("(%P|%t) SG::initialize - () repo=%@, ")
00474                   ACE_LIB_TEXT ("looking up static ")
00475                   ACE_LIB_TEXT ("service \'%s\' to initialize\n"),
00476                   this->repo_,
00477                   svc_name));
00478     }
00479 #endif
00480 
00481   const ACE_Service_Type *srp = 0;
00482   for (int i = 0; this->repo_->find (svc_name, &srp) == -1 && i < 2; i++)
00483     //  if (this->repo_->find (svc_name, &srp) == -1)
00484     {
00485       const ACE_Static_Svc_Descriptor *assd =
00486         ACE_Service_Config::global()->find_processed_static_svc(svc_name);
00487       if (assd != 0)
00488         {
00489           this->process_directive_i(*assd,0);
00490         }
00491       else
00492         {
00493           ACE_ERROR_RETURN ((LM_ERROR,
00494                              ACE_LIB_TEXT ("(%P|%t) SG::initialize - service \'%s\'")
00495                              ACE_LIB_TEXT (" was not located.\n"),
00496                              svc_name),
00497                             -1);
00498         }
00499     }
00500   if (srp == 0)
00501     ACE_ERROR_RETURN ((LM_ERROR,
00502                        ACE_LIB_TEXT ("(%P|%t) SG::initialize - service \'%s\'")
00503                        ACE_LIB_TEXT (" was not located.\n"),
00504                        svc_name),
00505                       -1);
00506 
00507   /// If initialization fails ...
00508   if (srp->type ()->init (args.argc (),
00509                           args.argv ()) == -1)
00510     {
00511       // ... report and remove this entry.
00512       ACE_ERROR ((LM_ERROR,
00513       ACE_LIB_TEXT ("(%P|%t) SG::initialize - static init of \'%s\'")
00514       ACE_LIB_TEXT (" failed (%p)\n"),
00515       svc_name));
00516       this->repo_->remove (svc_name);
00517       return -1;
00518     }
00519 
00520   // If everything is ok, activate it
00521   const_cast<ACE_Service_Type *>(srp)->active (1);
00522   return 0;
00523 }
00524 
00525 
00526 int
00527 ACE_Service_Gestalt::initialize (const ACE_Service_Type_Factory *stf,
00528                                  const ACE_TCHAR *parameters)
00529 {
00530   ACE_TRACE ("ACE_Service_Gestalt::initialize");
00531 
00532 #ifndef ACE_NLOGGING
00533   if (ACE::debug () > 1)
00534     ACE_DEBUG ((LM_DEBUG,
00535                 ACE_LIB_TEXT ("(%P|%t) SG::initialize - repo=%@, looking up dynamic ")
00536                 ACE_LIB_TEXT ("service \'%s\' to initialize\n"),
00537                 this->repo_,
00538                 stf->name ()));
00539 #endif
00540 
00541   ACE_Service_Type *srp = 0;
00542   int const retv = this->repo_->find (stf->name (),
00543                                       (const ACE_Service_Type **) &srp);
00544 
00545   // If there is an active service already, it must first be removed,
00546   // before it could be re-installed.
00547   if (retv >= 0)
00548     {
00549 #ifndef ACE_NLOGGING
00550       if (ACE::debug ())
00551         ACE_ERROR_RETURN ((LM_WARNING,
00552                            ACE_LIB_TEXT ("(%P|%t) \'%s\' already installed.")
00553                            ACE_LIB_TEXT (" Must be removed before re-installing\n"),
00554                            stf->name ()),
00555                           0);
00556 #endif
00557         return 0;
00558     }
00559 
00560   // There is an inactive service by that name, so it may have been
00561   // either inactivated, or just a forward declaration for a service,
00562   // that is in the process of being loaded. If the latter, then we
00563   // have detected an attempt to initialize the same dynamic service
00564   // while still processing previous attempt. This can lock up the
00565   // process, because the ACE_DLL_Manager::open () is not re-entrant -
00566   // it uses a Singleton lock to serialize concurent invocations. This
00567   // use case must be handled here, because if the DLL_Manager was
00568   // re-entrant we would have entered an infinite recursion here.
00569   if (retv == -2 && srp->type () == 0)
00570     ACE_ERROR_RETURN ((LM_WARNING,
00571                        ACE_LIB_TEXT ("(%P|%t) \'%s\' has not been ")
00572                        ACE_LIB_TEXT ("completely defined. Recursive ")
00573                        ACE_LIB_TEXT ("initialization request while ")
00574                        ACE_LIB_TEXT ("already performing one.\n"),
00575                        stf->name ()),
00576                       -1);
00577 
00578   // Reserve a spot for the dynamic service by inserting an incomplete
00579   // service declaration, i.e. one that can not produce a service
00580   // object if asked.  Having this incomplete declaration works
00581   // similar to C++'s forward declaration to allow, in this case
00582   // proper partial ordering of the loaded services in respect to
00583   // their finalization. I.e. dependent static services must be
00584   // registered *after* the dynamic service that loads them, so that
00585   // their finalization is complete *before* finalizing the dynamic
00586   // service.
00587   ACE_Service_Type_Forward_Declaration_Guard dummy (this->repo_,
00588                                                     stf->name ());
00589 
00590   // make_service_type() is doing the dynamic loading and also runs
00591   // any static initializers
00592   ACE_Auto_Ptr<ACE_Service_Type> tmp (stf->make_service_type (this));
00593   if (tmp.get () != 0 &&
00594       this->initialize_i (tmp.get (), parameters) == 0)
00595     {
00596       // All good the ACE_Service_Type instance is now owned by the repository
00597       // and we should make sure it is not destroyed upon exit from this method.
00598       (void)tmp.release ();
00599       return 0;
00600     }
00601 
00602   // Something went wrong ...
00603 #ifndef ACE_NLOGGING
00604   if (ACE::debug ())
00605     ACE_ERROR_RETURN ((LM_ERROR,
00606                        ACE_LIB_TEXT ("(%P|%t) Error initializing %s: %m\n"),
00607                        stf->name()),
00608                       -1);
00609 #endif
00610 
00611   return -1;
00612 }
00613 
00614 
00615 // Dynamically link the shared object file and retrieve a pointer to
00616 // the designated shared object in this file.
00617 // @note This is obsolete (and error-prone) in the presense of dynamic
00618 // services with their own static services. This method will allow those
00619 // static services to register *before* the dynamic service that owns them.
00620 // Upon finalization of the static services the process may crash, because
00621 // the dynamic service's DLL may have been already released, together with
00622 // the memory in which the static services reside.
00623 // It may not crash, for instance, when the first static service to register
00624 // is the same as the dynamic service being loaded. You should be so lucky! ..
00625 
00626 int
00627 ACE_Service_Gestalt::initialize (const ACE_Service_Type *sr,
00628                                  const ACE_TCHAR *parameters)
00629 {
00630   ACE_TRACE ("ACE_Service_Gestalt::initialize");
00631 
00632   if (ACE::debug ())
00633     ACE_DEBUG ((LM_DEBUG,
00634                 ACE_LIB_TEXT ("(%P|%t) SG::initialize - looking up dynamic ")
00635                 ACE_LIB_TEXT (" service \'%s\' to initialize\n"),
00636                 sr->name ()));
00637 
00638   ACE_Service_Type *srp = 0;
00639   if (this->repo_->find (sr->name (),
00640                          (const ACE_Service_Type **) &srp) >= 0)
00641     ACE_ERROR_RETURN ((LM_WARNING,
00642                        ACE_LIB_TEXT ("(%P|%t) SG::initialize - \'%s\' ")
00643                        ACE_LIB_TEXT ("has already been installed. ")
00644                        ACE_LIB_TEXT ("Remove before reinstalling\n"),
00645                        sr->name ()),
00646                       0);
00647 
00648   return this->initialize_i (sr, parameters);
00649 
00650 }
00651 
00652 // Dynamically link the shared object file and retrieve a pointer to
00653 // the designated shared object in this file.
00654 int
00655 ACE_Service_Gestalt::initialize_i (const ACE_Service_Type *sr,
00656                                    const ACE_TCHAR *parameters)
00657 {
00658   ACE_TRACE ("ACE_Service_Gestalt::initialize_i");
00659   ACE_ARGV args (parameters);
00660   if (sr->type ()->init (args.argc (),
00661                          args.argv ()) == -1)
00662     {
00663       // We just get ps to avoid having remove() delete it.
00664       ACE_Service_Type *ps = 0;
00665       this->repo_->remove (sr->name (), &ps);
00666 
00667 #ifndef ACE_NLOGGING
00668       if (ACE::debug ())
00669         ACE_ERROR_RETURN ((LM_ERROR,
00670                            ACE_LIB_TEXT ("(%P|%t) SG - initialize_i ")
00671                            ACE_LIB_TEXT ("failed for %s: %m\n"),
00672                            sr->name ()),
00673                           -1);
00674 #endif
00675       return -1;
00676     }
00677 
00678   if (this->repo_->insert (sr) == -1)
00679     {
00680 #ifndef ACE_NLOGGING
00681       if (ACE::debug ())
00682         ACE_ERROR_RETURN ((LM_ERROR,
00683                            ACE_LIB_TEXT ("(%P|%t) SG - repository insert ")
00684                            ACE_LIB_TEXT ("failed for %s: %m\n"),
00685                            sr->name ()),
00686                           -1);
00687 #endif
00688         return -1;
00689     }
00690 
00691   return 0;
00692 }
00693 
00694 // Totally remove <svc_name> from the daemon by removing it from the
00695 // ACE_Reactor, and unlinking it if necessary.
00696 
00697 int
00698 ACE_Service_Gestalt::remove (const ACE_TCHAR svc_name[])
00699 {
00700   ACE_TRACE ("ACE_Service_Gestalt::remove");
00701   return this->repo_->remove (svc_name);
00702 }
00703 
00704 // Suspend <svc_name>.  Note that this will not unlink the service
00705 // from the daemon if it was dynamically linked, it will mark it as
00706 // being suspended in the Service Repository and call the <suspend>
00707 // member function on the appropriate <ACE_Service_Object>.  A service
00708 // can be resumed later on by calling the <resume> method...
00709 
00710 int
00711 ACE_Service_Gestalt::suspend (const ACE_TCHAR svc_name[])
00712 {
00713   ACE_TRACE ("ACE_Service_Gestalt::suspend");
00714   return this->repo_->suspend (svc_name);
00715 }
00716 
00717 // Resume a SVC_NAME that was previously suspended or has not yet
00718 // been resumed (e.g., a static service).
00719 
00720 int
00721 ACE_Service_Gestalt::resume (const ACE_TCHAR svc_name[])
00722 {
00723   ACE_TRACE ("ACE_Service_Gestalt::resume");
00724   return this->repo_->resume (svc_name);
00725 }
00726 
00727 
00728 int
00729 ACE_Service_Gestalt::process_directive (const ACE_Static_Svc_Descriptor &ssd,
00730                                         int force_replace)
00731 {
00732   int result = process_directive_i(ssd,force_replace);
00733   if (result == 0)
00734     {
00735       this->add_processed_static_svc(&ssd);
00736     }
00737   return result;
00738 }
00739 
00740 int
00741 ACE_Service_Gestalt::process_directive_i (const ACE_Static_Svc_Descriptor &ssd,
00742                                         int force_replace)
00743 {
00744 #ifndef ACE_NLOGGING
00745   if (ACE::debug () > 2)
00746     ACE_DEBUG ((LM_DEBUG,
00747                 ACE_LIB_TEXT ("(%P|%t) SG::process_directive, ")
00748                 ACE_LIB_TEXT ("repo=%@, replace=%d - %s\n"),
00749                 this->repo_,
00750                 force_replace,
00751                 ssd.name_));
00752 #endif
00753 
00754   if (!force_replace)
00755     {
00756       if (this->repo_->find (ssd.name_, 0, 0) >= 0)
00757         {
00758           // The service is already there, just return
00759           return 0;
00760         }
00761     }
00762 
00763   ACE_Service_Object_Exterminator gobbler;
00764   void *sym = (ssd.alloc_)(&gobbler);
00765 
00766   ACE_Service_Type_Impl *stp =
00767     ACE_Service_Config::create_service_type_impl (ssd.name_,
00768                                                   ssd.type_,
00769                                                   sym,
00770                                                   ssd.flags_,
00771                                                   gobbler);
00772   if (stp == 0)
00773     return 0;
00774 
00775 
00776   ACE_Service_Type *service_type;
00777 
00778   // This is just a temporary to force the compiler to use the right
00779   // constructor in ACE_Service_Type
00780   ACE_DLL tmp_dll;
00781 
00782   ACE_NEW_RETURN (service_type,
00783                   ACE_Service_Type (ssd.name_,
00784                                     stp,
00785                                     tmp_dll,
00786                                     ssd.active_),
00787                   -1);
00788 
00789   return this->repo_->insert (service_type);
00790 }
00791 
00792 #if (ACE_USES_CLASSIC_SVC_CONF == 1)
00793 
00794 int
00795 ACE_Service_Gestalt::process_directives_i (ACE_Svc_Conf_Param *param)
00796 {
00797   // AC 970827 Skip the heap check because yacc allocates a buffer
00798   // here which will be reported as a memory leak for some reason.
00799   ACE_NO_HEAP_CHECK
00800 
00801     // Were we called in the context of the current instance?
00802     ACE_ASSERT (this == param->config);
00803 
00804   // Temporarily (for the duration of this call) make sure that *any* static
00805   // service registrations will happen with this instance. Such registrations
00806   // are possible as a side-effect of dynamically loading a DLL, which has
00807   // other static services registered. Thus this instance will own both the
00808   // DLL and those static services, which implies that their finalization
00809   // will be performed in the correct order, i.e. prior to finalizing the DLL
00810   ACE_Service_Config_Guard guard (this);
00811 
00812 #ifndef ACE_NLOGGING
00813   if (ACE::debug ())
00814     ACE_DEBUG ((LM_DEBUG,
00815                 ACE_LIB_TEXT ("(%P|%t) SG::process_directives_i, ")
00816                 ACE_LIB_TEXT ("repo=%@ - %s\n"),
00817                 this->repo_,
00818                 (param->type == ACE_Svc_Conf_Param::SVC_CONF_FILE)
00819     ? ACE_TEXT ("<from file>")
00820     : param->source.directive));
00821 #endif
00822 
00823   ::ace_yyparse (param);
00824 
00825   // This is a hack, better errors should be provided...
00826   if (param->yyerrno > 0)
00827     {
00828       if (ACE_OS::last_error () == 0)
00829         ACE_OS::last_error (EINVAL);
00830 
00831       return param->yyerrno;
00832     }
00833   else
00834     return 0;
00835 }
00836 
00837 #else
00838 
00839 ACE_XML_Svc_Conf *
00840 ACE_Service_Gestalt::get_xml_svc_conf (ACE_DLL &xmldll)
00841 {
00842   if (xmldll.open (ACE_LIB_TEXT ("ACEXML_XML_Svc_Conf_Parser")) == -1)
00843     ACE_ERROR_RETURN ((LM_ERROR,
00844                        ACE_LIB_TEXT ("Fail to open ACEXML_XML_Svc_Conf_Parser: %p\n"),
00845                        "ACE_Service_Config::get_xml_svc_conf"),
00846                       0);
00847 
00848   void *foo;
00849   foo = xmldll.symbol (ACE_LIB_TEXT ("_ACEXML_create_XML_Svc_Conf_Object"));
00850 
00851   // Cast the void* to long first.
00852   long tmp = reinterpret_cast<long> (foo);
00853   ACE_XML_Svc_Conf::Factory factory =
00854     reinterpret_cast<ACE_XML_Svc_Conf::Factory> (tmp);
00855   if (factory == 0)
00856     ACE_ERROR_RETURN ((LM_ERROR,
00857                        ACE_LIB_TEXT ("Unable to resolve factory: %p\n"),
00858                        xmldll.error ()),
00859                       0);
00860 
00861   return factory ();
00862 }
00863 #endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
00864 
00865 int
00866 ACE_Service_Gestalt::process_file (const ACE_TCHAR file[])
00867 {
00868   ACE_TRACE ("ACE_Service_Gestalt::process_file");
00869 
00870   // To avoid recursive processing of the same file and the same repository
00871   // we maintain an implicit stack of dummy "services" named after the file
00872   // being processed. Anytime we have to open a new file, we then can check
00873   // to see if it is not already being processed by searching for a dummy
00874   // service with a matching name.
00875   if (this->repo_->find (file, 0, 0) >=0)
00876     {
00877       ACE_DEBUG ((LM_WARNING,
00878       ACE_TEXT ("(%P|%t) Configuration file %s has not finished")
00879       ACE_TEXT (" processing yet. Ignoring.\n"),
00880       file));
00881       return 0;
00882     }
00883 
00884   // Register a dummy service as a forward decl, using the file name as name.
00885   // The entry will be automaticaly removed once the thread exits this block.
00886   ACE_Service_Type_Forward_Declaration_Guard recursion_guard (this->repo_, file);
00887 
00888   /*
00889    * @TODO: Test with ACE_USES_CLASSIC_SVC_CONF turned off!
00890    */
00891 #if (ACE_USES_CLASSIC_SVC_CONF == 1)
00892   int result = 0;
00893 
00894   FILE *fp = ACE_OS::fopen (file,
00895                             ACE_LIB_TEXT ("r"));
00896 
00897   if (fp == 0)
00898     {
00899       // Invalid svc.conf file.  We'll report it here and break out of
00900       // the method.
00901       if (ACE::debug ())
00902         ACE_DEBUG ((LM_ERROR,
00903                     ACE_LIB_TEXT ("%p\n"),
00904                     file));
00905 
00906       // Use stat to find out if the file exists.  I didn't use access()
00907       // because stat is better supported on most non-unix platforms.
00908       ACE_stat exists;
00909       if (ACE_OS::stat (file, &exists) == 0)
00910         // If it exists, but we couldn't open it for reading then we
00911         // must not have permission to read it.
00912         errno = EPERM;
00913       else
00914         errno = ENOENT;
00915       result = -1;
00916     }
00917   else
00918     {
00919       ACE_Svc_Conf_Param f (this, fp);
00920 
00921       // Keep track of the number of errors.
00922       result = this->process_directives_i (&f);
00923 
00924       (void) ACE_OS::fclose (fp);
00925     }
00926   return result;
00927 #else
00928   ACE_DLL dll;
00929 
00930   auto_ptr<ACE_XML_Svc_Conf>
00931     xml_svc_conf (ACE_Service_Config::get_xml_svc_conf (dll));
00932 
00933   if (xml_svc_conf.get () == 0)
00934     return -1;
00935 
00936   return xml_svc_conf->parse_file (file);
00937 #endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
00938 }
00939 
00940 int
00941 ACE_Service_Gestalt::process_directive (const ACE_TCHAR directive[])
00942 {
00943   ACE_TRACE ("ACE_Service_Gestalt::process_directive");
00944 
00945   if (ACE::debug ())
00946     ACE_DEBUG ((LM_DEBUG,
00947                 ACE_LIB_TEXT ("(%P|%t) SG::process_directive, repo=%@ - %s\n"),
00948                 this->repo_,
00949                 directive));
00950 
00951 #if (ACE_USES_CLASSIC_SVC_CONF == 1)
00952   ACE_UNUSED_ARG (directive);
00953 
00954   ACE_Svc_Conf_Param d (this, directive);
00955 
00956   int result = this->process_directives_i (&d);
00957 
00958   return result;
00959 #else
00960   ACE_DLL dll;
00961 
00962   auto_ptr<ACE_XML_Svc_Conf>
00963     xml_svc_conf (this->get_xml_svc_conf (dll));
00964 
00965   if (xml_svc_conf.get () == 0)
00966     return -1;
00967 
00968   return xml_svc_conf->parse_string (directive);
00969 #endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
00970 
00971 } /* process_directive () */
00972 
00973 
00974 int
00975 ACE_Service_Gestalt::init_svc_conf_file_queue (void)
00976 {
00977   if (this->svc_conf_file_queue_ == 0)
00978     {
00979       ACE_SVC_QUEUE *tmp = 0;
00980       ACE_NEW_RETURN (tmp,
00981           ACE_SVC_QUEUE,
00982           -1);
00983       delete this->svc_conf_file_queue_;
00984       this->svc_conf_file_queue_ = tmp;
00985     }
00986 
00987   if (ACE::debug () > 1)
00988     ACE_DEBUG ((LM_DEBUG,
00989                 ACE_LIB_TEXT ("(%P|%t) SG::init_svc_conf_file_queue ")
00990                 ACE_LIB_TEXT ("- this=%@, repo=%@\n"),
00991                 this, this->repo_));
00992   return 0;
00993 
00994 } /* init_svc_conf_file_queue () */
00995 
00996 
00997 int
00998 ACE_Service_Gestalt::open_i (const ACE_TCHAR /*program_name*/[],
00999                              const ACE_TCHAR* /*logger_key*/,
01000                              bool /*ignore_static_svcs*/,
01001                              bool /*ignore_default_svc_conf_file*/,
01002                              bool ignore_debug_flag)
01003 {
01004   ACE_TRACE ("ACE_Service_Gestalt::open_i");
01005   int result = 0;
01006   ACE_Log_Msg *log_msg = ACE_LOG_MSG;
01007 
01008   // Record the current log setting upon entering this thread.
01009   u_long old_process_mask = log_msg->priority_mask
01010     (ACE_Log_Msg::PROCESS);
01011 
01012   u_long old_thread_mask = log_msg->priority_mask
01013     (ACE_Log_Msg::THREAD);
01014 
01015   if (ACE::debug ())
01016     ACE_DEBUG ((LM_DEBUG,
01017                 ACE_TEXT ("(%P|%t) SG::open_i - this=%@, ")
01018                 ACE_TEXT ("opened=%d, loadstatics=%d\n"),
01019                 this, this->is_opened_, this->no_static_svcs_));
01020 
01021   // Guard against reentrant processing. For example,
01022   // if the singleton gestalt (ubergestalt) was already open,
01023   // do not open it again...
01024   if (this->is_opened_++ != 0)
01025     return 0;
01026 
01027   if (ignore_debug_flag == 0)
01028     {
01029       // If -d was included as a startup parameter, the user wants debug
01030       // information printed during service initialization.
01031       if (ACE::debug ())
01032         ACE_Log_Msg::enable_debug_messages ();
01033       else
01034         // The user has requested no debugging info.
01035         ACE_Log_Msg::disable_debug_messages ();
01036     }
01037 
01038   // See if we need to load the static services.
01039   if (this->no_static_svcs_ == 0
01040       && this->load_static_svcs () == -1)
01041     result = -1;
01042   else
01043     {
01044       if (this->process_commandline_directives () == -1)
01045         result = -1;
01046       else
01047         result = this->process_directives ();
01048     }
01049 
01050 
01051   // Reset debugging back to the way it was when we came into
01052   // into <open_i>.
01053   {
01054     // Make sure to save/restore errno properly.
01055     ACE_Errno_Guard error (errno);
01056 
01057     if (ignore_debug_flag == 0)
01058       {
01059         log_msg->priority_mask (old_process_mask, ACE_Log_Msg::PROCESS);
01060         log_msg->priority_mask (old_thread_mask, ACE_Log_Msg::THREAD);
01061       }
01062   }
01063 
01064   return result;
01065 } /* open_i () */
01066 
01067 
01068 int
01069 ACE_Service_Gestalt::is_opened (void)
01070 {
01071   return this->is_opened_;
01072 }
01073 
01074 int
01075 ACE_Service_Gestalt::process_commandline_directives (void)
01076 {
01077   int result = 0;
01078   if (this->svc_queue_ != 0)
01079     {
01080       ACE_TString *sptr = 0;
01081       for (ACE_SVC_QUEUE_ITERATOR iter (*this->svc_queue_);
01082            iter.next (sptr) != 0;
01083            iter.advance ())
01084   {
01085     // Process just a single directive.
01086     if (this->process_directive ((sptr->fast_rep ())) != 0)
01087       {
01088         ACE_ERROR ((LM_ERROR,
01089         ACE_LIB_TEXT ("%p\n"),
01090         ACE_LIB_TEXT ("process_directive")));
01091         result = -1;
01092       }
01093   }
01094 
01095       delete this->svc_queue_;
01096       this->svc_queue_ = 0;
01097     }
01098 
01099   return result;
01100 
01101 } /* process_commandline_directives () */
01102 
01103 
01104 int
01105 ACE_Service_Gestalt::parse_args (int argc, ACE_TCHAR *argv[])
01106 {
01107   ACE_TRACE ("ACE_Service_Gestalt::parse_args");
01108   return parse_args_i (argc, argv);
01109 }
01110 
01111 int
01112 ACE_Service_Gestalt::parse_args_i (int argc, ACE_TCHAR *argv[])
01113 {
01114   ACE_TRACE ("ACE_Service_Gestalt::parse_args_i");
01115   ACE_Get_Opt getopt (argc,
01116                       argv,
01117                       ACE_LIB_TEXT ("df:k:nyp:s:S:"),
01118                       1); // Start at argv[1].
01119 
01120   if (this->init_svc_conf_file_queue () == -1)
01121     return -1;
01122 
01123   for (int c; (c = getopt ()) != -1; )
01124     switch (c)
01125       {
01126       case 'd':
01127         ACE::debug (1);
01128         break;
01129       case 'f':
01130         if (this->svc_conf_file_queue_->enqueue_tail (ACE_TString (getopt.opt_arg ())) == -1)
01131           ACE_ERROR_RETURN ((LM_ERROR,
01132                              ACE_LIB_TEXT ("%p\n"),
01133                              ACE_LIB_TEXT ("enqueue_tail")),
01134                             -1);
01135         break;
01136       case 'k':
01137         /*
01138          * @TODO: Is this always a static storage? Shouldn't we copy
01139          * & gain ownership of the value?
01140          */
01141         this->logger_key_ = getopt.opt_arg ();
01142         break;
01143       case 'n':
01144         this->no_static_svcs_ = 1;
01145         break;
01146       case 'y':
01147         this->no_static_svcs_ = 0;
01148         break;
01149       case 'S':
01150         if (this->svc_queue_ == 0)
01151           {
01152             ACE_NEW_RETURN (this->svc_queue_,
01153                             ACE_SVC_QUEUE,
01154                             -1);
01155           }
01156 
01157         if (this->svc_queue_->enqueue_tail (ACE_TString (getopt.opt_arg ())) == -1)
01158           ACE_ERROR_RETURN ((LM_ERROR,
01159                              ACE_LIB_TEXT ("%p\n"),
01160                              ACE_LIB_TEXT ("enqueue_tail")),
01161                             -1);
01162         break;
01163       default:
01164         if (ACE::debug () > 0)
01165           ACE_DEBUG ((LM_DEBUG,
01166                       ACE_LIB_TEXT ("%c is not a ACE_Service_Config option\n"),
01167                       c));
01168       }
01169 
01170   return 0;
01171 } /* parse_args_i () */
01172 
01173 
01174 
01175 // Process service configuration requests as indicated in the queue of
01176 // svc.conf files.
01177 int
01178 ACE_Service_Gestalt::process_directives (void)
01179 {
01180   ACE_TRACE ("ACE_Service_Gestalt::process_directives");
01181 
01182   int result = 0;
01183 
01184   if (this->svc_conf_file_queue_ != 0)
01185     {
01186       ACE_TString *sptr = 0;
01187 
01188       // Iterate through all the svc.conf files.
01189       for (ACE_SVC_QUEUE_ITERATOR iter (*this->svc_conf_file_queue_);
01190            iter.next (sptr) != 0;
01191            iter.advance ())
01192         {
01193           int r = this->process_file (sptr->fast_rep ());
01194 
01195           if (r < 0)
01196             {
01197               result = r;
01198               break;
01199             }
01200 
01201           result += r;
01202         }
01203     }
01204 
01205   return result;
01206 
01207 } /* process_directives () */
01208 
01209 // Tidy up and perform last rites on a terminating ACE_Service_Gestalt.
01210 int
01211 ACE_Service_Gestalt::close (void)
01212 {
01213   ACE_TRACE ("ACE_Service_Gestalt::close");
01214 
01215   this->is_opened_--;
01216   if (this->is_opened_ > 0)
01217     return 0;
01218 
01219   // Delete the service repository.  All the objects inside the
01220   // service repository should already have been finalized.
01221   //  ACE_Service_Config::close_svcs ();
01222 
01223   // Delete the list fo svc.conf files
01224   delete this->svc_conf_file_queue_;
01225   this->svc_conf_file_queue_ = 0;
01226 
01227   // Delete the dynamically allocated static_svcs instance.
01228   if (ACE::debug ())
01229     ACE_DEBUG ((LM_DEBUG,
01230                 ACE_LIB_TEXT ("(%P|%t) SG::close - this=%@, repo=%@, pss = %@\n"),
01231                 this, this->repo_, this->processed_static_svcs_));
01232 
01233   delete this->static_svcs_;
01234   this->static_svcs_ = 0;
01235 
01236   if (this->processed_static_svcs_ &&
01237       !this->processed_static_svcs_->is_empty())
01238     {
01239       Processed_Static_Svc **pss = 0;
01240       for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_);
01241            iter.next (pss) != 0;
01242            iter.advance ())
01243         {
01244           delete *pss;
01245         }
01246     }
01247   delete this->processed_static_svcs_;
01248   this->processed_static_svcs_ = 0;
01249   if (ACE::debug ())
01250     ACE_DEBUG ((LM_DEBUG,
01251                 ACE_LIB_TEXT ("(%P|%t) SG::close - complete this=%@, repo=%@\n"),
01252                 this, this->repo_));
01253 
01254 
01255   return 0;
01256 
01257 } /* close () */
01258 
01259 
01260 ACE_END_VERSIONED_NAMESPACE_DECL
01261 
01262 #if !defined (__ACE_INLINE__)
01263 #include "ace/Service_Gestalt.inl"
01264 #endif /* __ACE_INLINE__ */
01265 
01266 // Allocate a Service Manager.
01267 ACE_FACTORY_DEFINE (ACE, ACE_Service_Manager)

Generated on Thu Nov 9 09:42:02 2006 for ACE by doxygen 1.3.6