Changeset 172


Ignore:
Timestamp:
03/02/10 13:24:35 (15 years ago)
Author:
ogrimm
Message:
DColl now also unsubscribes from services that are deleted
File:
1 edited

Legend:

Unmodified
Added
Removed
  • Evidence/DColl.cc

    r160 r172  
    2222#define SERVER_NAME "DColl"
    2323
    24 #define DATE_ROLLOVER 12 // localtime hour after which next date is used
     24#define DATE_ROLLOVER 12        // localtime hour after which next date is used
     25#define MIN_HIST_SIZE 1024      // Minimum history buffer in bytes (> 3*sizeof(int) !)
    2526
    2627#include "Evidence.h"
     
    5051      DimService *HistService;
    5152          char *Buffer;
     53          unsigned int HistSize;
    5254          int Next;
    5355          double LastValue;
     
    6668    DimService *LogSizeService, *DataSizeService, *DataFilename;
    6769        string HistDir;
    68     int HistSize;
    6970        int SizeUpdateDelay;
    7071        int TimeForNextFile;
     
    7374        regex_t *RegEx;
    7475        double *MinChange;
     76    unsigned int *HistSize;
    7577       
    7678    void infoHandler();
    7779    void commandHandler();
    7880        void AddService(string);
     81        void RemoveService(string);
    7982        float FileSize(FILE *);
    8083           
     
    102105
    103106  // Request configuration data
    104   char *Change = GetConfig(SERVER_NAME " minchange");
     107  char *Change = GetConfig(SERVER_NAME " items");
    105108  DataDir = GetConfig(SERVER_NAME " datadir");
    106109  char *Logname = GetConfig(SERVER_NAME " logfile");
    107110  SizeUpdateDelay = atoi(GetConfig(SERVER_NAME " sizeupdate"));
    108   HistSize = atoi(GetConfig(SERVER_NAME " histsize"));
    109   if (HistSize < 3*sizeof(int)) HistSize = 3*sizeof(int);
    110111  HistDir = GetConfig(SERVER_NAME " histdir");
    111112   
     
    135136  }
    136137 
    137   // Allocate memory for regular expressions and minimum change values
     138  // Allocate memory for regular expressions, minimum change and history size
    138139  RegEx = new regex_t[RegExCount];
    139140  MinChange = new double [RegExCount];
    140 
    141   // Compile regular expressions
     141  HistSize = new unsigned int [RegExCount];
     142
     143  // Compile regular expressions and extract minimum change and history size
    142144  int Pos = 0;
    143145  for (int i=0; i<RegExCount; i++) {
     
    152154        }
    153155        else {
    154           if ((Token=strtok(NULL, "")) != NULL) MinChange[i] = atof(Token);
     156          if ((Token=strtok(NULL, ": \t")) != NULL) MinChange[i] = atof(Token);
    155157          else MinChange[i] = 0;
     158          if ((Token=strtok(NULL, "")) != NULL) HistSize[i] = atoi(Token)*1024;
     159          else HistSize[i] = MIN_HIST_SIZE;
     160          if (HistSize[i] < MIN_HIST_SIZE) HistSize[i] = MIN_HIST_SIZE;
    156161        }
    157162        Pos += Len;
     
    167172DataHandler::~DataHandler() {
    168173
    169   // Delete DIM subscriptions and command first so handlers and not called anymore
    170   for (int i=0; i<List.size(); i++) {
    171     delete List[i].DataItem;
    172   }
     174  // Delete all DIM subscriptions
     175  while (List.size() != 0) RemoveService(List[0].DataItem->getName());
     176 
    173177  delete LogCommand;
    174 
    175   // Save history buffers to files (replace '/' by '_')
    176   State(INFO, "Writing history buffers to files");
    177 
    178   for (int i=0; i<List.size(); i++) {
    179     string Name = List[i].HistService->getName();
    180         for (int j=0; j<Name.size(); j++) if (Name[j] == '/') Name[j] = '_';
    181     FILE *File = fopen((HistDir + "/" + Name).c_str(), "wb");
    182         if (File != NULL) {
    183       fwrite(&List[i].Next, sizeof(List[i].Next), 1, File);
    184       fwrite(List[i].Buffer, sizeof(char), HistSize, File);
    185       fclose(File);
    186         }
    187         delete List[i].HistService;
    188     delete[] List[i].Buffer;
    189   }
    190 
    191178  delete DataFilename;
    192179  delete[] Filename;
     
    232219  // If service is DIS_DNS/SERVER_LIST, subscribe to all SERVICE_LIST services
    233220  if (strcmp(Info->getName(), "DIS_DNS/SERVER_LIST") == 0) {   
    234         char *Token = strtok(Info->getString(), "@");   
     221        char *Token = strtok(Info->getString(), "+-!@");       
    235222        while (Token != NULL) {
    236           if (isalpha(*Token) == 0) Token++; // Name can start with +,-,!
    237          
    238           AddService(string(Token)+"/SERVICE_LIST");     
    239          
    240           Token = strtok(NULL, "|");
    241           Token = strtok(NULL, "|@");   // ???? Why needed ?????
     223          if (*Info->getString()=='-' || *Info->getString()=='!') RemoveService(string(Token)+"/SERVICE_LIST");   
     224          else AddService(string(Token)+"/SERVICE_LIST");
     225          Token = strtok(NULL, "|"); // Skip server IP address
     226          Token = strtok(NULL, "@");
    242227        }       
    243228        return;
     
    247232  // Subscribe to all services (but not to commands and RPCs)
    248233  if (strstr(Info->getName(), "/SERVICE_LIST") != NULL) {
    249 
    250         char *Name = strtok(Info->getString(), "|");
     234        char *Name = strtok(Info->getString(), "+-!|");
    251235        while (Name != NULL) {
     236          // Check if item is a service
    252237          char *Type = strtok(NULL, "\n");
    253238          if (Type == NULL) return; // for safety, should not happen
    254           if (isalpha(*Name) == 0) Name++; // Name can start with +,-,!
    255239      if (strstr(Type, "|CMD")==NULL && strstr(Type, "|RPC")==NULL) {
    256                 AddService(Name);
     240            // Add or remove service
     241            if (*Info->getString()=='-' || *Info->getString()=='!') RemoveService(Name);
     242                else AddService(Name);
    257243          }
    258244          Name = strtok(NULL, "|");
     
    323309  // If negative value for absolute change, do not write to file
    324310  if (List[Service].MinAbsChange >= 0) {
    325 
    326   // Write data header
    327   time_t RawTime = Info->getTimestamp();
    328   struct tm *TM = localtime(&RawTime);
    329 
    330   fprintf(DataFile, "%s %d %d %d %d %d %d %d %lu ", Info->getName(), TM->tm_year+1900, TM->tm_mon+1, TM->tm_mday, TM->tm_hour, TM->tm_min, TM->tm_sec, Info->getTimestampMillisecs(), Info->getTimestamp());
    331 
    332   // Translate data into ASCII
    333   char *Text = EvidenceServer::ToString(Info);
    334 
    335   if (Text != NULL) {
    336         // Replace all control characters by white space
    337         for (int i=0; i<strlen(Text); i++) if (iscntrl(Text[i])) Text[i] = ' ';
    338        
    339         // Write to file
    340     fprintf(DataFile, "%s\n", Text);
    341        
     311        // Write data header
     312        time_t RawTime = Info->getTimestamp();
     313        struct tm *TM = localtime(&RawTime);
     314
     315        fprintf(DataFile, "%s %d %d %d %d %d %d %d %lu ", Info->getName(), TM->tm_year+1900, TM->tm_mon+1, TM->tm_mday, TM->tm_hour, TM->tm_min, TM->tm_sec, Info->getTimestampMillisecs(), Info->getTimestamp());
     316
     317        // Translate data into ASCII
     318        char *Text = EvidenceServer::ToString(Info);
     319
     320        if (Text != NULL) {
     321          // Replace all control characters by white space
     322          for (int i=0; i<strlen(Text); i++) if (iscntrl(Text[i])) Text[i] = ' ';
     323
     324          // Write to file
     325      fprintf(DataFile, "%s\n", Text);
     326
     327          free(Text);
     328        }
     329        else fprintf(DataFile, "Cannot interpret format identifier\n");
     330
     331        // Terminate if error because otherwise infinite loop might result as
     332        // next call to this infoHandler() will try to (re-)open file
     333        if(ferror(DataFile)) {
     334      fclose(DataFile);
     335          DataFile = NULL;
     336          State(FATAL, "Error writing to data file, closed file (%s)", strerror(errno));
     337        }
     338
     339        // Update datafile size service (not every time to avoid infinite loop)
     340        if (time(NULL) - DataSizeLastUpdate > SizeUpdateDelay) {
     341      fflush(DataFile); // not continuously to reduce load
     342
     343          DataSizekB = FileSize(DataFile);
     344          DataSizeService->updateService();
     345          DataSizeLastUpdate = time(NULL);
     346        } 
     347  } // Check for disk writing
     348
     349  //
     350  // ====== Part D: Handle history service ===
     351  //
     352 
     353  if (Info->getSize() == 0) return;
     354
     355  // Check if data should be added to history buffer
     356  if (strcmp(Info->getFormat(),"C") != 0 && strlen(Info->getFormat())==1) {
     357        // Calculate sum of all number in array
     358        char *Text = EvidenceServer::ToString(Info);
     359        char *Token = strtok(Text, " ");
     360        double Sum = 0;
     361        while (Token != NULL) {
     362          Sum += atof(Token);
     363      Token = strtok(NULL, " ");
     364        }
    342365        free(Text);
    343   }
    344   else fprintf(DataFile, "Cannot interpret format identifier\n");
    345  
    346   // Terminate if error because otherwise infinite loop might result as
    347   // next call to this infoHandler() will try to (re-)open file
    348   if(ferror(DataFile)) {
    349     fclose(DataFile);
    350         DataFile = NULL;
    351         State(FATAL, "Error writing to data file, closed file (%s)", strerror(errno));
    352   }
    353 
    354   // Update datafile size service (not every time to avoid infinite loop)
    355   if (time(NULL) - DataSizeLastUpdate > SizeUpdateDelay) {
    356     fflush(DataFile); // not continuously to reduce load
    357 
    358         DataSizekB = FileSize(DataFile);
    359         DataSizeService->updateService();
    360         DataSizeLastUpdate = time(NULL);
    361   }
    362  
    363   } // Check for MinAbsChange
    364 
    365   //
    366   // ====== Part D: Handle history service ===
    367   //
    368  
    369   if (Info->getSize() == 0) return;
    370  
    371   // Check if data should be added to history buffer
    372   char *Text = EvidenceServer::ToString(Info);
    373   if (Text != NULL && strcmp(Info->getFormat(),"C") != 0
    374           && fabs(atof(Text)-List[Service].LastValue) < fabs(List[Service].MinAbsChange)) {
    375         free(Text);
    376         return;
    377   }
    378   free(Text);
    379 
     366        // Minimum change?
     367        if (fabs(Sum-List[Service].LastValue) < fabs(List[Service].MinAbsChange)) return;
     368        List[Service].LastValue = Sum;
     369  }
     370 
    380371  // Check if data fits into buffer
    381   if (HistSize < Info->getSize() + 5*sizeof(int)) return;
     372  if (List[Service].HistSize < Info->getSize() + 5*sizeof(int)) return;
    382373
    383374  int Size = Info->getSize() + 4*sizeof(int), Next = List[Service].Next;
     
    387378
    388379  // Check if buffer wrap-around (write wrap mark after Oldest is adjusted)
    389   if (Next + Size >= HistSize) {
     380  if (Next + Size >= List[Service].HistSize) {
    390381    WrapPos = Buffer + Next;
    391382    Next = 4;
     
    482473  // Set minimum required change by comparing to regular expressions
    483474  New.MinAbsChange = 0;
     475  New.HistSize = MIN_HIST_SIZE;
    484476  for (int i=0; i<RegExCount; i++) {
    485477    if (regexec(&RegEx[i], Name.c_str(), (size_t) 0, NULL, 0) == 0) {
    486478          New.MinAbsChange = MinChange[i];
     479          New.HistSize = HistSize[i];
    487480        }
    488481  }
    489482
    490483  // Create history service
    491   New.Buffer = new char [HistSize];
    492   memset(New.Buffer, 0, HistSize);
     484  New.Buffer = new char [New.HistSize];
     485  memset(New.Buffer, 0, New.HistSize);
    493486  *(int *) New.Buffer = 4;
    494487  New.Next = 4;
    495488  New.LastValue = DBL_MAX;
    496489  New.HistService = new DimService ((Name+".hist").c_str(), (char *) "C",
    497                                           New.Buffer, HistSize);
     490                                          New.Buffer, New.HistSize);
    498491
    499492  // Load history buffer from file if existing
     
    503496  if (File != NULL) {
    504497    // Only load if current buffer size if equal or larger
    505     if (FileSize(File) <= HistSize*sizeof(char)+sizeof(New.Next) && FileSize(File) != -1) {
     498    if (FileSize(File) <= New.HistSize*sizeof(char)+sizeof(New.Next) && FileSize(File) != -1) {
    506499      fread(&New.Next, sizeof(New.Next), 1, File);
    507       fread(New.Buffer, sizeof(char), HistSize, File);
     500      fread(New.Buffer, sizeof(char), New.HistSize, File);
    508501      fclose(File);
    509502        }
     
    516509  List.push_back(New);
    517510}
     511
     512
     513//
     514// Remove service from watch list
     515//
     516void DataHandler::RemoveService(string Name) {
     517
     518  // Find service index
     519  vector<struct Item>::iterator E;
     520  for (E=List.begin(); E<List.end(); ++E) if (Name == (*E).DataItem->getName()) {
     521        // Delete subscription first so handler and not called anymore
     522        delete (*E).DataItem;
     523
     524        // Save history buffer (replace '/' by '_')
     525    string Name = (*E).HistService->getName();
     526        for (int j=0; j<Name.size(); j++) if (Name[j] == '/') Name[j] = '_';
     527    FILE *File = fopen((HistDir + "/" + Name).c_str(), "wb");
     528        if (File != NULL) {
     529      fwrite(&(*E).Next, sizeof((*E).Next), 1, File);
     530      fwrite((*E).Buffer, sizeof(char), (*E).HistSize, File);
     531      fclose(File);
     532        }
     533       
     534        // Delete history service and free memory
     535        delete (*E).HistService;
     536    delete[] (*E).Buffer;
     537        List.erase(E);
     538  }
     539}
     540
    518541
    519542//
Note: See TracChangeset for help on using the changeset viewer.