#include #include #include #include #include #include #include #include #include #include #include #include #include #include "unistd.h" #include "timing.hpp" #include "threading.hpp" #include "networking.hpp" #include "SNFMulti.hpp" #include "snf_xci.hpp" #include "snf_sync.hpp" #include "config.h" // temporary - proving base64codec #include "base64codec.hpp" //#include "../nvwa-0.6/nvwa/debug_new.h" using namespace std; // Introduce standard namespace. const char* SERVER_VERSION_INFO = "SNF Server Version " PACKAGE_VERSION " Build: " __DATE__ " " __TIME__; static const string XCIShutdownResponse = "\n"; class XCIShutdownWatcher : public snfXCIServerCommandHandler { // Shutdown watcher. public: XCIShutdownWatcher():TimeToStop(false){} // Construct with shutdown flag false. bool TimeToStop; // Here is the flag. string processXCIRequest(snf_xci& X) { // Here is how we process requests. if(0 == X.xci_server_command.find("shutdown")) { // If we find shutdown then TimeToStop = true; // set the shutdown flag return XCIShutdownResponse; // and let them know we got it. } // If we get some other request return XCIErrorResponse; // return the error response. } }; // Thread Status Analysis For Debugging. void ThreadStatusToCout() { // Produce a thread status list. ThreadStatusReport R = Threads.StatusReport(); // Get a report from Threads. cout << endl; // Break the line. for( ThreadStatusReport::iterator iR = R.begin(); // Loop through the report. iR != R.end(); iR++ ) { ThreadStatusRecord& S = (*iR); // Take each status report and cout // send it to cout on it's own line. << S.getName() << " (" << S.getPointer() << "), " << S.getType().Name << ", " << S.getState().Name << ", " << ((S.getRunning()) ? "Running, " : "Not Running, ") << ((S.getBad()) ? "Broken, " : "Ok, ") << S.getFault() << endl; } cout << endl; // Leave a blank line at the end. } // Here in the main thread is where we get executive tasks done. int go(int argc, char* argv[]) { //// go() stands in for main(). main() catches any unhandled exceptions. // Check for debug mode. bool DebugMode = false; // This will be our debug mode. string argv0(argv[0]); // Capture how we were called. if( string::npos != argv0.find("Debug") || // If we find "Debug" or string::npos != argv0.find("debug") // "debug" in our command path ) { // then we are in DebugMode. DebugMode = true; // Set the flag and tell the cout << "Debug Mode" << endl; // watchers. } // DebugMode = true; // Force it when needed. // Announce Version / Build Info. cout << SERVER_VERSION_INFO << endl; // Shout out our version. cout << SNF_ENGINE_VERSION << endl; // Shout out the engine version. // Sanity checks before we get going. if(2 != argc) { // Check the command line args. cout << "Use: SNFServer " << endl; // If wrong, say how we work. return 0; } if(0 != access(argv[1], R_OK)) { // Check the config file path. cout << "Can't read " << argv[1] << endl; // If it's not accessible, punt. return 0; } cout << "Launching with " << argv[1] << endl; // Tell them we're going. snf_RulebaseHandler MyRulebase; // Create a rulebase manager. MyRulebase.PlatformVersion(SERVER_VERSION_INFO); // Set the Platform version string. XCIShutdownWatcher ShutdownWatcher; // Make a server shutdown processor MyRulebase.XCIServerCommandHandler(ShutdownWatcher); // and register it with the engine. MyRulebase.open(argv[1], "", ""); // Open a configured rulebase. Sleeper WaitATic(1000); // Learn to wait a second. cout << "Running." << endl << endl; // Tell them we're running. char Tic = '\\'; // Tic/Toc indicator. while(false == ShutdownWatcher.TimeToStop) { // While running, update the screen. WaitATic(); // One second between updates. // Animate the Tick/Toc Indicator switch(Tic) { case '\\': Tic = '|'; break; case '|': Tic = '/'; break; case '/': Tic = '-'; break; default: Tic = '\\'; break; } // Format and output the screen update. At the end post a \r so that // the line appears to update in place. cout << "M/min: " << setw(4) << (int) MyRulebase.MyLOGmgr.MessagesPerMinute() << " " << "SP: " << setw(6) << setprecision(2) << setiosflags(ios::fixed) << ((0 < MyRulebase.MyLOGmgr.MessagesPerMinute()) ? (100 * MyRulebase.MyLOGmgr.SpamPerMinute() / MyRulebase.MyLOGmgr.MessagesPerMinute()) : 0.0) << "% " << "LR:" << setw(7) << MyRulebase.MyLOGmgr.LatestRuleID() << " [" << MyRulebase.MyXCImgr.pollClientCount() << "/" << MyRulebase.MyXCImgr.pollLoopCount() << " " << Tic << " " << (int) MyRulebase.MyXCImgr.TotalQueue() << "] " << "W:" << (int) MyRulebase.MyLOGmgr.WhitePerMinute() << " " << "C:" << (int) MyRulebase.MyLOGmgr.CautionPerMinute() << " " << "B:" << (int) MyRulebase.MyLOGmgr.BlackPerMinute() << " " << "T:" << (int) MyRulebase.MyLOGmgr.TruncatePerMinute() << " " << "S:" << (int) MyRulebase.MyLOGmgr.SamplePerMinute() << " \r" << flush; if(DebugMode) ThreadStatusToCout(); // Debug? Show Thread Status Report. } cout << endl << endl << "Shutdown Received." << endl; // When this loop fails it is time to shut down. // All the rest happens via XCI now. cout << "Closing Rulebase Handler..." << endl; MyRulebase.close(); // All done... cout << "Bye bye." << endl; return 0; } /* class DebugExceptionHandler { // Hand wrapper for exception handler. public: DebugExceptionHandler() { LoadLibrary("exchndl.dll"); } }; static DebugExceptionHandler TheDebugExceptionHandler; // Global exception handler. */ int main(int argc, char* argv[]) { try { go(argc, argv); } catch(exception& e) { cout << "Unhandled Exception: " << e.what() << " Thrown!" << endl; } catch(...) { cout << "Unknown, Unhandled Exception Discovered!" << endl; } return 0; }