Changeset 232


Ignore:
Timestamp:
06/30/10 08:48:02 (15 years ago)
Author:
ogrimm
Message:
Made Lock()/Unlock() public, automatic configuration tracking for Bridge
Location:
Evidence
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • Evidence/Bridge.cc

    r229 r232  
    1010  and commands.
    1111 
     12  Configuraton changes are automatically tracked through ConfigChanged()
     13   
    1214  Oliver Grimm, June 2010
    1315
     
    1921#include <string>
    2022#include <vector>
     23#include <regex.h>
    2124
    2225const int DEFAULT_PORT = 2505;
     
    3336          char *Data;
    3437        };
     38
    3539        map<string, struct Item> Map;
    36 
     40        vector<regex_t> RegEx;
    3741        DimInfo *ServerList;
    3842       
    3943    void infoHandler();
    4044    void commandHandler();
    41         public:
    4245        void AddService(string, char *, int);
    4346        void RemoveService(string);
     47        void ConfigChanged();
    4448        void BugFix();
     49        void Undo();
    4550
    4651  public:
     
    5560  DimClient::setDnsNode(Name, Port);
    5661
    57   // Subsribe to top-level server list
    58   ServerList = new DimInfo((char *) "DIS_DNS/SERVER_LIST", NO_LINK, this);
    59 }
    60 
    61 
    62 // Destructor: Delete all subscriptions and services
     62  // Initialise and request notification of configuration changes
     63  ServerList = NULL;
     64  GetConfig("cmdallow", " ");
     65  ActivateSignal(SIGUSR2);
     66}
     67
     68
     69// Destructor
    6370Bridge::~Bridge() {
     71
     72  Undo();
     73}
     74
     75
     76// Undo: Delete all subscriptions and regular expressions
     77void Bridge::Undo() {
    6478
    6579  while (Map.size() != 0) RemoveService((*Map.begin()).first); 
    6680  delete ServerList;
     81  for (int i=0; i<RegEx.size(); i++) regfree(&RegEx[i]);
     82  RegEx.clear();
     83}
     84
     85
     86// Called by signal handler in case configuration changes (also initially)
     87void Bridge::ConfigChanged() {
     88
     89  static string ExcludeString;
     90
     91  // Check if configuratiomn changed
     92  if (ExcludeString == GetConfig("exclude")) return;
     93  ExcludeString = GetConfig("exclude");
     94 
     95  // Remove all previous subscriptions
     96  Undo();
     97
     98  // Compile regular expressions
     99  regex_t R;
     100  vector<string> Exclude = Tokenize(ExcludeString, " \t");
     101  for (int i=0; i<Exclude.size(); i++) {
     102        int Ret = regcomp(&R, Exclude[i].c_str(), REG_EXTENDED|REG_NOSUB);
     103        if (Ret != 0) {
     104          char Err[200];
     105          regerror(Ret, &R, Err, sizeof(Err));
     106          Message(ERROR, "Error compiling regular expression '%s' (%s)", Exclude[i].c_str(), Err);
     107        }
     108        else RegEx.push_back(R);
     109  }
     110
     111  // Subscribe to top-level server list
     112  ServerList = new DimInfo((char *) "DIS_DNS/SERVER_LIST", NO_LINK, this);
    67113}
    68114
     
    78124  // If service is DIS_DNS/SERVER_LIST, subscribe to all SERVICE_LIST services
    79125  if (strcmp(I->getName(), "DIS_DNS/SERVER_LIST") == 0) {
    80     printf("DIS_DNS/SERVER_LIST: '%s'\n", I->getString());
     126
    81127        char *Token = strtok(I->getString(), "+-!@");   
    82128        while (Token != NULL) {
     
    156202
    157203
    158 // Command repeating
     204// Command repeating (also handles requests for remote procedure calls)
    159205void Bridge::commandHandler() {
    160  
     206
     207  // Check if client allowed to send commands
     208  vector<string> Client = Tokenize(getClientName(), "@");
     209  if (Client.size() == 2 && GetConfig("cmdallow").find(Client[1]) == string::npos) {
     210        Message(INFO, "Rejected command/rpc from %s (ID %d)", getClientName(), getClientId());
     211        return; 
     212  }
     213
     214  // Send command to server
    161215  sendCommandNB(getCommand()->getName(), getCommand()->getData(), getCommand()->getSize());
    162216}
     
    166220void Bridge::AddService(string Name, char *Format, int Type) {
    167221
    168   // Do not forward  DIS_DNS and History services
    169   if ((Name.find("DIS_DNS/") != string::npos) || (Name.find("History/") != string::npos)) return;
    170 
    171222  // Check if already subscribed to this service
    172223  if (Map.count(Name) != 0) return;
     224
     225  // Should service be ignored?
     226  for (int i=0; i<RegEx.size(); i++) {
     227    if (regexec(&RegEx[i], Name.c_str(), (size_t) 0, NULL, 0) == 0) return;
     228  }
    173229
    174230  // Create subscription and service to secondary DNS or new command
  • Evidence/DColl.cc

    r231 r232  
    253253  for (int Service=0; Service<List.size(); Service++) if (I == List[Service].DataItem) {
    254254
    255         // Service excluded from writing?
    256         if (List[Service].Exclude) return;
     255        // Service excluded from writing or contains no data?
     256        if (List[Service].Exclude || I->getSize()==0) return;
    257257       
    258258        // Write data header
     
    263263
    264264        // Translate data into ASCII
    265         string Text = EvidenceServer::ToString(I);
     265        string Text = EvidenceServer::ToString(I->getFormat(), I->getData(), I->getSize());
    266266
    267267        if (!Text.empty()) {
  • Evidence/Edd/Edd.cc

    r231 r232  
    6464
    6565  W->setStatusTip(Status);
    66   if (W->parent() == NULL) W->setToolTip(Status);
    6766 
    6867  return(Time != -1);
     
    132131    }
    133132        Text = Text.section(' ', 1);
    134   }     
    135   else if (Format[0].toUpper() != 'C') Text = Text.section(' ', Index, Index);
     133  }
     134  else if (Format[0].toUpper() != 'C' && Format != "I:1;C") Text = Text.section(' ', Index, Index);
    136135
    137136  if (!ShowAsTime) setText(Text);
     
    233232//////////////////////////////////
    234233
    235 EddPlot::EddPlot(QString DIMService, int Index, QWidget *P): EddBasePlot(P) {
     234EddPlot::EddPlot(QString Service, int Index, QWidget *P): EddBasePlot(P) {
    236235
    237236  // Widget properties
     
    247246  // Connect to DIM handler
    248247  if (connect(Handler, SIGNAL(YEP(QString, int, QByteArray, QString, QString)), SLOT(Update(QString, int, QByteArray, QString, QString))) == false) {
    249     printf("Failed connection for %s\n", DIMService.toAscii().data());
     248    printf("Failed connection for %s\n", Service.toAscii().data());
    250249  }
    251250
     
    259258
    260259  // DIM client
    261   if (!DIMService.isEmpty()) AddService(DIMService, Index);
     260  if (!Service.isEmpty()) AddService(Service, Index);
    262261}
    263262
     
    328327        }
    329328
    330         // Appen data only if service available
     329        // Append data only if service available
    331330        if (SetStatus(this, Name, Time, Format)) {
    332331          QString Txt = Text;
     
    597596  // Rescale y axis (increase range if selected rectangle larger than axis area)
    598597  if (R.right() < 0) {
    599         if (R.top() < plotLayout()->canvasRect().top()) {
     598        if (yMouse.maxValue() > axisScaleDiv(QwtPlot::yLeft)->upperBound()) {
    600599          yMouse.setMaxValue(yMouse.maxValue() + yPlot.width());
    601600        }
    602         if (R.bottom() > plotLayout()->canvasRect().bottom()) {
     601        if (yMouse.minValue() < axisScaleDiv(QwtPlot::yLeft)->lowerBound()) {
    603602          yMouse.setMinValue(yMouse.minValue() - yPlot.width());
    604603        }
     
    609608  // Rescale x axis (increase range if selected rectangle larger than axis area)
    610609  if (R.top() > plotLayout()->canvasRect().height()) {
    611         if (R.left() < plotLayout()->canvasRect().left()) {
     610        if (xMouse.maxValue() > axisScaleDiv(QwtPlot::xBottom)->upperBound()) {
     611          xMouse.setMaxValue(xMouse.maxValue() + xPlot.width());
     612        }
     613        if (xMouse.minValue() < axisScaleDiv(QwtPlot::xBottom)->lowerBound()) {
    612614          xMouse.setMinValue(xMouse.minValue() - xPlot.width());
    613615        }
    614         if (R.right() > plotLayout()->canvasRect().right()) {
    615           xMouse.setMaxValue(xMouse.maxValue() + xPlot.width());
    616         }
     616
    617617        setAxisScale(QwtPlot::xBottom, xMouse.minValue(), xMouse.maxValue());
    618618  }
     
    741741
    742742  if (!Pure) {
    743         // Get history for this service 
     743        // Get history for this service
    744744        const struct EvidenceHistory::Item *R;
    745745        class EvidenceHistory *Hist;
     
    748748          while ((R=Hist->Next()) != NULL) {
    749749                moveCursor (QTextCursor::Start);
    750                 insertPlainText(QString("(")+QDateTime::fromTime_t(R->Time).toString()+") ");     
    751                 insertPlainText(QString((char *) R->Data) + "\n");       
    752           }
     750                insertPlainText(QString("(")+QDateTime::fromTime_t(R->Time).toString()+") " +
     751                  QString::fromStdString(EvidenceServer::ToString(Hist->GetFormat(), (void *) R->Data, R->Size)) + "\n");
     752          }     
    753753        }
    754754        Handler->DropHistory(Name);
     
    814814}
    815815
     816// Destructor
    816817EddDim::~EddDim() {
    817818
    818   for (int i=0; i<HistoryList.size(); i++) delete HistoryList[i].HistClass;
     819  QList<QString> L = HistoryList.keys();
     820  for(int i=0; i<L.size(); i++) delete HistoryList[L[i]].HistClass;
    819821
    820822  delete Mutex;
     
    827829  QMutexLocker Locker(Mutex);
    828830
    829   // If already subscribed to service, increase usage count
    830   for (int i=0; i<ServiceList.size(); i++) if (ServiceList[i].Name == Name) {
    831         ServiceList[i].Count++;
    832         // If service already received, reemit for new subscriber
    833         if (!ServiceList[i].ByteArray.isEmpty()) {
    834           YEP(Name, ServiceList[i].TimeStamp, ServiceList[i].ByteArray, ServiceList[i].Format, ServiceList[i].Text);
    835         }
    836         else YEP(Name, -1);
     831  // If already subscribed to service, increase usage count and reemit data for new subscriber
     832  if (ServiceList.contains(Name)) {
     833        ServiceList[Name].Count++;
     834        YEP(Name, ServiceList[Name].TimeStamp, ServiceList[Name].ByteArray, ServiceList[Name].Format, ServiceList[Name].Text);
    837835        return;
    838836  }
    839837
    840838  // Create new entry in service list
    841   struct Item New;
    842   New.Name = Name;
    843   New.ByteArray = QByteArray();
    844   New.Count = 1;
    845   New.DIMService = new DimStampedInfo(Name.toAscii().data(), INT_MAX, NO_LINK, this);
    846   ServiceList.append(New);
    847 
     839  ServiceList[Name].ByteArray = QByteArray();
     840  ServiceList[Name].TimeStamp = -1;
     841  ServiceList[Name].Count = 1;
     842  ServiceList[Name].DIMService = new DimStampedInfo(Name.toAscii().data(), INT_MAX, NO_LINK, this);
    848843  return;
    849844}
     
    855850  QMutexLocker Locker(Mutex);
    856851
    857   for (int i=0; i<ServiceList.size(); i++) if (ServiceList[i].Name == Name) {
    858         ServiceList[i].Count--;
    859         if (ServiceList[i].Count == 0) {
    860           delete ServiceList[i].DIMService;
    861           ServiceList.removeAt(i);
    862           return;
    863         }
     852  if (ServiceList.contains(Name)) ServiceList[Name].Count--;
     853
     854  if (ServiceList[Name].Count == 0) {
     855        delete ServiceList[Name].DIMService;
     856        ServiceList.remove(Name);
     857        return;
    864858  }
    865859}
     
    869863
    870864  // History already available (only request again if too old)
    871   for (int i=0; i<HistoryList.size(); i++) if (HistoryList[i].Name == Name) {
    872         HistoryList[i].Count++;
    873         if (time(NULL)-HistoryList[i].LastUpdate < 5) {
    874           HistoryList[i].HistClass->Rewind();
    875           return HistoryList[i].HistClass;
     865  if (HistoryList.contains(Name)) {
     866        HistoryList[Name].Count++;
     867
     868        if (time(NULL)-HistoryList[Name].LastUpdate < 5) {
     869          HistoryList[Name].HistClass->Rewind();
     870          return HistoryList[Name].HistClass;
    876871        }
    877         HistoryList[i].LastUpdate = time(NULL);
    878         if (HistoryList[i].HistClass->GetHistory()) return HistoryList[i].HistClass;
     872        HistoryList[Name].LastUpdate = time(NULL);
     873        if (HistoryList[Name].HistClass->GetHistory()) return HistoryList[Name].HistClass;
    879874        else return NULL;
    880875  }
    881876
    882877  // Create new history class
    883   struct HistItem New;
    884   New.Name = Name;
    885   New.HistClass = new EvidenceHistory(Name.toStdString());
    886   New.Count = 1;
    887   New.LastUpdate = time(NULL);
    888   HistoryList.append(New);
    889 
    890   if (New.HistClass->GetHistory()) return New.HistClass;
     878  HistoryList[Name].HistClass = new EvidenceHistory(Name.toStdString());
     879  HistoryList[Name].Count = 1;
     880  HistoryList[Name].LastUpdate = time(NULL);
     881
     882  if (HistoryList[Name].HistClass->GetHistory()) return HistoryList[Name].HistClass;
    891883  else return NULL;
    892884}
     
    895887void EddDim::DropHistory(QString Name) {
    896888
    897   for (int i=0; i<HistoryList.size(); i++) {
    898         if (HistoryList[i].Name == Name) HistoryList[i].Count--;
    899   }
     889  if (HistoryList.contains(Name)) HistoryList[Name].Count--;
    900890}
    901891
     
    903893void EddDim::UpdateStatistics() {
    904894
    905   // Remove unused histories after not less than 5 seconds
    906   for (int i=0; i<HistoryList.size(); i++) {
    907         if ((HistoryList[i].Count <= 0) && (time(NULL)-HistoryList[i].LastUpdate) > 5) {
    908           delete HistoryList[i].HistClass;
    909           HistoryList.removeAt(i);
    910         }
    911   }
    912 
    913895  // Lock before accessing internal variables
    914896  QMutexLocker Locker(Mutex);
    915897
     898  // Remove unused histories after not less than 5 seconds
     899  QList<QString> L = HistoryList.keys();
     900  for(int i=0; i<L.size(); i++) {
     901        if ((HistoryList[L[i]].Count <= 0) && (time(NULL)-HistoryList[L[i]].LastUpdate) > 5) {
     902          delete HistoryList[L[i]].HistClass;
     903          HistoryList.remove(L[i]);
     904        }
     905  }
     906 
    916907  float Rate = Volume/1024.0/10;
    917 
     908  Volume = 0;
    918909  YEP("Edd/Rate_kBSec", time(NULL), QByteArray::number(Rate), "F", QString::number(Rate));
    919   Volume = 0;
    920 }
    921 
    922 // Store service information for usage by Subscribe() and update statistics
     910}
     911
     912// Store service information for usage by Subscribe(), update statistics and emit signal to widgets
    923913void EddDim::Update(QString Name, int Time, QByteArray Data, QString Format, QString Text) {
    924914
     
    926916  QMutexLocker Locker(Mutex);
    927917
    928   for (int i=0; i<ServiceList.size(); i++) if (ServiceList[i].Name == Name) {
    929           ServiceList[i].TimeStamp = Time;
    930           ServiceList[i].ByteArray = Data;
    931           ServiceList[i].Format = Format;
    932           ServiceList[i].Text = Text;
    933   }
    934 
    935   // Update statistics only for Dim services
     918  // Store service data
     919  if (ServiceList.contains(Name)) {
     920          ServiceList[Name].TimeStamp = Time;
     921          ServiceList[Name].ByteArray = Data;
     922          ServiceList[Name].Format = Format;
     923          ServiceList[Name].Text = Text;
     924  }
     925
     926  // Update statistics only for actual Dim services
    936927  if (!Name.startsWith("Edd/")) Volume += Data.size();
    937928 
    938   YEP(Name, Time, Data, Format, Text); 
     929  // Emit signal to all widgets
     930  YEP(Name, Time, Data, Format, Text);
    939931}
    940932
    941933// Handling of DIM service update
     934// No locking allowed. Signal triggers only EddDim::Update() when the main event loop is idle.
    942935void EddDim::infoHandler() {
    943936
     
    945938  else {
    946939        INT(getInfo()->getName(), getInfo()->getTimestamp(), QByteArray((char *) getInfo()->getData(),
    947                 getInfo()->getSize()), getInfo()->getFormat(), QString::fromStdString(EvidenceServer::ToString(getInfo())));
     940                getInfo()->getSize()), getInfo()->getFormat(), QString::fromStdString(EvidenceServer::ToString(getInfo()->getFormat(), getInfo()->getData(), getInfo()->getSize())));
    948941  }
    949942}
     
    12351228  EddText *Text = new EddText("Bias/ConsoleOut", true);
    12361229  Text->setFixedWidth(400);
    1237   Layout->addWidget(Text, 11, 0, 4, 4);     
     1230  Layout->addWidget(Text, 11, 0, 4, 4);
    12381231}
    12391232
     
    12491242  EddPlot *Plot = new EddPlot();
    12501243  for (int i=0; i<36; i++) {
    1251     Line = new EddLineDisplay("drsdaq/Average", i);
     1244    Line = new EddLineDisplay("Feedback/Average", i);
    12521245        Line->setMaximumWidth(60);
    1253     Layout->addWidget(Line, i%9+1, 0+i/9, 1, 1);
    1254     Plot->AddService("drsdaq/Average", i);
     1246    Layout->addWidget(Line, i%9+2, 0+i/9, 1, 1);
     1247    Plot->AddService("Feedback/Average", i);
    12551248  }
    12561249  Layout->addWidget(Plot, 0, 4, 12, 10);
    1257 
    1258   //Graph = new EddPlot();
    1259   //for (int i=0; i<36; i++) {
    1260     //Text = Text.sprintf("Feedback/Sigma/ID%.2d/%.2d-%.3d",i/16, (i%16)/8, i%8);
    1261     //Graph->AddService(Text);
    1262   //}
    1263   //FeedbackLayout->addWidget(Graph, 10, 0, 10, 3);
    12641250
    12651251  Line = new EddLineDisplay("drsdaq/Message");
    12661252  Line->setMaximumWidth(200);
    12671253  Layout->addWidget(Line, 0, 0, 1, 2);     
    1268   Line = new EddLineDisplay("drsdaq/Count");
     1254
     1255  Line = new EddLineDisplay("Feedback/State");
     1256  Line->setMaximumWidth(150);
     1257  Layout->addWidget(Line, 1, 0, 1, 2);     
     1258  Line = new EddLineDisplay("Feedback/Count");
    12691259  Line->setMaximumWidth(60);
    1270   Layout->addWidget(Line, 0, 2);     
     1260  Layout->addWidget(Line, 1, 2);     
    12711261
    12721262  QWidget *Button = new QPushButton("Details");
    1273   Layout->addWidget(Button, 10, 0, 1, 1);     
     1263  Layout->addWidget(Button, 12, 0, 1, 1);     
    12741264  connect(Button, SIGNAL(pressed()), SLOT(FeedbackDetails()));
    12751265
     
    12781268void TP_Feedback::FeedbackDetails() {
    12791269
    1280   setAttribute(Qt::WA_DeleteOnClose);
     1270  QMainWindow *M = new QMainWindow;
     1271  M->setCentralWidget(new QWidget);
     1272  M->setStatusBar(new QStatusBar(M));
     1273  M->setWindowTitle("Edd - Feedback Details");
     1274  M->setAttribute(Qt::WA_DeleteOnClose);
     1275
     1276  QGridLayout *Layout = new QGridLayout(M->centralWidget());
    12811277  EddLineDisplay *Line;
    1282   QWidget *Widget = new QWidget();
    1283   QGridLayout *Layout = new QGridLayout(Widget);
    12841278  EddPlot *Plot = new EddPlot();
     1279
    12851280  for (int i=0; i<36; i++) {
    1286     Line = new EddLineDisplay("drsdaq/Sigma", i);
    1287         Line->setMaximumWidth(50);
    1288     Layout->addWidget(Line, i%9+1, 0+i/9, 1, 1);
    1289     Plot->AddService("drsdaq/Sigma", i);
    1290   }
    1291   Layout->addWidget(Plot, 0, 4, 12, 10);
    1292  
    1293   Widget->show();
     1281    Line = new EddLineDisplay("Feedback/Sigma", i);
     1282        Line->setMaximumWidth(60);
     1283    Layout->addWidget(Line, i%9, 0+i/9, 1, 1);
     1284    Plot->AddService("Feedback/Sigma", i);
     1285       
     1286    Line = new EddLineDisplay("Feedback/Target", i);
     1287        Line->setMaximumWidth(60);
     1288    Layout->addWidget(Line, i%9+10, 0+i/9, 1, 1);
     1289       
     1290        Line = new EddLineDisplay("Feedback/Response", i);
     1291        Line->setMaximumWidth(60);
     1292    Layout->addWidget(Line, i%9+20, 0+i/9, 1, 1);
     1293  }
     1294  Layout->addWidget(Plot, 0, 4, 30, 12);
     1295 
     1296  M->show();
    12941297}
    12951298
  • Evidence/Edd/Edd.h

    r231 r232  
    3636bool SetStatus(QWidget *, QString, int, QString, int = -1);
    3737
     38
    3839// Base class for Edd plot
    3940// DeleteCurve() is pure virtual and needs to be implemented iin the application class
     
    213214  private:
    214215        struct Item {
    215           QString Name;
    216216          DimStampedInfo *DIMService;
    217217          int Count;
     
    221221          QString Text;
    222222        };
    223     QList<Item> ServiceList;
     223    QMap<QString, struct Item> ServiceList;
    224224    QMutex *Mutex;
    225225
    226226        struct HistItem {
    227           QString Name;
    228227          int Count;
    229228          int LastUpdate;
    230229          class EvidenceHistory *HistClass;
    231230        };
    232     QList<HistItem> HistoryList;
     231    QMap<QString, struct HistItem> HistoryList;
    233232
    234233        long long Volume;
  • 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  }
  • Evidence/Evidence.h

    r231 r232  
    2626        class Config: public DimClient, public DimRpcInfo {
    2727
    28                 pthread_mutex_t Mutex;
    2928                std::string Name;
    3029                DimInfo *Service;
     
    4443
    4544                std::string GetConfig(std::string, std::string);
    46                 void Lock();
    47                 void Unlock();
    4845                void infoHandler();
    4946                void rpcInfoHandler();
     
    6057        class Config *ConfClass;
    6158        static int ConfigSignal;                // static since accessed in signal handler
     59        pthread_mutex_t Mutex;
     60        static EvidenceServer *This;
    6261
    6362    static void SignalHandler(int); // static for signal()
     
    7776        std::string GetConfig(std::string, std::string = std::string());
    7877        void ActivateSignal(int);
    79         static std::string ToString(DimInfo *);
     78        void Lock();
     79        void Unlock();
     80        static std::string ToString(char *, void *, int);
    8081        static bool ServiceOK(DimInfo *);
    8182        static bool ServiceOK(DimRpcInfo *);
     
    8586};
    8687
     88// Class declaration of EvidenceHistory
    8789class EvidenceHistory {
    8890
  • Evidence/History.cc

    r229 r232  
    137137  char *Service = I->getName();
    138138
    139   // Check if service known and ignore empty service
    140   if (Map.count(Service) == 0 || I->getSize()==0 || I->getTimestamp()==0) return;
     139  // Check if service known and ignore empty or illegal time stamped service
     140  if (Map.count(Service) == 0 || I->getSize()==0 || I->getTimestamp()<=0) return;
    141141 
    142142  // Resize buffer if necessary
     
    148148  if (strcmp(I->getFormat(), "C") != 0) {
    149149        // Calculate sum of all number in array
    150         istringstream Text(EvidenceServer::ToString(I));
     150        istringstream Text(EvidenceServer::ToString(I->getFormat(), I->getData(), I->getSize()));
    151151        double Num, Sum = 0;
    152152        while (Text.good()) {
  • Evidence/readme.txt

    r229 r232  
    464623/6/2010       GetConfig() returns std::string. Non-blocking configuration request in case
    4747                        GetConfig() not called from main thread. Access to configuration information
    48                         internally mutex protected. Signal SIGUSR2 send to main thread upon configuration
    49                         file change, signal handler invokes (virtual) method ConfigChanged().
     48                        internally mutex protected. With ActivateSignal() a signal can be set that is send
     49                        to main thread upon configuration file change, the build-in signal handler then
     50                        invokes the (virtual) method ConfigChanged().
    505124/6/2010       Workaround for erroneous /SERVICE_LIST updates. Added static tokenize method to
    5152                        Evidence class.
    52 
     5330/6/2010       Made Lock()/Unlock() publicly available (mutex of type PTHREAD_MUTEX_ERRORCHECK),
     54                        in case signal is set with ActivateSignal() this signal will be blocked while locked.
     55                        Implemented experimental automatic full configuration tracking for Bridge.
    5356
    5457
Note: See TracChangeset for help on using the changeset viewer.