00001 // mutableserverbase.h: interface for the MutableServerBase class. 00002 // 00004 00005 #if !defined(MUTABLESERVERBASE_H) 00006 #define MUTABLESERVERBASE_H 00007 00008 #if _MSC_VER > 1000 00009 #pragma once 00010 #endif // _MSC_VER > 1000 00011 00012 // microsoft pragma to avoid warnings relating to the container 00013 // template names being too long 00014 #pragma warning(disable:4786) 00015 00016 #include "serverbase.h" 00017 #include <mutableservermessage.h> 00018 #include <mutableserverrequest.h> 00019 #include <mutableserverresult.h> 00020 #include <result_status.h> 00021 #include <string> 00022 #include <vector> 00023 #include <queue> 00024 00025 00026 // Descriptive strings for these are 00027 // held in static class variable MSB_MODE_NAME[], 00028 // defined in mutableserverbase.cpp. 00029 // 00030 enum MUTABLE_MODE_TYPE 00031 { 00032 MMT_NONE = 0 // for validation 00033 , MMT_STANDALONE = 1 // command from args/stdin, data access and calculations internally 00034 , MMT_MODULE = 2 // command from ring, data access and calculations internally [MT] 00035 , MMT_SERVER = 3 // command from socket, calculations internally [MT] 00036 , MMT_CLIENT = 4 // command from atgs/stdin, socket call to client for calculations 00037 }; 00038 00039 00040 typedef struct _PROVIDER_ADDR 00041 { 00042 std::string IPAddr; 00043 std::string Port; 00044 } PROVIDER_ADDR; 00045 00046 typedef std::vector<PROVIDER_ADDR> PROVIDER_VECTOR; 00047 00048 00049 00050 #define SERVE_MAX_LOGOS 20 // maximum incoming logo ids 00051 00052 00053 // sacred definitions for message types to report to heartbeat/status ring 00054 // 00055 // 00056 #define MSB_ERR_MISSMSG 0 /* message missed in transport ring */ 00057 #define MSB_ERR_TOOBIG 1 /* retrieved msg too large for buffer */ 00058 #define MSB_ERR_NOTRACK 2 /* severe weirdness in the cellar */ 00059 #define MSB_ERR_QUEUE 3 /* error queueing message for sending */ 00060 #define MSG_ERR_BASE 10 /* base value for derivative classes to start 00061 ** declaring their own error codes 00062 */ 00063 00064 00065 // ---------------------------------------------------------------------- 00066 class MutableServerBase : public WormServerBase 00067 { 00068 private: 00069 int MaxMessageLength; 00070 char * MessageBuffer; // buffer for arriving messages 00071 00072 00073 // - - - - - - - - - - - - - - - - - - - - - - - - - 00074 // Client (sending to Server across socket, await response) 00075 // 00076 WORM_STATUS_CODE TransmitRequest( MutableServerRequest * p_request 00077 , MutableServerResult * r_result 00078 ); 00079 00080 00081 // - - - - - - - - - - - - - - - - - - - - - - - - - 00082 // Server (socket) or Module (ring) 00083 // 00084 // if p_result is NULL, this will transmit a message or the appropriate type 00085 // with status = MSB_RESULT_ERROR (system failure) 00086 // 00087 WORM_STATUS_CODE TransmitResult( MutableServerResult * p_result 00088 , const SOCKET * p_socketdescriptor = NULL 00089 ); 00090 00091 protected: 00092 00093 // ======================================================================= 00094 // from TConfigurable 00095 // ======================================================================= 00096 00097 /* CheckConfig() -- allows derivative classes to report the status of their 00098 ** the lookup values. 00099 ** 00100 ** From within any deriving class, or further derivation, ALWAYS contain a call to 00101 ** <super_class>::CheckConfig() in their own CheckConfig() method... 00102 ** except that MutableServerBase::CheckConfig() should NOT call 00103 ** WormServerBase::CheckConfig(). 00104 ** This ensures that all classes in the heirarchy get their chance to report status. 00105 ** Furthermore, any derivative classes that need to have the Mode set before 00106 ** doing their own CheckConfig(), should call MutableServerBase::CheckConfig() 00107 ** at the top of theirs. 00108 ** 00109 ** All implementations should set ConfigStatus value to WORM_STAT_BADSTATE if there 00110 ** is a configuration problem, otherwise leave it alone. 00111 ** 00112 */ 00113 void CheckConfig(); 00114 00115 // ======================================================================= 00116 // WormServerBase 00117 // ======================================================================= 00118 00119 /* 00120 ** PrepareToRun() -- sets LoggingLevel 00121 */ 00122 virtual bool PrepareToRun() { return WormServerBase::PrepareToRun(); } 00123 00124 00125 /* ClientServicer() -- method to perform the work of servicing a client 00126 ** 00127 ** note: THREAD_RETURN is a kind of void, so just return or leave the method. 00128 */ 00129 THREAD_RETURN ClientServicer( void * p_socketdescriptor ); 00130 00131 00132 // ======================================================================= 00133 // MutableServerBase 00134 // ======================================================================= 00135 00136 00137 // Array of lookup names 00138 // 00139 static const char * MSB_MODE_NAME[]; 00140 00141 // Mode is set in 00142 // 00143 MUTABLE_MODE_TYPE Mode; 00144 00145 // - - - - - - - - - - - - - - - - - - - - - - - - - 00146 // Server 00147 // 00148 // see WormServerBase() 00149 00150 unsigned short MaxClients; 00151 00152 00153 // - - - - - - - - - - - - - - - - - - - - - - - - - 00154 // Client 00155 // 00156 PROVIDER_VECTOR Providers; 00157 00158 // Attempt connection to providers in a round-robin 00159 // fashion until connection achieved or until this 00160 // number of seconds has passed 00161 // 00162 int ConnectFailureSec; 00163 00164 // max times that each server will be queried before 00165 // client finally throws in the towel. 00166 int MaxServerTryLoopCount; 00167 00168 // - - - - - - - - - - - - - - - - - - - - - - - - - 00169 // Module 00170 // 00171 std::string InputRingName 00172 , OutputRingName 00173 ; 00174 WORM_RING_ID InputRingKey 00175 , OutputRingKey 00176 ; 00177 SHM_INFO * InputRegion // pointer to SHM_INFO used for input 00178 , * OutputRegion // pointer to SHM_INFO used for output 00179 , InputRegionStruct 00180 , OutputRegionStruct 00181 ; 00182 00183 MSG_LOGO ServeLogo[SERVE_MAX_LOGOS]; 00184 short ServeLogoCount; 00185 00186 char * TransmitBuffer; 00187 long TransmitBufferLength; 00188 00189 00190 // MessageMutex -- mutex to prevent collisions over the MessageBuffer, 00191 // should be used in both Stacker() 00192 // and Handler() 00193 // 00194 // MessageMutex.RequestLock(); 00195 // MessageMutex.ReleaseLock(); 00196 // 00197 TMutex * MessageMutex; 00198 00199 std::queue<std::string> MessageQueue; 00200 00201 TO_THREAD_ID StackerThreadId; 00202 long LastStackerPulse; 00203 00204 THREAD_RETURN Stacker(); 00205 00206 TO_THREAD_ID HandlerThreadId; 00207 long LastHandlerPulse; 00208 00209 THREAD_RETURN Handler(); 00210 00211 MSG_LOGO ResultMsgLogo; 00212 00213 // OutputMessageTypeKey() -- Returns the string used to identify 00214 // result messages sent in Module mode 00215 // via the ring (e.g.: TYPE_XXXXXXX). 00216 // This is intended to allow different 00217 // derivative servers to emit different 00218 // message types. 00219 // 00220 virtual const char * OutputMessageTypeKey() = 0; 00221 00222 00223 // - - - - - - - - - - - - - - - - - - - - - - - - - 00224 // Server or Module (required for Module) 00225 // 00226 // in WormServerBase 00227 00228 // std::string CommandRingName; 00229 // WORM_RING_ID CommandRingKey; 00230 // SHM_INFO CommandRegion; 00231 00232 int LoggingOptions; 00233 00234 00235 // returns true if a processing thread died 00236 // false if all still okay 00237 // 00238 bool CheckForThreadDeath(); 00239 00240 /* 00241 ** Server and Module enter this to start worker threads 00242 ** and start main loop 00243 ** (sending heartbeats, checking shut 00244 */ 00245 WORM_STATUS_CODE MainThreadActions(); 00246 00247 00248 /* 00249 ** GetMaxSocketBufferSize() -- Server mode uses this to allocate 00250 ** a buffer of sufficient size to 00251 ** parse the arriving and format 00252 ** the outgoing message 00253 */ 00254 virtual long GetMaxSocketBufferSize() = 0; 00255 00256 00257 /* 00258 ** GetRequestContainer() -- gets a container to hold the request 00259 ** (e.g. passport & event info). 00260 ** Since we don't know what all 00261 ** possible content that can be in a 00262 ** request for the various derivative 00263 ** classes of servers, the container 00264 ** is returned as a void pointer, 00265 ** This base class code does not need 00266 ** to know about the container, only 00267 ** the following virtual methods do. 00268 ** 00269 ** RETURNS: 00270 ** a pointer to the container 00271 ** or NULL on failure 00272 */ 00273 virtual MutableServerRequest * GetRequestContainer() = 0; 00274 00275 virtual MutableServerResult * GetResultContainer() = 0; 00276 00277 00278 // - - - - - - - - - - - - - - - - - - - - - - - - - 00279 // Standalone or Client 00280 // 00281 // Gets request parameters/instructions from command line args 00282 // or stdin 00283 // 00284 // r_container = a pointer to the appropriate type of 00285 // MutableServerRequest derivative class 00286 // (cast to the specific type herein). 00287 // 00288 virtual WORM_STATUS_CODE GetRequestFromInput( int p_argc 00289 , char * p_argv[] 00290 , void * r_container 00291 ) = 0; 00292 00293 // - - - - - - - - - - - - - - - - - - - - - - - - - 00294 // Server, Module or Standalone 00295 // 00296 virtual WORM_STATUS_CODE ProcessRequest( void * p_request 00297 , void * r_result 00298 ) = 0; 00299 00300 00301 // - - - - - - - - - - - - - - - - - - - - - - - - - 00302 // Client, Module or Standalone 00303 // 00304 // p_result is a pointer to the appropriate type of 00305 // MutableServerResult derivative class 00306 // (cast to the specific type herein). 00307 // 00308 // MUST RETURN: 00309 // WORM_STAT_SUCCESS = good results 00310 // WORM_STAT_BADSTATE = algorithmic, not system, failure (no results obtained) 00311 // WORM_STAT_FAILURE = system failure 00312 // 00313 virtual WORM_STATUS_CODE HandleResult( void * p_result ) = 0; 00314 00315 00316 public: 00317 00318 // ======================================================================= 00319 // from TConfigurable 00320 // ======================================================================= 00321 00322 /* 00323 ** HandleConfigLine() 00324 ** 00325 ** PARMS: 00326 ** p_parser -- the parser being used, command string already 00327 ** in the current token for comparison with Its() 00328 ** 00329 ** RETURN: 00330 ** HANDLE_INVALID -- line invalid 00331 ** HANDLE_UNUSED -- line not used 00332 ** HANDLE_USED -- line used okay 00333 ** 00334 ** Override for child classes to handle command lines 00335 ** Call <super_class::HandleConfigLine() within derivative classes 00336 ** to allow them a whack at the parameter as well. 00337 */ 00338 HANDLE_STATUS HandleConfigLine( ConfigSource * p_parser ); 00339 00340 // ======================================================================= 00341 // from ThreadableObject 00342 // ======================================================================= 00343 00344 /* StartThreadFunc -- used by ThreadableObject global function to reenter 00345 ** this class in a new thread 00346 */ 00347 void StartThreadFunc( void * p_arg ); 00348 00349 00350 // ======================================================================= 00351 // for MutableServerBase 00352 // ======================================================================= 00353 00354 MutableServerBase(); 00355 ~MutableServerBase(); 00356 00357 // Run( int argc, char* argv[] ) 00358 // 00359 // Not quite an override of the ServerBase:;Run() method. 00360 // This one must switch on the mode, and start thread or 00361 // call methods as appropriate. 00362 // 00363 // Included the parameters to enable derivative classes to 00364 // get what they need from the command line or from stdin 00365 // as preferred. 00366 // 00367 WORM_STATUS_CODE Run( int argc, char* argv[] ); 00368 00369 }; 00370 00371 #endif // !defined(MUTABLESERVERBASE_H)