Changeset 232 for Evidence/Evidence.cc


Ignore:
Timestamp:
06/30/10 08:48:02 (14 years ago)
Author:
ogrimm
Message:
Made Lock()/Unlock() public, automatic configuration tracking for Bridge
File:
1 edited

Legend:

Unmodified
Added
Removed
  • Evidence/Evidence.cc

    r231 r232  
    1717    These signals will then cause pause() to return which can be used
    1818        by the application to terminate gracefully.
    19   - The static method ToString() converts the contents of a DIMInfo service into text
     19  - The static method ToString() converts the contents of a DIM service into text
    2020  - A terminate-handler is installed for catching unhandled C++ exceptions.
    2121
     
    2727using namespace std;
    2828
    29 EvidenceServer *ThisServer;
    30 
    3129//
    3230// Internal configuration class of EvidenceServer
    3331//
    34 // Data that might be accessed by two threads are protected by mutex
    3532
    3633// Constructor
     
    3835
    3936  // Initialise
    40   int Ret;
    41   if ((Ret = pthread_mutex_init(&Mutex, NULL)) != 0) {
    42     ThisServer->Message(ThisServer->FATAL, "pthread_mutex_init() failed in Config constructor (%s)", strerror(Ret));
    43   }
    4437  CurrentItem = string();
    4538  ConfigTimeStamp = 0;
    46  
    47   // Signal delivered to this thread if configuration file changes
    4839  ThreadID = pthread_self();
    4940
     
    5647 
    5748  delete Service;
    58 
    59   int Ret;
    60   if ((Ret = pthread_mutex_destroy(&Mutex)) != 0) {
    61         ThisServer->Message(ThisServer->ERROR, "pthread_mutex_destroy() failed in Config destructor (%s)", strerror(Ret));
    62   }
    6349}
    6450
     
    6652void EvidenceServer::Config::infoHandler() {
    6753
    68   Lock();
     54  This->Lock();
    6955  ConfigTimeStamp = getInfo()->getInt();
    70   Unlock();
    71 
    72   if (pthread_kill(ThreadID, ThisServer->ConfigSignal) != 0) {
    73         ThisServer->Message(ThisServer->WARN, "Could not send signal to main thread");
     56  This->Unlock();
     57
     58  if (pthread_kill(ThreadID, This->ConfigSignal) != 0) {
     59        This->Message(WARN, "Could not send signal to main thread");
    7460  }
    7561}
     
    7864void EvidenceServer::Config::rpcInfoHandler(){
    7965
    80   Lock();
     66  This->Lock();
    8167  // Update map
    8268  List[CurrentItem].Value = string(getString(), getSize()-1);
     
    8470  // Clear to allow new rpc call
    8571  CurrentItem.clear();
    86   Unlock();
     72  This->Unlock();
    8773}
    8874
     
    9379
    9480  // If up-to-date data in configuration list available, return this
    95   Lock();
     81  This->Lock();
    9682  if ((List.count(Item) > 0) && (List[Item].Time >= ConfigTimeStamp)) Result = List[Item].Value;
    97   Unlock();
     83  This->Unlock();
    9884  if (!Result.empty()) return Result;
    9985
     
    10692        if (!EvidenceServer::ServiceOK(&Config)) {
    10793      if (Default.empty()) {
    108                 ThisServer->Message(ThisServer->FATAL, "Configuration server unreachable, can't retrieve '%s'", Item.c_str());
     94                This->Message(FATAL, "Configuration server unreachable, can't retrieve '%s'", Item.c_str());
    10995          }
    11096          else Result = Default;
     
    117103        // Update configuration map     
    118104        if (!Result.empty()) {
    119           Lock();
     105          This->Lock();
    120106          List[Item].Value = Result;
    121107          List[Item].Time = ConfigTimeStamp;
    122           Unlock();
     108          This->Unlock();
    123109        }       
    124110  }
    125111
    126   // Non-blocking configuration request fro other threads
     112  // Non-blocking configuration request from other threads
    127113  if (pthread_self() != ThreadID) {
    128         Lock();
     114        This->Lock();
    129115        if (List.count(Item) > 0) {
    130116          // New request possible only when answer to previous request received
     
    136122          // Return current value
    137123          Result = List[Item].Value;
    138           Unlock();
     124          This->Unlock();
    139125        }
    140126  }
    141127
    142128  return Result;
    143 }
    144 
    145 // Locking and unlocking for list access
    146 // Signal blocked before locking to avaoid dead-lock by calling GetConfig() from ConfigChanged().
    147 void EvidenceServer::Config::Lock() {
    148 
    149   int Ret = 0;
    150   sigset_t Set;
    151 
    152   if (ThisServer->ConfigSignal != 0) {
    153         Ret += abs(sigemptyset(&Set));
    154         Ret += abs(sigaddset(&Set, ThisServer->ConfigSignal));
    155         Ret += abs(pthread_sigmask(SIG_BLOCK, &Set, NULL));
    156   }
    157   Ret += abs(pthread_mutex_lock(&Mutex));
    158  
    159   if (Ret != 0) {
    160         ThisServer->Message(ThisServer->FATAL, "Thread related call failed in Config::Lock()");
    161   }
    162 }
    163 
    164 void EvidenceServer::Config::Unlock() {
    165 
    166   int Ret = 0;
    167   sigset_t Set;
    168 
    169   Ret += abs(pthread_mutex_unlock(&Mutex));
    170   if (ThisServer->ConfigSignal != 0) {
    171         Ret += abs(sigemptyset(&Set));
    172         Ret += abs(sigaddset(&Set, ThisServer->ConfigSignal));
    173         Ret += abs(pthread_sigmask(SIG_UNBLOCK, &Set, NULL));
    174   }
    175 
    176   if (Ret != 0) {
    177         ThisServer->Message(ThisServer->FATAL, "Thread related call failed in Config::Unlock()");
    178   }
    179129}
    180130
     
    185135
    186136int EvidenceServer::ConfigSignal = 0;
     137EvidenceServer *EvidenceServer::This = NULL;
    187138
    188139// Constructor starts server with given name
     
    193144  MessageData = NULL;
    194145  ExitRequest = false;
    195   ThisServer = this;
     146  This = this;
     147
     148  // Initialise mutex
     149  int Ret;
     150  pthread_mutexattr_t Attr;
     151
     152  if ((Ret = pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_ERRORCHECK)) != 0) {
     153    Message(FATAL, "pthread_mutex_settype() failed (%s)", strerror(Ret));
     154  }
     155  if ((Ret = pthread_mutex_init(&Mutex, &Attr)) != 0) {
     156    Message(FATAL, "pthread_mutex_init() failed (%s)", strerror(Ret));
     157  }
    196158
    197159  // Catch some signals
     
    225187  delete ConfClass;
    226188  delete MessageService;
    227   delete MessageData;
     189  delete[] MessageData;
     190 
     191  int Ret;
     192  if ((Ret = pthread_mutex_destroy(&Mutex)) != 0) {
     193        Message(ERROR, "pthread_mutex_destroy() failed (%s)", strerror(Ret));
     194  }
    228195}
    229196
     
    270237        MessageService->updateService(NewMsg, sizeof(struct Message)+strlen(NewMsg->Text)+1);
    271238  }
    272   delete MessageData;
     239  delete[] MessageData;
    273240  MessageData = NewMsg;
    274241
     
    311278}
    312279
    313 // Signal emitted when configuraton file changes, signal handler calls ConfigChanged()
     280
     281// Set signal emitted when configuraton file changes, signal handler calls ConfigChanged()
    314282void EvidenceServer::ActivateSignal(int Signal) {
    315283
     
    323291
    324292
     293// Locking and unlocking for list access
     294// Signal blocked before locking to avoid dead-lock by calling GetConfig() from ConfigChanged().
     295void EvidenceServer::Lock() {
     296
     297  int Ret;
     298  sigset_t Set;
     299
     300  if (ConfigSignal != 0) {
     301        Ret = abs(sigemptyset(&Set));
     302        Ret += abs(sigaddset(&Set, ConfigSignal));
     303        Ret += abs(pthread_sigmask(SIG_BLOCK, &Set, NULL));
     304
     305        if (Ret != 0) Message(FATAL, "Signal masking failed in Lock()");
     306  }
     307
     308  if ((Ret = pthread_mutex_lock(&Mutex)) != 0) {
     309        Message(FATAL, "pthread_mutex_lock() failed in Lock() (%s)", strerror(Ret));
     310  }
     311}
     312
     313void EvidenceServer::Unlock() {
     314
     315  int Ret;
     316  sigset_t Set;
     317
     318  if ((Ret = pthread_mutex_unlock(&Mutex)) != 0) {
     319        Message(FATAL, "pthread_mutex_unlock() failed in Unlock() (%s)", strerror(Ret));
     320  }
     321 
     322  if (ConfigSignal != 0) {
     323        Ret = abs(sigemptyset(&Set));
     324        Ret += abs(sigaddset(&Set, ConfigSignal));
     325        Ret += abs(pthread_sigmask(SIG_UNBLOCK, &Set, NULL));
     326
     327        if (Ret != 0) Message(FATAL, "Signal unmasking failed in Unlock()");
     328  }
     329}
     330
     331
    325332// ====== Static methods ======
    326333
     
    332339  // If signal indicates configuration change, invoke call-back
    333340  if (Signal == EvidenceServer::ConfigSignal) {
    334     ThisServer->ConfigChanged();
     341    This->ConfigChanged();
    335342        return;
    336343  }
     
    339346  if (!Called) {
    340347        Called = true;
    341         ThisServer->ExitRequest = true;
     348        This->ExitRequest = true;
    342349        return;
    343350  }
    344351
    345352  // If invoked twice, call exit()
    346   ThisServer->Message(ThisServer->WARN, "Signal handler called again, invoking exit() (signal %d)", Signal);
     353  This->Message(WARN, "Signal handler called again, invoking exit() (signal %d)", Signal);
    347354  exit(EXIT_FAILURE);
    348355}
     
    355362
    356363  if (Terminating) {
    357         Msg << ThisServer->Name << ": Terminate() called recursively, calling abort()";
     364        Msg << This->Name << ": Terminate() called recursively, calling abort()";
    358365        printf("%s\n", Msg.str().c_str());
    359         ThisServer->SendToLog(Msg.str().c_str());
     366        This->SendToLog(Msg.str().c_str());
    360367        abort();
    361368  }
     
    383390  else Msg << "Terminate() called without an active exception";
    384391
    385   ThisServer->Message(FATAL, Msg.str().c_str());
    386 }
    387 
    388 
    389 // Translates DIMInfo safely to string (assures no inivalid memory accesses are made)
    390 string EvidenceServer::ToString(DimInfo *I) {
     392  This->Message(FATAL, Msg.str().c_str());
     393}
     394
     395
     396// Translates DIM data safely to string (assures no invalid memory accesses are made)
     397string EvidenceServer::ToString(char *Format, void *Data, int Size) {
    391398
    392399  ostringstream Text;
    393400 
    394   // Safety check
    395   if (I->getSize() < 1) return string();
    396 
    397401  // 'Message' service format handled here
    398   if (strcmp(I->getFormat(), "I:1;C") == 0 && I->getSize()>=(int) sizeof(struct Message)) {
    399         struct Message *Msg = (struct Message *) I->getData();
     402  if (strcmp(Format, "I:1;C") == 0 && Size >= (int) sizeof(struct Message)) {
     403        struct Message *Msg = (struct Message *) Data;
    400404        // Safely extract string and limit to length of C string (padding might make it longer)
    401         string MsgText(Msg->Text, I->getSize()-sizeof(struct Message));
    402     //MsgText.erase(strlen(MsgText.c_str()));
     405        string MsgText(Msg->Text, Size-sizeof(struct Message));
    403406        Text << Msg->Severity << " " << MsgText.erase(strlen(MsgText.c_str()));
    404407
     
    407410 
    408411  // Structure: print hex representation
    409   if (strlen(I->getFormat()) != 1) {
    410         for (int i=0; i<I->getSize(); i++) {
    411           Text << setw(2) << hex << *((char *) I->getData() + i) << " ";
     412  if (strlen(Format) != 1) {
     413        for (int i=0; i<Size; i++) {
     414          Text << setw(2) << hex << *((char *) Data + i) << " ";
    412415        }
    413416        return Text.str();
     
    415418
    416419  // String if format "C" and terminated with \0
    417   if (strcmp(I->getFormat(),"C")==0 && *((char *) I->getData()+I->getSize()-1)=='\0') { 
    418     Text << I->getString();
    419         return Text.str();
     420  if (strcmp(Format, "C") == 0 && Size > 0 && *((char *) Data+Size-1)=='\0') {
     421        return string((char *) Data);
    420422  }
    421423
    422424  // Number array
    423   int Size;
    424   switch (*(I->getFormat())) {
    425     case 'C': Size = sizeof(char);              break;
     425  int ElementSize;
     426  switch (*Format) {
     427    case 'C': ElementSize = sizeof(char);               break;
    426428    case 'I':
    427     case 'L': Size = sizeof(int);               break;
    428     case 'S': Size = sizeof(short);             break;
    429     case 'F': Size = sizeof(float);             break;
    430     case 'D': Size = sizeof(double);    break;
    431     case 'X': Size = sizeof(long long); break;
     429    case 'L': ElementSize = sizeof(int);                break;
     430    case 'S': ElementSize = sizeof(short);              break;
     431    case 'F': ElementSize = sizeof(float);              break;
     432    case 'D': ElementSize = sizeof(double);             break;
     433    case 'X': ElementSize = sizeof(long long);  break;
    432434    default: return string();
    433435  }
    434436
    435   for (int i=0; i<I->getSize()/Size; i++) {
     437  for (int i=0; i<Size/ElementSize; i++) {
    436438        // Space between entries
    437439    if (i != 0) Text << " ";
    438440
    439441        // Translate data
    440         switch (*(I->getFormat())) {
    441       case 'C': Text << *((char *) I->getData() + i);
    442                                 break;
     442        switch (*Format) {
     443      case 'C': Text << *((char *) Data + i);           break;
    443444      case 'I':
    444       case 'L': Text << *((int *) I->getData() + i);
    445                                 break;
    446       case 'S': Text << *((short *) I->getData() + i);
    447                                 break;
    448       case 'F': Text << *((float *) I->getData() + i);
    449                                 break;
    450       case 'D': Text << *((double *) I->getData() + i);
    451                                 break;
    452       case 'X': Text << *((long long *) I->getData() + i);
    453                                 break;
     445      case 'L': Text << *((int *) Data + i);            break;
     446      case 'S': Text << *((short *) Data + i);          break;
     447      case 'F': Text << *((float *) Data + i);          break;
     448      case 'D': Text << *((double *) Data + i);         break;
     449      case 'X': Text << *((long long *) Data + i);      break;
    454450        }
    455451  }
Note: See TracChangeset for help on using the changeset viewer.