Changeset 232
- Timestamp:
- 06/30/10 08:48:02 (14 years ago)
- Location:
- Evidence
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
Evidence/Bridge.cc
r229 r232 10 10 and commands. 11 11 12 Configuraton changes are automatically tracked through ConfigChanged() 13 12 14 Oliver Grimm, June 2010 13 15 … … 19 21 #include <string> 20 22 #include <vector> 23 #include <regex.h> 21 24 22 25 const int DEFAULT_PORT = 2505; … … 33 36 char *Data; 34 37 }; 38 35 39 map<string, struct Item> Map; 36 40 vector<regex_t> RegEx; 37 41 DimInfo *ServerList; 38 42 39 43 void infoHandler(); 40 44 void commandHandler(); 41 public:42 45 void AddService(string, char *, int); 43 46 void RemoveService(string); 47 void ConfigChanged(); 44 48 void BugFix(); 49 void Undo(); 45 50 46 51 public: … … 55 60 DimClient::setDnsNode(Name, Port); 56 61 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 63 70 Bridge::~Bridge() { 71 72 Undo(); 73 } 74 75 76 // Undo: Delete all subscriptions and regular expressions 77 void Bridge::Undo() { 64 78 65 79 while (Map.size() != 0) RemoveService((*Map.begin()).first); 66 80 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) 87 void 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); 67 113 } 68 114 … … 78 124 // If service is DIS_DNS/SERVER_LIST, subscribe to all SERVICE_LIST services 79 125 if (strcmp(I->getName(), "DIS_DNS/SERVER_LIST") == 0) { 80 printf("DIS_DNS/SERVER_LIST: '%s'\n", I->getString()); 126 81 127 char *Token = strtok(I->getString(), "+-!@"); 82 128 while (Token != NULL) { … … 156 202 157 203 158 // Command repeating 204 // Command repeating (also handles requests for remote procedure calls) 159 205 void 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 161 215 sendCommandNB(getCommand()->getName(), getCommand()->getData(), getCommand()->getSize()); 162 216 } … … 166 220 void Bridge::AddService(string Name, char *Format, int Type) { 167 221 168 // Do not forward DIS_DNS and History services169 if ((Name.find("DIS_DNS/") != string::npos) || (Name.find("History/") != string::npos)) return;170 171 222 // Check if already subscribed to this service 172 223 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 } 173 229 174 230 // Create subscription and service to secondary DNS or new command -
Evidence/DColl.cc
r231 r232 253 253 for (int Service=0; Service<List.size(); Service++) if (I == List[Service].DataItem) { 254 254 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; 257 257 258 258 // Write data header … … 263 263 264 264 // Translate data into ASCII 265 string Text = EvidenceServer::ToString(I );265 string Text = EvidenceServer::ToString(I->getFormat(), I->getData(), I->getSize()); 266 266 267 267 if (!Text.empty()) { -
Evidence/Edd/Edd.cc
r231 r232 64 64 65 65 W->setStatusTip(Status); 66 if (W->parent() == NULL) W->setToolTip(Status);67 66 68 67 return(Time != -1); … … 132 131 } 133 132 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); 136 135 137 136 if (!ShowAsTime) setText(Text); … … 233 232 ////////////////////////////////// 234 233 235 EddPlot::EddPlot(QString DIMService, int Index, QWidget *P): EddBasePlot(P) {234 EddPlot::EddPlot(QString Service, int Index, QWidget *P): EddBasePlot(P) { 236 235 237 236 // Widget properties … … 247 246 // Connect to DIM handler 248 247 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()); 250 249 } 251 250 … … 259 258 260 259 // DIM client 261 if (! DIMService.isEmpty()) AddService(DIMService, Index);260 if (!Service.isEmpty()) AddService(Service, Index); 262 261 } 263 262 … … 328 327 } 329 328 330 // Appen data only if service available329 // Append data only if service available 331 330 if (SetStatus(this, Name, Time, Format)) { 332 331 QString Txt = Text; … … 597 596 // Rescale y axis (increase range if selected rectangle larger than axis area) 598 597 if (R.right() < 0) { 599 if ( R.top() < plotLayout()->canvasRect().top()) {598 if (yMouse.maxValue() > axisScaleDiv(QwtPlot::yLeft)->upperBound()) { 600 599 yMouse.setMaxValue(yMouse.maxValue() + yPlot.width()); 601 600 } 602 if ( R.bottom() > plotLayout()->canvasRect().bottom()) {601 if (yMouse.minValue() < axisScaleDiv(QwtPlot::yLeft)->lowerBound()) { 603 602 yMouse.setMinValue(yMouse.minValue() - yPlot.width()); 604 603 } … … 609 608 // Rescale x axis (increase range if selected rectangle larger than axis area) 610 609 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()) { 612 614 xMouse.setMinValue(xMouse.minValue() - xPlot.width()); 613 615 } 614 if (R.right() > plotLayout()->canvasRect().right()) { 615 xMouse.setMaxValue(xMouse.maxValue() + xPlot.width()); 616 } 616 617 617 setAxisScale(QwtPlot::xBottom, xMouse.minValue(), xMouse.maxValue()); 618 618 } … … 741 741 742 742 if (!Pure) { 743 // Get history for this service 743 // Get history for this service 744 744 const struct EvidenceHistory::Item *R; 745 745 class EvidenceHistory *Hist; … … 748 748 while ((R=Hist->Next()) != NULL) { 749 749 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 } 753 753 } 754 754 Handler->DropHistory(Name); … … 814 814 } 815 815 816 // Destructor 816 817 EddDim::~EddDim() { 817 818 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; 819 821 820 822 delete Mutex; … … 827 829 QMutexLocker Locker(Mutex); 828 830 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); 837 835 return; 838 836 } 839 837 840 838 // 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); 848 843 return; 849 844 } … … 855 850 QMutexLocker Locker(Mutex); 856 851 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; 864 858 } 865 859 } … … 869 863 870 864 // 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; 876 871 } 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; 879 874 else return NULL; 880 875 } 881 876 882 877 // 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; 891 883 else return NULL; 892 884 } … … 895 887 void EddDim::DropHistory(QString Name) { 896 888 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--; 900 890 } 901 891 … … 903 893 void EddDim::UpdateStatistics() { 904 894 905 // Remove unused histories after not less than 5 seconds906 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 913 895 // Lock before accessing internal variables 914 896 QMutexLocker Locker(Mutex); 915 897 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 916 907 float Rate = Volume/1024.0/10; 917 908 Volume = 0; 918 909 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 923 913 void EddDim::Update(QString Name, int Time, QByteArray Data, QString Format, QString Text) { 924 914 … … 926 916 QMutexLocker Locker(Mutex); 927 917 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 936 927 if (!Name.startsWith("Edd/")) Volume += Data.size(); 937 928 938 YEP(Name, Time, Data, Format, Text); 929 // Emit signal to all widgets 930 YEP(Name, Time, Data, Format, Text); 939 931 } 940 932 941 933 // Handling of DIM service update 934 // No locking allowed. Signal triggers only EddDim::Update() when the main event loop is idle. 942 935 void EddDim::infoHandler() { 943 936 … … 945 938 else { 946 939 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()))); 948 941 } 949 942 } … … 1235 1228 EddText *Text = new EddText("Bias/ConsoleOut", true); 1236 1229 Text->setFixedWidth(400); 1237 Layout->addWidget(Text, 11, 0, 4, 4); 1230 Layout->addWidget(Text, 11, 0, 4, 4); 1238 1231 } 1239 1232 … … 1249 1242 EddPlot *Plot = new EddPlot(); 1250 1243 for (int i=0; i<36; i++) { 1251 Line = new EddLineDisplay(" drsdaq/Average", i);1244 Line = new EddLineDisplay("Feedback/Average", i); 1252 1245 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); 1255 1248 } 1256 1249 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);1264 1250 1265 1251 Line = new EddLineDisplay("drsdaq/Message"); 1266 1252 Line->setMaximumWidth(200); 1267 1253 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"); 1269 1259 Line->setMaximumWidth(60); 1270 Layout->addWidget(Line, 0, 2);1260 Layout->addWidget(Line, 1, 2); 1271 1261 1272 1262 QWidget *Button = new QPushButton("Details"); 1273 Layout->addWidget(Button, 1 0, 0, 1, 1);1263 Layout->addWidget(Button, 12, 0, 1, 1); 1274 1264 connect(Button, SIGNAL(pressed()), SLOT(FeedbackDetails())); 1275 1265 … … 1278 1268 void TP_Feedback::FeedbackDetails() { 1279 1269 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()); 1281 1277 EddLineDisplay *Line; 1282 QWidget *Widget = new QWidget();1283 QGridLayout *Layout = new QGridLayout(Widget);1284 1278 EddPlot *Plot = new EddPlot(); 1279 1285 1280 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(); 1294 1297 } 1295 1298 -
Evidence/Edd/Edd.h
r231 r232 36 36 bool SetStatus(QWidget *, QString, int, QString, int = -1); 37 37 38 38 39 // Base class for Edd plot 39 40 // DeleteCurve() is pure virtual and needs to be implemented iin the application class … … 213 214 private: 214 215 struct Item { 215 QString Name;216 216 DimStampedInfo *DIMService; 217 217 int Count; … … 221 221 QString Text; 222 222 }; 223 Q List<Item> ServiceList;223 QMap<QString, struct Item> ServiceList; 224 224 QMutex *Mutex; 225 225 226 226 struct HistItem { 227 QString Name;228 227 int Count; 229 228 int LastUpdate; 230 229 class EvidenceHistory *HistClass; 231 230 }; 232 Q List<HistItem> HistoryList;231 QMap<QString, struct HistItem> HistoryList; 233 232 234 233 long long Volume; -
Evidence/Evidence.cc
r231 r232 17 17 These signals will then cause pause() to return which can be used 18 18 by the application to terminate gracefully. 19 - The static method ToString() converts the contents of a DIM Infoservice into text19 - The static method ToString() converts the contents of a DIM service into text 20 20 - A terminate-handler is installed for catching unhandled C++ exceptions. 21 21 … … 27 27 using namespace std; 28 28 29 EvidenceServer *ThisServer;30 31 29 // 32 30 // Internal configuration class of EvidenceServer 33 31 // 34 // Data that might be accessed by two threads are protected by mutex35 32 36 33 // Constructor … … 38 35 39 36 // 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 }44 37 CurrentItem = string(); 45 38 ConfigTimeStamp = 0; 46 47 // Signal delivered to this thread if configuration file changes48 39 ThreadID = pthread_self(); 49 40 … … 56 47 57 48 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 }63 49 } 64 50 … … 66 52 void EvidenceServer::Config::infoHandler() { 67 53 68 Lock();54 This->Lock(); 69 55 ConfigTimeStamp = getInfo()->getInt(); 70 Unlock();71 72 if (pthread_kill(ThreadID, This Server->ConfigSignal) != 0) {73 This Server->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"); 74 60 } 75 61 } … … 78 64 void EvidenceServer::Config::rpcInfoHandler(){ 79 65 80 Lock();66 This->Lock(); 81 67 // Update map 82 68 List[CurrentItem].Value = string(getString(), getSize()-1); … … 84 70 // Clear to allow new rpc call 85 71 CurrentItem.clear(); 86 Unlock();72 This->Unlock(); 87 73 } 88 74 … … 93 79 94 80 // If up-to-date data in configuration list available, return this 95 Lock();81 This->Lock(); 96 82 if ((List.count(Item) > 0) && (List[Item].Time >= ConfigTimeStamp)) Result = List[Item].Value; 97 Unlock();83 This->Unlock(); 98 84 if (!Result.empty()) return Result; 99 85 … … 106 92 if (!EvidenceServer::ServiceOK(&Config)) { 107 93 if (Default.empty()) { 108 This Server->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()); 109 95 } 110 96 else Result = Default; … … 117 103 // Update configuration map 118 104 if (!Result.empty()) { 119 Lock();105 This->Lock(); 120 106 List[Item].Value = Result; 121 107 List[Item].Time = ConfigTimeStamp; 122 Unlock();108 This->Unlock(); 123 109 } 124 110 } 125 111 126 // Non-blocking configuration request fro other threads112 // Non-blocking configuration request from other threads 127 113 if (pthread_self() != ThreadID) { 128 Lock();114 This->Lock(); 129 115 if (List.count(Item) > 0) { 130 116 // New request possible only when answer to previous request received … … 136 122 // Return current value 137 123 Result = List[Item].Value; 138 Unlock();124 This->Unlock(); 139 125 } 140 126 } 141 127 142 128 return Result; 143 }144 145 // Locking and unlocking for list access146 // 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 }179 129 } 180 130 … … 185 135 186 136 int EvidenceServer::ConfigSignal = 0; 137 EvidenceServer *EvidenceServer::This = NULL; 187 138 188 139 // Constructor starts server with given name … … 193 144 MessageData = NULL; 194 145 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 } 196 158 197 159 // Catch some signals … … 225 187 delete ConfClass; 226 188 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 } 228 195 } 229 196 … … 270 237 MessageService->updateService(NewMsg, sizeof(struct Message)+strlen(NewMsg->Text)+1); 271 238 } 272 delete MessageData;239 delete[] MessageData; 273 240 MessageData = NewMsg; 274 241 … … 311 278 } 312 279 313 // Signal emitted when configuraton file changes, signal handler calls ConfigChanged() 280 281 // Set signal emitted when configuraton file changes, signal handler calls ConfigChanged() 314 282 void EvidenceServer::ActivateSignal(int Signal) { 315 283 … … 323 291 324 292 293 // Locking and unlocking for list access 294 // Signal blocked before locking to avoid dead-lock by calling GetConfig() from ConfigChanged(). 295 void 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 313 void 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 325 332 // ====== Static methods ====== 326 333 … … 332 339 // If signal indicates configuration change, invoke call-back 333 340 if (Signal == EvidenceServer::ConfigSignal) { 334 This Server->ConfigChanged();341 This->ConfigChanged(); 335 342 return; 336 343 } … … 339 346 if (!Called) { 340 347 Called = true; 341 This Server->ExitRequest = true;348 This->ExitRequest = true; 342 349 return; 343 350 } 344 351 345 352 // If invoked twice, call exit() 346 This Server->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); 347 354 exit(EXIT_FAILURE); 348 355 } … … 355 362 356 363 if (Terminating) { 357 Msg << This Server->Name << ": Terminate() called recursively, calling abort()";364 Msg << This->Name << ": Terminate() called recursively, calling abort()"; 358 365 printf("%s\n", Msg.str().c_str()); 359 This Server->SendToLog(Msg.str().c_str());366 This->SendToLog(Msg.str().c_str()); 360 367 abort(); 361 368 } … … 383 390 else Msg << "Terminate() called without an active exception"; 384 391 385 This Server->Message(FATAL, Msg.str().c_str());386 } 387 388 389 // Translates DIM Info 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) 397 string EvidenceServer::ToString(char *Format, void *Data, int Size) { 391 398 392 399 ostringstream Text; 393 400 394 // Safety check395 if (I->getSize() < 1) return string();396 397 401 // '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; 400 404 // 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)); 403 406 Text << Msg->Severity << " " << MsgText.erase(strlen(MsgText.c_str())); 404 407 … … 407 410 408 411 // 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) << " "; 412 415 } 413 416 return Text.str(); … … 415 418 416 419 // 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); 420 422 } 421 423 422 424 // 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; 426 428 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; 432 434 default: return string(); 433 435 } 434 436 435 for (int i=0; i< I->getSize()/Size; i++) {437 for (int i=0; i<Size/ElementSize; i++) { 436 438 // Space between entries 437 439 if (i != 0) Text << " "; 438 440 439 441 // 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; 443 444 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; 454 450 } 455 451 } -
Evidence/Evidence.h
r231 r232 26 26 class Config: public DimClient, public DimRpcInfo { 27 27 28 pthread_mutex_t Mutex;29 28 std::string Name; 30 29 DimInfo *Service; … … 44 43 45 44 std::string GetConfig(std::string, std::string); 46 void Lock();47 void Unlock();48 45 void infoHandler(); 49 46 void rpcInfoHandler(); … … 60 57 class Config *ConfClass; 61 58 static int ConfigSignal; // static since accessed in signal handler 59 pthread_mutex_t Mutex; 60 static EvidenceServer *This; 62 61 63 62 static void SignalHandler(int); // static for signal() … … 77 76 std::string GetConfig(std::string, std::string = std::string()); 78 77 void ActivateSignal(int); 79 static std::string ToString(DimInfo *); 78 void Lock(); 79 void Unlock(); 80 static std::string ToString(char *, void *, int); 80 81 static bool ServiceOK(DimInfo *); 81 82 static bool ServiceOK(DimRpcInfo *); … … 85 86 }; 86 87 88 // Class declaration of EvidenceHistory 87 89 class EvidenceHistory { 88 90 -
Evidence/History.cc
r229 r232 137 137 char *Service = I->getName(); 138 138 139 // Check if service known and ignore empty service140 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; 141 141 142 142 // Resize buffer if necessary … … 148 148 if (strcmp(I->getFormat(), "C") != 0) { 149 149 // Calculate sum of all number in array 150 istringstream Text(EvidenceServer::ToString(I ));150 istringstream Text(EvidenceServer::ToString(I->getFormat(), I->getData(), I->getSize())); 151 151 double Num, Sum = 0; 152 152 while (Text.good()) { -
Evidence/readme.txt
r229 r232 46 46 23/6/2010 GetConfig() returns std::string. Non-blocking configuration request in case 47 47 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(). 50 51 24/6/2010 Workaround for erroneous /SERVICE_LIST updates. Added static tokenize method to 51 52 Evidence class. 52 53 30/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. 53 56 54 57
Note:
See TracChangeset
for help on using the changeset viewer.