Main Page Class Hierarchy Compound List File List Compound Members File Members

# modulebase.h

Go to the documentation of this file.

    00001 /*
    00002 **  ModuleBase -- A base class for modules.  Includes facilities for
    00003 **                spawning worker threads, sending heartbeat and error
    00004 **                messages to a shared memory ring and checking the
    00005 **                same ring for the shutdown flag.
    00006 **
    00007 **
    00008 **  Configuration file:
    00009 **  ------------------
    00010 **
    00011
    00012 # CmdRingName -- name of ring to check for flags and to send TYPE_HEARTBEAT
    00013 #                and TYPE_ERROR messages to.  REQUIRED
    00014 #
    00015 #
    00016 CmdRingName  WAVE_RING
    00017
    00018 # LoopSleepMS -- Milliseconds to sleep between main loop executions.
    00019 #                Default is 1000.  OPTIONAL
    00020 #
    00021 # LoopSleepMS 500
    00022
    00023 **
    00024 */
    00025 //---------------------------------------------------------------------------
    00026 #ifndef modulebaseH
    00027 #define modulebaseH
    00028
    00029 #include <configurable.h>
    00030 #include <threadableobject.h>
    00031 #include <string.h>
    00032 #include <worm_types.h>
    00033 #include <worm_statuscode.h>
    00034 #include <globalutils.h>
    00035 #include <ringwriter.h>
    00036 #include <msgheartbeat.h>
    00037 #include <msgerror.h>
    00038
    00039 #include <time.h>
    00040
    00041 // Default milliseconds to sleep between main loop executions
    00042 #define DEF_LOOP_SLEEP_MS  1000
    00043
    00044
    00045
    00046 /* Some stuff to standardize the tracking of the worker thread status
    00047 ** (an expanded version, WORM_SERVICE_THREAD_INFO, is defined in
    00048 **  serverbase.h, for service threads)
    00049 */
    00050
    00051 enum WORKER_THREAD_STATUS
    00052 {
    00053     THREAD_STATUS_STARTING  // set by starting thread
    00054   , THREAD_STATUS_INIT      // set by worker for any initialization
    00055   , THREAD_STATUS_GOOD      // set by worker
    00056   , THREAD_STATUS_QUIT      // set by worker
    00057   , THREAD_STATUS_ERROR     // set by worker
    00058 };
    00059
    00060 // Structure for used by derivative classes to track their
    00061 // worker threads
    00062 typedef struct WORKER_THREAD_INFO
    00063 {
    00064    TO_THREAD_ID          thread_id;
    00065    time_t                lastpulse; // from time(NULL)
    00066    WORKER_THREAD_STATUS  status;
    00067 } WORKER_THREAD_INFO_STRUCT;
    00068
    00069
    00070 //---------------------------------------------------------------------------
    00071 class TModuleBase : public TConfigurable
    00072                   , public ThreadableObject
    00073 {
    00074 protected:
    00075
    00076
    00077    // ----------------------------------------------------------------------
    00078    //                        FOR  TConfigurable
    00079
    00080    /*
    00081    **  HandleConfigLine()
    00082    **
    00083    **  PARMS:
    00084    **          p_parser -- the parser being used, command string already
    00085    **                      in the current token for comparison with Its()
    00086    **
    00087    ** RETURN:
    00088    **          HANDLE_INVALID --  line invalid
    00089    **          HANDLE_UNUSED  --  line not used
    00090    **          HANDLE_USED    --  line used okay
    00091    **
    00092    **  Override for child classes to handle command lines
    00093    **
    00094    ** In ModuleBase class, used as a convenient way to access the TGlobalUtils
    00095    ** for module initialization.  This means that derivative classes do not
    00096    ** have to deal with TGlobalUtils until needing to use it for lookups and such.
    00097    **
    00098    ** !!! NOTE: Ensure that derivative classes ALWAYS contain a call to their
    00099    **  <super_class>::HandleConfigLine() in their own HandleConfigLine() method...
    00100    ** this ensures that all classes in the heirarchy get their shot at the
    00101    ** configuration line.
    00102    **
    00103    */
    00104    HANDLE_STATUS HandleConfigLine( ConfigSource * p_parser );
    00105
    00106    /* CheckConfig() -- allows derivative classes to report the status of their
    00107    **                  the lookup values.
    00108    **
    00109    ** From within any deriving class, or further derivation, ALWAYS contain a call to
    00110    ** <super_class>::CheckConfig() in their own CheckConfig() method...
    00111    ** this ensures that all classes in the heirarchy get their chance to report status.
    00112    **
    00113    ** All implementations should set ConfigStatus value to WORM_STAT_BADSTATE if there
    00114    ** is a configuration problem, otherwise leave it alone.
    00115    */
    00116    void CheckConfig();
    00117
    00118
    00119    // ----------------------------------------------------------------------
    00120    //                         FOR TModuleBase
    00121
    00122    /* Running -- Variable that all worker threads should check
    00123    **            in their execution loops to discover if they should
    00124    **            continue running or not.
    00125    **            Most commonly, the main thread will set this to false
    00126    **            if the shutdown flag is found in the command ring.
    00127    **            In theory, worker threads might set this to initiate
    00128    **            a shutdown upon error.
    00129    */
    00130    volatile bool Running;
    00131
    00132    WORM_LOGGING_LEVEL LoggingLevel;
    00133
    00134    TGlobalUtils * MyGlobalUtils;
    00135
    00136    WORM_MSGTYPE_ID TYPE_ERROR
    00137                  , TYPE_HEARTBEAT
    00138                  ;
    00139
    00140    GEN_FILENAME ConfigFileName;
    00141
    00142    // milliseconds to sleep between main loop executions (default: DEF_LOOP_SLEEP_MS, above)
    00143    int LoopSleepMS;
    00144
    00145
    00146    // Ring to check for shutdown flags, to post heartbeats, etc.
    00147    WORM_RING_ID   CommandRingKey;   // key to transport ring
    00148    TRingWriter  * CommandRing;
    00149
    00150    /* SendStatus -- Standard method used to send TYPE_HEARTBEAT and
    00151    **               TYPE_ERROR messages to CommandRing (the ring).
    00152    **
    00153    ** PARAMETERS:
    00154    **      p_type = must be TYPE_HEARTBEAT or TYPE_ERROR
    00155    **      p_ierr = numberic error code (used only with TYPE_ERROR)
    00156    **      p_text = message text (used only with TYPE_ERROR)
    00157    **
    00158    ** Note: The default values make it possible to send a heartbeat with
    00159    **       only:  SendStatus(TYPE_HEARTBEAT)
    00160    */
    00161    void SendStatus( WORM_MSGTYPE_ID   p_type
    00162                   , short             p_ierr = 0
    00163                   , const char      * p_text = NULL
    00164                   );
    00165
    00166    /*
    00167    ** Message objects used by SendStatus
    00168    */
    00169    THeartbeatMessage * HeartbeatMsg;
    00170    TErrorMessage     * ErrorMsg;
    00171
    00172    /* GetDefaultConfigFile -- returns the name of the default configuration file
    00173    **                         for the derivative module class.
    00174    */
    00175    virtual const char * GetDefaultConfigFile() const = 0; // { return ""; }
    00176
    00177    /* Heartbeat -- sends a heartbeat at interval, but with no checking of
    00178    **              work thread status.
    00179    **
    00180    **  OVERRIDE as needed for derivative classes
    00181    */
    00182    virtual void Heartbeat();
    00183
    00184    long LastBeat; // second [time(NULL)] of last heartbeat
    00185
    00186
    00187    /*  PrepareToRun -- Actions to take prior to starting the main thread looping.
    00188    **                  Called once prior to entering the loop.
    00189    **                  (See StartThreadFunc, below about starting worker threads.)
    00190    **
    00191    ** RETURNS:   true = preparations were good
    00192    **           false = preparations failed
    00193    **
    00194    **  OVERRIDE as needed for derivative classes
    00195    */
    00196    virtual bool PrepareToRun()
    00197    {
    00198       LoggingLevel = TGlobalUtils::GetLoggingLevel();
    00199       return true;
    00200    }
    00201
    00202    /* CheckForFatal -- allows the main loop to query derived classes
    00203    **                  if a fatal error has been encountered.
    00204    **
    00205    ** RETURNS:  true if an error occurred and must exit.
    00206    **          false if no fatal error has occurred.
    00207    */
    00208    virtual bool CheckForFatal() { return false; }
    00209
    00210    /* MainThreadActions -- Actions to be performed in a derived class
    00211    **                      with each pass through the main thread loop.
    00212    **                      Called by Run().
    00213    **
    00214    ** RETURN:
    00215    **     WORM_STAT_SUCCESS = good actions
    00216    **                         The main thread will immediately repeat its loop
    00217    **     WORM_STAT_NOMATCH = no actions to take (good return)
    00218    **                         The main thread will sleep before repeating its loop
    00219    **     WORM_STAT_FAILURE = actions resulted in, or encountered a fatal error
    00220    **                         The main thread will leave its loop and exit (-1)
    00221    **
    00222    **  OVERRIDE as needed for derivative classes
    00223    */
    00224    virtual WORM_STATUS_CODE MainThreadActions() = 0;
    00225
    00226    /*  FinishedRunning -- Actions to take prior after completing the main thread
    00227    **                     looping.  Called once, after exiting the loop.
    00228    **
    00229    **  OVERRIDE as needed for derivative classes, although clean up
    00230    **           may also be coded into derived classes destructor methods.
    00231    */
    00232    virtual bool FinishedRunning() { return true; }
    00233
    00234
    00235 public:
    00236
    00237    // ----------------------------------------------------------------------
    00238    //                        FOR  ThreadableObject
    00239
    00240    /* StartThreadFunc() -- Method through which a newly-spawned
    00241    **                      thread returns to the "That" object
    00242    **                      to start execution.
    00243    **
    00244    **  If a derivative class needs to start a worker thread, it
    00245    **  should call StartThread() or StartThreadWithArg().  A new
    00246    **  thread will be started, and will return through this method
    00247    **  (which must be overridden in the derivative class).
    00248    **  Generally, this method will include a call to a specific
    00249    **  method for the handler to run.
    00250    **  The methods that are to be entered by newly spawned threads should
    00251    **  have the return type  THREAD_RETURN.  Furthermore, all
    00252    **  threads should exit loops and return if variable Running is false.
    00253    */
    00254    virtual void StartThreadFunc( void * p_argument ) { };
    00255
    00256
    00257    // ----------------------------------------------------------------------
    00258    //                        FOR  TModuleBase
    00259
    00260
    00261
    00262    /* ModuleBase -- constructor
    00263    **
    00264    ** ACTIONS:  Instantiates the global utilities object
    00265    **
    00266    ** Derivative classes be sure to call this by:
    00267    **
    00268    **     <derivative_constructor>(.....) : ModuleBase(p_programname, p_configfilename) { }
    00269    */
    00270    TModuleBase( char * p_programname
    00271               , char * p_configfilename = NULL
    00272               );
    00273
    00274    /* Destructor -- cleans up the global utilities and ring writer objects
    00275    **
    00276    */
    00277    ~TModuleBase();
    00278
    00279    /* Run -- the entry point for the main function to start the module
    00280    **        running.
    00281    **
    00282    ** ACTIONS: Parses the command file (.d)
    00283    **          Check for good instantiation of the global utilities
    00284    **          Call IsReady() to check module configuration variables.
    00285    **          Instantiate the ring writer (for heartbeats and errors)
    00286    **          Set up Solaris signal handling
    00287    **          Call PrepareToRun() enabling derived classes to start
    00288    **             worker threads, etc.
    00289    **          Enter a loop that:
    00290    **             Calls CheckForFatal() to check for fatal errors
    00291    **             Looks for shutdown flag on command ring (sets Running = false if so)
    00292    **             Sends Heartbeat
    00293    **             Calls MainThreadActions() for derived classes to
    00294    **                 perform main thread actions.
    00295    **             Departs loop on CheckForFatal() == true
    00296    **                          or shutdown flag (-1)
    00297    **                          or worker thread sets Running = false
    00298    **          Calls FinishedRunning() for derived class clean up.
    00299    **
    00300    ** CAUTION: IT IS USUALLY NOT A GOOD IDEA TO OVERRIDE THIS METHOD.
    00301    */
    00302    int Run();
    00303 };
    00304
    00305 #endif