// snfGBUdbmgr.cpp // Copyright (C) 2006 - 2009 ARM Research Labs, LLC. // See www.armresearch.com for the copyright terms. // // See snfGBUdbmgr.hpp for details. #include "snfGBUdbmgr.hpp" #include using namespace std; const ThreadType snfGBUdbmgr::Type("snfGBUdbmgr"); // The thread's type. snfGBUdbmgr::snfGBUdbmgr() : // Clean init and start thread. Thread(snfGBUdbmgr::Type, "GBUdb Manager"), // XCI Manager type and Name. CondenseGuardTime(600000), // 10 minute guard time by default. TimeTriggerOnOff(true), // By default, condense once per day. TimeTrigger(84600000), PostsTriggerOnOff(false), // By default do not trigger on posts. PostsTriggerValue(262144), // but if we do, use a quarter million. RecordsTriggerOnOff(false), // By default do not trigger on records. RecordsTriggerValue(150000), // but if we do, use 150K. SizeTriggerOnOff(true), // By default trigger on size as a SizeTriggerValue(150), // safety valve at 150Mbytes. CheckpointOnOff(true), // By default save a snapshot once CheckpointTrigger(3600000), // every hour. MyGBUdb(NULL), // NULL our links to avoid MyLOGmgr(NULL), // any errors when the thread starts. TimeToStop(false) { // It is not time to stop ;-) run(); // Start our thread. } snfGBUdbmgr::~snfGBUdbmgr() { // Clean shutdown & stop thread. stop(); // Stop the thread if it's not already. MyGBUdb = NULL; // NULL our links and false our MyLOGmgr = NULL; // configuration for safety. Configured = false; } void snfGBUdbmgr::linkGBUdb(GBUdb& G) { // Connect to our GBUdb ScopeMutex JustMe(MyMutex); // Lock for the config change. MyGBUdb = &G; // Set the new link. } void snfGBUdbmgr::linkLOGmgr(snfLOGmgr& L) { // Connect to our LOGmgr ScopeMutex JustMe(MyMutex); // Lock for the config change. MyLOGmgr = &L; // Set the new link. } void snfGBUdbmgr::configure(snfCFGData& CFGData) { // Establish or change our CFG. ScopeMutex JustMe(MyMutex); // Only when we're not busy. // Set up our configuration from the CFGData provided. // Being careful not to muck with running timers unless their // configuration values have actually changed... const int SECsASms = 1000; // How to convert seconds to milliseconds. if(CondenseGuardTime.getDuration() != // If the condensation guard time is (SECsASms * CFGData.gbudb_database_condense_minimum_seconds_between)) { // new and different then set the CondenseGuardTime.setDuration( // condensation guard timer to the (SECsASms * CFGData.gbudb_database_condense_minimum_seconds_between) // new value. ); } TimeTriggerOnOff = CFGData.gbudb_database_condense_time_trigger_on_off; // Time-Trigger On? if(TimeTrigger.getDuration() != // Time-Trigger different? (SECsASms * CFGData.gbudb_database_condense_time_trigger_seconds)) { TimeTrigger.setDuration( // If it is then adopt the new value. SECsASms * CFGData.gbudb_database_condense_time_trigger_seconds ); } PostsTriggerOnOff = CFGData.gbudb_database_condense_posts_trigger_on_off; // Posts trigger on? PostsTriggerValue = CFGData.gbudb_database_condense_posts_trigger_posts; // What is the posts trigger threshold? RecordsTriggerOnOff = CFGData.gbudb_database_condense_records_trigger_on_off; // Records trigger on? RecordsTriggerValue = CFGData.gbudb_database_condense_records_trigger_records; // What is the records trigger threshold? SizeTriggerOnOff = CFGData.gbudb_database_condense_size_trigger_on_off; // Size trigger on? SizeTriggerValue = CFGData.gbudb_database_condense_size_trigger_megabytes; // What is the size trigger threshold? // Checkpoint CheckpointOnOff = CFGData.gbudb_database_checkpoint_on_off; // Checkpoint on? if(CheckpointTrigger.getDuration() != // If the Checkpoint time is (SECsASms * CFGData.gbudb_database_checkpoint_secs)) { // new and different then CheckpointTrigger.setDuration( // adopt the new value. (SECsASms * CFGData.gbudb_database_checkpoint_secs) ); } // GBUdb file name string GBUdbFileName; // Formulate the correct GBUdb file name GBUdbFileName = CFGData.paths_workspace_path + // using the CFGData. CFGData.node_licenseid + ".gbx"; if( // If the file name for our GBUdb NULL == (*MyGBUdb).FileName() || // is not yet set, or 0 != GBUdbFileName.compare((*MyGBUdb).FileName()) // if it is different than the ) { // formulated file name we have then (*MyGBUdb).FileName(GBUdbFileName.c_str()); // set the GBUdb file name. } // Safety check to set the Configured bit. if(NULL != MyGBUdb && NULL != MyLOGmgr) { // If we have all of our parts Configured = true; // then set our configured flag. } else { // If anything is missing then Configured = false; // make sure the flag is false. } } //// The snfGBUdbmgr::load() method isn't exactly what you would expect. It // will load the rulebase file if that file exists, but if not it does nothing. // The intention is that a new GBUdb will alread have been created. If a // pre-existing GBUdb is available then that one will be loaded for use. If // it does not exist, then the new, empty GBUdb will be used instead and will // eventually be saved for later re-use. void snfGBUdbmgr::load() { // Load the GBUdb as configured. ScopeMutex JustMe(MyMutex); // Just me while I do this. if( // Perform some sanity checks. NULL != MyGBUdb && // If we have a GBUdb and 0 < string(MyGBUdb->FileName()).length() && // it has a file name and 0 == access(MyGBUdb->FileName(),R_OK) // the file can be accessed ) { // then we can proceed: MyGBUdb->load(); // Load the GBUdb from disk. } // If that didn't work we'll assume } // we're starting up a new gbx file ;-) // DoMaintenanceWork encapsulates all of our maintenance functions. It runs // with the mutex locked so that the configuration is stable during each pass. void snfGBUdbmgr::DoMaintenanceWork() { // Do our watchdog work. if(!Configured) return; // Do nothing if we're not configured. ScopeMutex JustMe(MyMutex); // No CFG changes while I'm busy. if(CondenseGuardTime.isExpired()) { // If we are allowed to condense bool CondenseTriggered = false; // check to see if we should. // time-trigger if( TimeTriggerOnOff && // If the time-trigger is on TimeTrigger.isExpired() // and the time has expired ) { // then it is time to condense. CondenseTriggered = true; // Set the condense flag and TimeTrigger.restart(); // restart the timer. } // posts-trigger if( PostsTriggerOnOff && // If posts-trigger is on (*MyGBUdb).Posts() >= PostsTriggerValue // and the Posts() count is high ) { // enough then trigger the CondenseTriggered = true; // condense operation. } // records-trigger if( RecordsTriggerOnOff && // If records-trigger is on (*MyGBUdb).IPCount() >= RecordsTriggerValue // and the number of IPs is high ) { // enough then trigger the CondenseTriggered = true; // condense operation. } // size-trigger const int MByte = 1048576; // How big is a megabyte anyway? if( SizeTriggerOnOff && // If size-trigger is on ((*MyGBUdb).Size()/MByte) >= SizeTriggerValue // and the size of the db is high ) { // enough then trigger CondenseTriggered = true; // the condense operation. } if(CondenseTriggered) { // If we need to condense then (*MyGBUdb).reduce(); // reduce all counts in the db (*MyGBUdb).compress(); // and elminate any that drop to zero. CondenseGuardTime.restart(); // That done, reset the guard timer. (*MyLOGmgr).RecordCondenseEvent(); // Log the event. } } // Time to save a snapshot? if( CheckpointOnOff && // If checkpoints are turned on CheckpointTrigger.isExpired() // and it is time to create one ) { (*MyGBUdb).saveSnapshot(); // then save a snapshot and CheckpointTrigger.restart(); // restart the timer. (*MyLOGmgr).RecordSaveEvent(); // Log the event. } } // Stopping the thread... void snfGBUdbmgr::stop() { // To stop the manager thread we if(!TimeToStop) { // check to see we need to then TimeToStop = true; // set the time to stop flag join(); // and join the thread. } } // The thread's task is to call DoMaintenanceWork() once every second. void snfGBUdbmgr::myTask() { // This is what our thread does. Sleeper WaitATic(1000); // We need a 1 second sleeper. while(!TimeToStop) { // While it's not time to stop WaitATic(); // wait a tic and then do work. DoMaintenanceWork(); } } void snfGBUdbmgr::GetAlertsForSync(list& AlertList) { // Fill AlertList w/ outgoing alerts. (*MyGBUdb).GetAlerts(AlertList); // For now, just pass this through. } void snfGBUdbmgr::ProcessReflections(list& Reflections) { // Integrate returning reflections. (*MyGBUdb).ImportAlerts(Reflections); // For now, just pass this through. }