Changeset 12910 for fact/Evidence


Ignore:
Timestamp:
02/20/12 22:04:50 (13 years ago)
Author:
ogrimm
Message:
EvidenceServer::ToString() can handle all DIM formats as long as padding is disabled
Location:
fact/Evidence
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • fact/Evidence/DColl.cc

    r11205 r12910  
    393393//
    394394int main() {
     395
     396  dic_disable_padding();
     397  dis_disable_padding();
    395398       
    396399  // Static ensures calling of destructor by exit()
  • fact/Evidence/Doc/Evidence.tex

    r10996 r12910  
    185185The methods \underline{\lstinline{Lock()}} and \underline{\lstinline{Unlock()}} work on an internal mutex.\footnote{Its type is \lstinline{PTHREAD_MUTEX_ERRORCHECK}. In case an already locked mutex is re-locked, the corresponding system call will therefore return a error and thus avoid dead-locking. Error messages from \lstinline{Lock()} and \lstinline{Unlock()} are written to the console and to the log file. They are not published using \lstinline{Message()} since this method itself uses locking and calling it would result in an infinite recursion.} They are used by \lstinline{GetConfig()} but are also available for the user application to serialize access from multiple threads. Calling functions in the locked state should be avoided as it might result in re-locking.
    186186
    187 The static method \underline{\lstinline{ToString()}} translates the contents of a DIM service safely into a string that is returned. As no consistency between a service format and the contained data is guaranteed by DIM, precautions are necessary to avoid buffer overruns. The method currently handles the standardized message format \lstinline{"I:1;C"}, arrays of numbers and strings. All other formats are translated into a hex representation. The arguments are the DIM service format, a pointer to the service data and the data size in bytes. It is thread safe as it uses only the arguments and dynamically allocated storage.
     187The static method \underline{\lstinline{ToString()}} translates the contents of a DIM service safely into a string that is returned. As no consistency between a service format and the contained data is guaranteed by DIM, precautions are necessary to avoid buffer overruns. The method handles all DIM formats, as long as padding is disabled in DIM. The arguments are the DIM service format, a pointer to the service data and the data size in bytes. It is thread safe as it uses only the arguments and dynamically allocated storage. A format entry \lstinline{C} with no length indication is treated as a string, all other as numbers.
    188188
    189189The static methods \underline{\lstinline{ServiceOK()}} take a pointer to a received service update or result of a remote procedure call (as available in the respective handlers) and safely checks if its contents is identical to the constant \lstinline{NO_LINK}. If so, they return false. If using the same constant in the service declaration, this provides a safe way of being informed if a particular service becomes unavailable. Then, the handler is called once for that service with the data content \lstinline{NO_LINK}.
     
    298298\multicolumn{2}{l}{\lstinline|History <Directory for storing history buffers>|} \\[1ex]
    299299\multicolumn{2}{l}{\textbf{Configuration section \lstinline|[History]|}} \\
    300 \lstinline|minchange| & Minimum absolute change necessary for a service to be added to the history buffer. The format is \lstinline|ServiceName:MinChange|. This is only meaningful for services that represent numbers or number arrays. For an array, the difference of the sum of the absolute values of all elements is compared to \lstinline|MinChange|.\\
     300\lstinline|minchange| & Minimum absolute change of a value or of the average of a range of values necessary for adding to the history buffer. This can extend the time reach of the ring buffer by avoiding noise entries. The format is \lstinline|ServiceName:MinChange| or \lstinline|ServiceName:IndexRange:MinChange|, where \lstinline|IndexRange| can be a single number of in the form a-b.\\
    301301\lstinline|maxsize_kb| & Maximum size of a single history buffer in kByte. Default value is 2000.\\
    302302\lstinline|numentries| & Numer of entries that a history buffer should hold, provided its size does not exceed the defined maximum. Default value is 1000. For DIM services of varying size, buffer sizes are recalculated at each update and never shrink.\\
  • fact/Evidence/Evidence.cc

    r12894 r12910  
    103103  This = this;
    104104
     105  dis_disable_padding();
     106  dic_disable_padding();
     107 
    105108  // Initialise mutex
    106109  int Ret;
     
    407410
    408411// Translates DIM data safely to string (assures no invalid memory accesses are made)
    409 string EvidenceServer::ToString(char *Format, void *Data, int Size) {
     412// Structure evaluation requires that no padding is used
     413string EvidenceServer::ToString(char *Format, const void *Data, int Size) {
    410414
    411415  ostringstream Text;
    412  
    413   // 'Message' service format handled here
    414   if (strcmp(Format, "I:1;C") == 0 && Size >= (int) sizeof(struct Message)) {
    415         struct Message *Msg = (struct Message *) Data;
    416         // Safely extract string and limit to length of C string (padding might make it longer)
    417         string MsgText(Msg->Text, Size-sizeof(struct Message));
    418         Text << Msg->Severity << " " << MsgText.erase(strlen(MsgText.c_str()));
    419 
    420         return Text.str();
    421   }
    422 
    423   // String if format "C" and terminated with \0
    424   if (strcmp(Format, "C") == 0 && Size > 0 && *((char *) Data+Size-1)=='\0') {
    425         return string((char *) Data);
    426   }
    427  
    428   // Check if format is made of identical component types
    429   vector<string> Components = Tokenize(Format, ";");
    430  
    431   for (unsigned int i=0; i<Components.size(); i++) {
    432         if (Components[i].empty()) return string();
    433 
    434         // Print hex representation if format complex
    435         if (Components[i][0] != Components[0][0]) {
    436           for (int i=0; i<Size; i++) {
    437                 Text << setw(2) << hex << *((char *) Data + i) << " ";
    438           }
    439           return Text.str();
    440         }
    441   }
    442  
    443   // Number array
    444   int ElementSize;
    445 
    446   switch (toupper(*Format)) {
    447     case 'B':
    448         case 'V':
    449     case 'C': ElementSize = sizeof(char);               break;
    450     case 'I':
    451     case 'L': ElementSize = sizeof(int);                break;
    452     case 'S': ElementSize = sizeof(short);              break;
    453     case 'F': ElementSize = sizeof(float);              break;
    454     case 'D': ElementSize = sizeof(double);             break;
    455     case 'X': ElementSize = sizeof(long long);  break;
    456     default: return string();
    457   }
    458 
    459   for (int i=0; i<Size/ElementSize; i++) {
    460         // Space between entries
    461     if (i != 0) Text << " ";
    462 
    463         // Translate data
    464         switch (toupper(*Format)) {
     416  vector<string> Components;
     417  int ElementSize, N, Byte = 0;
     418
     419  // Find component types
     420  Components = Tokenize(Format, ";");
     421 
     422  for (unsigned int n=0; n<Components.size(); n++) {
     423    // If empty, format error
     424        if (Components[n].empty()) return string();
     425
     426        // Determine maximum number of elements
     427        if (Components[n].size() > 2) N = atoi(Components[n].c_str()+2);
     428        else N = numeric_limits<int>::max();
     429
     430        // Determine length in bytes of elements
     431        switch (toupper(Components[n][0])) {
    465432          case 'B':
    466433          case 'V':
    467       case 'C': Text << *((char *) Data + i);           break;
    468       case 'I':
    469       case 'L': Text << *((int *) Data + i);            break;
    470       case 'S': Text << *((short *) Data + i);          break;
    471       case 'F': Text << *((float *) Data + i);          break;
    472       case 'D': Text << *((double *) Data + i);         break;
    473       case 'X': Text << *((long long *) Data + i);      break;
     434          case 'C': ElementSize = sizeof(char);                 break;
     435          case 'I':
     436          case 'L': ElementSize = sizeof(int);                  break;
     437          case 'S': ElementSize = sizeof(short);                break;
     438          case 'F': ElementSize = sizeof(float);                break;
     439          case 'D': ElementSize = sizeof(double);               break;
     440          case 'X': ElementSize = sizeof(long long);    break;
     441          default: return string();
    474442        }
    475   }
    476  
     443
     444        // Covert elements
     445        for (int i=0; i<N; i++) {       
     446          // Check that not overrunning memory
     447          if (Byte + ElementSize > Size) return Text.str();
     448         
     449          // Translate elements into text (handle string specially when format is 'C')
     450          switch (toupper(Components[n][0])) {
     451        case 'C': if (Components[n].size() == 1) {
     452                                        string String((char *) Data, Size-Byte);
     453                                       
     454                                        // Remove trailing '\0'
     455                                        if (!String.empty() && String[String.size()-1] == '\0') String.resize(String.size()-1);
     456                                       
     457                                        Text << String;
     458                                        return Text.str();
     459                                  }
     460                                  Text << *((char *) Data);
     461                                  break;
     462                case 'B':
     463                case 'V': Text << *((char *) Data);
     464                                  break;
     465        case 'I':
     466        case 'L': Text << *((int *) Data);
     467                                  break;
     468        case 'S': Text << *((short *) Data);
     469                                  break;
     470        case 'F': Text << *((float *) Data);
     471                                  break;
     472        case 'D': Text << *((double *) Data);
     473                                  break;
     474        case 'X': Text << *((long long *) Data);
     475                              break;
     476          }
     477
     478          Byte += ElementSize;
     479          Data = (void *) ((char *) Data + ElementSize);
     480
     481          // Space between entries
     482          Text << " ";
     483        }
     484  }
    477485  return Text.str();
    478486}
  • fact/Evidence/Evidence.h

    r12892 r12910  
    1111#include <map>
    1212#include <set>
     13#include <limits>
    1314
    1415#include <exception>
     
    7980        static void Lock();
    8081        static void Unlock();
    81         static std::string ToString(char *, void *, int);
     82        static std::string ToString(char *, const void *, int);
    8283        static bool ServiceOK(DimInfo *);
    8384        static bool ServiceOK(DimRpcInfo *);
  • fact/Evidence/GUI.cc

    r12894 r12910  
    2929  if (strcmp(Service, "Edd/Rate_kBSec") == 0) Format = "F";
    3030  else if (Hist == NULL || Hist->GetFormat() == NULL) {
    31         //QMessageBox::warning(NULL, "Edd Message", QString("Could not retrieve history for service ") + Service ,QMessageBox::Ok);
    3231        printf("Edd Message: Could not retrieve history for service %s\n", Service);
    3332  }
     
    4948  QGridLayout *Layout = new QGridLayout(M->centralWidget());
    5049 
    51   if (Format.size() == 1 && Format[0] == 'C') Layout->addWidget(new EddText(Service), 0, 0);
     50  if (Format.endsWith('C', Qt::CaseInsensitive)) Layout->addWidget(new EddText(Service), 0, 0);
    5251  else  {
    5352    EddPlot *W = new EddPlot(Service, FromIndex);
     
    387386        double Number=0;
    388387        while ((R=Hist->Next()) != NULL) {
    389           switch (*(Hist->GetFormat())) {
    390         case 'I':
    391                 case 'L':  Number = *((int *) R->Data + N.Index);   break;
    392         case 'S':  Number = *((short *) R->Data + N.Index);   break;
    393         case 'F':  Number = *((float *) R->Data + N.Index);   break;
    394         case 'D':  Number = *((double *) R->Data + N.Index);   break;
    395         case 'X':  Number = *((long long *) R->Data + N.Index);   break;
    396         default: break;
    397           }
     388          std::vector<std::string> Data = EvidenceServer::Tokenize(EvidenceServer::ToString(Hist->GetFormat(), R->Data, R->Size));
     389          if (N.Index > 0 && N.Index < (int) Data.size()) Number = atof(Data[N.Index].c_str());
    398390          AddPoint(List.size()-1, R->Time, Number);
    399391        }
  • fact/Evidence/History.cc

    r12909 r12910  
    426426  }
    427427
     428  dic_disable_padding();
     429  dis_disable_padding();
     430
    428431  // Static ensures calling of destructor by exit()
    429432  static History Hist(argv[1]);
  • fact/Evidence/readme.txt

    r12909 r12910  
    6060                        into account (e.g. Service:a-b:0.4 requires an minimum absolute change of 0.4 for the average
    6161                        value of indices a to b)
     6220/2/2012       Disabled padding per default in Evidence class constructor, and also in History and DColl
     63                        servers. EvidenceServer::ToString() can because of this now handle all format strings.
Note: See TracChangeset for help on using the changeset viewer.