ab70527cc37e99af6506f50359aacd183011b0de
[senf.git] / Scheduler / Daemon.hh
1 // $Id$
2 //
3 // Copyright (C) 2007 
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer NETwork research (NET)
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief Daemon public header */
25
26 #ifndef HH_Daemon_
27 #define HH_Daemon_ 1
28
29 // Custom includes
30 #include <boost/utility.hpp>
31
32 //#include "Daemon.mpp"
33 ///////////////////////////////hh.p////////////////////////////////////////
34
35 namespace senf {
36
37     /** \brief Daemon process
38
39         This class provides the infrastructure to implement robust daemon processes. A daemon
40         process is implemented by deriving from senf::Daemon and implementing the necessary
41         (virtual) member functions.
42         \code
43         class MyDaemon : public senf::Daemon
44         {
45             void configure() {
46                 // Set configuration parameters like daemonize(), pidFile() etc.
47             }
48
49             void init() {
50                 // Initialize application. Setup all necessary objects. After init()
51                 // has completed, is startup should not fail anymore
52             }
53
54             void run() {
55                 // Main application code should be called here.
56             }
57         };
58         \endcode
59
60         The startup procedure is divided into three steps:
61         \li First, configure() is called. configure() should be as simple as possible. It just needs
62             to set the daemon parameters. No further setup should be done here.
63         \li init() is called after fork() but while still connected to the terminal. init() should
64             do all necessary application setup. Here, all configuration or user errors should be
65             detected and properly diagnosed.
66         \li After init() returns, the application will detach from the terminal. Now run() is called
67             to enter the application main loop.
68
69         Since there are times, where separating init() and run() into two separate functions is
70         difficult, instead of defining init() and run(), the member main() may be defined. This
71         member must call detach() as soon as initialization is completed to detach from the
72         foreground terminal.
73       */
74     class Daemon : boost::noncopyable
75     {
76     public:
77         ///////////////////////////////////////////////////////////////////////////
78         // Types
79         
80         /// Select standard stream to redirect
81         enum StdStream { 
82             StdOut  /** Standard output stream */
83         ,   StdErr  /** Standard error stream */
84         ,   Both    /** Both, standard output and error stream */
85         }; 
86
87         ///////////////////////////////////////////////////////////////////////////
88         ///\name Structors and default members
89         ///\{
90
91         virtual ~Daemon();
92
93         ///\}
94         ///\name Parameters
95         ///\{
96
97         void daemonize(bool);           ///< Configure whether to run in fore- or background
98         bool daemon();                  ///< \c true, if running as daemon
99
100         void consoleLog(std::string const &, StdStream which = Both); 
101                                         ///< Configure console log file
102                                         /**< May be called multiple times to set the log file
103                                              for stdout and stderr seperately. Any standard stream
104                                              not assigned to a log file will be redirected to
105                                              <tt>/dev/null</tt>. 
106
107                                              When running in the foreground, the log files will be
108                                              ignored. */
109
110         void pidFile(std::string const &); ///< Configure pid file
111
112         ///\}
113         ///\name Auxiliary helpers
114         ///\{
115
116         void detach();                  ///< Detach into background now
117                                         /**< This is \e not the same as forking. The process will
118                                              already have forked into the background but until
119                                              detach() is called (either automatically after init()
120                                              returns or manually), the front end (foreground)
121                                              process will wait for the background process to ensure
122                                              successful startup. */
123
124         int argc();                     ///< Access command line parameter count
125         char const ** argv();           ///< Access command line parameters
126
127         void fail(int code=1);          ///< Terminate startup with failure
128
129         ///\}
130         
131         int start(int argc, char const ** argv); ///< Called from main() to launch daemon.
132                                         /**< Normally not called directly but from the
133                                              \ref SENF_DAEMON_MAIN macro. */
134
135     protected:
136         Daemon();
137
138 #   ifdef DOXYGEN
139     protected:
140 #   else
141     private:
142 #   endif
143
144         virtual void configure();       ///< Called before forking to configure the daemon class
145         virtual void main();            ///< Called after forking to execute the main application
146                                         /**< The default implementation will call init(), detach()
147                                              and then run(). It is preferred to override init() and
148                                              run() if possible. */
149         virtual void init();            ///< Called to initialize the main application
150                                         /**< While init() is running, the application still is
151                                              connected to the controlling terminal. Error messages
152                                              will be shown to the user.
153
154                                              This member is only called, if the default main()
155                                              implementation is not overridden. */
156         virtual void run();             ///< Called to execute main application
157                                         /**< Called after detaching from the controlling
158                                              terminal.
159
160                                              This member is only called, if the default main()
161                                              implementation is not overridden. */
162     private:
163
164         void fork();
165         bool pidfileCreate();
166
167         int argc_;
168         char const ** argv_;
169
170         bool daemonize_;
171         int stdout_;
172         int stderr_;
173         std::string pidfile_;
174
175         bool detached_;
176     };
177
178     /** \brief Provide \c main() function
179
180         This macro will provide a \c main() function to launch the daemon process defined in \a
181         klass. \a klass must be a class derived from senf::Daemon.
182
183         \ingroup process
184      */
185 #   define SENF_DAEMON_MAIN(klass)                                                                \
186         int main(int argc, char const ** argv)                                                    \
187         {                                                                                         \
188             klass instance;                                                                       \
189             return instance.start(argc, argv);                                                    \
190         }
191
192 }
193
194 ///////////////////////////////hh.e////////////////////////////////////////
195 //#include "Daemon.cci"
196 //#include "Daemon.ct"
197 //#include "Daemon.cti"
198 #endif
199
200 \f
201 // Local Variables:
202 // mode: c++
203 // fill-column: 100
204 // comment-column: 40
205 // c-file-style: "senf"
206 // indent-tabs-mode: nil
207 // ispell-local-dictionary: "american"
208 // compile-command: "scons -u test"
209 // End: