Index: Evidence/Bridge.cc
===================================================================
--- Evidence/Bridge.cc	(revision 231)
+++ Evidence/Bridge.cc	(revision 232)
@@ -10,4 +10,6 @@
   and commands.
   
+  Configuraton changes are automatically tracked through ConfigChanged()
+    
   Oliver Grimm, June 2010
 
@@ -19,4 +21,5 @@
 #include <string>
 #include <vector>
+#include <regex.h>
 
 const int DEFAULT_PORT = 2505;
@@ -33,14 +36,16 @@
 	  char *Data;
 	};
+
 	map<string, struct Item> Map;
-
+	vector<regex_t> RegEx;
 	DimInfo *ServerList;
 	
     void infoHandler();
     void commandHandler();
-	public:
 	void AddService(string, char *, int);
 	void RemoveService(string);
+	void ConfigChanged();
 	void BugFix();
+	void Undo();
 
   public:
@@ -55,14 +60,55 @@
   DimClient::setDnsNode(Name, Port);
 
-  // Subsribe to top-level server list
-  ServerList = new DimInfo((char *) "DIS_DNS/SERVER_LIST", NO_LINK, this);
-}
-
-
-// Destructor: Delete all subscriptions and services
+  // Initialise and request notification of configuration changes
+  ServerList = NULL;
+  GetConfig("cmdallow", " ");
+  ActivateSignal(SIGUSR2);
+}
+
+
+// Destructor
 Bridge::~Bridge() {
+
+  Undo();
+}
+
+
+// Undo: Delete all subscriptions and regular expressions
+void Bridge::Undo() {
 
   while (Map.size() != 0) RemoveService((*Map.begin()).first);  
   delete ServerList;
+  for (int i=0; i<RegEx.size(); i++) regfree(&RegEx[i]);
+  RegEx.clear();
+}
+
+
+// Called by signal handler in case configuration changes (also initially)
+void Bridge::ConfigChanged() {
+
+  static string ExcludeString;
+
+  // Check if configuratiomn changed
+  if (ExcludeString == GetConfig("exclude")) return;
+  ExcludeString = GetConfig("exclude");
+  
+  // Remove all previous subscriptions
+  Undo();
+
+  // Compile regular expressions
+  regex_t R;
+  vector<string> Exclude = Tokenize(ExcludeString, " \t");
+  for (int i=0; i<Exclude.size(); i++) {
+	int Ret = regcomp(&R, Exclude[i].c_str(), REG_EXTENDED|REG_NOSUB);
+	if (Ret != 0) {
+	  char Err[200];
+	  regerror(Ret, &R, Err, sizeof(Err));
+	  Message(ERROR, "Error compiling regular expression '%s' (%s)", Exclude[i].c_str(), Err);
+	}
+	else RegEx.push_back(R);
+  }
+
+  // Subscribe to top-level server list
+  ServerList = new DimInfo((char *) "DIS_DNS/SERVER_LIST", NO_LINK, this);
 }
 
@@ -78,5 +124,5 @@
   // If service is DIS_DNS/SERVER_LIST, subscribe to all SERVICE_LIST services
   if (strcmp(I->getName(), "DIS_DNS/SERVER_LIST") == 0) {
-    printf("DIS_DNS/SERVER_LIST: '%s'\n", I->getString());
+
 	char *Token = strtok(I->getString(), "+-!@");	
 	while (Token != NULL) {
@@ -156,7 +202,15 @@
 
 
-// Command repeating
+// Command repeating (also handles requests for remote procedure calls)
 void Bridge::commandHandler() {
- 
+
+  // Check if client allowed to send commands
+  vector<string> Client = Tokenize(getClientName(), "@");
+  if (Client.size() == 2 && GetConfig("cmdallow").find(Client[1]) == string::npos) {
+	Message(INFO, "Rejected command/rpc from %s (ID %d)", getClientName(), getClientId());
+	return;  
+  } 
+
+  // Send command to server
   sendCommandNB(getCommand()->getName(), getCommand()->getData(), getCommand()->getSize());
 }
@@ -166,9 +220,11 @@
 void Bridge::AddService(string Name, char *Format, int Type) {
 
-  // Do not forward  DIS_DNS and History services
-  if ((Name.find("DIS_DNS/") != string::npos) || (Name.find("History/") != string::npos)) return;
-
   // Check if already subscribed to this service
   if (Map.count(Name) != 0) return;
+
+  // Should service be ignored?
+  for (int i=0; i<RegEx.size(); i++) {
+    if (regexec(&RegEx[i], Name.c_str(), (size_t) 0, NULL, 0) == 0) return;
+  }
 
   // Create subscription and service to secondary DNS or new command
Index: Evidence/DColl.cc
===================================================================
--- Evidence/DColl.cc	(revision 231)
+++ Evidence/DColl.cc	(revision 232)
@@ -253,6 +253,6 @@
   for (int Service=0; Service<List.size(); Service++) if (I == List[Service].DataItem) {
 
-	// Service excluded from writing?
-	if (List[Service].Exclude) return;
+	// Service excluded from writing or contains no data?
+	if (List[Service].Exclude || I->getSize()==0) return;
 	
 	// Write data header
@@ -263,5 +263,5 @@
 
 	// Translate data into ASCII
-	string Text = EvidenceServer::ToString(I);
+	string Text = EvidenceServer::ToString(I->getFormat(), I->getData(), I->getSize());
 
 	if (!Text.empty()) {
Index: Evidence/Edd/Edd.cc
===================================================================
--- Evidence/Edd/Edd.cc	(revision 231)
+++ Evidence/Edd/Edd.cc	(revision 232)
@@ -64,5 +64,4 @@
 
   W->setStatusTip(Status);
-  if (W->parent() == NULL) W->setToolTip(Status);
   
   return(Time != -1);
@@ -132,6 +131,6 @@
     }
 	Text = Text.section(' ', 1);
-  }	
-  else if (Format[0].toUpper() != 'C') Text = Text.section(' ', Index, Index);
+  }
+  else if (Format[0].toUpper() != 'C' && Format != "I:1;C") Text = Text.section(' ', Index, Index);
 
   if (!ShowAsTime) setText(Text);
@@ -233,5 +232,5 @@
 //////////////////////////////////
 
-EddPlot::EddPlot(QString DIMService, int Index, QWidget *P): EddBasePlot(P) {
+EddPlot::EddPlot(QString Service, int Index, QWidget *P): EddBasePlot(P) {
 
   // Widget properties
@@ -247,5 +246,5 @@
   // Connect to DIM handler
   if (connect(Handler, SIGNAL(YEP(QString, int, QByteArray, QString, QString)), SLOT(Update(QString, int, QByteArray, QString, QString))) == false) {
-    printf("Failed connection for %s\n", DIMService.toAscii().data());
+    printf("Failed connection for %s\n", Service.toAscii().data());
   }
 
@@ -259,5 +258,5 @@
 
   // DIM client
-  if (!DIMService.isEmpty()) AddService(DIMService, Index);
+  if (!Service.isEmpty()) AddService(Service, Index);
 }
 
@@ -328,5 +327,5 @@
 	}
 
- 	// Appen data only if service available
+ 	// Append data only if service available
 	if (SetStatus(this, Name, Time, Format)) {
 	  QString Txt = Text;
@@ -597,8 +596,8 @@
   // Rescale y axis (increase range if selected rectangle larger than axis area)
   if (R.right() < 0) {
-	if (R.top() < plotLayout()->canvasRect().top()) {
+	if (yMouse.maxValue() > axisScaleDiv(QwtPlot::yLeft)->upperBound()) {
 	  yMouse.setMaxValue(yMouse.maxValue() + yPlot.width());
 	}
-	if (R.bottom() > plotLayout()->canvasRect().bottom()) {
+	if (yMouse.minValue() < axisScaleDiv(QwtPlot::yLeft)->lowerBound()) {
 	  yMouse.setMinValue(yMouse.minValue() - yPlot.width());
 	}
@@ -609,10 +608,11 @@
   // Rescale x axis (increase range if selected rectangle larger than axis area)
   if (R.top() > plotLayout()->canvasRect().height()) {
-	if (R.left() < plotLayout()->canvasRect().left()) {
+	if (xMouse.maxValue() > axisScaleDiv(QwtPlot::xBottom)->upperBound()) {
+	  xMouse.setMaxValue(xMouse.maxValue() + xPlot.width());
+	}
+	if (xMouse.minValue() < axisScaleDiv(QwtPlot::xBottom)->lowerBound()) {
 	  xMouse.setMinValue(xMouse.minValue() - xPlot.width());
 	}
-	if (R.right() > plotLayout()->canvasRect().right()) {
-	  xMouse.setMaxValue(xMouse.maxValue() + xPlot.width());
-	}
+
 	setAxisScale(QwtPlot::xBottom, xMouse.minValue(), xMouse.maxValue());
   }
@@ -741,5 +741,5 @@
 
   if (!Pure) {
-	// Get history for this service 
+	// Get history for this service
 	const struct EvidenceHistory::Item *R;
 	class EvidenceHistory *Hist;
@@ -748,7 +748,7 @@
 	  while ((R=Hist->Next()) != NULL) {
 		moveCursor (QTextCursor::Start);
-		insertPlainText(QString("(")+QDateTime::fromTime_t(R->Time).toString()+") ");	  
-		insertPlainText(QString((char *) R->Data) + "\n");	  
-	  }
+		insertPlainText(QString("(")+QDateTime::fromTime_t(R->Time).toString()+") " +
+		  QString::fromStdString(EvidenceServer::ToString(Hist->GetFormat(), (void *) R->Data, R->Size)) + "\n"); 
+	  }	
 	}
 	Handler->DropHistory(Name);
@@ -814,7 +814,9 @@
 }
 
+// Destructor
 EddDim::~EddDim() {
 
-  for (int i=0; i<HistoryList.size(); i++) delete HistoryList[i].HistClass;
+  QList<QString> L = HistoryList.keys();
+  for(int i=0; i<L.size(); i++) delete HistoryList[L[i]].HistClass;
 
   delete Mutex;
@@ -827,23 +829,16 @@
   QMutexLocker Locker(Mutex);
 
-  // If already subscribed to service, increase usage count
-  for (int i=0; i<ServiceList.size(); i++) if (ServiceList[i].Name == Name) {
-	ServiceList[i].Count++;
-	// If service already received, reemit for new subscriber
-	if (!ServiceList[i].ByteArray.isEmpty()) {
-	  YEP(Name, ServiceList[i].TimeStamp, ServiceList[i].ByteArray, ServiceList[i].Format, ServiceList[i].Text);
-	}
-	else YEP(Name, -1);
+  // If already subscribed to service, increase usage count and reemit data for new subscriber
+  if (ServiceList.contains(Name)) {
+	ServiceList[Name].Count++;
+	YEP(Name, ServiceList[Name].TimeStamp, ServiceList[Name].ByteArray, ServiceList[Name].Format, ServiceList[Name].Text);
 	return;
   }
 
   // Create new entry in service list
-  struct Item New;
-  New.Name = Name;
-  New.ByteArray = QByteArray();
-  New.Count = 1;
-  New.DIMService = new DimStampedInfo(Name.toAscii().data(), INT_MAX, NO_LINK, this);
-  ServiceList.append(New);
-
+  ServiceList[Name].ByteArray = QByteArray();
+  ServiceList[Name].TimeStamp = -1;
+  ServiceList[Name].Count = 1;
+  ServiceList[Name].DIMService = new DimStampedInfo(Name.toAscii().data(), INT_MAX, NO_LINK, this);
   return;
 }
@@ -855,11 +850,10 @@
   QMutexLocker Locker(Mutex);
 
-  for (int i=0; i<ServiceList.size(); i++) if (ServiceList[i].Name == Name) {
-	ServiceList[i].Count--;
-	if (ServiceList[i].Count == 0) {
-	  delete ServiceList[i].DIMService;
-	  ServiceList.removeAt(i);
-	  return;
-	}
+  if (ServiceList.contains(Name)) ServiceList[Name].Count--;
+
+  if (ServiceList[Name].Count == 0) {
+	delete ServiceList[Name].DIMService;
+	ServiceList.remove(Name);
+	return;
   }
 }
@@ -869,24 +863,22 @@
 
   // History already available (only request again if too old)
-  for (int i=0; i<HistoryList.size(); i++) if (HistoryList[i].Name == Name) {
-	HistoryList[i].Count++;
-	if (time(NULL)-HistoryList[i].LastUpdate < 5) {
-	  HistoryList[i].HistClass->Rewind();
-	  return HistoryList[i].HistClass;
+  if (HistoryList.contains(Name)) {
+	HistoryList[Name].Count++;
+
+	if (time(NULL)-HistoryList[Name].LastUpdate < 5) {
+	  HistoryList[Name].HistClass->Rewind();
+	  return HistoryList[Name].HistClass;
 	}
-	HistoryList[i].LastUpdate = time(NULL);
-	if (HistoryList[i].HistClass->GetHistory()) return HistoryList[i].HistClass;
+	HistoryList[Name].LastUpdate = time(NULL);
+	if (HistoryList[Name].HistClass->GetHistory()) return HistoryList[Name].HistClass;
 	else return NULL;
   }
 
   // Create new history class
-  struct HistItem New;
-  New.Name = Name;
-  New.HistClass = new EvidenceHistory(Name.toStdString());
-  New.Count = 1;
-  New.LastUpdate = time(NULL);
-  HistoryList.append(New);
-
-  if (New.HistClass->GetHistory()) return New.HistClass;
+  HistoryList[Name].HistClass = new EvidenceHistory(Name.toStdString());
+  HistoryList[Name].Count = 1;
+  HistoryList[Name].LastUpdate = time(NULL);
+
+  if (HistoryList[Name].HistClass->GetHistory()) return HistoryList[Name].HistClass;
   else return NULL;
 }
@@ -895,7 +887,5 @@
 void EddDim::DropHistory(QString Name) {
 
-  for (int i=0; i<HistoryList.size(); i++) {
-	if (HistoryList[i].Name == Name) HistoryList[i].Count--;
-  }
+  if (HistoryList.contains(Name)) HistoryList[Name].Count--;
 }
 
@@ -903,22 +893,22 @@
 void EddDim::UpdateStatistics() {
 
-  // Remove unused histories after not less than 5 seconds
-  for (int i=0; i<HistoryList.size(); i++) {
-	if ((HistoryList[i].Count <= 0) && (time(NULL)-HistoryList[i].LastUpdate) > 5) { 
-	  delete HistoryList[i].HistClass;
-	  HistoryList.removeAt(i);
-	}
-  }
-
   // Lock before accessing internal variables
   QMutexLocker Locker(Mutex);
 
+  // Remove unused histories after not less than 5 seconds
+  QList<QString> L = HistoryList.keys();
+  for(int i=0; i<L.size(); i++) {
+	if ((HistoryList[L[i]].Count <= 0) && (time(NULL)-HistoryList[L[i]].LastUpdate) > 5) { 
+	  delete HistoryList[L[i]].HistClass;
+	  HistoryList.remove(L[i]);
+	}
+  }
+  
   float Rate = Volume/1024.0/10;
-
+  Volume = 0;
   YEP("Edd/Rate_kBSec", time(NULL), QByteArray::number(Rate), "F", QString::number(Rate));
-  Volume = 0;
-}
-
-// Store service information for usage by Subscribe() and update statistics
+}
+
+// Store service information for usage by Subscribe(), update statistics and emit signal to widgets
 void EddDim::Update(QString Name, int Time, QByteArray Data, QString Format, QString Text) {
 
@@ -926,18 +916,21 @@
   QMutexLocker Locker(Mutex);
 
-  for (int i=0; i<ServiceList.size(); i++) if (ServiceList[i].Name == Name) {
-	  ServiceList[i].TimeStamp = Time;
-	  ServiceList[i].ByteArray = Data;
-	  ServiceList[i].Format = Format;
-	  ServiceList[i].Text = Text;
-  }
-
-  // Update statistics only for Dim services
+  // Store service data
+  if (ServiceList.contains(Name)) {
+	  ServiceList[Name].TimeStamp = Time;
+	  ServiceList[Name].ByteArray = Data;
+	  ServiceList[Name].Format = Format;
+	  ServiceList[Name].Text = Text;
+  }
+
+  // Update statistics only for actual Dim services
   if (!Name.startsWith("Edd/")) Volume += Data.size();
   
-  YEP(Name, Time, Data, Format, Text);  
+  // Emit signal to all widgets
+  YEP(Name, Time, Data, Format, Text);
 }
 
 // Handling of DIM service update
+// No locking allowed. Signal triggers only EddDim::Update() when the main event loop is idle.
 void EddDim::infoHandler() {
 
@@ -945,5 +938,5 @@
   else {
 	INT(getInfo()->getName(), getInfo()->getTimestamp(), QByteArray((char *) getInfo()->getData(), 
-		getInfo()->getSize()), getInfo()->getFormat(), QString::fromStdString(EvidenceServer::ToString(getInfo())));
+		getInfo()->getSize()), getInfo()->getFormat(), QString::fromStdString(EvidenceServer::ToString(getInfo()->getFormat(), getInfo()->getData(), getInfo()->getSize())));
   }
 }
@@ -1235,5 +1228,5 @@
   EddText *Text = new EddText("Bias/ConsoleOut", true);
   Text->setFixedWidth(400);
-  Layout->addWidget(Text, 11, 0, 4, 4);      
+  Layout->addWidget(Text, 11, 0, 4, 4);
 }
 
@@ -1249,27 +1242,24 @@
   EddPlot *Plot = new EddPlot();
   for (int i=0; i<36; i++) {
-    Line = new EddLineDisplay("drsdaq/Average", i);
+    Line = new EddLineDisplay("Feedback/Average", i);
 	Line->setMaximumWidth(60);
-    Layout->addWidget(Line, i%9+1, 0+i/9, 1, 1);
-    Plot->AddService("drsdaq/Average", i);
+    Layout->addWidget(Line, i%9+2, 0+i/9, 1, 1);
+    Plot->AddService("Feedback/Average", i);
   }
   Layout->addWidget(Plot, 0, 4, 12, 10);
-
-  //Graph = new EddPlot();
-  //for (int i=0; i<36; i++) {
-    //Text = Text.sprintf("Feedback/Sigma/ID%.2d/%.2d-%.3d",i/16, (i%16)/8, i%8);
-    //Graph->AddService(Text);
-  //}
-  //FeedbackLayout->addWidget(Graph, 10, 0, 10, 3);
 
   Line = new EddLineDisplay("drsdaq/Message");
   Line->setMaximumWidth(200);
   Layout->addWidget(Line, 0, 0, 1, 2);      
-  Line = new EddLineDisplay("drsdaq/Count");
+
+  Line = new EddLineDisplay("Feedback/State");
+  Line->setMaximumWidth(150);
+  Layout->addWidget(Line, 1, 0, 1, 2);      
+  Line = new EddLineDisplay("Feedback/Count");
   Line->setMaximumWidth(60);
-  Layout->addWidget(Line, 0, 2);      
+  Layout->addWidget(Line, 1, 2);      
 
   QWidget *Button = new QPushButton("Details");
-  Layout->addWidget(Button, 10, 0, 1, 1);      
+  Layout->addWidget(Button, 12, 0, 1, 1);      
   connect(Button, SIGNAL(pressed()), SLOT(FeedbackDetails()));
 
@@ -1278,18 +1268,31 @@
 void TP_Feedback::FeedbackDetails() {
 
-  setAttribute(Qt::WA_DeleteOnClose);
+  QMainWindow *M = new QMainWindow;
+  M->setCentralWidget(new QWidget);
+  M->setStatusBar(new QStatusBar(M));
+  M->setWindowTitle("Edd - Feedback Details");
+  M->setAttribute(Qt::WA_DeleteOnClose);
+
+  QGridLayout *Layout = new QGridLayout(M->centralWidget());
   EddLineDisplay *Line;
-  QWidget *Widget = new QWidget();
-  QGridLayout *Layout = new QGridLayout(Widget);
   EddPlot *Plot = new EddPlot();
+
   for (int i=0; i<36; i++) {
-    Line = new EddLineDisplay("drsdaq/Sigma", i);
-	Line->setMaximumWidth(50);
-    Layout->addWidget(Line, i%9+1, 0+i/9, 1, 1);
-    Plot->AddService("drsdaq/Sigma", i);
-  }
-  Layout->addWidget(Plot, 0, 4, 12, 10);
-  
-  Widget->show();
+    Line = new EddLineDisplay("Feedback/Sigma", i);
+	Line->setMaximumWidth(60);
+    Layout->addWidget(Line, i%9, 0+i/9, 1, 1);
+    Plot->AddService("Feedback/Sigma", i);
+	
+    Line = new EddLineDisplay("Feedback/Target", i);
+	Line->setMaximumWidth(60);
+    Layout->addWidget(Line, i%9+10, 0+i/9, 1, 1);
+	
+	Line = new EddLineDisplay("Feedback/Response", i);
+	Line->setMaximumWidth(60);
+    Layout->addWidget(Line, i%9+20, 0+i/9, 1, 1);
+  }
+  Layout->addWidget(Plot, 0, 4, 30, 12);
+  
+  M->show();
 }
 
Index: Evidence/Edd/Edd.h
===================================================================
--- Evidence/Edd/Edd.h	(revision 231)
+++ Evidence/Edd/Edd.h	(revision 232)
@@ -36,4 +36,5 @@
 bool SetStatus(QWidget *, QString, int, QString, int = -1);
 
+
 // Base class for Edd plot
 // DeleteCurve() is pure virtual and needs to be implemented iin the application class
@@ -213,5 +214,4 @@
   private:
 	struct Item {
-	  QString Name;
 	  DimStampedInfo *DIMService;
 	  int Count;
@@ -221,14 +221,13 @@
 	  QString Text;
 	};
-    QList<Item> ServiceList;
+    QMap<QString, struct Item> ServiceList;
     QMutex *Mutex;
 
 	struct HistItem {
-	  QString Name;
 	  int Count;
 	  int LastUpdate;
 	  class EvidenceHistory *HistClass;
 	};
-    QList<HistItem> HistoryList;
+    QMap<QString, struct HistItem> HistoryList;
 
 	long long Volume;
Index: Evidence/Evidence.cc
===================================================================
--- Evidence/Evidence.cc	(revision 231)
+++ Evidence/Evidence.cc	(revision 232)
@@ -17,5 +17,5 @@
     These signals will then cause pause() to return which can be used
 	by the application to terminate gracefully.
-  - The static method ToString() converts the contents of a DIMInfo service into text
+  - The static method ToString() converts the contents of a DIM service into text
   - A terminate-handler is installed for catching unhandled C++ exceptions.
 
@@ -27,10 +27,7 @@
 using namespace std;
 
-EvidenceServer *ThisServer;
-
 //
 // Internal configuration class of EvidenceServer
 //
-// Data that might be accessed by two threads are protected by mutex
 
 // Constructor
@@ -38,12 +35,6 @@
 
   // Initialise
-  int Ret;
-  if ((Ret = pthread_mutex_init(&Mutex, NULL)) != 0) {
-    ThisServer->Message(ThisServer->FATAL, "pthread_mutex_init() failed in Config constructor (%s)", strerror(Ret));
-  }
   CurrentItem = string();
   ConfigTimeStamp = 0;
-  
-  // Signal delivered to this thread if configuration file changes 
   ThreadID = pthread_self();
 
@@ -56,9 +47,4 @@
   
   delete Service;
-
-  int Ret;
-  if ((Ret = pthread_mutex_destroy(&Mutex)) != 0) {
-	ThisServer->Message(ThisServer->ERROR, "pthread_mutex_destroy() failed in Config destructor (%s)", strerror(Ret));
-  }
 }
 
@@ -66,10 +52,10 @@
 void EvidenceServer::Config::infoHandler() {
 
-  Lock();
+  This->Lock();
   ConfigTimeStamp = getInfo()->getInt();
-  Unlock();
-
-  if (pthread_kill(ThreadID, ThisServer->ConfigSignal) != 0) {
-	ThisServer->Message(ThisServer->WARN, "Could not send signal to main thread");
+  This->Unlock();
+
+  if (pthread_kill(ThreadID, This->ConfigSignal) != 0) {
+	This->Message(WARN, "Could not send signal to main thread");
   }
 }
@@ -78,5 +64,5 @@
 void EvidenceServer::Config::rpcInfoHandler(){
 
-  Lock();
+  This->Lock();
   // Update map
   List[CurrentItem].Value = string(getString(), getSize()-1);
@@ -84,5 +70,5 @@
   // Clear to allow new rpc call
   CurrentItem.clear(); 
-  Unlock();
+  This->Unlock();
 }
 
@@ -93,7 +79,7 @@
 
   // If up-to-date data in configuration list available, return this
-  Lock();
+  This->Lock();
   if ((List.count(Item) > 0) && (List[Item].Time >= ConfigTimeStamp)) Result = List[Item].Value;
-  Unlock();
+  This->Unlock();
   if (!Result.empty()) return Result;
 
@@ -106,5 +92,5 @@
 	if (!EvidenceServer::ServiceOK(&Config)) {
       if (Default.empty()) {
-		ThisServer->Message(ThisServer->FATAL, "Configuration server unreachable, can't retrieve '%s'", Item.c_str());
+		This->Message(FATAL, "Configuration server unreachable, can't retrieve '%s'", Item.c_str());
 	  }
 	  else Result = Default;
@@ -117,14 +103,14 @@
 	// Update configuration map	
 	if (!Result.empty()) {
-	  Lock();
+	  This->Lock();
 	  List[Item].Value = Result;
 	  List[Item].Time = ConfigTimeStamp;
-	  Unlock();
+	  This->Unlock();
 	}	
   }
 
-  // Non-blocking configuration request fro other threads
+  // Non-blocking configuration request from other threads
   if (pthread_self() != ThreadID) {
- 	Lock();
+ 	This->Lock();
 	if (List.count(Item) > 0) {
 	  // New request possible only when answer to previous request received
@@ -136,45 +122,9 @@
 	  // Return current value
 	  Result = List[Item].Value;
-	  Unlock();
+	  This->Unlock();
 	}
   }
 
   return Result;
-}
-
-// Locking and unlocking for list access
-// Signal blocked before locking to avaoid dead-lock by calling GetConfig() from ConfigChanged().
-void EvidenceServer::Config::Lock() {
-
-  int Ret = 0;
-  sigset_t Set;
-
-  if (ThisServer->ConfigSignal != 0) {
-	Ret += abs(sigemptyset(&Set));
-	Ret += abs(sigaddset(&Set, ThisServer->ConfigSignal));
-	Ret += abs(pthread_sigmask(SIG_BLOCK, &Set, NULL));
-  }
-  Ret += abs(pthread_mutex_lock(&Mutex));
-  
-  if (Ret != 0) {
-	ThisServer->Message(ThisServer->FATAL, "Thread related call failed in Config::Lock()");
-  }
-}
-
-void EvidenceServer::Config::Unlock() {
-
-  int Ret = 0;
-  sigset_t Set;
-
-  Ret += abs(pthread_mutex_unlock(&Mutex));
-  if (ThisServer->ConfigSignal != 0) {
-	Ret += abs(sigemptyset(&Set));
-	Ret += abs(sigaddset(&Set, ThisServer->ConfigSignal));
-	Ret += abs(pthread_sigmask(SIG_UNBLOCK, &Set, NULL));
-  }
-
-  if (Ret != 0) {
-	ThisServer->Message(ThisServer->FATAL, "Thread related call failed in Config::Unlock()");
-  }
 }
 
@@ -185,4 +135,5 @@
 
 int EvidenceServer::ConfigSignal = 0;
+EvidenceServer *EvidenceServer::This = NULL;
 
 // Constructor starts server with given name
@@ -193,5 +144,16 @@
   MessageData = NULL;
   ExitRequest = false;
-  ThisServer = this;
+  This = this;
+
+  // Initialise mutex
+  int Ret;
+  pthread_mutexattr_t Attr;
+
+  if ((Ret = pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_ERRORCHECK)) != 0) {
+    Message(FATAL, "pthread_mutex_settype() failed (%s)", strerror(Ret));
+  }
+  if ((Ret = pthread_mutex_init(&Mutex, &Attr)) != 0) {
+    Message(FATAL, "pthread_mutex_init() failed (%s)", strerror(Ret));
+  }
 
   // Catch some signals
@@ -225,5 +187,10 @@
   delete ConfClass;
   delete MessageService;
-  delete MessageData;
+  delete[] MessageData;
+  
+  int Ret;
+  if ((Ret = pthread_mutex_destroy(&Mutex)) != 0) {
+	Message(ERROR, "pthread_mutex_destroy() failed (%s)", strerror(Ret));
+  }
 }
 
@@ -270,5 +237,5 @@
 	MessageService->updateService(NewMsg, sizeof(struct Message)+strlen(NewMsg->Text)+1);
   }
-  delete MessageData;
+  delete[] MessageData;
   MessageData = NewMsg;
 
@@ -311,5 +278,6 @@
 }
 
-// Signal emitted when configuraton file changes, signal handler calls ConfigChanged()
+
+// Set signal emitted when configuraton file changes, signal handler calls ConfigChanged()
 void EvidenceServer::ActivateSignal(int Signal) {
 
@@ -323,4 +291,43 @@
 
 
+// Locking and unlocking for list access
+// Signal blocked before locking to avoid dead-lock by calling GetConfig() from ConfigChanged().
+void EvidenceServer::Lock() {
+
+  int Ret;
+  sigset_t Set;
+
+  if (ConfigSignal != 0) {
+	Ret = abs(sigemptyset(&Set));
+	Ret += abs(sigaddset(&Set, ConfigSignal));
+	Ret += abs(pthread_sigmask(SIG_BLOCK, &Set, NULL));
+
+	if (Ret != 0) Message(FATAL, "Signal masking failed in Lock()");
+  }
+
+  if ((Ret = pthread_mutex_lock(&Mutex)) != 0) {
+	Message(FATAL, "pthread_mutex_lock() failed in Lock() (%s)", strerror(Ret));
+  }
+}
+
+void EvidenceServer::Unlock() {
+
+  int Ret;
+  sigset_t Set;
+
+  if ((Ret = pthread_mutex_unlock(&Mutex)) != 0) {
+	Message(FATAL, "pthread_mutex_unlock() failed in Unlock() (%s)", strerror(Ret));
+  }
+  
+  if (ConfigSignal != 0) {
+	Ret = abs(sigemptyset(&Set));
+	Ret += abs(sigaddset(&Set, ConfigSignal));
+	Ret += abs(pthread_sigmask(SIG_UNBLOCK, &Set, NULL));
+
+	if (Ret != 0) Message(FATAL, "Signal unmasking failed in Unlock()");
+  }
+}
+
+
 // ====== Static methods ======
 
@@ -332,5 +339,5 @@
   // If signal indicates configuration change, invoke call-back
   if (Signal == EvidenceServer::ConfigSignal) {
-    ThisServer->ConfigChanged();
+    This->ConfigChanged();
 	return;
   }
@@ -339,10 +346,10 @@
   if (!Called) {
 	Called = true;
-	ThisServer->ExitRequest = true;
+	This->ExitRequest = true;
 	return;
   }
 
   // If invoked twice, call exit()
-  ThisServer->Message(ThisServer->WARN, "Signal handler called again, invoking exit() (signal %d)", Signal);
+  This->Message(WARN, "Signal handler called again, invoking exit() (signal %d)", Signal);
   exit(EXIT_FAILURE);
 }
@@ -355,7 +362,7 @@
 
   if (Terminating) {
-	Msg << ThisServer->Name << ": Terminate() called recursively, calling abort()";
+	Msg << This->Name << ": Terminate() called recursively, calling abort()";
 	printf("%s\n", Msg.str().c_str());
-	ThisServer->SendToLog(Msg.str().c_str());
+	This->SendToLog(Msg.str().c_str());
 	abort();
   }
@@ -383,22 +390,18 @@
   else Msg << "Terminate() called without an active exception";
 
-  ThisServer->Message(FATAL, Msg.str().c_str());
-}
-
-
-// Translates DIMInfo safely to string (assures no inivalid memory accesses are made)
-string EvidenceServer::ToString(DimInfo *I) {
+  This->Message(FATAL, Msg.str().c_str());
+}
+
+
+// Translates DIM data safely to string (assures no invalid memory accesses are made)
+string EvidenceServer::ToString(char *Format, void *Data, int Size) {
 
   ostringstream Text;
   
-  // Safety check
-  if (I->getSize() < 1) return string();
-
   // 'Message' service format handled here
-  if (strcmp(I->getFormat(), "I:1;C") == 0 && I->getSize()>=(int) sizeof(struct Message)) {
-	struct Message *Msg = (struct Message *) I->getData();
+  if (strcmp(Format, "I:1;C") == 0 && Size >= (int) sizeof(struct Message)) {
+	struct Message *Msg = (struct Message *) Data;
 	// Safely extract string and limit to length of C string (padding might make it longer)
-	string MsgText(Msg->Text, I->getSize()-sizeof(struct Message));
-    //MsgText.erase(strlen(MsgText.c_str()));
+	string MsgText(Msg->Text, Size-sizeof(struct Message));
 	Text << Msg->Severity << " " << MsgText.erase(strlen(MsgText.c_str()));
 
@@ -407,7 +410,7 @@
   
   // Structure: print hex representation 
-  if (strlen(I->getFormat()) != 1) {
-	for (int i=0; i<I->getSize(); i++) {
-	  Text << setw(2) << hex << *((char *) I->getData() + i) << " ";
+  if (strlen(Format) != 1) {
+	for (int i=0; i<Size; i++) {
+	  Text << setw(2) << hex << *((char *) Data + i) << " ";
 	} 
 	return Text.str();
@@ -415,41 +418,34 @@
 
   // String if format "C" and terminated with \0
-  if (strcmp(I->getFormat(),"C")==0 && *((char *) I->getData()+I->getSize()-1)=='\0') {  
-    Text << I->getString(); 
-	return Text.str();
+  if (strcmp(Format, "C") == 0 && Size > 0 && *((char *) Data+Size-1)=='\0') {
+	return string((char *) Data);
   }
 
   // Number array
-  int Size;
-  switch (*(I->getFormat())) {
-    case 'C': Size = sizeof(char);		break;
+  int ElementSize;
+  switch (*Format) {
+    case 'C': ElementSize = sizeof(char);		break;
     case 'I':
-    case 'L': Size = sizeof(int);		break;
-    case 'S': Size = sizeof(short);		break;
-    case 'F': Size = sizeof(float);		break;
-    case 'D': Size = sizeof(double);	break;
-    case 'X': Size = sizeof(long long);	break;
+    case 'L': ElementSize = sizeof(int);		break;
+    case 'S': ElementSize = sizeof(short);		break;
+    case 'F': ElementSize = sizeof(float);		break;
+    case 'D': ElementSize = sizeof(double);		break;
+    case 'X': ElementSize = sizeof(long long);	break;
     default: return string();
   }
 
-  for (int i=0; i<I->getSize()/Size; i++) {
+  for (int i=0; i<Size/ElementSize; i++) {
 	// Space between entries
     if (i != 0) Text << " ";
 
 	// Translate data
-	switch (*(I->getFormat())) {
-      case 'C': Text << *((char *) I->getData() + i);
-				break;
+	switch (*Format) {
+      case 'C': Text << *((char *) Data + i);		break;
       case 'I':
-      case 'L': Text << *((int *) I->getData() + i);
-				break;
-      case 'S': Text << *((short *) I->getData() + i);
-				break;
-      case 'F': Text << *((float *) I->getData() + i);
-				break;
-      case 'D': Text << *((double *) I->getData() + i);
-				break;
-      case 'X': Text << *((long long *) I->getData() + i);
-				break;
+      case 'L': Text << *((int *) Data + i);		break;
+      case 'S': Text << *((short *) Data + i);		break;
+      case 'F': Text << *((float *) Data + i);		break;
+      case 'D': Text << *((double *) Data + i);		break;
+      case 'X': Text << *((long long *) Data + i);	break;
 	}
   }
Index: Evidence/Evidence.h
===================================================================
--- Evidence/Evidence.h	(revision 231)
+++ Evidence/Evidence.h	(revision 232)
@@ -26,5 +26,4 @@
 	class Config: public DimClient, public DimRpcInfo {
 
-		pthread_mutex_t Mutex;
 		std::string Name;
 		DimInfo *Service;
@@ -44,6 +43,4 @@
 
 		std::string GetConfig(std::string, std::string);
-		void Lock();
-		void Unlock();
 		void infoHandler();
 		void rpcInfoHandler();
@@ -60,4 +57,6 @@
 	class Config *ConfClass;
 	static int ConfigSignal;		// static since accessed in signal handler
+	pthread_mutex_t Mutex;
+	static EvidenceServer *This;
 
     static void SignalHandler(int); // static for signal()
@@ -77,5 +76,7 @@
 	std::string GetConfig(std::string, std::string = std::string());
 	void ActivateSignal(int);
-	static std::string ToString(DimInfo *);
+	void Lock();
+	void Unlock();
+	static std::string ToString(char *, void *, int);
 	static bool ServiceOK(DimInfo *);
 	static bool ServiceOK(DimRpcInfo *);
@@ -85,4 +86,5 @@
 };
 
+// Class declaration of EvidenceHistory
 class EvidenceHistory {
 
Index: Evidence/History.cc
===================================================================
--- Evidence/History.cc	(revision 231)
+++ Evidence/History.cc	(revision 232)
@@ -137,6 +137,6 @@
   char *Service = I->getName();
 
-  // Check if service known and ignore empty service
-  if (Map.count(Service) == 0 || I->getSize()==0 || I->getTimestamp()==0) return;
+  // Check if service known and ignore empty or illegal time stamped service
+  if (Map.count(Service) == 0 || I->getSize()==0 || I->getTimestamp()<=0) return;
   
   // Resize buffer if necessary
@@ -148,5 +148,5 @@
   if (strcmp(I->getFormat(), "C") != 0) {
 	// Calculate sum of all number in array
-	istringstream Text(EvidenceServer::ToString(I));
+	istringstream Text(EvidenceServer::ToString(I->getFormat(), I->getData(), I->getSize()));
 	double Num, Sum = 0;
 	while (Text.good()) {
Index: Evidence/readme.txt
===================================================================
--- Evidence/readme.txt	(revision 231)
+++ Evidence/readme.txt	(revision 232)
@@ -46,9 +46,12 @@
 23/6/2010	GetConfig() returns std::string. Non-blocking configuration request in case
 			GetConfig() not called from main thread. Access to configuration information
-			internally mutex protected. Signal SIGUSR2 send to main thread upon configuration
-			file change, signal handler invokes (virtual) method ConfigChanged().
+			internally mutex protected. With ActivateSignal() a signal can be set that is send
+			to main thread upon configuration file change, the build-in signal handler then
+			invokes the (virtual) method ConfigChanged().
 24/6/2010	Workaround for erroneous /SERVICE_LIST updates. Added static tokenize method to
 			Evidence class.
-
+30/6/2010	Made Lock()/Unlock() publicly available (mutex of type PTHREAD_MUTEX_ERRORCHECK),
+			in case signal is set with ActivateSignal() this signal will be blocked while locked.
+			Implemented experimental automatic full configuration tracking for Bridge.
 
 
