Changeset 209 for Evidence


Ignore:
Timestamp:
05/19/10 09:08:40 (14 years ago)
Author:
ogrimm
Message:
Service histories now available via DimRpc from DColl
Location:
Evidence
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • Evidence/Config.cc

    r203 r209  
    105105  if (pthread_mutex_lock(&Mutex) != 0) State(ERROR, "pthread_mutex_lock() failed in rpcHandler()");
    106106
    107   // Search for config data in list
     107  // Search for config data in list (default response is empty string)
    108108  for (int i=0; i<List.size(); i++) {
    109109    if (List[i].Name == getString()) Response = List[i].Data;
  • Evidence/DColl.cc

    r203 r209  
    55  - DColl subscribes to all services given by the configuration
    66    server and writes these to the data file at every update.
    7   - One data file per day is generated, with roll-over at 13:00 local time.
    8   - For each service, it creates a new service with '.hist' appended
    9         that contains a history of events kept within a ring buffer. Each
     7  - One data file per day is generated.
     8  - A history of events is kept within a ring buffer for each service. Each
    109        entry will be the result of a conversion to double of the text
    1110        written to the data file. Only if the new value has changed by a
    12         minimum amout it will be added to the ring buffer.
     11        minimum amout it will be added to the ring buffer. The history is
     12        available via an rpc call.
    1313  - The history buffers are written to disk at program termination and
    1414    are tired to be read when adding a service.
     
    1616    file specified in the configuration.
    1717 
    18   Oliver Grimm, December 2009
     18  Oliver Grimm, May 2010
    1919
    2020\********************************************************************/
     
    2222#define SERVER_NAME "DColl"
    2323
    24 #define DATE_ROLLOVER 12        // localtime hour after which next date is used
    2524#define MIN_HIST_SIZE 1024      // Minimum history buffer in bytes (> 3*sizeof(int) !)
    2625
     
    4443// Class declaration
    4544//
    46 class DataHandler:      public DimClient, public DimBrowser,
     45class DataHandler:      public DimRpc, public DimClient, public DimBrowser,
    4746                                        public EvidenceServer {
    4847
    4948        struct Item {
    5049          DimStampedInfo *DataItem;
    51       DimService *HistService;
    5250          char *Buffer;
    5351          unsigned int HistSize;
     
    7068        int SizeUpdateDelay;
    7169        int TimeForNextFile;
    72        
     70        int RollOver;
     71
    7372        int RegExCount;
    7473        regex_t *RegEx;
     
    7776       
    7877    void infoHandler();
     78    void rpcHandler();
    7979    void commandHandler();
    8080        void AddService(string);
    8181        void RemoveService(string);
    8282        float FileSize(FILE *);
    83            
     83        FILE *OpenHistFile(string, const char *);
     84   
    8485  public:
    8586    DataHandler();
     
    9091// Constructor
    9192//
    92 DataHandler::DataHandler(): EvidenceServer(SERVER_NAME) {
     93DataHandler::DataHandler(): DimRpc("ServiceHistory", "C", "C"), EvidenceServer(SERVER_NAME) {
    9394
    9495  // Initialization to prevent freeing unallocated memory
     
    108109  SizeUpdateDelay = atoi(GetConfig("sizeupdate"));
    109110  HistDir = GetConfig("histdir");
    110    
     111  RollOver = atoi(GetConfig("rollover"));
     112
    111113  // Open log file
    112114  char *Logname = GetConfig("logfile");
     
    127129  DataFilename = new DimService(SERVER_NAME "/CurrentFile", (char *) "");
    128130
    129   // Count how many minimum change value regular expressions are present
     131  // Count how many minimum change regular expressions are present
    130132  char *Change = GetConfig("items");
    131133  RegExCount = 0;
     
    137139 
    138140  // Allocate memory for regular expressions, minimum change and history size
    139   RegEx = new regex_t[RegExCount];
     141  RegEx = new regex_t [RegExCount];
    140142  MinChange = new double [RegExCount];
    141143  HistSize = new unsigned int [RegExCount];
     
    151153          char ErrMsg[200];
    152154          regerror(Ret, &RegEx[i], ErrMsg, sizeof(ErrMsg));
    153           State(FATAL, "Error compiling regular expression '%s' (%s)", Token, ErrMsg);
     155          RegExCount--;
     156          i--;
     157          State(ERROR, "Error compiling regular expression '%s' (%s)", Token, ErrMsg);
    154158        }
    155159        else {
     
    179183  delete[] Filename;
    180184 
    181   //delete LogSizeService; // These create segmentation faults?!
    182   //delete DataSizeService;
     185  delete LogSizeService;
     186  delete DataSizeService;
    183187
    184188  // Close files
     
    258262        DataFile = NULL;
    259263  }
    260  
     264
    261265  // Open new data file if necessary
    262266  if (DataFile == NULL) {
    263267        time_t Time = time(NULL);
    264268        struct tm *T = localtime(&Time);
    265        
     269
    266270        // Get time structure with date rollover
    267         if(T->tm_hour >= DATE_ROLLOVER) T->tm_mday++;
     271        if (T->tm_hour >= RollOver) T->tm_mday++;
    268272        if (mktime(T) == -1) State(ERROR, "mktime() failed, check filename");
    269273
     
    294298        T->tm_sec = 0;
    295299        T->tm_min = 0;
    296         T->tm_hour = DATE_ROLLOVER;
     300        T->tm_hour = RollOver;
    297301        TimeForNextFile = mktime(T);
    298302  }
     
    460464
    461465//
     466// Implementation of history buffer distribution
     467//
     468void DataHandler::rpcHandler() {
     469
     470  // Search for history buffer
     471  for (int i=0; i<List.size(); i++) {
     472    if (strcmp(List[i].DataItem->getName(), getString()) == 0) {
     473          setData((void *) List[i].Buffer, List[i].HistSize);
     474          return;
     475        }
     476  }
     477 
     478  // Default response
     479  setData(NULL, 0);
     480}
     481
     482
     483//
    462484// Add service to watch list
    463485//
    464486void DataHandler::AddService(string Name) {
    465 
    466   // Do not subscribe to history services (otherwise infinite loop)
    467   if (Name.find(".hist") != string::npos) return;
    468487
    469488  // Check if already subscribed to this service
     
    492511  New.Next = 4;
    493512  New.LastValue = DBL_MAX;
    494   New.HistService = new DimService ((Name+".hist").c_str(), (char *) "C",
    495                                           New.Buffer, New.HistSize);
    496513
    497514  // Load history buffer from file if existing
    498   string Filename = New.HistService->getName();
    499   for (int j=0; j<Filename.size(); j++) if (Filename[j] == '/') Filename[j] = '_';
    500   FILE *File = fopen((HistDir + "/" + Filename).c_str(), "rb");
     515  FILE *File = OpenHistFile(Name, "rb");
    501516  if (File != NULL) {
    502     // Only load if current buffer size if equal or larger
     517    // Only load if current buffer size is equal or larger
    503518    if (FileSize(File) <= New.HistSize*sizeof(char)+sizeof(New.Next) && FileSize(File) != -1) {
    504519      fread(&New.Next, sizeof(New.Next), 1, File);
     
    527542        delete (*E).DataItem;
    528543
    529         // Save history buffer (replace '/' by '_')
    530     string Name = (*E).HistService->getName();
    531         for (int j=0; j<Name.size(); j++) if (Name[j] == '/') Name[j] = '_';
    532     FILE *File = fopen((HistDir + "/" + Name).c_str(), "wb");
     544        // Save history buffer
     545        FILE *File = OpenHistFile(Name, "wb");
    533546        if (File != NULL) {
    534547      fwrite(&(*E).Next, sizeof((*E).Next), 1, File);
     
    538551       
    539552        // Delete history service and free memory
    540         delete (*E).HistService;
    541553    delete[] (*E).Buffer;
    542554        List.erase(E);
     
    558570
    559571  return (float) FileStatus.st_size/1024;
     572}
     573
     574//
     575// Replace all '/' by '_' in string
     576//
     577FILE *DataHandler::OpenHistFile(string Service, const char *Mode) {
     578
     579  for (int i=0; i<Service.size(); i++) if (Service[i] == '/') Service[i] = '_';
     580  return fopen((HistDir + "/" + Service).c_str(), Mode);
    560581}
    561582
  • Evidence/Evidence.cc

    r199 r209  
    3838  // Initialize
    3939  Status = NULL;
     40  StdOutText = NULL;
    4041  ExitRequest = false;
    4142  ThisServer = this;
     
    6061 
    6162  Status = new DimService((ServerName+"/Status").c_str(), (char *) "C", InitMsg, strlen(InitMsg)+1);
     63  StdOut = new DimService((ServerName+"/Textout").c_str(), (char *) "");
    6264
    6365  start(Name);
     
    7476  }
    7577  delete ModifyInfo;
     78 
     79  delete Status;
     80  delete StdOut;
    7681}
    7782
     
    126131  // Terminate if message type is fatal
    127132  if (Severity == FATAL) exit(EXIT_FAILURE);
     133}
     134
     135// Set text of StdOut service
     136void EvidenceServer::SetStdOut(char *Text) {
     137
     138  // Copy text to permanent buffer
     139  char *Tmp = new char[strlen(Text)+1];
     140  strcpy(Tmp, Text);
     141  StdOut->updateService(Tmp);
     142
     143  // Delete old buffer and save new buffer pointer
     144  delete[] StdOutText;
     145  StdOutText = Tmp;   
    128146}
    129147
     
    148166        break;
    149167  }
    150  
     168
    151169  // Make configuration request
    152   DimRpcInfo Config((char *) "ConfigRequest", (char *) "");
     170  DimRpcInfo Config((char *) "ConfigRequest", NO_LINK);
    153171  Config.setData((char *) (ServerName + " " + Item).c_str());
    154172  char *Result = Config.getString();
    155  
     173
    156174  // Terminate if not successful
     175  if (!EvidenceServer::ServiceOK(&Config)) {
     176    State(FATAL, "Configuration server unreachable, can't get '%s'", Item.c_str());
     177  }
     178
    157179  if (strlen(Result) == 0) {
    158180    if (Default == NULL) State(FATAL, "Missing configuration data '%s'", Item.c_str());
     
    172194  strcpy(ConfigList[ItemNo].Value, Result);
    173195  ConfigList[ItemNo].Time = ModifyInfo->LastModifyTime;
    174    
     196
    175197  // Return address to configuration value 
    176198  return ConfigList[ItemNo].Value;
     
    314336  return !((Item->getSize() == strlen(NO_LINK)+1) && 
    315337          (memcmp(Item->getData(), NO_LINK, Item->getSize()) == 0));
    316 
    317 }
    318 
     338}
     339
     340bool EvidenceServer::ServiceOK(DimRpcInfo *Item) {
     341
     342  return !((Item->getSize() == strlen(NO_LINK)+1) && 
     343          (memcmp(Item->getData(), NO_LINK, Item->getSize()) == 0));
     344}
    319345
    320346///////////////////////////
     
    333359
    334360// Constructor
    335 EvidenceHistory::EvidenceHistory(std::string Name, int Delay):
    336         Name(Name+".hist"),
    337         Delay(Delay) {
     361EvidenceHistory::EvidenceHistory(std::string Name):     Name(Name) {
    338362
    339363  Buffer = NULL;
    340   LastUpdate = 0;
    341364}
    342365
     
    350373bool EvidenceHistory::GetHistory() {
    351374
    352   // Check if last buffer update less than minimum delay in the past
    353   if ((Buffer != NULL) && (time(NULL)-LastUpdate < Delay)) {
    354         Offset = *(int *) Buffer;
    355         return true;
    356   }
    357   LastUpdate = time(NULL);
    358  
    359   // Check if service available
    360   DimCurrentInfo Info(Name.c_str(), NO_LINK);
    361   if (((Info.getSize() == strlen(NO_LINK)+1) && 
    362           (memcmp(Info.getData(), NO_LINK, Info.getSize()) == 0))) return false;
     375  DimRpcInfo R((char *) "ServiceHistory", NO_LINK);
     376  R.setData((char *) Name.c_str());
     377  if (!EvidenceServer::ServiceOK(&R)) return false;
    363378
    364379  delete[] Buffer;
    365   BufferSize = Info.getSize();
     380  BufferSize = R.getSize();
    366381  Buffer = new char [BufferSize];
    367382
    368   memcpy(Buffer, Info.getData(), BufferSize);
     383  memcpy(Buffer, R.getData(), BufferSize);
    369384  Offset = *(int *) Buffer;
    370385 
  • Evidence/Evidence.h

    r187 r209  
    4747
    4848        std::string ServerName;
    49     DimService *Status;
     49    DimService *Status, *StdOut;
    5050        class ConfigUpdate *ModifyInfo;
    5151       
    5252        char InitMsg[STATUS_SIZE];
    5353        int LastModifyTime;
    54 
     54        char *StdOutText;
     55       
    5556    static void SignalHandler(int); // static for signal()
    5657    static void Terminate();            // static for set_terminate()
     
    6566
    6667        void State(StateType, const char *, ...);
     68        void SetStdOut(char *);
    6769        char* GetConfig(std::string, const char * = NULL);
    6870        static char* ToString(DimInfo *);
    6971        static bool ServiceOK(DimInfo *);
     72        static bool ServiceOK(DimRpcInfo *);
    7073
    7174    bool ExitRequest;
     
    8184  int BufferSize;
    8285  int Offset;
    83   int Delay;
    84   int LastUpdate;
    8586 
    8687  public:
    87         EvidenceHistory(std::string, int = 10);
     88        EvidenceHistory(std::string);
    8889        ~EvidenceHistory();
    8990       
  • Evidence/readme.txt

    r187 r209  
    2121
    2222- Oliver Grimm, 18/1/2010
     23
     24Version history
     25---------------
     26
     2719/5/2010       Service histories now available via DimRpc from DColl, not via .hist service
     28                        When regular expression compiling results in error, State is set to ERROR, not
     29                        FATAL. The erroneous expression is ignored in the following.
     30                       
    2331
    2432
Note: See TracChangeset for help on using the changeset viewer.