Restore build on FreeBSD.
[getmangos.git] / dep / ACE_wrappers / ace / Service_Config.cpp
blobf0f352cedcb11543c83d52c4ad2f655824da048f
1 // $Id: Service_Config.cpp 81756 2008-05-22 09:47:33Z johnnyw $
3 #include "ace/Service_Config.h"
5 #if !defined (__ACE_INLINE__)
6 #include "ace/Service_Config.inl"
7 #endif /* __ACE_INLINE__ */
9 #include "ace/Service_Types.h"
10 #include "ace/Reactor.h"
11 #include "ace/Singleton.h"
12 #include "ace/Service_Repository.h"
14 #ifndef ACE_LACKS_UNIX_SIGNALS
15 # include "ace/Sig_Adapter.h"
16 #endif /* !ACE_LACKS_UNIX_SIGNALS */
18 #include "ace/OS_NS_time.h"
19 #include "ace/OS_NS_stdio.h"
20 #include "ace/OS_NS_unistd.h"
21 #include "ace/Thread.h"
22 #include "ace/Get_Opt.h"
23 #include "ace/ARGV.h"
24 #include "ace/Log_Msg.h"
25 #include "ace/ACE.h"
27 ACE_RCSID (ace,
28 Service_Config,
29 "$Id: Service_Config.cpp 81756 2008-05-22 09:47:33Z johnnyw $")
31 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
33 ACE_Threading_Helper<ACE_Thread_Mutex>::~ACE_Threading_Helper ()
35 ACE_OS::thr_key_detach (this->key_, 0);
36 ACE_OS::thr_keyfree (this->key_);
39 ACE_Threading_Helper<ACE_Thread_Mutex>::ACE_Threading_Helper ()
40 : key_ (ACE_OS::NULL_key)
42 # if defined (ACE_HAS_TSS_EMULATION)
43 ACE_Object_Manager::init_tss ();
44 # endif
46 if (ACE_Thread::keycreate (&key_, 0, 0) == -1)
48 ACE_ERROR ((LM_ERROR,
49 ACE_TEXT ("(%P|%t) Failed to create thread key: %p\n"),
50 ""));
54 void
55 ACE_Threading_Helper<ACE_Thread_Mutex>::set (void* p)
57 if (ACE_Thread::setspecific (key_, p) == -1)
58 ACE_ERROR ((LM_ERROR,
59 ACE_TEXT ("(%P|%t) Service Config failed to set thread key value: %p\n"),
60 ""));
63 void*
64 ACE_Threading_Helper<ACE_Thread_Mutex>::get (void)
66 void* temp = 0;
67 if (ACE_Thread::getspecific (key_, &temp) == -1)
68 ACE_ERROR_RETURN ((LM_ERROR,
69 ACE_TEXT ("(%P|%t) Service Config failed to get thread key value: %p\n"),
70 ""),
71 0);
72 return temp;
75 ACE_Threading_Helper<ACE_Null_Mutex>::~ACE_Threading_Helper ()
79 ACE_Threading_Helper<ACE_Null_Mutex>::ACE_Threading_Helper ()
83 void
84 ACE_Threading_Helper<ACE_Null_Mutex>::set (void*)
88 void*
89 ACE_Threading_Helper<ACE_Null_Mutex>::get (void)
91 return ACE_Service_Config::singleton()->instance_.get ();
94 /**
95 * @c ACE_Service_Config is supposed to be a Singleton. This is the
96 * only Configuration Gestalt available for access from static
97 * initializers at proces start-up time. Using Unmanaged Singleton
98 * is safer because (a) the Object Manager may not yet be fully initialized
99 * in the context of a static initializer that uses SC, and (b) because we
100 * know that upon process exit the SC will still be automaticaly and explicitly
101 * closed by @c ACE_Object_Manager::fini().
103 typedef ACE_Unmanaged_Singleton<ACE_Service_Config,
104 ACE_SYNCH_RECURSIVE_MUTEX> ACE_SERVICE_CONFIG_SINGLETON;
107 /// ctor
108 ACE_Service_Config_Guard::ACE_Service_Config_Guard (ACE_Service_Gestalt * psg)
109 : saved_ (ACE_Service_Config::current ())
111 if (ACE::debug ())
112 ACE_DEBUG ((LM_DEBUG,
113 ACE_TEXT ("ACE (%P|%t) SCG:<ctor=%@>")
114 ACE_TEXT (" - config=%@ repo=%@ superceded by repo=%@\n"),
115 this,
116 this->saved_.get (),
117 this->saved_->repo_,
118 psg->repo_));
120 // Modify the TSS if the repo has changed
121 ACE_Service_Config::current (psg);
124 ACE_Service_Config_Guard::~ACE_Service_Config_Guard (void)
126 ACE_Service_Gestalt* s = this->saved_.get ();
127 ACE_ASSERT (s != 0);
129 ACE_Service_Config::current (s);
131 if (ACE::debug ())
132 ACE_DEBUG ((LM_DEBUG,
133 ACE_TEXT ("ACE (%P|%t) SCG:<dtor=%@>")
134 ACE_TEXT (" - new repo=%@\n"),
135 this,
136 this->saved_->repo_));
140 ACE_ALLOC_HOOK_DEFINE (ACE_Service_Config)
142 // Set the signal handler to point to the handle_signal() function.
143 ACE_Sig_Adapter *ACE_Service_Config::signal_handler_ = 0;
145 // Trigger a reconfiguration.
146 sig_atomic_t ACE_Service_Config::reconfig_occurred_ = 0;
148 // = Set by command-line options.
150 /// Pathname of file to write process id.
151 ACE_TCHAR *ACE_Service_Config::pid_file_name_ = 0;
153 /// Shall we become a daemon process?
154 bool ACE_Service_Config::be_a_daemon_ = false;
156 /// Number of the signal used to trigger reconfiguration.
157 int ACE_Service_Config::signum_ = SIGHUP;
159 void
160 ACE_Service_Config::dump (void) const
162 #if defined (ACE_HAS_DUMP)
163 ACE_TRACE ("ACE_Service_Config::dump");
164 #endif /* ACE_HAS_DUMP */
168 ACE_Service_Config::parse_args_i (int argc, ACE_TCHAR *argv[])
170 ACE_TRACE ("ACE_Service_Config::parse_args_i");
172 // Using PERMUTE_ARGS (default) in order to have all
173 // unrecognized options and their value arguments moved
174 // to the end of the argument vector. We'll pick them up
175 // after processing our options and pass them on to the
176 // base class for further parsing.
177 //FUZZ: disable check_for_lack_ACE_OS
178 ACE_Get_Opt getopt (argc,
179 argv,
180 ACE_TEXT ("bs:p:"),
181 1 , // Start at argv[1].
182 0, // Do not report errors
183 ACE_Get_Opt::RETURN_IN_ORDER);
184 //FUZZ: enable check_for_lack_ACE_OS
186 // Keep a list of all unknown arguments, begin with the
187 // executable's name
188 ACE_ARGV superargv;
189 superargv.add (argv[0]);
191 //FUZZ: disable check_for_lack_ACE_OS
192 for (int c; (c = getopt ()) != -1; )
193 //FUZZ: enable check_for_lack_ACE_OS
194 switch (c)
196 case 'p':
197 ACE_Service_Config::pid_file_name_ = getopt.opt_arg ();
198 break;
199 case 'b':
200 ACE_Service_Config::be_a_daemon_ = true;
201 break;
202 case 's':
204 // There's no point in dealing with this on NT since it
205 // doesn't really support signals very well...
206 #if !defined (ACE_LACKS_UNIX_SIGNALS)
207 ACE_Service_Config::signum_ =
208 ACE_OS::atoi (getopt.opt_arg ());
210 if (ACE_Reactor::instance ()->register_handler
211 (ACE_Service_Config::signum_,
212 ACE_Service_Config::signal_handler_) == -1)
213 ACE_ERROR_RETURN ((LM_ERROR,
214 ACE_TEXT ("cannot obtain signal handler\n")),
215 -1);
216 #endif /* ACE_LACKS_UNIX_SIGNALS */
217 break;
219 default:
220 superargv.add (argv[getopt.opt_ind () - 1], true);
223 // Collect any argumets that were left
224 for (int c = getopt.opt_ind (); c < argc; ++c)
225 superargv.add (argv[c-1], true);
227 bool ignore_default_svc_conf_file = false;
228 return instance_->parse_args_i (superargv.argc (),
229 superargv.argv (),
230 ignore_default_svc_conf_file);
232 } /* parse_args_i () */
236 ACE_Service_Config::open_i (const ACE_TCHAR program_name[],
237 const ACE_TCHAR *logger_key,
238 bool ,
239 bool ,
240 bool )
242 ACE_TRACE ("ACE_Service_Config::open_i");
243 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
245 ACE_Log_Msg *log_msg = ACE_LOG_MSG;
247 if (ACE::debug ())
248 ACE_DEBUG ((LM_DEBUG,
249 ACE_TEXT ("ACE (%P|%t) SC::open_i - this=%@, opened=%d\n"),
250 this, this->is_opened_));
252 // Guard against reentrant processing.
253 if (this->is_opened_)
254 return 0;
256 this->is_opened_ = true;
258 // Check for things we need to do on a per-process basis and which
259 // may not be safe, or wise to do an a per instance basis
261 // Become a daemon before doing anything else.
262 if (ACE_Service_Config::be_a_daemon_)
263 ACE::daemonize ();
265 // Write process id to file.
266 if (this->pid_file_name_ != 0)
268 FILE* pidf = ACE_OS::fopen (this->pid_file_name_,
269 ACE_TEXT("w"));
271 if (pidf != 0)
273 ACE_OS::fprintf (pidf,
274 "%ld\n",
275 static_cast<long> (ACE_OS::getpid()));
276 ACE_OS::fclose (pidf);
280 u_long flags = log_msg->flags ();
282 // Only use STDERR if the caller hasn't already set the flags.
283 if (flags == 0)
284 flags = (u_long) ACE_Log_Msg::STDERR;
286 const ACE_TCHAR *key = logger_key;
288 if (key == 0 || ACE_OS::strcmp (key, ACE_DEFAULT_LOGGER_KEY) == 0)
289 // Only use the static <logger_key_> if the caller doesn't
290 // override it in the parameter list or if the key supplied is
291 // equal to the default static logger key.
292 key = ACE_Service_Config::current()->logger_key_;
293 else
294 ACE_SET_BITS (flags, ACE_Log_Msg::LOGGER);
296 if (log_msg->open (program_name,
297 flags,
298 key) == -1)
299 return -1;
301 if (ACE::debug ())
302 ACE_DEBUG ((LM_STARTUP,
303 ACE_TEXT ("starting up daemon %n\n")));
305 // Initialize the Service Repository (this will still work if
306 // user forgets to define an object of type ACE_Service_Config).
307 ACE_Service_Repository::instance (ACE_Service_Gestalt::MAX_SERVICES);
309 // Initialize the ACE_Reactor (the ACE_Reactor should be the
310 // same size as the ACE_Service_Repository).
311 ACE_Reactor::instance ();
313 // There's no point in dealing with this on NT since it doesn't
314 // really support signals very well...
315 #if !defined (ACE_LACKS_UNIX_SIGNALS)
316 // Only attempt to register a signal handler for positive
317 // signal numbers.
318 if (ACE_Service_Config::signum_ > 0)
320 ACE_Sig_Set ss;
321 ss.sig_add (ACE_Service_Config::signum_);
322 if ((ACE_Reactor::instance () != 0) &&
323 (ACE_Reactor::instance ()->register_handler
324 (ss, ACE_Service_Config::signal_handler_) == -1))
325 ACE_ERROR ((LM_ERROR,
326 ACE_TEXT ("can't register signal handler\n")));
328 #endif /* ACE_LACKS_UNIX_SIGNALS */
330 return 0;
333 /// Return the global configuration instance. Always returns the same
334 /// instance
335 ACE_Service_Config *
336 ACE_Service_Config::singleton (void)
338 return ACE_SERVICE_CONFIG_SINGLETON::instance ();
342 ACE_Service_Config::insert (ACE_Static_Svc_Descriptor* stsd)
344 return ACE_Service_Config::instance ()->insert (stsd);
348 // Totally remove <svc_name> from the daemon by removing it from the
349 // ACE_Reactor, and unlinking it if necessary.
351 ACE_Service_Config::remove (const ACE_TCHAR svc_name[])
353 ACE_TRACE ("ACE_Service_Config::remove");
354 return ACE_Service_Repository::instance ()->remove (svc_name);
357 // Suspend <svc_name>. Note that this will not unlink the service
358 // from the daemon if it was dynamically linked, it will mark it as
359 // being suspended in the Service Repository and call the <suspend>
360 // member function on the appropriate <ACE_Service_Object>. A service
361 // can be resumed later on by calling the <resume> method...
364 ACE_Service_Config::suspend (const ACE_TCHAR svc_name[])
366 ACE_TRACE ("ACE_Service_Config::suspend");
367 return ACE_Service_Repository::instance ()->suspend (svc_name);
370 // Resume a SVC_NAME that was previously suspended or has not yet
371 // been resumed (e.g., a static service).
374 ACE_Service_Config::resume (const ACE_TCHAR svc_name[])
376 ACE_TRACE ("ACE_Service_Config::resume");
377 return ACE_Service_Repository::instance ()->resume (svc_name);
381 ACE_Service_Config::ACE_Service_Config (bool ignore_static_svcs,
382 size_t size,
383 int signum)
385 ACE_TRACE ("ACE_Service_Config::ACE_Service_Config");
387 // TODO: Need to find a more customizable way of instantiating the
388 // gestalt but perhaps we should leave this out untill such
389 // customizations are identified.
390 ACE_Service_Gestalt* tmp = 0;
391 ACE_NEW_NORETURN (tmp,
392 ACE_Service_Gestalt (size, false, ignore_static_svcs));
394 this->is_opened_ = false;
395 this->instance_ = tmp;
396 this->threadkey_.set (tmp);
398 ACE_Service_Config::signum_ = signum;
401 ACE_Service_Config::ACE_Service_Config (const ACE_TCHAR program_name[],
402 const ACE_TCHAR *logger_key)
404 ACE_TRACE ("ACE_Service_Config::ACE_Service_Config");
406 // TODO: Need to find a more customizable way of instantiating the
407 // gestalt but perhaps we should leave this out untill such
408 // customizations are identified.
409 ACE_Service_Gestalt* tmp = 0;
410 ACE_NEW_NORETURN (tmp,
411 ACE_Service_Gestalt (ACE_Service_Repository::DEFAULT_SIZE, false));
413 this->is_opened_ = false;
414 this->instance_ = tmp;
415 this->threadkey_.set (tmp);
417 if (this->open (program_name,
418 logger_key) == -1 && errno != ENOENT)
420 // Only print out an error if it wasn't the svc.conf file that was
421 // missing.
422 ACE_ERROR ((LM_ERROR,
423 ACE_TEXT ("(%P|%t) SC failed to open: %p\n"),
424 program_name));
428 /// Return the "global" configuration instance, for the current
429 /// thread. This may be the same as instance(), but on some occasions,
430 /// it may be a different one. For example, ACE_Service_Config_Guard
431 /// provides a way of temporarily replacing the "current"
432 /// configuration instance in the context of a thread.
433 ACE_Service_Gestalt*
434 ACE_Service_Config::current (void)
436 void* temp = ACE_Service_Config::singleton()->threadkey_.get ();
437 if (temp == 0) {
439 // The most likely reason is that the current thread was spawned
440 // by some native primitive, like pthreads or Windows API - not
441 // from ACE. This is perfectly legal for callers who are not, or
442 // do not need to be ACE-aware. Such callers must have no
443 // expectation that the pluggable, multi-context configuration
444 // support will work - they would always get the global context,
445 // because at this point there is no information what the "parent"
446 // thread's configuration context was.
448 temp = global();
449 singleton()->threadkey_.set (temp);
452 return static_cast<ACE_Service_Gestalt*> (temp);
455 /// A mutator to set the "current" (TSS) gestalt instance.
456 void
457 ACE_Service_Config::current (ACE_Service_Gestalt* newcurrent)
459 ACE_Service_Config::singleton()->threadkey_.set (newcurrent);
464 #if (ACE_USES_CLASSIC_SVC_CONF == 0)
465 ACE_Service_Type *
466 ACE_Service_Config::create_service_type (const ACE_TCHAR *n,
467 ACE_Service_Type_Impl *o,
468 ACE_DLL &dll,
469 int active)
471 ACE_Service_Type *sp = 0;
472 ACE_NEW_RETURN (sp,
473 ACE_Service_Type (n, o, dll, active),
475 return sp;
477 #endif /* ACE_USES_CLASSIC_SVC_CONF == 0 */
479 ACE_Service_Type_Impl *
480 ACE_Service_Config::create_service_type_impl (const ACE_TCHAR *name,
481 int type,
482 void *symbol,
483 u_int flags,
484 ACE_Service_Object_Exterminator gobbler)
486 ACE_Service_Type_Impl *stp = 0;
488 // Note, the only place we need to put a case statement. This is
489 // also the place where we'd put the RTTI tests, if the compiler
490 // actually supported them!
492 switch (type)
494 case ACE_Service_Type::SERVICE_OBJECT:
495 ACE_NEW_RETURN (stp,
496 ACE_Service_Object_Type ((ACE_Service_Object *) symbol,
497 name, flags,
498 gobbler),
500 break;
501 case ACE_Service_Type::MODULE:
502 ACE_NEW_RETURN (stp,
503 ACE_Module_Type (symbol, name, flags),
505 break;
506 case ACE_Service_Type::STREAM:
507 ACE_NEW_RETURN (stp,
508 ACE_Stream_Type (symbol, name, flags),
510 break;
511 default:
512 ACE_ERROR ((LM_ERROR,
513 ACE_TEXT ("unknown case\n")));
514 break;
516 return stp;
521 // Signal handling API to trigger dynamic reconfiguration.
522 void
523 ACE_Service_Config::handle_signal (int sig,
524 siginfo_t *,
525 ucontext_t *)
527 #if defined (ACE_NDEBUG)
528 ACE_UNUSED_ARG (sig);
529 #else /* ! ACE_NDEBUG */
530 ACE_ASSERT (ACE_Service_Config::signum_ == sig);
531 #endif /* ! ACE_NDEBUG */
533 ACE_Service_Config::reconfig_occurred_ = 1;
536 // Trigger reconfiguration to re-read configuration files.
537 void
538 ACE_Service_Config::reconfigure (void)
540 ACE_TRACE ("ACE_Service_Config::reconfigure");
542 ACE_Service_Config::reconfig_occurred_ = 0;
544 if (ACE::debug ())
546 #if !defined (ACE_NLOGGING)
547 time_t t = ACE_OS::time (0);
548 #endif /* ! ACE_NLOGGING */
549 if (ACE::debug ())
550 ACE_DEBUG ((LM_DEBUG,
551 ACE_TEXT ("beginning reconfiguration at %s"),
552 ACE_OS::ctime (&t)));
554 if (ACE_Service_Config::process_directives () == -1)
555 ACE_ERROR ((LM_ERROR,
556 ACE_TEXT ("%p\n"),
557 ACE_TEXT ("process_directives")));
560 // Tidy up and perform last rites on a terminating ACE_Service_Config.
562 ACE_Service_Config::close (void)
564 ACE_Service_Config::singleton ()->instance_->close ();
566 // Delete the service repository. All the objects inside the
567 // service repository should already have been finalized.
568 ACE_Service_Repository::close_singleton ();
570 // Do away with the singleton ACE_Service_Config (calls dtor)
571 ACE_SERVICE_CONFIG_SINGLETON::close ();
573 return 0;
578 ACE_Service_Config::fini_svcs (void)
580 ACE_TRACE ("ACE_Service_Config::fini_svcs");
582 // Clear the LM_DEBUG bit from log messages if appropriate
583 if (ACE::debug ())
584 ACE_Log_Msg::disable_debug_messages ();
586 int result = 0;
587 if (ACE_Service_Repository::instance () != 0)
588 result = ACE_Service_Repository::instance ()->fini ();
590 if (ACE::debug ())
591 ACE_Log_Msg::enable_debug_messages ();
593 return result;
596 /// Perform user-specified close activities and remove dynamic memory.
597 ACE_Service_Config::~ACE_Service_Config (void)
599 ACE_TRACE ("ACE_Service_Config::~ACE_Service_Config");
602 // ************************************************************
604 /* static */
606 ACE_Service_Config::reconfig_occurred (void)
608 ACE_TRACE ("ACE_Service_Config::reconfig_occurred");
609 return ACE_Service_Config::reconfig_occurred_ != 0;
612 void
613 ACE_Service_Config::reconfig_occurred (int config_occurred)
615 ACE_TRACE ("ACE_Service_Config::reconfig_occurred");
616 ACE_Service_Config::reconfig_occurred_ = config_occurred;
619 ACE_END_VERSIONED_NAMESPACE_DECL