From: g0dil Date: Wed, 14 Nov 2007 10:47:34 +0000 (+0000) Subject: Utils/Daemon: Documentation X-Git-Url: http://g0dil.de/git?p=senf.git;a=commitdiff_plain;h=b41b8147c7a2d40e2f69471e183840be8a0b95da Utils/Daemon: Documentation Utils/Daemon: Last implementation fixes Fix installation of some missing files git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@515 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Packets/SConscript b/Packets/SConscript index 64bc78c..9be4d50 100644 --- a/Packets/SConscript +++ b/Packets/SConscript @@ -19,3 +19,4 @@ SENFSCons.Doxygen(env, extra_sources = [ SConscript(glob.glob("*/SConscript")) +SENFSCons.InstallIncludeFiles(env, [ 'parse_fixed_setup.hh' , 'parse_setup.hh' ]) diff --git a/Socket/Protocols/SConscript b/Socket/Protocols/SConscript index bbf7262..3b7b158 100644 --- a/Socket/Protocols/SConscript +++ b/Socket/Protocols/SConscript @@ -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') diff --git a/Utils/Daemon.hh b/Utils/Daemon.hh new file mode 100644 index 0000000..79909ac --- /dev/null +++ b/Utils/Daemon.hh @@ -0,0 +1,37 @@ +// $Id$ +// +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer NETwork research (NET) +// Stefan Bund +// +// 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: diff --git a/Utils/Daemon/Daemon.cc b/Utils/Daemon/Daemon.cc index 34f476a..d008c38 100644 --- a/Utils/Daemon/Daemon.cc +++ b/Utils/Daemon/Daemon.cc @@ -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; diff --git a/Utils/Daemon/Daemon.hh b/Utils/Daemon/Daemon.hh index 3526cb3..dc3fb29 100644 --- a/Utils/Daemon/Daemon.hh +++ b/Utils/Daemon/Daemon.hh @@ -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 Safe startup. If the startup fails, the foreground process which launches the + daemon will terminate with an appropriate error exit code. + \li Straight forward application initialization. The daemon process is forked before + even initializing the application. The initialization procedure must not cater for a + later fork(). + \li Automatic pid file management. The daemon will not be started, if a valid pid file is + found. Stale pid files are automatically removed. + \li Console log management. 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 Optional foreground execution. 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: + + + + + + + + + +
--no-daemonRun in foreground
--console-log=stdout[,stderr]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.
--pid-file=pidfileSet pid file path
+ + 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: diff --git a/Utils/Daemon/Doxyfile b/Utils/Daemon/Doxyfile index 86ac1b9..05a476f 100644 --- a/Utils/Daemon/Doxyfile +++ b/Utils/Daemon/Doxyfile @@ -1,5 +1,5 @@ @INCLUDE = "$(TOPDIR)/doclib/Doxyfile.global" -PROJECT_NAME = libUtils_Daemon +PROJECT_NAME = Daemon GENERATE_TAGFILE = doc/Daemon.tag ALPHABETICAL_INDEX = NO diff --git a/Utils/Daemon/Mainpage.dox b/Utils/Daemon/Mainpage.dox new file mode 100644 index 0000000..ffde18d --- /dev/null +++ b/Utils/Daemon/Mainpage.dox @@ -0,0 +1,84 @@ +// $Id$ +// +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer NETwork research (NET) +// Stefan Bund +// +// 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: diff --git a/Utils/Logger/Doxyfile b/Utils/Logger/Doxyfile index 580c29f..15f2a11 100644 --- a/Utils/Logger/Doxyfile +++ b/Utils/Logger/Doxyfile @@ -1,5 +1,5 @@ @INCLUDE = "$(TOPDIR)/doclib/Doxyfile.global" -PROJECT_NAME = libLogger +PROJECT_NAME = Logger GENERATE_TAGFILE = doc/Logger.tag ALPHABETICAL_INDEX = NO diff --git a/Utils/SConscript b/Utils/SConscript index 561137b..1819533 100644 --- a/Utils/SConscript +++ b/Utils/SConscript @@ -19,3 +19,4 @@ SENFSCons.Lib(env, sources = objects) SENFSCons.Doxygen(env) +SENFSCons.InstallIncludeFiles(env, [ 'Logger.hh', 'Daemon.hh' ]) diff --git a/Utils/preprocessor.test.cc b/Utils/preprocessor.test.cc new file mode 100644 index 0000000..c890f6a --- /dev/null +++ b/Utils/preprocessor.test.cc @@ -0,0 +1,52 @@ +// $Id$ +// +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer NETwork research (NET) +// Stefan Bund +// +// 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 +#include + +#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: diff --git a/doclib/senf.css b/doclib/senf.css index ea77f17..c6e2d4b 100644 --- a/doclib/senf.css +++ b/doclib/senf.css @@ -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;