Skip to content
Snippets Groups Projects
Commit 736dd1bc authored by g0dil's avatar g0dil
Browse files

Utils/Daemon: Documentation

Utils/Daemon: Last implementation fixes
Fix installation of some missing files
parent 2bcfdb01
No related branches found
No related tags found
No related merge requests found
......@@ -19,3 +19,4 @@ SENFSCons.Doxygen(env, extra_sources = [
SConscript(glob.glob("*/SConscript"))
SENFSCons.InstallIncludeFiles(env, [ 'parse_fixed_setup.hh' , 'parse_setup.hh' ])
......@@ -14,6 +14,6 @@ for sc in glob.glob("*/SConscript"):
ob = SConscript(sc)
if ob : objects.extend(ob)
SENFSCons.InstallIncludeFiles(env, [ 'INet.hh', 'Raw.hh' ])
SENFSCons.InstallIncludeFiles(env, [ 'INet.hh', 'Raw.hh', 'DVB.hh' ])
Return('objects')
// $Id$
//
// Copyright (C) 2007
// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
// Kompetenzzentrum fuer NETwork research (NET)
// Stefan Bund <g0dil@berlios.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file
\brief Daemon public header */
#include "Daemon/Daemon.hh"
// Local Variables:
// mode: c++
// fill-column: 100
// comment-column: 40
// c-file-style: "senf"
// indent-tabs-mode: nil
// ispell-local-dictionary: "american"
// compile-command: "scons -u test"
// End:
......@@ -110,7 +110,7 @@ namespace {
prefix_ void senf::Daemon::detach()
{
if (daemonize_) {
if (daemonize_ && ! detached_) {
// Wow .. ouch ..
// To ensure all data is written to the console log file in the correct order, we suspend
// execution here until the parent process tells us to continue via SIGUSR1: We block
......@@ -144,20 +144,30 @@ prefix_ void senf::Daemon::detach()
LIBC_CALL( ::sigaction, (SIGUSR1, &oldact, 0) );
LIBC_CALL( ::sigprocmask, (SIG_SETMASK, &oldsig, 0) );
detached_ = true;
}
}
namespace {
/* Purposely *not* derived from std::exception */
struct DaemonFailureException {
DaemonFailureException(unsigned c) : code(c) {}
unsigned code;
};
}
prefix_ void senf::Daemon::fail(unsigned code)
{
throw DaemonFailureException(code);
}
prefix_ int senf::Daemon::start(int argc, char const ** argv)
{
argc_ = argc;
argv_ = argv;
# ifdef NDEBUG
try {
# endif
configure();
if (daemonize_) {
......@@ -171,10 +181,13 @@ prefix_ int senf::Daemon::start(int argc, char const ** argv)
}
main();
}
catch (DaemonFailureException & e) {
return e.code > 0 ? e.code : 1;
}
# ifdef NDEBUG
#ifdef NDEBUG
}
catch (std::exception & e) {
std::cerr << "\n*** Fatal exception: " << e.what() << std::endl;
return 1;
......
......@@ -36,40 +36,69 @@ 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.
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
{
......@@ -108,6 +137,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
......@@ -124,7 +156,7 @@ namespace senf {
int argc(); ///< Access command line parameter count
char const ** argv(); ///< Access command line parameters
void fail(int code=1); ///< Terminate startup with failure
void fail(unsigned code=1); ///< Terminate daemon with failure
///\}
......@@ -136,6 +168,8 @@ namespace senf {
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:
......
@INCLUDE = "$(TOPDIR)/doclib/Doxyfile.global"
PROJECT_NAME = libUtils_Daemon
PROJECT_NAME = Daemon
GENERATE_TAGFILE = doc/Daemon.tag
ALPHABETICAL_INDEX = NO
// $Id$
//
// Copyright (C) 2007
// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
// Kompetenzzentrum fuer NETwork research (NET)
// Stefan Bund <g0dil@berlios.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \mainpage Daemon process management
The Daemon 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
consoleLog("MyDaemon.log");
// The default version provided by senf::Daemon will parse some special command line
// parameters to configure the daemon manager. You may optionally call this version
// here after setting default parameters
senf::Daemon::configure();
}
void init() {
// Initialize application. Setup all necessary objects. After init()
// has completed, the startup should not fail
}
void run() {
// Main application code should be called here.
}
};
// Provide main() function
SENF_DAEMON_MAIN(MyDaemon);
\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.
\see
\ref senf::Daemon class \n
\ref SENF_DAEMON_MAIN() main() implementation macro
*/
// Local Variables:
// mode: c++
// fill-column: 100
// comment-column: 40
// c-file-style: "senf"
// indent-tabs-mode: nil
// ispell-local-dictionary: "american"
// compile-command: "scons -u test"
// mode: flyspell
// mode: auto-fill
// End:
@INCLUDE = "$(TOPDIR)/doclib/Doxyfile.global"
PROJECT_NAME = libLogger
PROJECT_NAME = Logger
GENERATE_TAGFILE = doc/Logger.tag
ALPHABETICAL_INDEX = NO
......@@ -19,3 +19,4 @@ SENFSCons.Lib(env,
sources = objects)
SENFSCons.Doxygen(env)
SENFSCons.InstallIncludeFiles(env, [ 'Logger.hh', 'Daemon.hh' ])
// $Id$
//
// Copyright (C) 2007
// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
// Kompetenzzentrum fuer NETwork research (NET)
// Stefan Bund <g0dil@berlios.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file
\brief preprocessor.test unit tests */
//#include "preprocessor.test.hh"
//#include "preprocessor.test.ih"
// Custom includes
#include "preprocessor.hh"
#include <boost/test/auto_unit_test.hpp>
#include <boost/test/test_tools.hpp>
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
// Nothing to really to test ...
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
// Local Variables:
// mode: c++
// fill-column: 100
// comment-column: 40
// c-file-style: "senf"
// indent-tabs-mode: nil
// ispell-local-dictionary: "american"
// compile-command: "scons -u test"
// End:
......@@ -238,7 +238,7 @@ dl.note {
table.senf {
width: 95%;
margin: 0 auto;
margin: 10pt auto;
border: 1px solid #AAAAAA;
padding: 2px;
border-spacing: 0;
......@@ -249,6 +249,7 @@ table.senf td,th {
background-color: #EEEEEE;
padding: 2px 4px;
text-align: left;
vertical-align: top;
}
table.senf th {
......@@ -278,7 +279,7 @@ table.ebnf td:first-child {
}
table.listing {
margin: 0;
margin: 10pt 0;
padding: 0;
border-spacing: 0;
border: none;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment