Service_Config.cpp

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

Generated on Tue Feb 2 17:18:42 2010 for ACE by  doxygen 1.4.7