00001
00002 #pragma hdrstop
00003
00004 #if defined(_WINNT) || defined(_Windows)
00005
00006 #include <windows.h>
00007
00008 #elif defined(SOLARIS)
00009
00010 #include <unistd.h>
00011
00012 #else
00013 #error modulemase.cpp not completed for this O/S
00014 #endif
00015
00016
00017 #include "modulebase.h"
00018 #include <worm_environ.h>
00019 #include <worm_exceptions.h>
00020 #include <logger.h>
00021 #include <timefuncs.h>
00022 #include <comfile.h>
00023
00024
00025
00026
00027 TModuleBase::TModuleBase( char * p_programname
00028 , char * p_configfilename
00029 )
00030 : TConfigurable()
00031 , ThreadableObject()
00032 {
00033
00034 Running = false;
00035 LastBeat = 0;
00036
00037 LoopSleepMS = DEF_LOOP_SLEEP_MS;
00038
00039 CommandRingKey = WORM_RING_INVALID;
00040 CommandRing = NULL;
00041
00042 MyGlobalUtils = NULL;
00043
00044 HeartbeatMsg = NULL;
00045 ErrorMsg = NULL;
00046
00047 try
00048 {
00049 if ( p_configfilename == NULL )
00050 {
00051 strcpy ( ConfigFileName, "" );
00052 }
00053 else
00054 {
00055 strcpy ( ConfigFileName, p_configfilename );
00056 }
00057
00058
00059
00060
00061 if ( (MyGlobalUtils = new TGlobalUtils(p_programname)) == NULL )
00062 {
00063 throw worm_exception("failed creating global utilities object");
00064 }
00065
00066
00067
00068 char * runPath;
00069
00070 bool _isEW = false;
00071
00072 if ( (runPath = TGlobalUtils::GetEnvironmentValue( WORM_CONFIG_DIR )) == NULL )
00073 {
00074 _isEW = true;
00075 runPath = TGlobalUtils::GetEnvironmentValue( EW_CONFIG_DIR );
00076 }
00077
00078 if ( runPath == NULL )
00079 {
00080 worm_exception _expt( "Neither environment variable <" );
00081 _expt += WORM_CONFIG_DIR;
00082 _expt += "> nor <";
00083 _expt += EW_CONFIG_DIR;
00084 _expt += "> is defined";
00085 throw _expt;
00086 }
00087
00088 if ( *runPath == '\0' )
00089 {
00090 worm_exception _expt( "Environment variable " );
00091 _expt += (_isEW ? EW_CONFIG_DIR : WORM_CONFIG_DIR);
00092 _expt += " defined, but has no value";
00093 throw _expt;
00094 }
00095
00096 #if defined(_WINNT) || defined(_Windows)
00097 if ( ! SetCurrentDirectory( runPath ) )
00098 #elif defined(SOLARIS)
00099 if ( chdir( runPath ) == -1 )
00100 #else
00101 #error TModuleBase() changing directory not implemented for this O/S
00102 #endif
00103 {
00104 worm_exception _expt( "Params directory not found: " );
00105 _expt += runPath;
00106 _expt += "\nPlease set environment variable ";
00107 _expt += WORM_CONFIG_DIR;
00108 throw _expt;
00109 }
00110
00111 }
00112 catch( worm_exception & _we )
00113 {
00114 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDERR
00115 , "TModuleBase() ERROR: %s\n"
00116 , _we.what()
00117 );
00118 throw _we;
00119 }
00120 catch( ... )
00121 {
00122 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDERR|WORM_LOG_TIMESTAMP
00123 , "TModuleBase(): Unidentifed Exception\n"
00124 );
00125 throw worm_exception("TModuleBase(): unidentified exception");
00126 }
00127 }
00128
00129 TModuleBase::~TModuleBase()
00130 {
00131 if ( CommandRing != NULL )
00132 {
00133 delete( CommandRing );
00134 CommandRing = NULL;
00135 }
00136 if ( MyGlobalUtils != NULL )
00137 {
00138 delete( MyGlobalUtils );
00139 MyGlobalUtils = NULL;
00140 }
00141 if ( HeartbeatMsg != NULL )
00142 {
00143 delete( HeartbeatMsg );
00144 HeartbeatMsg = NULL;
00145 }
00146 if ( ErrorMsg != NULL )
00147 {
00148 delete( ErrorMsg );
00149 ErrorMsg = NULL;
00150 }
00151 }
00152
00153 HANDLE_STATUS TModuleBase::HandleConfigLine( ConfigSource * p_parser )
00154 {
00155
00156
00157 HANDLE_STATUS r_handled = MyGlobalUtils->HandleConfigLine(p_parser);
00158
00159 if ( r_handled == HANDLER_UNUSED )
00160 {
00161 try
00162 {
00163 char * _token;
00164
00165 r_handled = HANDLER_USED;
00166
00167 do
00168 {
00169
00170 if ( p_parser->Its("CmdRingName") )
00171 {
00172 _token = p_parser->String();
00173 if ( strlen(_token) == 0 )
00174 {
00175 throw worm_exception("missing <CmdRingName> value");
00176 }
00177
00178 if ( (CommandRingKey = TGlobalUtils::LookupRingKey(_token)) == WORM_RING_INVALID )
00179 {
00180 throw worm_exception("invalid <CmdRingName> value");
00181 }
00182
00183 continue;
00184 }
00185
00186 if ( p_parser->Its("LoopSleepMS") )
00187 {
00188 if ( (LoopSleepMS = p_parser->Int()) == ConfigSource::INVALID_INT )
00189 {
00190 LoopSleepMS = DEF_LOOP_SLEEP_MS;
00191 throw worm_exception("invalid <LoopSleepMS> value");
00192 }
00193 continue;
00194 }
00195
00196 r_handled = HANDLER_UNUSED;
00197
00198 } while ( false );
00199 }
00200 catch( worm_exception _we )
00201 {
00202 r_handled = HANDLER_INVALID;
00203 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDERR
00204 , "TModuleBase::HandleConfigLine(): configuration error: %s\nin line: %s\n" , _we.what()
00205 , p_parser->GetCurrentLine()
00206 );
00207 }
00208 }
00209
00210 return r_handled;
00211 }
00212
00213 void TModuleBase::CheckConfig()
00214 {
00215
00216 if ( MyGlobalUtils == NULL )
00217 {
00218 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDERR
00219 , "TModuleBase::CheckConfig(): Global Configurations object not created\n"
00220 );
00221 ConfigState = WORM_STAT_BADSTATE;
00222 }
00223 else if ( ! MyGlobalUtils->IsReady() )
00224 {
00225 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDERR
00226 , "TModuleBase::CheckConfig(): Global Configurations object not configured\n"
00227 );
00228 ConfigState = WORM_STAT_BADSTATE;
00229 }
00230
00231 if ( TGlobalUtils::GetHeartbeatInt() == ConfigSource::INVALID_INT )
00232 {
00233 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDERR
00234 , "TModuleBase::CheckConfig(): No <HeartBeatInt> value from the config file\n"
00235 );
00236 ConfigState = WORM_STAT_BADSTATE;
00237 }
00238
00239 if ( CommandRingKey == WORM_RING_INVALID )
00240 {
00241 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDERR
00242 , "TModuleBase::CheckConfig(): No <CmdRingName> value from the config file\n"
00243 );
00244 ConfigState = WORM_STAT_BADSTATE;
00245 }
00246
00247 if ( LoopSleepMS < 10 || 30000 < LoopSleepMS )
00248 {
00249 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDERR
00250 , "TModuleBase::CheckConfig(): <LoopSleepMS> value (%d) must be in range 10 - 30000\n"
00251 , LoopSleepMS
00252 );
00253 ConfigState = WORM_STAT_BADSTATE;
00254 }
00255
00256 if ( (TYPE_ERROR = TGlobalUtils::LookupMessageTypeId("TYPE_ERROR")) == WORM_MSGTYPE_INVALID )
00257 {
00258 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDERR
00259 , "TModuleBase::CheckConfig(): TYPE_ERROR not found in config files\n"
00260 , LoopSleepMS
00261 );
00262 ConfigState = WORM_STAT_BADSTATE;
00263 }
00264
00265 if ( (TYPE_HEARTBEAT = TGlobalUtils::LookupMessageTypeId("TYPE_HEARTBEAT")) == WORM_MSGTYPE_INVALID )
00266 {
00267 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDERR
00268 , "TModuleBase::CheckConfig(): TYPE_HEARTBEAT not found in config files\n"
00269 , LoopSleepMS
00270 );
00271 ConfigState = WORM_STAT_BADSTATE;
00272 }
00273 }
00274
00275 void TModuleBase::SendStatus( WORM_MSGTYPE_ID p_type
00276 , short p_ierr
00277 , const char * p_text
00278 )
00279 {
00280 TMessageBase * _msg = NULL;
00281
00282 try
00283 {
00284 if ( CommandRing == NULL )
00285 {
00286 throw worm_exception("Command Ring is NULL");
00287 }
00288
00289 if ( p_type == TYPE_HEARTBEAT )
00290 {
00291 HeartbeatMsg->SetTime();
00292 _msg = HeartbeatMsg;
00293 }
00294 else if ( p_type == TYPE_ERROR )
00295 {
00296 ErrorMsg->SetTime();
00297 ErrorMsg->SetErrorCode(p_ierr);
00298 ErrorMsg->SetText(p_text);
00299 _msg = ErrorMsg;
00300 }
00301 else
00302 {
00303 worm_exception _expt("invalid message type "):
00304 _expt += (int)p_type;
00305 throw _expt;
00306 }
00307
00308 if ( _msg != NULL )
00309 {
00310 if ( CommandRing->PutMessage(*_msg) != WORM_STAT_SUCCESS )
00311 {
00312 if( p_type == TYPE_HEARTBEAT )
00313 {
00314 throw worm_exception("Error sending heartbeat." );
00315 }
00316 else
00317 {
00318 worm_exception _expt("Error sending error: ");
00319 _expt += (int)p_ierr;
00320 throw _expt;
00321 }
00322 }
00323 }
00324 }
00325 catch( worm_exception & _we )
00326 {
00327 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDERR
00328 , "TModuleBase::SendStatus() Error: %s\n"
00329 , _we.what()
00330 );
00331 }
00332 catch( ... )
00333 {
00334 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDERR
00335 , "TModuleBase::SendStatus() Error\n"
00336 );
00337 Running = false;
00338 }
00339 }
00340
00341 void TModuleBase::Heartbeat()
00342 {
00343 static long _interval = TGlobalUtils::GetHeartbeatInt();
00344
00345 if ( 0 < _interval )
00346 {
00347 if ( (LastBeat + _interval) < time(NULL) )
00348 {
00349 SendStatus(TYPE_HEARTBEAT);
00350 LastBeat = time(NULL);
00351 }
00352 }
00353 }
00354
00355 int TModuleBase::Run()
00356 {
00357 int r_status = 0;
00358
00359 TComFileParser * _parser = NULL;
00360
00361 try
00362 {
00363
00364
00365 if ( (_parser = new TComFileParser()) == NULL )
00366 {
00367 throw worm_exception("failed creating parser for configuration file");
00368 }
00369
00370
00371 if ( strlen(ConfigFileName) == 0 )
00372 {
00373 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDERR
00374 , "%s.main(): using default configuration file %s\n"
00375 , TGlobalUtils::GetProgramName()
00376 , GetDefaultConfigFile()
00377 );
00378 strcpy ( ConfigFileName, GetDefaultConfigFile() );
00379 }
00380
00381
00382 if ( ! _parser->Open(ConfigFileName) )
00383 {
00384 worm_exception _expt("failed opening configuration file: ");
00385 _expt += ConfigFileName;
00386 throw _expt;
00387 }
00388
00389
00390 bool _parsing = true;
00391
00392 do
00393 {
00394 switch ( _parser->ReadLine() )
00395 {
00396 case COMFILE_ERROR:
00397 {
00398 char * _errortxt;
00399 _parser->Error( &_errortxt );
00400 worm_exception _expt( "Error while parsing config file " );
00401 _expt += ConfigFileName;
00402 _expt += "\n";
00403 _expt += _errortxt;
00404 throw _expt;
00405 }
00406
00407 case COMFILE_EOF:
00408 _parsing = false;
00409 break;
00410
00411 default:
00412
00413 (void *)_parser->NextToken();
00414
00415
00416 if ( HandleConfigLine(_parser) == HANDLER_UNUSED )
00417 {
00418 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDOUT
00419 , "unrecognized command in line:\n%s\n%s\n%s\n"
00420 , _parser->GetCurrentLine()
00421 , "while parsing config file:"
00422 , ConfigFileName
00423 );
00424 }
00425
00426 break;
00427
00428 }
00429
00430 } while(_parsing);
00431
00432
00433 delete( _parser );
00434 _parser = NULL;
00435
00436
00437 if ( (HeartbeatMsg = new THeartbeatMessage( TGlobalUtils::GetThisInstallationId()
00438 , TGlobalUtils::GetThisModuleId()
00439 ) ) == NULL )
00440 {
00441 throw worm_exception("failed creating heartbeat message object");
00442 }
00443
00444
00445 if ( (ErrorMsg = new TErrorMessage( TGlobalUtils::GetThisInstallationId()
00446 , TGlobalUtils::GetThisModuleId()
00447 ) ) == NULL )
00448 {
00449 throw worm_exception("failed creating error message object");
00450 }
00451
00452 if ( ! IsReady() )
00453 {
00454 throw worm_exception( "Module is not configured, must exit");
00455 }
00456
00457
00458
00459 LoggingLevel = TGlobalUtils::GetLoggingLevel();
00460
00461 #ifdef SOLARIS
00462
00463
00464
00465
00466 nice( -nice( 0 ) );
00467
00468
00469
00470 sigignore( SIGINT );
00471 sigignore( SIGQUIT );
00472 sigset( SIGTERM, SigtermHandler );
00473
00474
00475 sigignore( SIGTTIN );
00476 #endif
00477
00478
00479 if ( (Running = PrepareToRun()) == true )
00480 {
00481 if ( (CommandRing = new TRingWriter(CommandRingKey)) == NULL )
00482 {
00483 throw worm_exception( "Failed creating command ring writer, must exit");
00484 }
00485 }
00486
00487 int _flag;
00488
00489 while( Running )
00490 {
00491 if ( CheckForFatal() )
00492 {
00493 if ( TGlobalUtils::GetLoggingLevel() == WORM_LOG_DEBUG )
00494 {
00495 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDERR|WORM_LOG_TIMESTAMP
00496 , "TModuleBase::Run(): Worker thread reported fatal error\n"
00497 );
00498 }
00499 Running = false;
00500 }
00501 else
00502 {
00503 _flag = CommandRing->GetFlag();
00504
00505 if ( _flag == WORM_STOP_ALL_MODULES
00506 || _flag == TGlobalUtils::GetThisModuleId()
00507 )
00508 {
00509 if ( WORM_LOG_STATUS <= TGlobalUtils::GetLoggingLevel() )
00510 {
00511 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDOUT|WORM_LOG_TIMESTAMP
00512 , "TModuleBase::Run(): Shutting down\n"
00513 );
00514 }
00515 Running = false;
00516 }
00517 else
00518 {
00519 Heartbeat();
00520
00521 switch ( MainThreadActions() )
00522 {
00523 case WORM_STAT_NOMATCH:
00524
00525
00526 TTimeFuncs::MSecSleep(LoopSleepMS);
00527
00528 case WORM_STAT_SUCCESS:
00529
00530
00531
00532
00533 break;
00534
00535 case WORM_STAT_FAILURE:
00536 if ( TGlobalUtils::GetLoggingLevel() == WORM_LOG_DEBUG )
00537 {
00538 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDERR|WORM_LOG_TIMESTAMP
00539 , "TModuleBase::Run(): Main thread reported fatal error\n"
00540 );
00541 }
00542 r_status = -1;
00543 Running = false;
00544 break;
00545 }
00546 }
00547 }
00548
00549 }
00550
00551 FinishedRunning();
00552
00553 }
00554 catch( worm_exception & _we )
00555 {
00556 if ( WORM_LOG_ERRORS <= TGlobalUtils::GetLoggingLevel() )
00557 {
00558 TLogger::Logit( WORM_LOG_TOFILE|WORM_LOG_TOSTDERR
00559 , "TModuleBase::Run() Error: %s\n"
00560 , _we.what()
00561 );
00562 }
00563 r_status = -1;
00564
00565
00566 if ( Running )
00567 {
00568 Running = false;
00569 TTimeFuncs::MSecSleep(750);
00570 FinishedRunning();
00571 }
00572 }
00573
00574 if ( _parser != NULL )
00575 {
00576 delete( _parser );
00577 _parser = NULL;
00578 }
00579
00580 return r_status;
00581 }
00582