Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Examples

vos/applibs/daemon/vosdaemon.hh

Go to the documentation of this file.
00001 /* $Id: vosdaemon.hh,v 1.8 2003/07/22 05:09:56 tetron Exp $ */
00002 
00003 
00004 /** @file vosdaemon.cc
00005     @author Reed Hedges (reed@zerohour.net)
00006 
00007     TODO:
00008         * use site callbacks for periodic save state instead of SIGALRM
00009         * Special option spit out Docbook <cmdsynopsis> text for help: 
00010             also change <foo> to <replacable>foo</replacable> in output.
00011 
00012     Copyright 2003 Reed Hedges
00013 
00014     This program is free software; you can redistribute it and/or modify
00015     it under the terms of the GNU General Public License as published by
00016     the Free Software Foundation; either version 2 of the License, or
00017     (at your option) any later version.
00018 
00019     This program is distributed in the hope that it will be useful,
00020     but WITHOUT ANY WARRANTY; without even the implied warranty of
00021     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022     GNU General Public License for more details.
00023 
00024     You should have received a copy of the GNU General Public License
00025     along with this program; if not, write to the Free Software
00026     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00027 */
00028 
00029 #ifndef VOSDAEMON_HH
00030 
00031 #include <vos/corelibs/vos/vos.hh>
00032 #include <fstream>
00033 
00034 /** 
00035     This class contains many convenient features useful for running a 
00036     background service, a.k.a. a daemon.  
00037 
00038     @ingroup applibs
00039     @ingroup vosdaemon
00040 
00041     It will fork and run in the background automatically.
00042     To use it for your daemon, simply subclass this class, and instantiate
00043     it from your program. 
00044     You can add and check for command-line arguments with addArg, addFlag, getArg 
00045     and getFlag.
00046     You can also turn on automatic saving, loading and periodic saving by 
00047     enabling the Save and Load built in command line parameters.
00048     Then call checkArgs, and run. 
00049     You can override loop() to do something every program loop, or you can use 
00050     a site callback. Other virtual methods may be overridden, but be sure
00051     to call the method in the parent class (VOSDaemon::) from your method.
00052 
00053     VOSDaemon will automatically handle the following arguments:
00054     <dl>
00055         <dt>--help, -h and -?</dt>  <dd>Print help message and quit</dd>
00056         <dt>--log, -L</dt>          <dd>Set log file</dd>
00057         <dt>--loglevel, -E</dt>     <dd>Set log level</dd>
00058         <dt>--save, -s</dt>         <dd>Reserved for a future autosave feature</dd>
00059         <dt>--safe-feq, -S</dt>     <dd>Reserved for a future autosave feature</dd>
00060         <dt>--load, -l</dt>         <dd>Reserved for a future COD loading feature</dd>
00061         <dt>--name</dt>             <dd>Reserved for a future COD loading feature</dd>
00062     </dl>
00063 
00064     
00065     Here is an example of use:
00066 
00067     @code
00068     #include <iostream> // for cerr
00069     #include <vos/corelibs/vos/vos.hh>
00070     #include <vos/metaobjects/property/property.hh>
00071     #include <vosdaemon.hh>
00072 
00073     class MyDaemon : public virtual VOSDaemon {
00074     public:
00075         MyDaemon() : VOSDaemon("example") {
00076         }
00077 
00078         void setup() {
00079             addArg("example", "value", "Example argument. <value> is any string.", 'e', "VOSDAEMON_EXAMPLE");
00080             addFlag("test", "Test flag.", 't', "VOSDAEMON_TEST_FLAG");
00081         }
00082 
00083         void preRun() {
00084             if(argGiven("example"))
00085                 cerr << "example arg is: " << getArg("example") << endl;
00086             if(argGiven("test"))
00087                 cerr << "test flag was given.\n";
00088             else
00089                 cerr << "test flag was not given.\n";
00090         }
00091 
00092         virtual void loop() {
00093             cerr << "loop!\n";
00094         }
00095     };
00096 
00097     int main(int argc, char** argv) {
00098         Property::registerExtenders();
00099         MyDaemon myDaemon("mydaemon");
00100         myDaemon->setup();
00101         myDaemon->checkArgs(argc, argv);
00102         myDaemon->preRun();
00103         cerr << "Now running in the background...\n";
00104         myDaemon->run();
00105     }
00106     @endcode
00107 
00108 
00109 */
00110 class VOSDaemon {
00111 
00112 
00113 private:
00114     vRef<LocalSite> site;
00115     char*   saveFile;
00116     int     saveFreq;
00117     Vobject*    rootObj;
00118     char*   programName;
00119     char*   rootName;
00120     char*   logFile;
00121     bool    mayLoad, maySave, mayNameRoot;
00122     ofstream*   logStream;
00123 
00124     char* loadfile;
00125     bool dontFork;
00126 
00127     typedef struct {
00128         string  argName;
00129         string  valueLabel;
00130         string  value;
00131         char    argChar;
00132         bool    isFlag;
00133         string  description;
00134         bool    given;
00135         string  envVar;
00136     } ArgInfo;
00137     typedef map <string, ArgInfo> ArgMap;
00138     typedef map <char, ArgInfo*>  ShortArgMap;
00139     ArgMap  args;
00140     ShortArgMap shortArgs;
00141 
00142     bool checkBuiltinArgs(char o, char* val);
00143 
00144 public:
00145 
00146     /** Constructor.  If site is omitted, a LocalSlocketSite
00147      *  will be created with select timeout -1. (You can dynamic_cast
00148      *  the LocalSite (returned by getSite()) to LocalSocketSite) once its created */
00149     VOSDaemon(char* progName, LocalSite* site = 0);
00150 
00151     /** Destructor */
00152     virtual ~VOSDaemon();
00153 
00154     /** Get the site. */
00155     LocalSite* getSite() {
00156         return &site;
00157     }
00158 
00159     /** Set the save file. Must be called before run. */
00160     void setSaveFile(char* savefile);
00161 
00162     /** Set the save frequency. Must be called before run. */
00163     void setSaveFrequency(int freq);
00164 
00165     /** Set the root object (for saving). Must be called before run. */
00166     void setRootObject(Vobject* rood);
00167 
00168     /** Set the name of the root object (for loading). Must be called before
00169      * run. */
00170     void setRootName(char* name);
00171 
00172     /** Set the log level  */
00173     void setLogLevel(int lev);
00174 
00175     /** Log to the named file. Must be called before run. */
00176     void setLogFile(char* file);
00177 
00178     /** Parse the command line arguments. Some built in arguments may
00179      * override any previously set settings.  Any arguments you added
00180      * with addArg will also be recognized, and after a call to this
00181      * function, will be available from getArg.
00182      *
00183      *  The following built in  command line arguments may override some settings:
00184      *      -L  Log file
00185      *      -E  Log level
00186      *      -s  Save file   (if enabled)
00187      *      -S  Save Frequency  (if save is enabled)
00188      *      -l  Load state from this file   (if enabled)
00189      *      -N  don't fork  (if fork is available on this platform)
00190      */
00191     virtual void checkArgs(int argc, char** argv);
00192 
00193     /** Start running the daemon in the background. */
00194     virtual void run();
00195 
00196     /** Virtual method called right after flushIncomingBuffers. Subclasses can
00197      *  use this to perform actions during the run loop. Note that the frequency
00198      *  with which this gets called depends on the select timeout (see 
00199      *  setTimeoutOnSelect()).
00200      */
00201     virtual void loop() {}
00202 
00203 
00204     /* Enable or disable availability of some of the built in command-line arguments */
00205     //@{
00206     //void enableArg_load(bool p);
00207     //void enableArg_save(bool p);
00208     //void enableArg_nameRoot(bool p);
00209     //@}
00210     
00211     /** Add command line arguments. If found, they will be available
00212      *  by calling getArg or getFlag(). This functiow must 
00213      *  be called before calling run(). 
00214      *  @param argName long name of argument. 
00215      *  @param valueLabel label for the argument's value (used in help text).
00216      *  @param description  A description of the argument (used in help text).
00217      *  @param defaultValue If supplied, then use this value if argument is not  given.
00218      *  @param argChar short one-character name of argument. (note that long arguments are
00219      *  unavailable on some platforms, so always give a non-empty char for this)
00220      *  @param envVar  If supplied, then an environment variable with this name
00221      *  may be used to supply a default value. (Command-line arguments always
00222      *  override environment variables)
00223      *
00224      *  @example addArg("example", "value", "An example", 'x');    // for --example or -x
00225      *  @example addArg("example", "value", "An example");         
00226      *  @example addArg("example", "value", "An example", "default value", 'e', "VOSDAEMON_EXAMPLE");
00227      *  @example addArg("example", "value", "An example", "default");
00228      *  @note The built in options are: 
00229      *      <ul>
00230      *          <li>"help" or 'h' to generate help text</li>
00231      *          <li>"loglevel" or 'E' to set the log level</li>
00232      *          <li>"log" or 'L' to set the log file</li>
00233      *          <li>"name" or 'n' to set the root object name (if enabled)</li>
00234      *          <li>"load" or 'l' to load a saved file (if enabled)</li>
00235      *          <li>"save" or 's' to set save-file name (if enabled)</li>
00236      *          <li>"save-freq" or 'S' to set save frequency (if enabled and possible on this platform)</li>
00237      *      </ul>
00238      *      
00239      */
00240       
00241     //@{
00242     void addArg(string argName, string valueLabel, string description, char argChar, string envVar = "");
00243     void addArg(string argName, string valueLabel, string description, string defaultValue, char argChar, string envVar = "");
00244     //@}
00245 
00246     
00247 
00248     /** Add flag argument . This function must be called before calling 
00249      * run().
00250      */
00251     void addFlag(string flagName, string description, char flagChar, string envVar);
00252 
00253 
00254     /** Get value of a command line argument. If it wasn't given then
00255      * the default value is returned. If it wasn't added using addArg(), or it
00256      * was added using addFlag(), then
00257      * a runtime_error exception will be thrown. */
00258     string getArg(string argName);
00259 
00260     /** Get presence of a command line option with no argiment (ie, a flag).
00261      *  If it was given, true will be returned. If it wasn't then false
00262      *  will be returned. If it wasn't added using addArg, then a
00263      *  runtime_error exception will be thrown.
00264      */
00265     bool argGiven(string argName);
00266 
00267     /** Same as argGiven */
00268     inline bool getFlag(string argName) {
00269         return argGiven(argName);
00270     }
00271 
00272     /** Print out help for command-line arguments. */
00273     virtual void printHelp();
00274 
00275     /** Save current state of the site and it's objects to the file previously
00276         set by setSaveFile or command line arguments. */
00277     virtual void save();
00278 
00279 
00280     /** Print the internal command-line argument map to stderr. */
00281     void debugArgs();
00282 };
00283 
00284 #endif //VOSDAEMON_HH

Generated on Tue Aug 12 03:55:37 2003 for Interreality Project - VOS by doxygen 1.3.2