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