00001 /* 00002 * server_template.h -- Template and server class deriving from 00003 * the DBMutableServerBase class. 00004 * 00005 * The base class handles communications, so this class 00006 * primarily must only concern itself with the specific 00007 * handling for this type of server (to include relevant 00008 * configuration, passports and calculations). 00009 * 00010 */ 00011 /* 00012 * Variable which are available from the base classes: 00013 * 00014 * bool Running; true while running 00015 * false when told to quit/shutdown 00016 * 00017 * int LoggingOptions = various logging parameters (set in the base 00018 * class, depending on the mode) 00019 * 00020 * int LoggingLevel = Logging level assigned from the .d file. 00021 * Values: 00022 * WORM_LOG_ERRORS 00023 * WORM_LOG_STATUS 00024 * WORM_LOG_TRACKING 00025 * WORM_LOG_DETAILS 00026 * WORM_LOG_DEBUG 00027 * 00028 * MUTABLE_MODE_TYPE Mode = Current mode in which the program is operating 00029 * Values: 00030 * MMT_STANDALONE = command from args/stdin, data access and calculations internally 00031 * MMT_MODULE = command from ring, data access and calculations internally [MT] 00032 * MMT_SERVER = command from socket, calculations internally [MT] 00033 * MMT_CLIENT = command from atgs/stdin, socket call to client for calculations 00034 * 00035 * 00036 * 00037 * MODULE AND MESSAGE TYPE IDS: 00038 * 00039 * WORM_INSTALLATION_ID InstId = TGlobalUtils::LookupInstallationId("INST_XXXX"); 00040 * WORM_MODULE_ID ModulId = TGlobalUtils::LookupModuleId("INST_XXXX"); 00041 * WORM_MSGTYPE_ID MsgId = TGlobalUtils::LookupMessageTypeId("INST_XXXX"); 00042 * 00043 * 00044 * AVAILABLE FUNCTIONS: 00045 * 00046 * // Put a status/error message onto the command ring 00047 * // type must be TYPE_ERROR 00048 * void SendStatus( unsigned char type, short ierr, char *note ); 00049 * 00050 * void InitializeDB(); // called by DBMutableServer::PrepareToRun(), 00051 * // but it might also need to be called elsewhere 00052 * // for some modes 00053 * 00054 * void GetDefaultsFromDB(); 00055 * 00056 * // Compare SCNLs with wildcards 00057 * // returns true or false 00058 * bool DoSCNLsMatch( const char * p_s1 00059 * , const char * p_c1 00060 * , const char * p_n1 00061 * , const char * p_l1 00062 * , const char * p_s2 00063 * , const char * p_c2 00064 * , const char * p_n2 00065 * , const char * p_l2 00066 * ) 00067 * 00068 * LOGGING: 00069 * 00070 * Based upon the value of LoggingLevel (value list above), 00071 * use the TLogger object to perform the logging functions: 00072 * 00073 * if( WORM_LOG_ERRORS <= LoggingLevel ) 00074 * { 00075 * TLogger::Logit( LoggingOptions 00076 * , "ServerTemplate::GetRequestFromInput(): %d\n" 00077 * , some_int_value 00078 * ); 00079 * } 00080 * 00081 * ERROR HANDLING WITH EXCEPTIONS: 00082 * 00083 * Through base class headers a class called worm_exception is 00084 * understood. 00085 * 00086 * Often errors are handled in the methods using a try-catch pair: 00087 * 00088 * try 00089 * { 00090 * // some code 00091 * 00092 * if ( some_condition ) 00093 * { 00094 * // an error was discovered 00095 * 00096 * throw worm_exception("My error message"); 00097 * } 00098 * 00099 * 00100 * if ( some_int_value != 0 ) 00101 * { 00102 * // an error was discovered 00103 * 00104 * worm_exception MyExcept("some_int_value not = 0: "); 00105 * MyExcept += (int)some_int_value; 00106 * MyExcept += ", Must quit"; 00107 * throw MyExcept; 00108 * } 00109 * 00110 * } 00111 * catch( worm_exception & _we ) 00112 * { 00113 * // Handle any worm exception thrown in the above try block 00114 * 00115 * // At this point, '_we' is a reference to a worm_exception object 00116 * // it has one method most useful here: 00117 * 00118 * char * _errptr = _we.what(); // returns the error message as a pointer to char 00119 * 00120 * // If desired, the exception may be re-thrown 00121 * // (uncommon, but can be done). 00122 * throw _we; 00123 * } 00124 * catch( ... ) 00125 * { 00126 * // This second catch block is not needed, but it shown here to 00127 * // demonstrate how to catch any type of exception. 00128 * // Unfortunately, there is no available reference to the exception. 00129 * } 00130 * 00131 * If a method/function includes a throw statement that is not surrounded 00132 * by at try block (with an applicable catch block), then execution 00133 * returns from the method immediately and then entire calling chain of 00134 * functions are returned from -- Until one of the function calls is 00135 * surrounded by a try block with an appropriate catch block. 00136 * 00137 * Memory allocations are NOT released, and file pointers may not be 00138 * closed, so they should be handled in a manner such as this: 00139 * 00140 * char * MyBuffer = NULL; 00141 * 00142 * try 00143 * { 00144 * // some code, part A 00145 * 00146 * if ( (MyBuffer = new char[120]) == NULL ) 00147 * { 00148 * throw worm_exception("failed allocation buffer"); 00149 * } 00150 * 00151 * // some other code, part B 00152 * 00153 * } 00154 * catch( worm_exception & _we ) 00155 * { 00156 * // error handling for worm_exceptions 00157 * } 00158 * catch( ... ) 00159 * { 00160 * // error handling for other exceptions 00161 * } 00162 * 00163 * 00164 * if ( MyBuffer != NULL ) 00165 * { 00166 * // Ensure memory is released 00167 * // (we allocated an array of char, so we use "delete []" 00168 * // instead of just "delete") 00169 * // 00170 * delete [] MyBuffer; 00171 * } 00172 */ 00173 00174 00175 // STEP 1: Do a global replacement of the string "ServerTemplate" 00176 // with the name of the new class 00177 // 00178 00179 // STEP 2: Replace this include with the .h file for the new class 00180 // 00181 #include "server_template.h" 00182 00183 00184 // STEP 3: Add includes for the appropriate type of message classes 00185 #include "request_template.h" 00186 #include "result_template.h" 00187 00188 00189 00190 extern "C" { 00191 00192 // STEP 4: Include any headers for C-style code 00193 00194 } 00195 00196 00197 //------------------------------------------------------------------------------ 00198 ServerTemplate::ServerTemplate() 00199 { 00200 // STEP 5 Perform any required variable initialization here 00201 // Usually, that means initializing the default parameters: 00202 DefaultParameters.ExampleLongParam = 0L; 00203 DefaultParameters.ExampleStringParam[0] = '\0'; 00204 DefaultParameters.ExampleFlagParam = false; 00205 00206 00207 // (Any pointers that will refer to dynamically allocated memory 00208 // must be NULLified here). 00209 // 00210 // MyPointer = NULL; 00211 } 00212 00213 //------------------------------------------------------------------------------ 00214 ServerTemplate::~ServerTemplate() 00215 { 00216 // STEP 6 Perform any requisite clean-up for server termination here 00217 00218 // (generally only needed to delete any dynamically-allocated memory) 00219 00220 /* 00221 * if ( MyPointer != NULL ) 00222 * { 00223 * delete [] MyPointer; 00224 * } 00225 */ 00226 00227 } 00228 00229 //------------------------------------------------------------------------------ 00230 HANDLE_STATUS ServerTemplate::HandleConfigLine( ConfigSource * p_parser ) 00231 { 00232 // STEP 7: Handle any Configuration parameter parsing here. 00233 // 00234 // THIS METHOD RECEIVES A SINGLE CONFIGURATION LINE AT A TIME; THUS, IT IS 00235 // CALLED REPEATEDLY. 00236 // 00237 // GENERALLY, ONLY THOSE CONFIGURATION ITEMS THAT MAY ONLY COME 00238 // FROM THE CONFIGURATION FILE (i.e. STARTUP CONFIGURATION) ARE 00239 // PROCESSED HERE. THOSE ITEMS WHICH MAY ALSO BE CHANGED VIA A PASSPORT 00240 // ARE HANDED OFF TO THE METHOD HandleParameterLine() TOWARDS THE BOTTOM OF 00241 // THIS METHOD. 00242 // 00243 // THIS METHOD MUST RETURN ONE OF THESE VALUES: 00244 // 00245 // HANDLE_INVALID -- line invalid 00246 // HANDLE_UNUSED -- line not used 00247 // HANDLE_USED -- line used okay 00248 // 00249 00250 // BASE CLASSES MUST BE GIVEN THE CHANCE TO GET CONFIG VARIABLES: 00251 HANDLE_STATUS r_status = DBMutableServerBase::HandleConfigLine( p_parser ); 00252 00253 00254 if ( r_status == HANDLE_UNUSED ) 00255 { 00256 // Base class didn't use it, then it must belong to this 00257 // derivative class 00258 00259 try 00260 { 00261 // this do-while is solely to allow a single return point, 00262 // thus simplifying the code. 00263 00264 do 00265 { 00266 char * _token; 00267 00268 // WHEN ARRIVING HERE, p_parser HAS THE FIRST TOKEN ON 00269 // THE [COMMAND] LINE LOADED INTO THE CURRENT TOKEN. 00270 // THUS WE MAY PERFORM A TEST FOR THE LINE TYPE USING Its("") 00271 // 00272 // Among others, a ConfigSource object has these methods: 00273 // 00274 // bool Its(""); // compare current token to a string 00275 // const char * GetCurrentToken(); 00276 // const char * GetCurrentLine(); 00277 // char * String(); // next token as a string 00278 // int Int(); // next tokan as an int 00279 // int Long(); // next tokan as a long 00280 // int Double(); // next tokan as a double 00281 // 00282 // And these member values: 00283 // 00284 // INVALID_INT 00285 // INVALID_LONG 00286 // INVALID_DOUBLE 00287 // 00288 00289 00290 00291 // EXAMPLE LINE: 00292 // 00293 // ExampleFlagParam true 00294 // ExampleFlagParam false 00295 // 00296 if ( p_parser->Its("ExampleFlagParam") ) 00297 { 00298 _token = p_parser->String(); 00299 00300 // The ConfigSource::String() method will return an empty string 00301 // if no token is found, must perform a specific check for 00302 // that condition. 00303 00304 if ( p_parser->IsTokenNull() ) 00305 { 00306 // Didn't find an expected value on the line 00307 throw worm_exception("Incomplete <ExampleFlagParam> line"); 00308 } 00309 00310 // Grab the value 00311 if ( strcmp( _token, "true" ) == 0 ) 00312 { 00313 DefaultParameters.ExampleFlagParam = true; 00314 } 00315 else 00316 { 00317 DefaultParameters.ExampleFlagParam = false; 00318 } 00319 00320 // Set the return status to indicate that the line was handled 00321 // okay. 00322 r_status = HANDLE_USED; 00323 00324 // Skip past any other line checking 00325 continue; 00326 } 00327 00328 00329 // Additional Its() and handling 00330 00331 00332 00333 // Pass any config-file only lines to the 00334 // shared config/passport handler 00335 // 00336 r_status = HandleParameterLine( p_parser, &DefaultParameters ); 00337 00338 } while( false ); 00339 } 00340 catch( worm_exception & _we ) 00341 { 00342 // Do all of our logging [including for HandleParameterLine()] here 00343 00344 if ( WORM_LOG_ERRORS <= LoggingLevel ) 00345 { 00346 TLogger::Logit( LoggingOptions 00347 , "ServerTemplate::HandleConfigLine() Error:\n%s" 00348 , _we.what() 00349 ); 00350 } 00351 00352 r_status = HANDLE_INVALID; 00353 } 00354 } 00355 00356 return r_status; 00357 } 00358 00359 //------------------------------------------------------------------------------ 00360 HANDLE_STATUS ServerTemplate::HandleParameterLine( ConfigSource * p_parser 00361 , void * p_params 00362 ) 00363 { 00364 // STEP 8: Handle processing parameters here. 00365 // 00366 // GENERALLY, THIS METHOD IS USED TO HANDLE PROCESSING-RELATED PARAMETERS THAT 00367 // MIGHT ORIGINATE FROM EITHER THE CONFIGURATION FILE, OR THE PASSPORT. 00368 // 00369 // THIS METHOD RECEIVES A SINGLE CONFIGURATION LINE AT A TIME; THUS, IT IS 00370 // CALLED REPEATEDLY. 00371 // 00372 // THIS METHOD MUST RETURN ONE OF THESE VALUES: 00373 // 00374 // HANDLE_INVALID -- line invalid 00375 // HANDLE_UNUSED -- line not used 00376 // HANDLE_USED -- line used okay 00377 // 00378 // OR THROW worm_exception() FOR ERRORS. 00379 // 00380 // Any errors that are encountered are not logged here, but are throw as an 00381 // worm_exception for the caller to handle and report. 00382 00383 HANDLE_STATUS r_status = HANDLE_UNUSED; 00384 00385 // Cast the arriving pointer to a parameters struct to the correct type for 00386 // this server 00387 // 00388 ServerTemplate_PARAMS * CurrentParameters = (ServerTemplate_PARAMS *)p_params; 00389 00390 00391 do 00392 { 00393 char * _token; 00394 00395 // WHEN ARRIVING HERE, p_parser HAS THE FIRST TOKEN ON 00396 // THE [COMMAND] LINE LOADED INTO THE CURRENT TOKEN. 00397 // THUS WE MAY PERFORM A TEST FOR THE LINE TYPE. 00398 00399 00400 // EXAMPLE PARAMETER/PASSPORT LINE: 00401 // 00402 // ExampleDualValue some_string_without_whitespace some_integer 00403 // 00404 if ( p_parser->Its("ExampleDualValue") ) 00405 { 00406 _token = p_parser->String(); 00407 00408 if ( p_parser->IsTokenNull() ) 00409 { 00410 // Didn't find an expected value on the line 00411 throw worm_exception("Incomplete <ExampleDualValue> line"); 00412 } 00413 00414 if ( 30 < strlen( _token ) ) 00415 { 00416 throw worm_exception("Invalid <ExampleDualValue> line: string too long"); 00417 } 00418 00419 // Grab the string value 00420 strcpy( CurrentParameters->ExampleStringParam, _token ); 00421 00422 // Now get the int 00423 00424 if ( (CurrentParameters->ExampleLongParam = p_parser->Int()) == p_parser->INVALID_INT ) 00425 { 00426 // Didn't find an expected value on the line 00427 CurrentParameters->ExampleLongParam = 0; 00428 throw worm_exception("Incomplete <ExampleDualValue> line: missing int"); 00429 } 00430 00431 // Set the return status to indicate that the line was handled 00432 // okay. 00433 r_status = HANDLE_USED; 00434 00435 // Skip past any other line checking 00436 continue; 00437 } 00438 00439 00440 // Additional Its() and handling 00441 00442 00443 } while( false ); 00444 00445 return r_status; 00446 } 00447 00448 00449 //------------------------------------------------------------------------------ 00450 void ServerTemplate::CheckConfig() 00451 { 00452 // MUST ALWAYS ALLOW BASE CLASSES A CHANCE TO CHECK THEIR OWN 00453 // CONFIGURATION STATE. 00454 // 00455 // If the Mode is required for testing, then this statement must 00456 // come first. 00457 // 00458 DBMutableServerBase::CheckConfig(); 00459 00460 00461 // CHECK THIS CLASS'S CONFIGURATION VARIABLES, 00462 // 00463 // There may be need to perform testing based upon the mode in which the 00464 // program is to run. For example, a client won't likely need to know 00465 // about any waveservers, so it won't check the values of any waveserver 00466 // variables despite their existence in support of the server. 00467 // The operating mode is kept in variable 'Mode' (see top of file). 00468 // 00469 // IF A PROBLEM IS FOUND, LOG IT, AND DO: 00470 // 00471 // ConfigStatus = WORM_STAT_BADSTATE; 00472 // 00473 // BUT DON'T RETURN, THUS ALL CONFIGURATION ERRORS CAN BE REPORTED 00474 // FROM ONE ATTEMPTED RUN. 00475 00476 // STEP 9: Perform any configuration checking here 00477 00478 if ( DefaultParameters.ExampleLongParam == 0 ) 00479 { 00480 TLogger::Logit( LoggingOptions 00481 , "ServerTemplate::CheckConfig(): Did not find a valid <ExampleDualValue> line" 00482 ); 00483 ConfigStatus = WORM_STAT_BADSTATE; 00484 } 00485 00486 00487 } 00488 00489 //------------------------------------------------------------------------------ 00490 bool ServerTemplate::PrepareToRun() 00491 { 00492 bool r_status = false; 00493 00494 try 00495 { 00496 if ( DBMutableServerBase::PrepareToRun() ) 00497 { 00498 // Get any default parameters from the database 00499 // 00500 // (this will ultimately end up calling the HandleParameterLine() method) 00501 // 00502 if ( GetDefaultsFromDB( &DefaultParameters ) ) 00503 { 00504 00505 // STEP 10: If the new class needs to perform any activities after configuration, 00506 // but before starting the main processing, add that here. 00507 // 00508 // RETURN false IF AN ERROR PREVENTS CONTINUING. 00509 00510 00511 // indicate preparations completed successfully 00512 r_status = true; 00513 } 00514 } 00515 } 00516 catch( worm_exception & _we ) 00517 { 00518 if( WORM_LOG_ERRORS <= LoggingLevel ) 00519 { 00520 TLogger::Logit( LoggingOptions 00521 , "ServerTemplate::PrepareToRun() Error: %s\n" 00522 , _we.what() 00523 ); 00524 } 00525 00526 r_status = false; 00527 } 00528 return r_status; 00529 } 00530 00531 //------------------------------------------------------------------------------ 00532 MutableServerRequest * ServerTemplate::GetRequestContainer() 00533 { 00534 // STEP 11: Change "RequestTemplate" to the appropriate type of request container 00535 // (2 times) 00536 RequestTemplate * r_object = NULL; 00537 00538 try 00539 { 00540 if ( (r_object = new RequestTemplate()) == NULL ) 00541 { 00542 throw worm_exception("Failed to create Request container"); 00543 } 00544 } 00545 catch( worm_exception & _we ) 00546 { 00547 if( WORM_LOG_ERRORS <= LoggingLevel ) 00548 { 00549 TLogger::Logit( LoggingOptions 00550 , "ServerTemplate::GetRequestContainer(): %s\n" 00551 , _we.what() 00552 ); 00553 } 00554 } 00555 00556 return r_object; 00557 } 00558 00559 //------------------------------------------------------------------------------ 00560 MutableServerResult * ServerTemplate::GetResultContainer() 00561 { 00562 // STEP 12: Change "ResultTemplate" to the appropriate type of request container 00563 // (2 times) 00564 00565 ResultTemplate * r_object = NULL; 00566 00567 try 00568 { 00569 if ( (r_object = new ResultTemplate()) == NULL ) 00570 { 00571 throw worm_exception("Failed to create Result container"); 00572 } 00573 } 00574 catch( worm_exception & _we ) 00575 { 00576 if( WORM_LOG_ERRORS <= TGlobalUtils::GetLoggingLevel() ) 00577 { 00578 TLogger::Logit( LoggingOptions 00579 , "ServerTemplate::GetResultContainer(): %s\n" 00580 , _we.what() 00581 ); 00582 } 00583 } 00584 00585 return r_object; 00586 } 00587 00588 //------------------------------------------------------------------------------ 00589 WORM_STATUS_CODE ServerTemplate::GetRequestFromInput( int p_argc 00590 , char * p_argv[] 00591 , void * r_container 00592 ) 00593 { 00594 WORM_STATUS_CODE r_status = WORM_STAT_SUCCESS; 00595 00596 try 00597 { 00598 if ( r_container == NULL ) 00599 { 00600 throw worm_exception("NULL request container parameter"); 00601 } 00602 00603 if ( p_argc < 2 ) 00604 { 00605 throw worm_exception("Too few parameters from program command line"); 00606 } 00607 00608 if ( WORM_LOG_DEBUG < LoggingLevel ) 00609 { 00610 TLogger::Logit( LoggingOptions 00611 , "ServerTemplate::GetRequestFromInput() argc: %d [1] = %s\n" 00612 , p_argc 00613 , p_argv[1] 00614 ); 00615 } 00616 00617 00618 // STEP 13: Cast the arriving container to the request class appropriate to 00619 // this server class. 00620 // 00621 RequestTemplate * ThisRequest = (RequestTemplate *)r_container; 00622 00623 00624 // STEP 14: Perform whatever actions are needed, based upon the command line 00625 // input. Commonly this might include getting event info from the 00626 // database. 00627 // 00628 // Since this is for client and standalone modes only, these should 00629 // generally be activities needed to perform the processing request. 00630 // 00631 // Throw worm_exception for errors. 00632 // 00633 // For example, if the request class tracks origin id there might 00634 // be code that looks something like: 00635 // 00636 // ThisRequest->SetEventId( atoi(argv[1]) ); 00637 00638 00639 } 00640 catch( worm_exception & _we ) 00641 { 00642 r_status = WORM_STAT_FAILURE; 00643 00644 if( WORM_LOG_ERRORS <= TGlobalUtils::GetLoggingLevel() ) 00645 { 00646 TLogger::Logit( LoggingOptions 00647 , "ServerTemplate::GetRequestFromInput(): %s\n" 00648 , _we.what() 00649 ); 00650 } 00651 } 00652 00653 return r_status; 00654 } 00655 00656 //------------------------------------------------------------------------------ 00657 WORM_STATUS_CODE ServerTemplate::ProcessRequest( void * p_requestcontainer 00658 , void * r_resultcontainer 00659 ) 00660 { 00661 // on algorithm failure (but not error) set r_status = WORM_STAT_BADSTATE 00662 // before throwing a worm_exception 00663 // 00664 // (r_status is set to WORM_STAT_SUCCESS at bottom of method) 00665 // 00666 WORM_STATUS_CODE r_status = WORM_STAT_FAILURE; 00667 00668 // Passport for this processing run 00669 ServerTemplate_PARAMS LocalParameters; 00670 00671 ResultTemplate * ThisResult = NULL; 00672 00673 try 00674 { 00675 if ( p_request == NULL || r_result == NULL ) 00676 { 00677 throw worm_exception("NULL container parameter"); 00678 } 00679 00680 // STEP 15: 00681 // Cast request and result containers to the appropriate types for 00682 // this server 00683 RequestTemplate * ThisRequest = (RequestTemplate *)p_requestcontainer; 00684 ThisResult = (ResultTemplate *)r_resultcontainer; 00685 00686 00687 00688 // STEP 16: 00689 // Copy default parameters into the local parameters for this calculation 00690 00691 LocalParameters.ExampleLongParam = DefaultParameters.ExampleLongParam; 00692 strcpy( LocalParameters.ExampleStringParam , DefaultParameters.ExampleStringParam ); 00693 LocalParameters.ExampleFlagParam = DefaultParameters.ExampleFlagParam; 00694 00695 00696 // STEP 17: 00697 // 00698 // THIS IS EXAMPLE CODE THAT CAN BE USED IF THE REQUEST CONTAINER IS DERIVED 00699 // FROM MutableServerRequest CLASS (WHICH KNOWS ABOUT PASSPORTS. 00700 // IT CAN BE INCLUDED EVEN IF NO PASSPORT DATA IS BEING PASSED AT THIS TIME. 00701 // 00702 // IF THE REQUEST CONTAINER DOES NOT DERIVE FROM MutableServerRequest CLASS, 00703 // THIS PROBABLY MUST BE REMOVED. 00704 00705 if( WORM_LOG_DEBUG <= LoggingLevel ) 00706 { 00707 TLogger::Logit( WORM_LOG_TOFILE 00708 , "ServerTemplate::ProcessRequest() Getting Passport:\n" 00709 ); 00710 } 00711 00712 00713 // Process any passport lines that arrive 00714 // 00715 if ( 0 < ThisRequest->GetPassportLineCount() ) 00716 { 00717 // basic command line parser object 00718 ConfigSource _parser; 00719 00720 for ( int _p = 0, _sz = ThisRequest->GetPassportLineCount() ; _p < _sz ; _p++ ) 00721 { 00722 if( WORM_LOG_DEBUG <= LoggingLevel ) 00723 { 00724 TLogger::Logit( WORM_LOG_TOFILE 00725 , " >%s\n" 00726 , _request->GetPassportLine( _p ) 00727 ); 00728 } 00729 00730 _parser.Load( ThisRequest->GetPassportLine( _p ) ); 00731 00732 // HandleParameterLine() will throw worm_exception 00733 // which will be caught by the catch block at the end 00734 // of this method. To continue processing on parameter line 00735 // errors, this statement must be wrapped in at try block 00736 // 00737 HandleParameterLine( &_parser, &LocalParameters ); 00738 } 00739 } 00740 00741 00742 00743 // STEP 18: Perform the actual seimological processing here. 00744 // 00745 // Any parameters needed should be in LocalParameters (which should be 00746 // passed to any other methods instead of DefaultParameters. 00747 // 00748 // Any event data needed should be in the ThisRequest object, 00749 // something like: ThisRequest->GetEventId() 00750 // 00751 // On algorithmic incompletion/failure: 00752 // r_status = WORM_STAT_BADSTATE; 00753 // ThisResult->SetStatus( MSB_RESULT_FAIL ); 00754 // throw worm_exception("error description"); 00755 // 00756 // On system failure: 00757 // r_status = WORM_STAT_FAILURE; 00758 // ThisResult->SetStatus( MSB_RESULT_ERROR ); 00759 // throw worm_exception("error description"); 00760 00761 00762 00763 // Put the appropriate result status into the Result object 00764 // (alternatives above) 00765 ThisResult->SetStatus( MSB_RESULT_GOOD ); 00766 00767 // Set the return state 00768 // 00769 r_status = WORM_STAT_SUCCESS; 00770 } 00771 catch( worm_exception & _we ) 00772 { 00773 // r_status should have been set above 00774 00775 if( WORM_LOG_ERRORS <= TGlobalUtils::GetLoggingLevel() ) 00776 { 00777 TLogger::Logit( LoggingOptions 00778 , "ServerTemplate::ProcessRequest(): %s\n" 00779 , _we.what() 00780 ); 00781 } 00782 } 00783 } 00784 00785 //------------------------------------------------------------------------------ 00786 WORM_STATUS_CODE ServerTemplate::HandleResult( void * p_resultcontainer ) 00787 { 00788 WORM_STATUS_CODE r_status = WORM_STAT_SUCCESS; 00789 00790 try 00791 { 00792 // STEP 19: Cast the result container to the appropriate type 00793 // 00794 ResultTemplate * ThisResult = (ResultTemplate *)p_resultcontainer; 00795 00796 00797 if( WORM_LOG_DEBUG <= LoggingLevel ) 00798 { 00799 TLogger::Logit( LoggingOptions 00800 , "ServerTemplate::HandleResult(): DEBUG result of processing: %d\n" 00801 , _result->GetStatus() 00802 ); 00803 } 00804 00805 00806 if ( ThisResult->GetStatus() == MSB_RESULT_GOOD ) 00807 { 00808 00809 // STEP 20: Perform activities for a good result (i.e.: database storage) 00810 // 00811 // throw worm_exception for errors 00812 00813 00814 } // received good magnitude result 00815 else 00816 { 00817 switch( _result->GetStatus() ) 00818 { 00819 case MSB_RESULT_FAIL: 00820 r_status = WORM_STAT_BADSTATE; 00821 break; 00822 case MSB_RESULT_ERROR: 00823 r_status = WORM_STAT_FAILURE; 00824 break; 00825 } 00826 } // calculations not good 00827 } 00828 catch( worm_exception & _we ) 00829 { 00830 r_status = WORM_STAT_FAILURE; 00831 00832 if( WORM_LOG_ERRORS <= TGlobalUtils::GetLoggingLevel() ) 00833 { 00834 TLogger::Logit( LoggingOptions 00835 , "ServerTemplate::HandleResult(): %s\n" 00836 , _we.what() 00837 ); 00838 } 00839 } 00840 00841 return r_status; 00842 } 00843 //------------------------------------------------------------------------------