Changeset 159 for Evidence/DColl.cc


Ignore:
Timestamp:
02/04/10 15:26:55 (14 years ago)
Author:
ogrimm
Message:
Change in history handling
File:
1 edited

Legend:

Unmodified
Added
Removed
  • Evidence/DColl.cc

    r152 r159  
    3838#include <regex.h>
    3939
     40using namespace std;
     41
    4042//
    4143// Class declaration
     
    4749          DimStampedInfo *DataItem;
    4850      DimService *HistService;
    49           struct EvidenceHistoryItem *HistBuffer;
    50           int HistPointer;
     51          char *Buffer;
     52          int Next;
    5153          double LastValue;
    5254          double MinAbsChange;
     
    101103  // Request configuration data
    102104  char *Change = GetConfig(SERVER_NAME " minchange");
    103 
    104105  DataDir = GetConfig(SERVER_NAME " datadir");
    105 
    106106  char *Logname = GetConfig(SERVER_NAME " logfile");
    107 
    108107  SizeUpdateDelay = atoi(GetConfig(SERVER_NAME " sizeupdate"));
    109 
    110108  HistSize = atoi(GetConfig(SERVER_NAME " histsize"));
    111   if (HistSize < 1) HistSize = 1; // Minimum one items
    112 
     109  if (HistSize < 3*sizeof(int)) HistSize = 3*sizeof(int);
    113110  HistDir = GetConfig(SERVER_NAME " histdir");
    114111   
     
    163160  // Subscribe to list of servers at DIS_DNS
    164161  AddService("DIS_DNS/SERVER_LIST");
    165 
    166   DimClient::sendCommand("DColl/Log", SERVER_NAME" *** Logging started ***");
    167162}
    168163
     
    171166//
    172167DataHandler::~DataHandler() {
    173 
    174   DimClient::sendCommand("DColl/Log", SERVER_NAME" *** Logging stopped ***");
    175168
    176169  // Delete DIM subscriptions and command first so handlers and not called anymore
     
    179172  }
    180173  delete LogCommand;
    181  
     174
    182175  // Save history buffers to files (replace '/' by '_')
     176  State(INFO, "Writing history buffers to files");
     177
    183178  for (int i=0; i<List.size(); i++) {
    184179    string Name = List[i].HistService->getName();
     
    186181    FILE *File = fopen((HistDir + "/" + Name).c_str(), "wb");
    187182        if (File != NULL) {
    188       fwrite(&List[i].HistPointer, sizeof(List[i].HistPointer), 1, File);
    189       fwrite(List[i].HistBuffer, sizeof(EvidenceHistoryItem), HistSize, File);
     183      fwrite(&List[i].Next, sizeof(List[i].Next), 1, File);
     184      fwrite(List[i].Buffer, sizeof(char), HistSize, File);
    190185      fclose(File);
    191186        }
    192187        delete List[i].HistService;
    193     delete[] List[i].HistBuffer;
     188    delete[] List[i].Buffer;
    194189  }
    195190
     
    223218void DataHandler::infoHandler() {
    224219
     220  static const int WrapMark[] = {0, -1};
     221  static const int EndMark[] = {0, 0};
     222
    225223  DimInfo *Info = getInfo();
    226224
    227225  // Check if service available
    228   if (Info->getSize()==strlen(NO_LINK)+1 && strcmp(Info->getString(), NO_LINK)==0) return;
    229 
     226  if (!ServiceOK(Info)) return;
     227
     228  //
     229  // ====== Part A: Handle service subscriptions ===
     230  //
     231 
    230232  // If service is DIS_DNS/SERVER_LIST, subscribe to all SERVICE_LIST services
    231233  if (strcmp(Info->getName(), "DIS_DNS/SERVER_LIST") == 0) {   
     
    259261  }
    260262
     263  //
     264  // ====== Part B: Handle opening data files ===
     265  //
     266
    261267  // If it is time to open new data file, close the current one
    262268  if (time(NULL) >= TimeForNextFile) {
     
    296302        TimeForNextFile = mktime(T);
    297303  }
    298    
     304
     305  //
     306  // ====== Part C: Handle writing to data file ===
     307  //
     308
    299309  // Identify index of service
    300   int Service; 
     310  int Service;
    301311  for (Service=0; Service<List.size(); Service++) if (Info == List[Service].DataItem) break;
    302312  if (Service == List.size()) return;  // Service not found
    303313
    304   // If negative value for absolute change, ignore this entry
    305   if (List[Service].MinAbsChange < 0) return;
     314  // If negative value for absolute change, do not write to file
     315  if (List[Service].MinAbsChange >= 0) {
    306316
    307317  // Write data header
     
    313323  // Translate data into ASCII
    314324  char *Text = EvidenceServer::ToString(Info);
     325
    315326  if (Text != NULL) {
    316327        // Replace all control characters by white space
     
    320331    fprintf(DataFile, "%s\n", Text);
    321332       
    322         // Add to history buffer if change large enough
    323         if ((fabs(atof(Text)-List[Service].LastValue) > List[Service].MinAbsChange)) {
    324           List[Service].HistBuffer[List[Service].HistPointer].Seconds = Info->getTimestamp();
    325       List[Service].HistBuffer[List[Service].HistPointer].Value = atof(Text);
    326       List[Service].HistService->updateService();
    327           List[Service].HistPointer++;
    328           if (List[Service].HistPointer >= HistSize) List[Service].HistPointer = 0;
    329           List[Service].LastValue = atof(Text);
    330         }
    331333        free(Text);
    332334  }
    333335  else fprintf(DataFile, "Cannot interpret format identifier\n");
    334336 
    335   fflush(DataFile);
    336 
    337337  // Terminate if error because otherwise infinite loop might result as
    338338  // next call to this infoHandler() will try to (re-)open file
     
    343343  }
    344344
    345   // Update datafile size service
     345  // Update datafile size service (not every time to avoid infinite loop)
    346346  if (time(NULL) - DataSizeLastUpdate > SizeUpdateDelay) {
     347    fflush(DataFile); // not continuously to reduce load
     348
    347349        DataSizekB = FileSize(DataFile);
    348350        DataSizeService->updateService();
    349351        DataSizeLastUpdate = time(NULL);
    350352  }
     353 
     354  } // Check for MinAbsChange
     355
     356  //
     357  // ====== Part D: Handle history service ===
     358  //
     359 
     360  if (Info->getSize() == 0) return;
     361 
     362  // Check if data should be added to history buffer
     363  char *Text = EvidenceServer::ToString(Info);
     364  if (Text != NULL && strcmp(Info->getFormat(),"C") != 0
     365          && fabs(atof(Text)-List[Service].LastValue) < fabs(List[Service].MinAbsChange)) {
     366        free(Text);
     367        return;
     368  }
     369  free(Text);
     370
     371  // Check if data fits into buffer
     372  if (HistSize < Info->getSize() + 5*sizeof(int)) return;
     373
     374  int Size = Info->getSize() + 4*sizeof(int), Next = List[Service].Next;
     375  void *WrapPos = NULL;
     376  char *Buffer = List[Service].Buffer;
     377  int Oldest = *(int *) Buffer;
     378
     379  // Check if buffer wrap-around (write wrap mark after Oldest is adjusted)
     380  if (Next + Size >= HistSize) {
     381    WrapPos = Buffer + Next;
     382    Next = 4;
     383  }
     384
     385  // Adapt pointer to oldest entry
     386  while ((Oldest < Next + Size) &&
     387                 (Oldest + *((int *) (Buffer + Oldest) + 1) + 2*sizeof(int) > Next)) {
     388        // Check for wrap-around
     389        if (memcmp(Buffer + Oldest, WrapMark, sizeof(WrapMark)) == 0) {
     390          Oldest = 4;
     391          continue;
     392        }
     393        // Check if end marker reached, then only one event fits buffer
     394        if (memcmp(Buffer + Oldest, EndMark, sizeof(EndMark)) == 0) {
     395          Oldest = Next;
     396          break;
     397        }
     398        // Move to next entry
     399    Oldest += *((int *) (Buffer + Oldest) + 1) + 2*sizeof(int);
     400  }
     401  // Update pointer in buffer
     402  *(int *) Buffer = Oldest;
     403
     404  // Write wrap mark if necessary
     405  if (WrapPos != NULL) memcpy(WrapPos, WrapMark, sizeof(WrapMark));
     406
     407  // Copy data into ring buffer
     408  *((int *) (Buffer + Next)) = Info->getTimestamp();
     409  *((int *) (Buffer + Next + sizeof(int))) = Info->getSize();
     410  memcpy(Buffer + Next + 2*sizeof(int), Info->getData(), Info->getSize());
     411
     412  // Adjust pointer for next entry and write end marker to buffer
     413  Next += Info->getSize() + 2*sizeof(int);
     414  memcpy(Buffer + Next, EndMark, sizeof(EndMark));
     415 
     416  List[Service].Next = Next;
    351417}
    352418
     
    403469  }
    404470 
    405   // Create new entry in item list
    406471  struct Item New;
    407472
     
    413478        }
    414479  }
    415                
     480
    416481  // Create history service
    417   New.HistBuffer = new struct EvidenceHistoryItem [HistSize];
    418   memset(New.HistBuffer, 0, HistSize*sizeof(EvidenceHistoryItem));
    419   New.HistPointer = 0;
     482  New.Buffer = new char [HistSize];
     483  memset(New.Buffer, 0, HistSize);
     484  *(int *) New.Buffer = 4;
     485  New.Next = 4;
    420486  New.LastValue = DBL_MAX;
    421487  New.HistService = new DimService ((Name+".hist").c_str(), (char *) "C",
    422                                           New.HistBuffer, HistSize*sizeof(EvidenceHistoryItem));
    423        
     488                                          New.Buffer, HistSize);
     489
    424490  // Load history buffer from file if existing
    425491  string Filename = New.HistService->getName();
     
    427493  FILE *File = fopen((HistDir + "/" + Filename).c_str(), "rb");
    428494  if (File != NULL) {
    429     fread(&New.HistPointer, sizeof(New.HistPointer), 1, File);
    430     fread(New.HistBuffer, sizeof(EvidenceHistoryItem), HistSize, File);
    431     fclose(File);
     495    // Only load if current buffer size if equal or larger
     496    if (FileSize(File) <= HistSize*sizeof(char)+sizeof(New.Next) && FileSize(File) != -1) {
     497      fread(&New.Next, sizeof(New.Next), 1, File);
     498      fread(New.Buffer, sizeof(char), HistSize, File);
     499      fclose(File);
     500        }
    432501  }
    433502 
Note: See TracChangeset for help on using the changeset viewer.