Scheduler: Implement new file descriptor event API
[senf.git] / Utils / Daemon / Daemon.hh
index 3526cb3..f0c45c0 100644 (file)
@@ -1,8 +1,8 @@
 // $Id$
 //
-// Copyright (C) 2007 
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer NETwork research (NET)
+// Copyright (C) 2007
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
 //     Stefan Bund <g0dil@berlios.de>
 //
 // This program is free software; you can redistribute it and/or modify
 
 // Custom includes
 #include <boost/utility.hpp>
+#include "../Logger/SenfLog.hh"
 
 //#include "Daemon.mpp"
 ///////////////////////////////hh.p////////////////////////////////////////
 
 namespace senf {
 
-    /** \brief Daemon process
-
-        This class provides the infrastructure to implement robust daemon processes. A daemon
-        process is implemented by deriving from senf::Daemon and implementing the necessary
-        (virtual) member functions.
-        \code
-        class MyDaemon : public senf::Daemon
-        {
-            void configure() {
-                // Set configuration parameters like daemonize(), pidFile() etc.
-            }
-
-            void init() {
-                // Initialize application. Setup all necessary objects. After init()
-                // has completed, is startup should not fail anymore
-            }
-
-            void run() {
-                // Main application code should be called here.
-            }
-        };
-        \endcode
-
-        The startup procedure is divided into three steps:
-        \li First, configure() is called. configure() should be as simple as possible. It just needs
-            to set the daemon parameters. No further setup should be done here.
-        \li init() is called after fork() but while still connected to the terminal. init() should
-            do all necessary application setup. Here, all configuration or user errors should be
-            detected and properly diagnosed.
-        \li After init() returns, the application will detach from the terminal. Now run() is called
-            to enter the application main loop.
-
-        Since there are times, where separating init() and run() into two separate functions is
-        difficult, instead of defining init() and run(), the member main() may be defined. This
-        member must call detach() as soon as initialization is completed to detach from the
-        foreground terminal.
+    /** \brief %Daemon process
+
+        %senf::Daemon provides simple management for daemon processes. Specifically, the %Daemon class
+        implements
+        \li <i>Safe startup.</i> If the startup fails, the foreground process which launches the
+            daemon will terminate with an appropriate error exit code.
+        \li <i>Straight forward application initialization.</i> The daemon process is forked before
+            even initializing the application. The initialization procedure must not cater for a
+            later fork().
+        \li <i>Automatic pid file management.</i> The daemon will not be started, if a valid pid file is
+            found. Stale pid files are automatically removed.
+        \li <i>Console log management.</i> It is possible, to redirect standard output and error to
+            one or two log files. Messages pertaining to application initialization will be written
+            to both the console and the log file whereas later messages will be directed to the log
+            file only.
+        \li <i>Optional foreground execution.</i> The daemon may be started in the foreground for
+            debugging purposes. In this case, the console log file(s) is/are automatically
+            suppressed.
+        
+        Starting the daemon process proceeds along the following steps:
+        \li The daemon is started by calling the daemon class instances start() member. This
+            normally happens from the \c main() function generated by \ref SENF_DAEMON_MAIN().
+        \li configure() is called. This (virtual) member configures the daemon manager by calling
+            the Daemon class parameter members.
+        \li The log files are opened, \c fork() is called and the pid file is checked and
+            created. The parent (foreground) process keeps running overseeing the daemon process.
+        \li main() is called. This virtual member may optionally be overridden in the derived
+            class. Here we assume, main() is not overridden so the default implementation is used.
+        \li main() calls init(). 
+        \li after init() returns, main() calls detach().
+        \li detach() signals successful startup to the parent process. The parent process terminates
+            leaving the daemon process running in the background.
+        \li main() calls run()
+        \li If run() ever returns, the daemon process terminates.
+        \li Whenever the process terminates normally (not necessarily successfully), the pid file is
+            automatically removed.
+
+        The parameter members are used from configure() to configure the daemon manager. See below
+        for details. The \e default configure() implementation will scan the command line arguments
+        to check for the following parameters:
+
+        <table class="senf">
+
+        <tr><td><tt>--no-daemon</tt></td><td>Run in foreground</td></tr>
+
+        <tr><td><tt>--console-log=</tt><i>stdout</i>[<tt>,</tt><i>stderr</i>]</td><td>Set the
+        console log file(s). If only \a stdout is specified (with no comma), the same log file
+        configuration will be applied to the standard output and error stream. Otherwise each stream
+        is assigned it's own log file. If either log file name is empty, the command will not change
+        the log file of that stream, the default log file will be used. If the log file name is set
+        to 'none', the log file will be disabled.</td></tr>
+
+        <tr><td><tt>--pid-file=</tt><i>pidfile</i></td><td>Set pid file path</td></tr>
+
+        </table>
+
+        The default configure() implementation will use whatever parameters have been set beforehand
+        as default values. These default values should be set in a derived class configure()
+        implementation. After setting the default values, the configure() implementation may choose
+        to call this default configure() implementation to scan for command line parmeters.  The
+        default configure() implementation does \e not completely parse the command line
+        arguments. It just checks, if any of above arguments are present and precesses them. Other
+        arguments are completely ignored. The command line parameters should be completely processed
+        within init().
+        
       */
     class Daemon : boost::noncopyable
     {
     public:
+        SENF_LOG_CLASS_AREA();
+
         ///////////////////////////////////////////////////////////////////////////
         // Types
         
@@ -108,6 +140,9 @@ namespace senf {
                                              ignored. */
 
         void pidFile(std::string const &); ///< Configure pid file
+                                        /**< If a pid file is configured it will be checked on
+                                             daemon startup. If another running instance of the
+                                             daemon is detected, starting the daemon will fail. */
 
         ///\}
         ///\name Auxiliary helpers
@@ -122,20 +157,29 @@ namespace senf {
                                              successful startup. */
 
         int argc();                     ///< Access command line parameter count
-        char const ** argv();           ///< Access command line parameters
+        char ** argv();                 ///< Access command line parameters
+        void removeDaemonArgs();        ///< Remove the daemon arguments from argc()/argv()
+
+        static void exit(unsigned code=0); ///< Terminate daemon with failure
 
-        void fail(int code=1);          ///< Terminate startup with failure
+        void logReopen();               ///< Reopen the log files
+                                        /**< This is used when rotating the logs. By default,
+                                             SIGHUP calls logReopen. */
 
         ///\}
         
-        int start(int argc, char const ** argv); ///< Called from main() to launch daemon.
+        int start(int argc, char ** argv); ///< Called from main() to launch daemon.
                                         /**< Normally not called directly but from the
                                              \ref SENF_DAEMON_MAIN macro. */
 
+        static Daemon & instance();     ///< Return the Daemon instance
+
     protected:
         Daemon();
 
         virtual void configure();       ///< Called before forking to configure the daemon class
+                                        /**< This default implementation will parser some command
+                                             line parameters. See the class documentation above. */
 
 #   ifdef DOXYGEN
     protected:
@@ -161,13 +205,13 @@ namespace senf {
                                              This member is only called, if the default main()
                                              implementation is not overridden. */
     private:
-
         void openLog();
         void fork();
         bool pidfileCreate();
+        void installSighandlers();
 
         int argc_;
-        char const ** argv_;
+        char ** argv_;
 
         bool daemonize_;
         std::string stdoutLog_;
@@ -175,8 +219,11 @@ namespace senf {
         int stdout_;
         int stderr_;
         std::string pidfile_;
+        bool pidfileCreated_;
 
         bool detached_;
+
+        static Daemon * instance_;
     };
 
     /** \brief Provide \c main() function
@@ -187,7 +234,7 @@ namespace senf {
         \ingroup process
      */
 #   define SENF_DAEMON_MAIN(klass)                                                                \
-        int main(int argc, char const ** argv)                                                    \
+        int main(int argc, char ** argv)                                                    \
         {                                                                                         \
             klass instance;                                                                       \
             return instance.start(argc, argv);                                                    \
@@ -196,7 +243,7 @@ namespace senf {
 }
 
 ///////////////////////////////hh.e////////////////////////////////////////
-//#include "Daemon.cci"
+#include "Daemon.cci"
 //#include "Daemon.ct"
 //#include "Daemon.cti"
 #endif