Changeset 253 for Evidence


Ignore:
Timestamp:
07/20/10 12:34:13 (14 years ago)
Author:
ogrimm
Message:
Added command ResetAlarm, Evidence servers now always safely translate a DIM string into a C string, added documentation, replaced several vectors my maps
Location:
Evidence
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • Evidence/Alarm.cc

    r229 r253  
    3636        char *AlarmText;
    3737        int MasterAlarm;
    38         pthread_mutex_t Mutex;
    3938
    4039    void infoHandler();
     
    6867  AlarmText = NULL;
    6968 
    70   if (pthread_mutex_init(&Mutex, NULL) != 0) {
    71     Message(FATAL, "pthread_mutex_init failed");
    72   }
    73 
    7469  // Handling of servies will only start after start()
    7570  autoStartOff();
     
    10297
    10398  // Provide command to reset Level   
    104   Command = new DimCommand("Alarm/ResetAlarm", (char *) "C", this);
     99  Command = new DimCommand("ResetAlarm", (char *) "C", this);
    105100 
    106101  // List set up, can start handling
     
    121116  delete Summary;
    122117  delete[] AlarmText;
    123  
    124   pthread_mutex_destroy(&Mutex);
    125118}
    126119
     
    143136void AlarmHandler::commandHandler() {
    144137
    145   DimCommand *C = getCommand();
    146 
    147   // Check for valid command parameter
    148   if (C != Command) return;
    149   if (C->getSize() == 0) return;
    150   if (*((char *) C->getData() + C->getSize() - 1) != '\0') return;
     138  // Safety check
     139  string Server = ToString((char *) "C", getCommand()->getData(), getCommand()->getSize());
     140  if (getCommand() != Command || Server.empty()) return;
    151141 
    152142  // Reset alarm level and publish/log action
    153   for (int i=0; i<List.size(); i++) if (List[i].Server == C->getString()) {
    154     Message(INFO, "Alarm level of server %s reset by %s (ID %d)", C->getString(), getClientName(), getClientId());
     143  for (int i=0; i<List.size(); i++) if (List[i].Server == Server) {
     144    Message(INFO, "Alarm level of server %s reset by %s (ID %d)", Server.c_str(), getClientName(), getClientId());
    155145        List[i].Level = 0;
    156146        List[i].WarnedLevel = 0;
     
    161151
    162152
    163 // Update alarm status summary
     153// Update alarm status summary (locking since access can be from main thread and DIM handler threads)
    164154void AlarmHandler::UpdateAlarmSummary() {
    165155
     
    167157  int Alarm, Ret; 
    168158
    169   // Lock because access can be from main thread and DIM handler thread
    170   if ((Ret = pthread_mutex_lock(&Mutex)) != 0) {
    171         Message(FATAL, "pthread_mutex_lock() failed (%s)", strerror(Ret));
    172   }
    173  
     159  Lock();
     160
    174161  for (int i=0; i<List.size(); i++) {
    175162        // Alarm level description
     
    211198  AlarmText = Tmp;
    212199 
    213   // Unlock
    214   if ((Ret = pthread_mutex_unlock(&Mutex)) != 0) {
    215         Message(FATAL, "pthread_mutex_unlock() failed (%s)", strerror(Ret));
    216   }
     200  Unlock();
    217201}
    218202
  • Evidence/Bridge.cc

    r232 r253  
    6464  GetConfig("cmdallow", " ");
    6565  ActivateSignal(SIGUSR2);
     66 
     67  ConfigChanged();
    6668}
    6769
     
    8486
    8587
    86 // Called by signal handler in case configuration changes (also initially)
     88// Called by signal handler in case configuration changes and by constructor
    8789void Bridge::ConfigChanged() {
    8890
  • Evidence/Config.cc

    r229 r253  
    77    "Config/ModifyTime" contains the last modification UNIX time.
    88  - The contents of the configuration file is available through Config/ConfigData.
    9   - The current parser removes all tabs, multiple, leading and trailing spaces, and
    10     concatenates lines ending with '+'.
     9  - The parser removes all tabs, multiple, leading and trailing spaces, and
     10    concatenates all lines until the next item.
    1111
    1212  A mutex is used for preventing concurrent access to the configuration data from
    1313  the methods rpcHandler() and ConfigChanged().
    1414         
    15   Oliver Grimm, April 2010
     15  Oliver Grimm, July 2010
    1616
    1717\********************************************************************/
    1818
    19 #define DEFAULT_CONFIG "../config/Evidence.conf"
    2019#define SERVER_NAME "Config"
    2120
     
    3534
    3635  private:
    37         struct Item {
    38           string Name;
    39           string Data;
    40         };
    41         vector<struct Item> List;
    42 
     36        map<string, string> Map;
    4337    FILE *File;
    4438        char *FileContent;
    4539    DimService *ConfigModified;
    4640        DimService *ConfigContent;
    47     pthread_mutex_t Mutex;
    4841
    4942    void rpcHandler();
     
    6760  FileContent = NULL;
    6861
    69   // Signaling interferes with inotify() mechnism
    70   signal(SIGUSR2, SIG_IGN);
    71  
    72   // Initialise mutex (errno is not set by pthread_mutex_init())
    73   if (pthread_mutex_init(&Mutex, NULL) != 0) {
    74     Message(FATAL, "pthread_mutex_init() failed");
    75   }
    76 
    7762  // Open configuration file
    7863  if ((File = fopen(Filename, "r")) == NULL) {
     
    9782  delete ConfigContent;
    9883  delete[] FileContent;
    99 
    100   if (pthread_mutex_destroy(&Mutex) != 0) Message(ERROR, "pthread_mutex_destroy() failed");
    10184}
    10285
     
    10588void EvidenceConfig::rpcHandler() {
    10689
    107   string Response;
    108  
    109   // Lock because ConfigChange() might access concurrently
    110   if (pthread_mutex_lock(&Mutex) != 0) Message(ERROR, "pthread_mutex_lock() failed in rpcHandler()");
    111 
     90  string Response, Item = ToString((char *) "C", getData(), getSize());
     91 
    11292  // Search for config data in list (default response is empty string)
    113   for (int i=0; i<List.size(); i++) {
    114     if (List[i].Name == getString()) Response = List[i].Data;
    115   }
    116  
    117   // Unlock
    118   if (pthread_mutex_unlock(&Mutex) != 0) Message(ERROR, "pthread_mutex_unlock() failed in rpcHandler()");
     93  // Lock because ConfigChange() might also access concurrently
     94  Lock();
     95  if (Map.count(Item) != 0) Response = Map[Item];
     96  Unlock();
    11997
    12098  // Send data and update Status
     
    122100   
    123101  Message(INFO, "Client '%s' (ID %d) requested '%s'. Send '%s'.",
    124                 DimServer::getClientName(),
    125                 DimServer::getClientId(),
    126                 getString(), Response.c_str());
     102                DimServer::getClientName(),     DimServer::getClientId(),
     103                Item.c_str(), Response.c_str());
    127104}
    128105
     
    227204  if (Section.empty() || Parameter.empty() || Data.empty()) return;
    228205
    229   // Prepare new item of configuration list
    230   struct Item New;
    231   New.Name = Section + ' ' + Parameter;
    232   New.Data = Data;
    233 
    234206  // Add to configuration list
    235   if (pthread_mutex_lock(&Mutex) != 0) Message(ERROR, "pthread_mutex_lock() failed in ConfigChanged()");
    236   List.push_back(New);
    237   if (pthread_mutex_unlock(&Mutex) != 0) Message(ERROR, "pthread_mutex_unlock() failed in ConfigChanged()");
     207  Lock();
     208  Map[Section + " " + Parameter] = Data;
     209  Unlock();
    238210}
    239211
     
    255227//
    256228int main(int argc, char *argv[]) {
    257        
    258   static EvidenceConfig Config(argc<2 ? DEFAULT_CONFIG : argv[1]);
    259 
     229
     230  if (argc != 2) {
     231        printf("Usage: %s <Configuration-File>\n", argv[0]);
     232        exit(EXIT_FAILURE);
     233  }
     234 
     235  static EvidenceConfig Config(argv[1]);
    260236  int Notify;
    261237  struct inotify_event Event;
     
    264240    Config.Message(EvidenceConfig::WARN, "inotify_init() failed, cannot monitor changes of configuration file (%s)\n", strerror(errno));
    265241  }
    266   else if (inotify_add_watch(Notify, argc<2 ? DEFAULT_CONFIG : argv[1], IN_MODIFY) == -1) {
     242  else if (inotify_add_watch(Notify, argv[1], IN_MODIFY) == -1) {
    267243      Config.Message(EvidenceConfig::WARN, "Could not set inotify watch on configuration file (%s)\n", strerror(errno));
    268244          close(Notify);
  • Evidence/DColl.cc

    r232 r253  
    274274      fprintf(DataFile, "%s\n", Text.c_str());
    275275        }
    276         else fprintf(DataFile, "Cannot interpret format identifier\n");
     276        else fprintf(DataFile, "Cannot interpret service format\n");
    277277
    278278        // Terminate if error because otherwise infinite loop might result as
    279279        // next call to this infoHandler() will try to (re-)open file
    280         if(ferror(DataFile)) {
    281       fclose(DataFile);
     280        if(ferror(DataFile) != 0) {
     281      if (fclose(DataFile) != 0) Message(ERROR, "Error closing data file (%s)", strerror(errno));
    282282          DataFile = NULL;
    283283          Message(FATAL, "Error writing to data file, closed file (%s)", strerror(errno));
     
    300300void DataHandler::commandHandler() {
    301301
    302   if (getCommand() != LogCommand || LogFile == NULL) return;
    303 
     302  // Translate text safely to string
     303  string Text = ToString((char *) "C", getCommand()->getData(), getCommand()->getSize());
     304
     305  // Safety check
     306  if (getCommand() != LogCommand || LogFile == NULL || Text.empty()) return;
     307 
    304308  // Replace all carriage-return by line feed and non-printable characters
    305   char *Text = getCommand()->getString();
    306   for (unsigned int i=0; i<strlen(Text); i++) {
     309  for (unsigned int i=0; i<Text.size(); i++) {
    307310    if (Text[i] == '\r') Text[i] = '\n';
    308311        if(isprint(Text[i])==0 && isspace(Text[i])==0) Text[i] = ' ';
     
    314317  fprintf(LogFile, "%.2d/%.2d/%4d %.2d:%.2d:%2.d %s (ID %d): %s\n",
    315318                TM->tm_mday, TM->tm_mon+1, TM->tm_year+1900,
    316                 TM->tm_hour, TM->tm_min, TM->tm_sec, getClientName(), getClientId(), Text);
     319                TM->tm_hour, TM->tm_min, TM->tm_sec, getClientName(), getClientId(), Text.c_str());
    317320  fflush(LogFile);
    318321 
  • Evidence/Evidence.cc

    r232 r253  
    134134//////////////////////////
    135135
     136// Initialise
    136137int EvidenceServer::ConfigSignal = 0;
    137138EvidenceServer *EvidenceServer::This = NULL;
    138139
    139 // Constructor starts server with given name
    140 EvidenceServer::EvidenceServer(const char *ServerName): Name(ServerName) {
     140// Constructor
     141EvidenceServer::EvidenceServer(string ServerName): Name(ServerName) {
    141142
    142143  // Initialize
     
    176177
    177178  // Start server
    178   start(ServerName);
     179  start(ServerName.c_str());
    179180  addExitHandler(this);
    180181}
     
    184185
    185186  Message(INFO, "Server stopped");
    186  
     187
    187188  delete ConfClass;
    188   delete MessageService;
    189   delete[] MessageData;
    190  
     189
    191190  int Ret;
    192191  if ((Ret = pthread_mutex_destroy(&Mutex)) != 0) {
    193192        Message(ERROR, "pthread_mutex_destroy() failed (%s)", strerror(Ret));
    194193  }
     194 
     195  delete MessageService;
     196  delete[] MessageData; 
    195197}
    196198
     
    203205
    204206// DIM error handler
    205 void EvidenceServer::errorHandler(int Severity, int Code, char *Text) {   
     207void EvidenceServer::errorHandler(int Severity, int Code, char *Text) {
     208
    206209  Message(ERROR, "%s (DIM error code %d, DIM severity %d)\n", Text, Code, Severity);
    207210}
     
    233236  SendToLog("%s (%s): %s", MessageService->getName(), StateString[Severity], NewMsg->Text);
    234237
    235   // Update DIM message service, then delete old message
     238  // Update DIM message service
    236239  if (MessageService != NULL) {
    237240        MessageService->updateService(NewMsg, sizeof(struct Message)+strlen(NewMsg->Text)+1);
    238241  }
     242
     243  // Terminate if severity if FATAL 
     244  if (Severity == FATAL) exit(EXIT_FAILURE);
     245
     246  // Delete old message
     247  // Note that Lock()/Unlock() might fail with a FATAL message. To avoid an infinite loop,
     248  // check for FATAL severity is done before here.
     249  Lock();
    239250  delete[] MessageData;
    240251  MessageData = NewMsg;
    241 
    242   // Terminate if severity if FATAL 
    243   if (Severity == FATAL) exit(EXIT_FAILURE);
     252  Unlock(); 
    244253}
    245254
  • Evidence/Evidence.h

    r232 r253  
    3838                std::map<std::string, struct Item> List;
    3939
     40                void infoHandler();
     41                void rpcInfoHandler();
     42
    4043          public:
    4144                Config(std::string);
     
    4346
    4447                std::string GetConfig(std::string, std::string);
    45                 void infoHandler();
    46                 void rpcInfoHandler();
    4748        };
    4849
     
    6263    static void SignalHandler(int); // static for signal()
    6364    static void Terminate();            // static for set_terminate()
    64         void errorHandler(int, int, char *);
    65         void exitHandler(int);
     65        virtual void errorHandler(int, int, char *);
     66        virtual void exitHandler(int);
    6667        virtual void ConfigChanged() {};
    6768
    6869  public:
    69     EvidenceServer(const char *);
     70    EvidenceServer(std::string);
    7071        ~EvidenceServer();
    7172
  • Evidence/History.cc

    r232 r253  
    1818#include "Evidence.h"
    1919
    20 const int MIN_SIZE_KB = 50;             // Minimum and maximum history buffer in kByte (> 3*sizeof(int) !)
    21 const int MAX_SIZE_KB = 2000;
    22 const int REQUEST_NUM = 1000;   // Requested number of entries in each history buffer
    23 
    2420#include <string>
    2521#include <sstream>
     
    3127
    3228using namespace std;
     29
     30const int MIN_SIZE_KB = 50;                                     // Min and max buffersize in kByte (> 3*sizeof(int) !)
     31const string DEFAULT_MAX_SIZE_KB = "2000";
     32const string DEFAULT_NUM_ENTRIES = "1000";      // Number of entries in each history buffer
    3333
    3434//
     
    6969                                                         Directory(Dir) {
    7070
    71   // Map of minimum required change for addition to history buffer
     71  // Get/initialize configuration
    7272  Change = GetConfig("minchange", " ");
     73  GetConfig("maxsize_kb", DEFAULT_MAX_SIZE_KB);
     74  GetConfig("numentries", DEFAULT_NUM_ENTRIES);
    7375
    7476  // Subscribe to top-level server list
     
    139141  // Check if service known and ignore empty or illegal time stamped service
    140142  if (Map.count(Service) == 0 || I->getSize()==0 || I->getTimestamp()<=0) return;
    141  
     143
    142144  // Resize buffer if necessary
    143   if (Map[Service].Buffer.size() < REQUEST_NUM*I->getSize()) {
    144         if (REQUEST_NUM*I->getSize() < MAX_SIZE_KB*1024) Map[Service].Buffer.resize(REQUEST_NUM*I->getSize());
     145  int NEntries = atoi(GetConfig("numentries").c_str());
     146  if (Map[Service].Buffer.size() < NEntries*I->getSize()) {
     147        if (NEntries*I->getSize() < atoi(GetConfig("maxsize_kb").c_str())*1024) {
     148          Map[Service].Buffer.resize(NEntries*I->getSize());
     149        }
    145150  }
    146151
     
    212217void History::rpcHandler() {
    213218
    214   char *Name = getString();
     219  string Name = ToString((char *) "C", getData(), getSize());
    215220 
    216221  // Search for history buffer in memory
     
    237242        fseek(File, sizeof(int), SEEK_SET); // Skip 'Next' pointer
    238243        if ((fread(Buffer, sizeof(char), Size-sizeof(int), File) != Size-sizeof(int)) || (ferror(File) != 0)) {
    239           Message(WARN, "Error reading history file '%s' in rpcHandler()", Name);
     244          Message(WARN, "Error reading history file '%s' in rpcHandler()", Name.c_str());
    240245          setData(NULL, 0);             // Default response
    241246        }
     
    244249  }
    245250 
    246   if (fclose(File) != 0) Message(WARN, "Error closing history file '%s' in rpcHandler()", Name);
     251  if (fclose(File) != 0) Message(WARN, "Error closing history file '%s' in rpcHandler()", Name.c_str());
    247252}
    248253
  • Evidence/readme.txt

    r232 r253  
    11Short description of Evidence control system
    22
    3 This directory contains the backbone of the control system.
    4 
    5 Config is the configuration server and needs to run before any other DIM
    6 server that requests configuration information is started (if a configuration
    7 request cannot be answered, a server will normally not start). A configuration
    8 file can be given on the command line.
    9 
    10 DColl is the central data collector. It subscribes to all services handled by
    11 the name server and writes them to disk (except those excluded in the
    12 configuration file). It also provides a history service for all DIM services
    13 and a command for logging.
    14 
    15 Alarm can be configured to check all servers for availability and status and
    16 can produce a master alarm.
    17 
    18 The DIMDIR environment variable needs to point to the DIM installation directory
    19 when compiling. DIM_DNS_NODE must point to the name server for any DIM server
    20 to run.
     3This directory contains the backbone of the control system. See directory Doc for documentation.
    214
    225
     
    5437                        in case signal is set with ActivateSignal() this signal will be blocked while locked.
    5538                        Implemented experimental automatic full configuration tracking for Bridge.
     397/7/2010        All commandHandler() and rpcHandler() safely translates data into string
     40                        using ToString(). EvidenceServer class constructor now takes std::string as argument.
     41                        Removed default configuration file from Config.
     4219/7/2010       Added documentation. Replaced std::vector by std::map at several locations. Access to
     43                        class-wide pointer in Message() protected by mutex (currently the memory of the
     44                        second-last message will not be freed correctly if severity is FATAL). Added
     45                        History server configuration parameters to adjust buffer size.
    5646
    57 
    58 Preliminary firewall settings on eth-vme02 (rule 5 for DIM, rule 6 for X11 over ssh)
    59 
    60 Chain INPUT (policy ACCEPT)
    61 num  target     prot opt source               destination
    62 1    RH-Firewall-1-INPUT  all  --  0.0.0.0/0            0.0.0.0/0
    63 
    64 Chain FORWARD (policy ACCEPT)
    65 num  target     prot opt source               destination
    66 1    RH-Firewall-1-INPUT  all  --  0.0.0.0/0            0.0.0.0/0
    67 
    68 Chain OUTPUT (policy ACCEPT)
    69 num  target     prot opt source               destination
    70 
    71 Chain RH-Firewall-1-INPUT (2 references)
    72 num  target     prot opt source               destination
    73 1    ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0           icmp type 255
    74 2    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
    75 3    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:22
    76 4    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:2000
    77 5    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpts:5100:6000 state NEW
    78 6    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpts:6000:6063 state NEW
    79 7    REJECT     all  --  0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited
Note: See TracChangeset for help on using the changeset viewer.