Service_Config.cpp

Go to the documentation of this file.
00001 // $Id: Service_Config.cpp 79636 2007-09-13 15:18:33Z sowayaa $
00002 
00003 #include "ace/Service_Config.h"
00004 
00005 #if !defined (__ACE_INLINE__)
00006 #include "ace/Service_Config.inl"
00007 #endif /* __ACE_INLINE__ */
00008 
00009 #include "ace/Service_Types.h"
00010 #include "ace/Reactor.h"
00011 #include "ace/Singleton.h"
00012 #include "ace/Service_Repository.h"
00013 
00014 #ifndef ACE_LACKS_UNIX_SIGNALS
00015 # include "ace/Sig_Adapter.h"
00016 #endif  /* !ACE_LACKS_UNIX_SIGNALS */
00017 
00018 #include "ace/OS_NS_stdio.h"
00019 #include "ace/OS_NS_time.h"
00020 #include "ace/OS_NS_unistd.h"
00021 #include "ace/Get_Opt.h"
00022 #include "ace/ARGV.h"
00023 #include "ace/Log_Msg.h"
00024 
00025 ACE_RCSID (ace,
00026            Service_Config,
00027            "$Id: Service_Config.cpp 79636 2007-09-13 15:18:33Z sowayaa $")
00028 
00029 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00030 
00031 /**
00032   * @c ACE_Service_Config is supposed to be a Singleton. This is the
00033   * only Configuration Gestalt available for access from static
00034   * initializers at proces start-up time. Using Unmanaged Singleton
00035   * is safer because (a) the Object Manager may not yet be fully initialized
00036   * in the context of a static initializer that uses SC, and (b) because we
00037   * know that upon process exit the SC will still be automaticaly and explicitly
00038   * closed by @c ACE_Object_Manager::fini().
00039   */
00040 typedef ACE_Unmanaged_Singleton<ACE_Service_Config,
00041                                 ACE_SYNCH_RECURSIVE_MUTEX> ACE_SERVICE_CONFIG_SINGLETON;
00042 
00043 
00044 ///
00045 ACE_Service_Config_Guard::ACE_Service_Config_Guard (ACE_Service_Gestalt * psg)
00046   : saved_ (ACE_Service_Config::instance ())
00047 {
00048   if (ACE::debug ())
00049     ACE_DEBUG ((LM_DEBUG,
00050                 ACE_TEXT ("ACE (%P|%t) Service_Config_Guard:<ctor=%@>")
00051                 ACE_TEXT (" - config=%@ repo=%@ superceded by repo=%@\n"),
00052                 this,
00053                 this->saved_,
00054                 this->saved_->repo_,
00055                 psg->repo_));
00056 
00057   // Modify the TSS if the repo has changed
00058   if (saved_ != psg)
00059       (void)ACE_Service_Config::current (psg);
00060 }
00061 
00062 ACE_Service_Config_Guard::~ACE_Service_Config_Guard (void)
00063 {
00064   ACE_Service_Config::current (this->saved_);
00065 
00066   if (ACE::debug ())
00067     ACE_DEBUG ((LM_DEBUG,
00068                 ACE_TEXT ("ACE (%P|%t) Service_Config_Guard:<dtor=%@>")
00069                 ACE_TEXT (" - new repo=%@\n"),
00070                 this,
00071                 this->saved_->repo_));
00072 }
00073 
00074 
00075 ACE_ALLOC_HOOK_DEFINE (ACE_Service_Config)
00076 
00077 // Set the signal handler to point to the handle_signal() function.
00078 ACE_Sig_Adapter *ACE_Service_Config::signal_handler_ = 0;
00079 
00080 // Trigger a reconfiguration.
00081 sig_atomic_t ACE_Service_Config::reconfig_occurred_ = 0;
00082 
00083 // = Set by command-line options.
00084 
00085 /// Pathname of file to write process id.
00086 ACE_TCHAR *ACE_Service_Config::pid_file_name_ = 0;
00087 
00088 /// Shall we become a daemon process?
00089 int ACE_Service_Config::be_a_daemon_ = 0;
00090 
00091 // Number of the signal used to trigger reconfiguration.
00092 int ACE_Service_Config::signum_ = SIGHUP;
00093 
00094 
00095 void
00096 ACE_Service_Config::dump (void) const
00097 {
00098 #if defined (ACE_HAS_DUMP)
00099   ACE_TRACE ("ACE_Service_Config::dump");
00100 #endif /* ACE_HAS_DUMP */
00101 }
00102 
00103 int
00104 ACE_Service_Config::parse_args_i (int argc, ACE_TCHAR *argv[])
00105 {
00106   ACE_TRACE ("ACE_Service_Config::parse_args_i");
00107 
00108   // Using PERMUTE_ARGS (default) in order to have all
00109   // unrecognized options and their value arguments moved
00110   // to the end of the argument vector. We'll pick them up
00111   // after processing our options and pass them on to the
00112   // base class for further parsing.
00113   //FUZZ: disable check_for_lack_ACE_OS
00114   ACE_Get_Opt getopt (argc,
00115                       argv,
00116                       ACE_TEXT ("bs:p:"),
00117                       1  ,                       // Start at argv[1].
00118                       0,                       // Do not report errors
00119                       ACE_Get_Opt::RETURN_IN_ORDER);
00120   //FUZZ: enable check_for_lack_ACE_OS
00121 
00122   // Keep a list of all unknown arguments, begin with the
00123   // executable's name
00124   ACE_ARGV superargv;
00125   superargv.add (argv[0]);
00126 
00127   //FUZZ: disable check_for_lack_ACE_OS
00128   for (int c; (c = getopt ()) != -1; )
00129   //FUZZ: enable check_for_lack_ACE_OS
00130     switch (c)
00131       {
00132       case 'p':
00133         ACE_Service_Config::pid_file_name_ = getopt.opt_arg ();
00134         break;
00135       case 'b':
00136         ACE_Service_Config::be_a_daemon_ = 1;
00137         break;
00138       case 's':
00139         {
00140           // There's no point in dealing with this on NT since it
00141           // doesn't really support signals very well...
00142 #if !defined (ACE_LACKS_UNIX_SIGNALS)
00143           ACE_Service_Config::signum_ =
00144             ACE_OS::atoi (getopt.opt_arg ());
00145 
00146           if (ACE_Reactor::instance ()->register_handler
00147               (ACE_Service_Config::signum_,
00148                ACE_Service_Config::signal_handler_) == -1)
00149             ACE_ERROR_RETURN ((LM_ERROR,
00150                                ACE_TEXT ("cannot obtain signal handler\n")),
00151                               -1);
00152 #endif /* ACE_LACKS_UNIX_SIGNALS */
00153           break;
00154         }
00155       default:
00156         superargv.add ( argv[getopt.opt_ind () - 1],true);
00157       }
00158 
00159   // Collect any argumets that were left
00160   for (int c = getopt.opt_ind (); c < argc; c++)
00161       superargv.add (argv[c-1],true);
00162 
00163   return ACE_Service_Gestalt::parse_args_i (superargv.argc (),
00164                                             superargv.argv ());
00165 
00166 } /* parse_args_i () */
00167 
00168 
00169 int
00170 ACE_Service_Config::open_i (const ACE_TCHAR program_name[],
00171                             const ACE_TCHAR *logger_key,
00172                             bool ignore_static_svcs,
00173                             bool ignore_default_svc_conf_file,
00174                             bool ignore_debug_flag)
00175 {
00176   int result = 0;
00177   ACE_TRACE ("ACE_Service_Config::open_i");
00178   ACE_Log_Msg *log_msg = ACE_LOG_MSG;
00179 
00180   if (ACE::debug ())
00181     ACE_DEBUG ((LM_DEBUG,
00182                 ACE_TEXT ("(%P|%t) SC::open_i - this=%@, opened=%d, ")
00183                 ACE_TEXT ("loadstatics=%d\n"),
00184                 this, this->is_opened_, this->no_static_svcs_));
00185 
00186   // Guard against reentrant processing. For example,
00187   // if the singleton gestalt (ubergestalt) was already open,
00188   // do not open it again...
00189   // The base class open_i increments this and we are
00190   // forwarding to it, so we don't have to increment here.
00191   if (this->is_opened_ != 0)
00192     return ACE_Service_Gestalt::open_i (program_name,
00193                                         logger_key,
00194                                         ignore_static_svcs,
00195                                         ignore_default_svc_conf_file,
00196                                         ignore_debug_flag);
00197 
00198   // Check for things we need to do on a per-process basis and which
00199   // may not be safe, or wise to do an a per instance basis
00200 
00201   // Override any defaults, if required
00202   this->no_static_svcs_ = ignore_static_svcs;
00203 
00204   // Become a daemon before doing anything else.
00205   if (this->be_a_daemon_)
00206     ACE::daemonize ();
00207 
00208   // Write process id to file.
00209   if (this->pid_file_name_ != 0)
00210     {
00211       FILE* pidf = ACE_OS::fopen (this->pid_file_name_,
00212                                   ACE_TEXT("w"));
00213 
00214       if (pidf != 0)
00215         {
00216           ACE_OS::fprintf (pidf,
00217                            "%ld\n",
00218                            static_cast<long> (ACE_OS::getpid()));
00219           ACE_OS::fclose (pidf);
00220         }
00221     }
00222 
00223   u_long flags = log_msg->flags ();
00224 
00225   // Only use STDERR if the caller hasn't already set the flags.
00226   if (flags == 0)
00227     flags = (u_long) ACE_Log_Msg::STDERR;
00228 
00229   const ACE_TCHAR *key = logger_key;
00230 
00231   if (key == 0 || ACE_OS::strcmp (key, ACE_DEFAULT_LOGGER_KEY) == 0)
00232     // Only use the static <logger_key_> if the caller doesn't
00233     // override it in the parameter list or if the key supplied is
00234     // equal to the default static logger key.
00235     key = this->logger_key_;
00236   else
00237     ACE_SET_BITS (flags, ACE_Log_Msg::LOGGER);
00238 
00239   if (log_msg->open (program_name,
00240                      flags,
00241                      key) == -1)
00242     result = -1;
00243   else
00244     {
00245       if (ACE::debug ())
00246         ACE_DEBUG ((LM_STARTUP,
00247                     ACE_TEXT ("starting up daemon %n\n")));
00248 
00249       // Initialize the Service Repository (this will still work if
00250       // user forgets to define an object of type ACE_Service_Config).
00251       ACE_Service_Repository::instance (ACE_Service_Config::MAX_SERVICES);
00252 
00253       // Initialize the ACE_Reactor (the ACE_Reactor should be the
00254       // same size as the ACE_Service_Repository).
00255       ACE_Reactor::instance ();
00256 
00257       // There's no point in dealing with this on NT since it doesn't
00258       // really support signals very well...
00259 #if !defined (ACE_LACKS_UNIX_SIGNALS)
00260       // Only attempt to register a signal handler for positive
00261       // signal numbers.
00262       if (ACE_Service_Config::signum_ > 0)
00263         {
00264           ACE_Sig_Set ss;
00265           ss.sig_add (ACE_Service_Config::signum_);
00266           if (ACE_Reactor::instance ()->register_handler
00267               (ss, ACE_Service_Config::signal_handler_) == -1)
00268             ACE_ERROR ((LM_ERROR,
00269                         ACE_TEXT ("can't register signal handler\n")));
00270         }
00271 #endif /* ACE_LACKS_UNIX_SIGNALS */
00272     }
00273 
00274   if (result == -1)
00275     return -1;
00276 
00277   if (this->init_svc_conf_file_queue () == -1)
00278     return -1;
00279 
00280   // Check if the default file exists before attempting to queue it
00281   // for processing
00282   if (!ignore_default_svc_conf_file)
00283     {
00284       FILE *fp = ACE_OS::fopen (ACE_DEFAULT_SVC_CONF,
00285                                 ACE_TEXT ("r"));
00286       ignore_default_svc_conf_file = (fp == 0);
00287       if (fp != 0)
00288         ACE_OS::fclose (fp);
00289     }
00290 
00291   if (!ignore_default_svc_conf_file
00292       && this->svc_conf_file_queue_->is_empty ())
00293     {
00294       // Load the default "svc.conf" entry here if there weren't
00295       // overriding -f arguments in <parse_args>.
00296       if (this->svc_conf_file_queue_->enqueue_tail
00297           (ACE_TString (ACE_DEFAULT_SVC_CONF)) == -1)
00298         {
00299           ACE_ERROR_RETURN ((LM_ERROR,
00300                              ACE_TEXT ("%p\n"),
00301                              ACE_TEXT ("enqueuing ")
00302                              ACE_DEFAULT_SVC_CONF
00303                              ACE_TEXT(" file")),
00304                             -1);
00305         }
00306     }
00307 
00308   return ACE_Service_Gestalt::open_i (program_name,
00309                                       logger_key,
00310                                       ignore_static_svcs,
00311                                       ignore_default_svc_conf_file,
00312                                       ignore_debug_flag);
00313 }
00314 
00315 // This method has changed to return the gestalt instead of the
00316 // container, underlying the service repository and defined
00317 // ACE_Service_Gestalt::insert (ACE_Static_Svc_Descriptor*). This way
00318 // the existing source code can keep using
00319 // ACE_Service_Config::static_svcs(), however now it is not necessary
00320 // to expose the repository storage *and* it is much easier to debug
00321 // service registration problems.
00322 
00323 ACE_Service_Gestalt *
00324 ACE_Service_Config::static_svcs (void)
00325 {
00326   return ACE_Service_Config::instance ();
00327 }
00328 
00329 /// Return the global configuration instance. Allways returns the same
00330 /// instance
00331 ACE_Service_Config *
00332 ACE_Service_Config::global (void)
00333 {
00334   return ACE_SERVICE_CONFIG_SINGLETON::instance ();
00335 }
00336 
00337 int
00338 ACE_Service_Config::insert (ACE_Static_Svc_Descriptor* stsd)
00339 {
00340   return ACE_Service_Config::instance ()->insert (stsd);
00341 }
00342 
00343 
00344 // Totally remove <svc_name> from the daemon by removing it from the
00345 // ACE_Reactor, and unlinking it if necessary.
00346 int
00347 ACE_Service_Config::remove (const ACE_TCHAR svc_name[])
00348 {
00349   ACE_TRACE ("ACE_Service_Config::remove");
00350   return ACE_Service_Repository::instance ()->remove (svc_name);
00351 }
00352 
00353 // Suspend <svc_name>.  Note that this will not unlink the service
00354 // from the daemon if it was dynamically linked, it will mark it as
00355 // being suspended in the Service Repository and call the <suspend>
00356 // member function on the appropriate <ACE_Service_Object>.  A service
00357 // can be resumed later on by calling the <resume> method...
00358 
00359 int
00360 ACE_Service_Config::suspend (const ACE_TCHAR svc_name[])
00361 {
00362   ACE_TRACE ("ACE_Service_Config::suspend");
00363   return ACE_Service_Repository::instance ()->suspend (svc_name);
00364 }
00365 
00366 // Resume a SVC_NAME that was previously suspended or has not yet
00367 // been resumed (e.g., a static service).
00368 
00369 int
00370 ACE_Service_Config::resume (const ACE_TCHAR svc_name[])
00371 {
00372   ACE_TRACE ("ACE_Service_Config::resume");
00373   return ACE_Service_Repository::instance ()->resume (svc_name);
00374 }
00375 
00376 
00377 ACE_Service_Config::ACE_Service_Config (int ignore_static_svcs,
00378                                         size_t size,
00379                                         int signum)
00380   : ACE_Service_Gestalt (size, false, ignore_static_svcs)
00381   , tss_ (this)
00382 {
00383   ACE_TRACE ("ACE_Service_Config::ACE_Service_Config");
00384   ACE_Service_Config::signum_ = signum;
00385 }
00386 
00387 
00388 #if (ACE_USES_CLASSIC_SVC_CONF == 0)
00389 ACE_Service_Type *
00390 ACE_Service_Config::create_service_type  (const ACE_TCHAR *n,
00391                                           ACE_Service_Type_Impl *o,
00392                                           ACE_DLL &dll,
00393                                           int active)
00394 {
00395   ACE_Service_Type *sp = 0;
00396   ACE_NEW_RETURN (sp,
00397                   ACE_Service_Type (n, o, dll, active),
00398                   0);
00399   return sp;
00400 }
00401 #endif /* ACE_USES_CLASSIC_SVC_CONF == 0 */
00402 
00403 ACE_Service_Type_Impl *
00404 ACE_Service_Config::create_service_type_impl (const ACE_TCHAR *name,
00405                                               int type,
00406                                               void *symbol,
00407                                               u_int flags,
00408                                               ACE_Service_Object_Exterminator gobbler)
00409 {
00410   ACE_Service_Type_Impl *stp = 0;
00411 
00412   // Note, the only place we need to put a case statement.  This is
00413   // also the place where we'd put the RTTI tests, if the compiler
00414   // actually supported them!
00415 
00416   switch (type)
00417     {
00418     case ACE_Service_Type::SERVICE_OBJECT:
00419       ACE_NEW_RETURN (stp,
00420                       ACE_Service_Object_Type ((ACE_Service_Object *) symbol,
00421                                                name, flags,
00422                                                gobbler),
00423                       0);
00424       break;
00425     case ACE_Service_Type::MODULE:
00426       ACE_NEW_RETURN (stp,
00427                       ACE_Module_Type (symbol, name, flags),
00428                       0);
00429       break;
00430     case ACE_Service_Type::STREAM:
00431       ACE_NEW_RETURN (stp,
00432                       ACE_Stream_Type (symbol, name, flags),
00433                       0);
00434       break;
00435     default:
00436       ACE_ERROR ((LM_ERROR,
00437                   ACE_TEXT ("unknown case\n")));
00438       break;
00439     }
00440   return stp;
00441 
00442 }
00443 
00444 
00445 ACE_Service_Config::ACE_Service_Config (const ACE_TCHAR program_name[],
00446                                         const ACE_TCHAR *logger_key)
00447   : ACE_Service_Gestalt (ACE_Service_Repository::DEFAULT_SIZE, false)
00448   , tss_ (this)
00449 {
00450   ACE_TRACE ("ACE_Service_Config::ACE_Service_Config");
00451 
00452   if (this->open (program_name,
00453                   logger_key) == -1 && errno != ENOENT)
00454     {
00455 
00456       // Only print out an error if it wasn't the svc.conf file that was
00457       // missing.
00458       ACE_ERROR ((LM_ERROR,
00459                   ACE_TEXT ("(%P|%t) SC failed to open: %p\n"),
00460                   program_name));
00461     }
00462 }
00463 
00464 // Signal handling API to trigger dynamic reconfiguration.
00465 
00466 void
00467 ACE_Service_Config::handle_signal (int sig,
00468                                    siginfo_t *,
00469                                    ucontext_t *)
00470 {
00471 #if defined (ACE_NDEBUG)
00472   ACE_UNUSED_ARG (sig);
00473 #else  /* ! ACE_NDEBUG */
00474   ACE_ASSERT (ACE_Service_Config::signum_ == sig);
00475 #endif /* ! ACE_NDEBUG */
00476 
00477   ACE_Service_Config::reconfig_occurred_ = 1;
00478 }
00479 
00480 // Trigger the reconfiguration process.
00481 
00482 void
00483 ACE_Service_Config::reconfigure (void)
00484 {
00485   ACE_TRACE ("ACE_Service_Config::reconfigure");
00486 
00487   ACE_Service_Config::reconfig_occurred_ = 0;
00488 
00489   if (ACE::debug ())
00490     {
00491 #if !defined (ACE_NLOGGING)
00492       time_t t = ACE_OS::time (0);
00493 #endif /* ! ACE_NLOGGING */
00494       if (ACE::debug ())
00495         ACE_DEBUG ((LM_DEBUG,
00496                     ACE_TEXT ("beginning reconfiguration at %s"),
00497                     ACE_OS::ctime (&t)));
00498     }
00499   if (ACE_Service_Config::process_directives () == -1)
00500     ACE_ERROR ((LM_ERROR,
00501                 ACE_TEXT ("%p\n"),
00502                 ACE_TEXT ("process_directives")));
00503 }
00504 
00505 // Tidy up and perform last rites on a terminating ACE_Service_Config.
00506 int
00507 ACE_Service_Config::close (void)
00508 {
00509   int result1 = ACE_Service_Config::instance ()->close ();
00510 
00511   // Delete the service repository.  All the objects inside the
00512   // service repository should already have been finalized.
00513   int result2 = ACE_Service_Config::close_svcs ();
00514 
00515   // Do away with the Singleton
00516   ACE_SERVICE_CONFIG_SINGLETON::close ();
00517 
00518   return (result1 | result2);
00519 }
00520 
00521 int
00522 ACE_Service_Config::close_svcs (void)
00523 {
00524   ACE_TRACE ("ACE_Service_Config::close_svcs");
00525 
00526   ACE_Service_Repository::close_singleton ();
00527   ACE_Service_Config::current (global ());
00528   return 0;
00529 }
00530 
00531 int
00532 ACE_Service_Config::fini_svcs (void)
00533 {
00534   ACE_TRACE ("ACE_Service_Config::fini_svcs");
00535 
00536   // Clear the LM_DEBUG bit from log messages if appropriate
00537   if (ACE::debug ())
00538     ACE_Log_Msg::disable_debug_messages ();
00539 
00540   int result = 0;
00541   if (ACE_Service_Repository::instance () != 0)
00542     result = ACE_Service_Repository::instance ()->fini ();
00543 
00544   if (ACE::debug ())
00545     ACE_Log_Msg::enable_debug_messages ();
00546 
00547   return result;
00548 }
00549 
00550 // Perform user-specified close activities and remove dynamic memory.
00551 
00552 ACE_Service_Config::~ACE_Service_Config (void)
00553 {
00554   ACE_TRACE ("ACE_Service_Config::~ACE_Service_Config");
00555 }
00556 
00557 // ************************************************************
00558 
00559 /* static */
00560 int
00561 ACE_Service_Config::reconfig_occurred (void)
00562 {
00563   ACE_TRACE ("ACE_Service_Config::reconfig_occurred");
00564   return ACE_Service_Config::reconfig_occurred_ != 0;
00565 }
00566 
00567 void
00568 ACE_Service_Config::reconfig_occurred (int config_occurred)
00569 {
00570   ACE_TRACE ("ACE_Service_Config::reconfig_occurred");
00571   ACE_Service_Config::reconfig_occurred_ = config_occurred;
00572 }
00573 
00574 // ************************************************************
00575 
00576 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Sun Jan 27 12:05:37 2008 for ACE by doxygen 1.3.6