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

# server_template.cpp

Go to the documentation of this file.

    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 //------------------------------------------------------------------------------