Index: Evidence/Alarm.cc
===================================================================
--- Evidence/Alarm.cc	(revision 213)
+++ Evidence/Alarm.cc	(revision 216)
@@ -71,5 +71,5 @@
   }
 
-  // Subscribe with handler to 'Status' service of all servers
+  // Subscribe with handler to 'Message' service of all servers
   StatusService = new DimStampedInfo* [NumServers];
   State = new int [NumServers];
@@ -79,5 +79,5 @@
     char *Buffer = new char [strlen(Server[i])+10];
     strcpy(Buffer, Server[i]);
-    strcat(Buffer, "/Status");
+    strcat(Buffer, "/Message");
     StatusService[i] = new DimStampedInfo(Buffer, NO_LINK, this);
     delete[] Buffer;
@@ -107,5 +107,5 @@
 
 	// Ignore DIS_DNS (has no status service)
-	if (strcmp(getInfo()->getName(),"DIS_DNS/Status") == 0) return;
+	if (strcmp(getInfo()->getName(),"DIS_DNS/Message") == 0) return;
 	
 	// Update State: unavailable or current severity of status  
Index: Evidence/Config.cc
===================================================================
--- Evidence/Config.cc	(revision 213)
+++ Evidence/Config.cc	(revision 216)
@@ -67,15 +67,15 @@
   // Initialise mutex (errno is not set by pthread_mutex_init())
   if (pthread_mutex_init(&Mutex, NULL) != 0) {
-    State(FATAL, "pthread_mutex_init() failed");
+    Message(FATAL, "pthread_mutex_init() failed");
   }
 
   // Open configuration file
   if ((File = fopen(Filename, "r")) == NULL) {
-    State(FATAL, "Could not open configuration file '%s' (%s)\n", Filename, strerror(errno));
+    Message(FATAL, "Could not open configuration file '%s' (%s)\n", Filename, strerror(errno));
   }
 
   // Disable buffering, so file modifications are immediately seen
   if (setvbuf(File, NULL, _IONBF, 0) != 0) {
-    State(WARN, "Error setting configuration file '%s' to unbuffered mode", Filename);
+    Message(WARN, "Error setting configuration file '%s' to unbuffered mode", Filename);
   }
   
@@ -87,5 +87,5 @@
 EvidenceConfig::~EvidenceConfig() {
 
-  if (File != NULL && fclose(File) != 0) State(ERROR, "Error closing configuration file (%s)", strerror(errno));
+  if (File != NULL && fclose(File) != 0) Message(ERROR, "Error closing configuration file (%s)", strerror(errno));
 
   delete ConfigModified;
@@ -93,5 +93,5 @@
   delete[] FileContent;
 
-  if (pthread_mutex_destroy(&Mutex) != 0) State(ERROR, "pthread_mutex_destroy() failed");
+  if (pthread_mutex_destroy(&Mutex) != 0) Message(ERROR, "pthread_mutex_destroy() failed");
 }
 
@@ -103,5 +103,5 @@
   
   // Lock because ConfigChange() might access concurrently
-  if (pthread_mutex_lock(&Mutex) != 0) State(ERROR, "pthread_mutex_lock() failed in rpcHandler()");
+  if (pthread_mutex_lock(&Mutex) != 0) Message(ERROR, "pthread_mutex_lock() failed in rpcHandler()");
 
   // Search for config data in list (default response is empty string)
@@ -111,10 +111,10 @@
   
   // Unlock
-  if (pthread_mutex_unlock(&Mutex) != 0) State(ERROR, "pthread_mutex_unlock() failed in rpcHandler()");
+  if (pthread_mutex_unlock(&Mutex) != 0) Message(ERROR, "pthread_mutex_unlock() failed in rpcHandler()");
 
   // Send data and update Status
   setData((char *) Response.c_str());
     
-  State(INFO, "Client '%s' (ID %d) requested '%s'. Send '%s'.",
+  Message(INFO, "Client '%s' (ID %d) requested '%s'. Send '%s'.",
 		DimServer::getClientName(),
 		DimServer::getClientId(), 
@@ -135,5 +135,5 @@
   struct stat Stat;
   if (fstat(fileno(File), &Stat) == -1) {
-    State(ERROR, "Error with stat() system call for configuration file, cannot update configuration file information (%s)", strerror(errno));
+    Message(ERROR, "Error with stat() system call for configuration file, cannot update configuration file information (%s)", strerror(errno));
 	delete ConfigModified;
 	delete ConfigContent;
@@ -152,5 +152,5 @@
   rewind(File);
   if (fread(NewContent, sizeof(char), Stat.st_size, File) != Stat.st_size) {
-    State(FATAL, "Could not read configuration file");
+    Message(FATAL, "Could not read configuration file");
   }
   NewContent[Stat.st_size] = '\0';
@@ -176,5 +176,5 @@
     // Remove comments
 	if (Line.find('#') != string::npos) Line.erase(Line.find('#'));
-    // Repace all tabs by spaces
+    // Replace all tabs by spaces
     while (Line.find("\t") != string::npos) Line[Line.find("\t")] = ' ';
 	// Remove leading spaces
@@ -206,7 +206,7 @@
 
 	// Add to configuration list
-	if (pthread_mutex_lock(&Mutex) != 0) State(ERROR, "pthread_mutex_lock() failed in ConfigChanged()");
+	if (pthread_mutex_lock(&Mutex) != 0) Message(ERROR, "pthread_mutex_lock() failed in ConfigChanged()");
 	List.push_back(New);
-	if (pthread_mutex_unlock(&Mutex) != 0) State(ERROR, "pthread_mutex_unlock() failed in ConfigChanged()");
+	if (pthread_mutex_unlock(&Mutex) != 0) Message(ERROR, "pthread_mutex_unlock() failed in ConfigChanged()");
   };
 }
@@ -224,8 +224,8 @@
   
   if ((Notify = inotify_init()) == -1) {
-    Config.State(EvidenceConfig::WARN, "inotify_init() failed, cannot monitor changes of configuration file (%s)\n", strerror(errno));
+    Config.Message(EvidenceConfig::WARN, "inotify_init() failed, cannot monitor changes of configuration file (%s)\n", strerror(errno));
   }
   else if (inotify_add_watch(Notify, argc<2 ? DEFAULT_CONFIG : argv[1], IN_MODIFY) == -1) { 
-      Config.State(EvidenceConfig::WARN, "Could not set inotify watch on configuration file (%s)\n", strerror(errno));
+      Config.Message(EvidenceConfig::WARN, "Could not set inotify watch on configuration file (%s)\n", strerror(errno));
 	  close(Notify);
 	  Notify = -1;
@@ -241,4 +241,5 @@
   }
   
+  // Closing will also free all inotify watches
   if (Notify != -1) close(Notify);
 }
Index: Evidence/DColl.cc
===================================================================
--- Evidence/DColl.cc	(revision 213)
+++ Evidence/DColl.cc	(revision 216)
@@ -13,6 +13,5 @@
   - The history buffers are written to disk at program termination and
     are tired to be read when adding a service.
-  - The command 'DColl/Log' writes the associated string to the log 
-    file specified in the configuration.
+  - The command 'DColl/Log' writes the associated string to the log file
   
   Oliver Grimm, May 2010
@@ -23,4 +22,5 @@
 
 #define MIN_HIST_SIZE 1024	// Minimum history buffer in bytes (> 3*sizeof(int) !)
+#define LOG_FILENAME "Evidence.log"
 
 #include "Evidence.h"
@@ -61,9 +61,8 @@
     FILE *LogFile;
 	char *Filename;
-	float DataSizekB, LogSizekB;
+	float DataSizeMB, LogSizeMB;
 	int DataSizeLastUpdate, LogSizeLastUpdate;
-	char *DataDir;
+	char *BaseDir;
     DimService *LogSizeService, *DataSizeService, *DataFilename;
-	string HistDir;
 	int SizeUpdateDelay;
 	int TimeForNextFile;
@@ -106,13 +105,11 @@
 
   // Request configuration data
-  DataDir = GetConfig("datadir");
+  BaseDir = GetConfig("basedir");
   SizeUpdateDelay = atoi(GetConfig("sizeupdate"));
-  HistDir = GetConfig("histdir");
   RollOver = atoi(GetConfig("rollover"));
 
   // Open log file
-  char *Logname = GetConfig("logfile");
-  if ((LogFile = fopen(Logname, "a")) == NULL) {
-    State(FATAL, "Could not open log file '%s' (%s)", Logname, strerror(errno));
+  if ((LogFile = fopen((string(BaseDir)+"/"+LOG_FILENAME).c_str(), "a")) == NULL) {
+    Message(FATAL, "Could not open log file (%s)", strerror(errno));
   }
 
@@ -121,9 +118,9 @@
               
   // Create services for file sizes and data file name
-  DataSizekB = 0;
-  DataSizeService = new DimService(SERVER_NAME "/DataSizekB", DataSizekB);
-  
-  LogSizekB = FileSize(LogFile)/1024.0;
-  LogSizeService = new DimService(SERVER_NAME "/LogSizekB", LogSizekB);
+  DataSizeMB = 0;
+  DataSizeService = new DimService(SERVER_NAME "/DataSizeMB", DataSizeMB);
+  
+  LogSizeMB = FileSize(LogFile)/1024.0/1024.0;
+  LogSizeService = new DimService(SERVER_NAME "/LogSizekB", LogSizeMB);
 
   DataFilename = new DimService(SERVER_NAME "/CurrentFile", (char *) "");
@@ -155,5 +152,5 @@
 	  RegExCount--;
 	  i--;
-	  State(ERROR, "Error compiling regular expression '%s' (%s)", Token, ErrMsg);
+	  Message(ERROR, "Error compiling regular expression '%s' (%s)", Token, ErrMsg);
 	}
 	else {
@@ -188,8 +185,8 @@
   // Close files
   if (LogFile != NULL) if (fclose(LogFile) != 0) {
-	State(ERROR, "Could not close log file (%s)", strerror(errno));
+	Message(ERROR, "Could not close log file (%s)", strerror(errno));
   }
   if (DataFile != NULL && fclose(DataFile) != 0) {
-	State(ERROR, "Error: Could not close data file (%s)", strerror(errno));
+	Message(ERROR, "Error: Could not close data file (%s)", strerror(errno));
   }
 
@@ -208,7 +205,4 @@
 // no mutex is needed to serialize writing to the file
 void DataHandler::infoHandler() {
-
-  static const int WrapMark[] = {0, -1};
-  static const int EndMark[] = {0, 0};
 
   DimInfo *Info = getInfo();
@@ -254,5 +248,5 @@
   if (time(NULL) >= TimeForNextFile) {
 	if (DataFile != NULL && fclose(DataFile) != 0) {
-	  State(ERROR, "Error: Could not close data file (%s)", strerror(errno));
+	  Message(ERROR, "Error: Could not close data file (%s)", strerror(errno));
 	}
 	DataFile = NULL;
@@ -266,13 +260,13 @@
 	// Get time structure with date rollover
 	if (T->tm_hour >= RollOver) T->tm_mday++;
-	if (mktime(T) == -1) State(ERROR, "mktime() failed, check filename");
+	if (mktime(T) == -1) Message(ERROR, "mktime() failed, check filename");
 
 	// Create direcory if not existing (ignore error if already existing)
 	char *Dir;
-	if (asprintf(&Dir, "%s/%d%02d",DataDir, T->tm_year+1900, T->tm_mon + 1) == -1) {
-	  State(FATAL, "asprintf() failed, could not create direcory name");	
+	if (asprintf(&Dir, "%s/%d%02d", BaseDir, T->tm_year+1900, T->tm_mon + 1) == -1) {
+	  Message(FATAL, "asprintf() failed, could not create direcory name");	
 	}
 	if(mkdir(Dir, S_IRWXU|S_IRWXG)==-1 && errno!=EEXIST) {
-	  State(FATAL, "Could not create directory '%s' (%s)", Dir, strerror(errno));
+	  Message(FATAL, "Could not create directory '%s' (%s)", Dir, strerror(errno));
 	}
 
@@ -280,5 +274,5 @@
 	free(Filename);
 	if (asprintf(&Filename, "%s/%d%02d%02d.slow", Dir, T->tm_year+1900, T->tm_mon+1, T->tm_mday) == 1) {
-	  State(FATAL, "asprintf() failed, could not create filename");		  
+	  Message(FATAL, "asprintf() failed, could not create filename");		  
 	}
 	free(Dir);
@@ -286,7 +280,7 @@
 	// Open file
 	if ((DataFile = fopen(Filename, "a")) == NULL) {
-      State(FATAL, "Could not open data file '%s' (%s)", Filename, strerror(errno));
-	}
-	else State(INFO, "Opened data file '%s'", Filename);
+      Message(FATAL, "Could not open data file '%s' (%s)", Filename, strerror(errno));
+	}
+	else Message(INFO, "Opened data file '%s'", Filename);
 	DataFilename->updateService(Filename);
 	
@@ -337,5 +331,5 @@
       fclose(DataFile);
 	  DataFile = NULL;
-	  State(FATAL, "Error writing to data file, closed file (%s)", strerror(errno));
+	  Message(FATAL, "Error writing to data file, closed file (%s)", strerror(errno));
 	}
 
@@ -344,5 +338,5 @@
       fflush(DataFile); // not continuously to reduce load
 
-	  DataSizekB = FileSize(DataFile)/1024.0;
+	  DataSizeMB = FileSize(DataFile)/1024.0/1024.0;
 	  DataSizeService->updateService();
 	  DataSizeLastUpdate = time(NULL);
@@ -354,5 +348,5 @@
   //
 
-  if (Info->getSize() == 0) return;
+  if (Info->getSize()==0 || Info->getTimestamp()==0) return;
 
   // Check if data should be added to history buffer
@@ -373,7 +367,7 @@
   
   // Check if data fits into buffer
-  if (List[Service].HistSize < Info->getSize() + 5*sizeof(int)) return;
-
-  int Size = Info->getSize() + 4*sizeof(int), Next = List[Service].Next;
+  if (List[Service].HistSize < Info->getSize() + sizeof(int)+ 2*sizeof(EvidenceHistory::Item)) return;
+
+  int Size = Info->getSize() + 2*sizeof(EvidenceHistory::Item), Next = List[Service].Next;
   void *WrapPos = NULL;
   char *Buffer = List[Service].Buffer;
@@ -390,10 +384,10 @@
   		 (Oldest + *((int *) (Buffer + Oldest) + 1) + 2*sizeof(int) > Next)) {
 	// Check for wrap-around
-	if (memcmp(Buffer + Oldest, WrapMark, sizeof(WrapMark)) == 0) {
+	if (memcmp(Buffer + Oldest, &EvidenceHistory::WrapMark, sizeof(EvidenceHistory::WrapMark)) == 0) {
 	  Oldest = 4;
 	  continue;
 	}
 	// Check if end marker reached, then only one event fits buffer
-  	if (memcmp(Buffer + Oldest, EndMark, sizeof(EndMark)) == 0) {
+  	if (memcmp(Buffer + Oldest, &EvidenceHistory::EndMark, sizeof(EvidenceHistory::EndMark)) == 0) {
 	  Oldest = Next;
 	  break;
@@ -406,5 +400,5 @@
 
   // Write wrap mark if necessary
-  if (WrapPos != NULL) memcpy(WrapPos, WrapMark, sizeof(WrapMark));
+  if (WrapPos != NULL) memcpy(WrapPos, &EvidenceHistory::WrapMark, sizeof(EvidenceHistory::WrapMark));
 
   // Copy data into ring buffer
@@ -414,6 +408,6 @@
 
   // Adjust pointer for next entry and write end marker to buffer
-  Next += Info->getSize() + 2*sizeof(int);
-  memcpy(Buffer + Next, EndMark, sizeof(EndMark));
+  Next += Info->getSize() + sizeof(EvidenceHistory::Item);
+  memcpy(Buffer + Next, &EvidenceHistory::EndMark, sizeof(EvidenceHistory::EndMark));
   
   List[Service].Next = Next;
@@ -437,20 +431,20 @@
   struct tm *TM = localtime(&RawTime);
 
-  fprintf(LogFile, "%d/%d/%d %d:%d:%d: %s\n",
+  fprintf(LogFile, "%2d/%2d/%4d %2d:%2d:%2d %s (ID %d): %s\n",
   		TM->tm_mday, TM->tm_mon+1, TM->tm_year+1900,
-		TM->tm_hour, TM->tm_min, TM->tm_sec, Text);
+		TM->tm_hour, TM->tm_min, TM->tm_sec, getClientName(), getClientId(), Text);
 
   fflush(LogFile);
   
-  // If error close file (otherwise infinite loop because State() also writes to log) 
+  // If error close file (otherwise infinite loop because Message() also writes to log) 
   if(ferror(LogFile)) {
     fclose(LogFile);
 	LogFile = NULL;
-    State(ERROR, "Error writing to log file, closing file (%s)", strerror(errno));
+    Message(ERROR, "Error writing to log file, closing file (%s)", strerror(errno));
   }
     
   // Update logfile size service
   if (time(NULL) - LogSizeLastUpdate > SizeUpdateDelay) {
-	LogSizekB = FileSize(LogFile)/1024.0;
+	LogSizeMB = FileSize(LogFile)/1024.0/1024.0;
 	LogSizeService->updateService();
 	LogSizeLastUpdate = time(NULL);
@@ -486,5 +480,5 @@
 	fread(Buffer, sizeof(char), Size-sizeof(int), File);
 	if (ferror(File) != 0) {
-	  State(WARN, "Error reading history file '%s' in rpcHandler()", getString());
+	  Message(WARN, "Error reading history file '%s' in rpcHandler()", getString());
 	  setData(NULL, 0);		// Default response
 	}
@@ -493,5 +487,5 @@
   }
   
-  if (fclose(File) != 0) State(WARN, "Error closing history file '%s' in rpcHandler()", getString());
+  if (fclose(File) != 0) Message(WARN, "Error closing history file '%s' in rpcHandler()", getString());
 }
 
@@ -535,6 +529,6 @@
       fread(&New.Next, sizeof(New.Next), 1, File);
       fread(New.Buffer, sizeof(char), New.HistSize, File);
-	  if (ferror(File) != 0) State(WARN, "Error reading history file '%s' in AddService()", Name.c_str());
-      if (fclose(File) != 0) State(WARN, "Error closing history file '%s' in AddService()", Name.c_str());;
+	  if (ferror(File) != 0) Message(WARN, "Error reading history file '%s' in AddService()", Name.c_str());
+      if (fclose(File) != 0) Message(WARN, "Error closing history file '%s' in AddService()", Name.c_str());;
 	}
   }
@@ -564,6 +558,6 @@
       fwrite(&(*E).Next, sizeof((*E).Next), 1, File);
       fwrite((*E).Buffer, sizeof(char), (*E).HistSize, File);
-	  if (ferror(File) != 0) State(WARN, "Error writing history file '%s' in RemoveService()", Name.c_str());
-      if (fclose(File) != 0) State(WARN, "Error closing history file '%s' in RemoveService()", Name.c_str());;
+	  if (ferror(File) != 0) Message(WARN, "Error writing history file '%s' in RemoveService()", Name.c_str());
+      if (fclose(File) != 0) Message(WARN, "Error closing history file '%s' in RemoveService()", Name.c_str());;
 	}
 	
@@ -574,5 +568,4 @@
 }
 
-
 //
 // Determine size of file in kB
@@ -583,5 +576,5 @@
 
   if (fstat(fileno(File), &FileStatus) == -1) {
-     State(WARN, "Could not determine size of file (%s)", strerror(errno));
+     Message(WARN, "Could not determine size of file (%s)", strerror(errno));
 	 return -1;
   }
@@ -591,10 +584,16 @@
 
 //
-// Replace all '/' by '_' in string
+// Open file for service history
 //
 FILE *DataHandler::OpenHistFile(string Service, const char *Mode) {
 
+  string Dir = string(BaseDir) + "/Histories/";
+
+  // Create directory if not yet existing
+  if(mkdir(Dir.c_str(), S_IRWXU|S_IRWXG)==-1 && errno!=EEXIST) return NULL;
+
+  // Replace all '/' by '_' in string and open file
   for (int i=0; i<Service.size(); i++) if (Service[i] == '/') Service[i] = '_';
-  return fopen((HistDir + "/" + Service).c_str(), Mode);
+  return fopen((Dir + Service).c_str(), Mode);
 }
 
Index: Evidence/Edd/Edd.cc
===================================================================
--- Evidence/Edd/Edd.cc	(revision 213)
+++ Evidence/Edd/Edd.cc	(revision 216)
@@ -30,7 +30,12 @@
   DimBrowser Browser;
 
+  // If status service displayed as text history
+  if (strstr(Service, "/Message") != NULL) return new EddText(Service);
+
+  // If service currently not available, default open as plot
   Browser.getServices(Service);
   if (Browser.getNextService(Name, Format) != DimSERVICE) return new EddPlot(Service, Index);
   
+  // Otherwise, determine from format if plot or text history
   if (strlen(Format) == 1 && *Format != 'C') return new EddPlot(Service, Index);
   else return new EddText(Service);
@@ -205,4 +210,5 @@
 
   DimClient::sendCommand(Name.toAscii().data(), text().toAscii().data());
+  clear();
 }
 
@@ -276,7 +282,4 @@
   for (ItemNo=0; ItemNo<List.size(); ItemNo++) if (List[ItemNo].Name == Name) {
 
-	// Service available?
-	if (!SetStatus(this, Name, Time, Format)) return;
-  
 	// If size limit reached, clear buffer
     if (List[ItemNo].Signal->dataSize() > SizeLimit) List[ItemNo].Signal->setData(QPolygonF());
@@ -284,21 +287,21 @@
 	// If buffer empty, request new history buffer
     if (List[ItemNo].Signal->dataSize() == 0) {
-	  int Time, Size, Count=0;
-	  void *Data;
+	  int Count=0;
+	  const struct EvidenceHistory::Item *R;
 	  class EvidenceHistory *Hist;
 
 	  if ((Hist = Handler->GetHistory(List[ItemNo].Name)) != NULL) {
 		double Number=0;
-		while (Hist->Next(Time, Size, Data)) {
+		while ((R=Hist->Next()) != NULL) {
 		  switch (Format[0].toUpper().toAscii()) {
     		case 'I':
-			case 'L':  Number = *((int *) Data + List[ItemNo].Index);   break;
-    		case 'S':  Number = *((short *) Data + List[ItemNo].Index);   break;
-    		case 'F':  Number = *((float *) Data + List[ItemNo].Index);   break;
-    		case 'D':  Number = *((double *) Data + List[ItemNo].Index);   break;
-    		case 'X':  Number = *((long long *) Data + List[ItemNo].Index);   break;
+			case 'L':  Number = *((int *) R->Data + List[ItemNo].Index);   break;
+    		case 'S':  Number = *((short *) R->Data + List[ItemNo].Index);   break;
+    		case 'F':  Number = *((float *) R->Data + List[ItemNo].Index);   break;
+    		case 'D':  Number = *((double *) R->Data + List[ItemNo].Index);   break;
+    		case 'X':  Number = *((long long *) R->Data + List[ItemNo].Index);   break;
     		default: break;
 		  }
-		  AddPoint(ItemNo, Time, Number);
+		  AddPoint(ItemNo, R->Time, Number);
 		  Count++;
 		}
@@ -309,8 +312,10 @@
 	}
 
-    // Append data
-	QString Txt = Text;
-	Txt = Txt.section(' ', List[ItemNo].Index, List[ItemNo].Index);
-    AddPoint(ItemNo, Time, atof(Txt.toAscii().data()));	
+ 	// Appen data only if service available
+	if (SetStatus(this, Name, Time, Format)) {
+	  QString Txt = Text;
+	  Txt = Txt.section(' ', List[ItemNo].Index, List[ItemNo].Index);
+      AddPoint(ItemNo, Time, atof(Txt.toAscii().data()));
+	}
   }
 
@@ -721,13 +726,12 @@
   if (!Pure) {
 	// Get history for this service 
-	int Time, Size;
-	void *Data;
+	const struct EvidenceHistory::Item *R;
 	class EvidenceHistory *Hist;
 
 	if ((Hist = Handler->GetHistory(Name)) != NULL) {
-	  while (Hist->Next(Time, Size, Data)) {
+	  while ((R=Hist->Next()) != NULL) {
 		moveCursor (QTextCursor::Start);
-		insertPlainText(QString("(")+QDateTime::fromTime_t(Time).toString()+") ");	  
-		insertPlainText(QString((char *) Data) + "\n");	  
+		insertPlainText(QString("(")+QDateTime::fromTime_t(R->Time).toString()+") ");	  
+		insertPlainText(QString((char *) R->Data) + "\n");	  
 	  }
 	}
@@ -780,7 +784,5 @@
 
   Mutex = new QMutex(QMutex::Recursive);
-
-  MinuteVolume = 0;
-  TotalVolume = 0;
+  Volume = 0;
 
   // Timer to calculate data rates
@@ -815,4 +817,5 @@
 	  YEP(Name, ServiceList[i].TimeStamp, ServiceList[i].ByteArray, ServiceList[i].Format, ServiceList[i].Text);
 	}
+	else YEP(Name, -1);
 	return;
   }
@@ -878,10 +881,8 @@
   QMutexLocker Locker(Mutex);
 
-  float Rate = MinuteVolume/1024.0 * 6;
-  float Total = TotalVolume/1024.0/1024.0;
-
-  YEP("Edd/Rate_kBMin", time(NULL), QByteArray::number(Rate), "F", QString::number(Rate));
-  YEP("Edd/Total_MB", time(NULL), QByteArray::number(Total), "F", QString::number(Total));
-  MinuteVolume = 0;
+  float Rate = Volume/1024.0/10;
+
+  YEP("Edd/Rate_kBSec", time(NULL), QByteArray::number(Rate), "F", QString::number(Rate));
+  Volume = 0;
 }
 
@@ -900,8 +901,5 @@
 
   // Update statistics only for Dim services
-  if (!Name.startsWith("Edd/")) {  
-	TotalVolume += Data.size();
-	MinuteVolume += Data.size();
-  }
+  if (!Name.startsWith("Edd/")) Volume += Data.size();
 }
 
@@ -1149,5 +1147,5 @@
 
   // Status display
-  EddLineDisplay *Line = new EddLineDisplay("ARDUINO/Status");
+  EddLineDisplay *Line = new EddLineDisplay("ARDUINO/Message");
   Line->setMaximumWidth(200);
   Layout->addWidget(Line, 0, 0, 1, 2);      
@@ -1188,5 +1186,5 @@
 
   Layout->addWidget(Plot, 0, 4, 12, 3);
-  Line = new EddLineDisplay("Bias/Status");
+  Line = new EddLineDisplay("Bias/Message");
   Line->setMaximumWidth(200);
   Layout->addWidget(Line, 0, 0, 1, 3);      
@@ -1195,5 +1193,5 @@
   Layout->addWidget(Command, 10, 0, 1, 4);    
 
-  EddText *Text = new EddText("Bias/StdOut", true);
+  EddText *Text = new EddText("Bias/Textout", true);
   Text->setFixedWidth(400);
   Layout->addWidget(Text, 11, 0, 4, 4);      
@@ -1224,5 +1222,5 @@
   //FeedbackLayout->addWidget(Graph, 10, 0, 10, 3);
 
-  Line = new EddLineDisplay("drsdaq/Status");
+  Line = new EddLineDisplay("drsdaq/Message");
   Line->setMaximumWidth(200);
   Layout->addWidget(Line, 0, 0, 1, 2);      
@@ -1409,5 +1407,5 @@
   EddText *Text;
   
-  Line = new EddLineDisplay("Alarm/Status");
+  Line = new EddLineDisplay("Alarm/Message");
   Line->setMaximumWidth(200);
   Layout->addWidget(Line, 0, 0, 1, 2);      
@@ -1422,12 +1420,12 @@
   Layout->addWidget(Text, 1, 0, 1, 2);
 
-  Line = new EddLineDisplay("DColl/Status");
+  Line = new EddLineDisplay("DColl/Message");
   Line->setMaximumWidth(200);
   Layout->addWidget(Line, 3, 0, 1, 2);      
 
-  Line = new EddLineDisplay("DColl/DataSizekB");
+  Line = new EddLineDisplay("DColl/DataSizeMB");
   Layout->addWidget(Line, 4, 0, 1, 1);
 
-  Line = new EddLineDisplay("DColl/LogSizekB");
+  Line = new EddLineDisplay("DColl/LogSizeMB");
   Layout->addWidget(Line, 4, 1, 1, 1);
 
@@ -1436,5 +1434,5 @@
   Layout->addWidget(Line, 5, 0, 1, 3);
 
-  Line = new EddLineDisplay("Config/Status");
+  Line = new EddLineDisplay("Config/Message");
   Line->setMaximumWidth(200);
   Layout->addWidget(Line, 6, 0, 1, 2);      
@@ -1450,8 +1448,6 @@
   Layout->addWidget(Button, 7, 1, 1, 1);
 
-  Line = new EddLineDisplay("Edd/Rate_kBMin");
+  Line = new EddLineDisplay("Edd/Rate_kBSec");
   Layout->addWidget(Line, 8, 0, 1, 1);
-  Line = new EddLineDisplay("Edd/Total_MB");
-  Layout->addWidget(Line, 8, 1, 1, 1);
 }
  
Index: Evidence/Edd/Edd.h
===================================================================
--- Evidence/Edd/Edd.h	(revision 213)
+++ Evidence/Edd/Edd.h	(revision 216)
@@ -232,6 +232,5 @@
     QList<HistItem> HistoryList;
 
-	long long TotalVolume;
-	long long MinuteVolume;
+	long long Volume;
 
 	void infoHandler();
Index: Evidence/Evidence.cc
===================================================================
--- Evidence/Evidence.cc	(revision 213)
+++ Evidence/Evidence.cc	(revision 216)
@@ -5,8 +5,8 @@
   - The server is started with the given name.
   - DIM exit and error handlers are implemented.
-  - The Status service is published (special format, see below).
-    It can be updated with the State() method. The text will also be logged.
-  - If the severity of a State() call is FATAL, exit() will be called (with
-    this severity, the call to State() is guranteed not to return).
+  - The Message service is published (special format, see below).
+    It can be updated with the Message() method. The text will also be logged.
+  - If the severity of a Message() call is FATAL, exit() will be called (with
+    this severity, the call to Message() is guranteed not to return).
   - Configuration data can be requested by GetConfig(). 
   - Signal handlers to ignore common signals are installed.
@@ -60,5 +60,5 @@
   snprintf(InitMsg, sizeof(InitMsg), "Server started (%s, compiled %s %s)", Rev.c_str(),__DATE__, __TIME__);
   
-  Status = new DimService((ServerName+"/Status").c_str(), (char *) "C", InitMsg, strlen(InitMsg)+1);
+  Status = new DimService((ServerName+"/Message").c_str(), (char *) "C", InitMsg, strlen(InitMsg)+1);
   StdOut = new DimService((ServerName+"/Textout").c_str(), (char *) "");
 
@@ -70,5 +70,5 @@
 EvidenceServer::~EvidenceServer() {
 
-  State(INFO, "Server stopped");
+  Message(INFO, "Server stopped");
   
   for (unsigned int i=0; i<ConfigList.size(); i++) {
@@ -84,11 +84,11 @@
 void EvidenceServer::exitHandler(int Code) {
 
-  State(INFO, "Exit handler called (DIM exit code %d)", Code);
+  Message(INFO, "Exit handler called (DIM exit code %d)", Code);
   exit(EXIT_SUCCESS);
 }
 
 // DIM error handler
-void EvidenceServer::errorHandler(int Severity, int Code, char *Message) {   
-  State(ERROR, "%s (DIM error code %d, severity %d)\n", Message, Code, Severity);
+void EvidenceServer::errorHandler(int Severity, int Code, char *Text) {   
+  Message(ERROR, "%s (DIM error code %d, severity %d)\n", Text, Code, Severity);
 }
 
@@ -98,8 +98,8 @@
 // is given, terminated by another '\0'  The buffer for the DIM service must have
 // the same lifetime as the DIM service. If Severity is FATAL, exit() will be invoked.
-void EvidenceServer::State(StateType Severity, const char *Format, ...) {
+void EvidenceServer::Message(MessageType Severity, const char *Format, ...) {
 
   static const char* StateString[] = {"Info", "Warn", "Error", "Fatal"};
-  static char ErrorString[] = "vasprintf() failed in State()";
+  static char ErrorString[] = "vasprintf() failed in Message()";
   static char SBuf[STATUS_SIZE];
   char TBuf[STATUS_SIZE];
@@ -116,7 +116,7 @@
 
   // Create string with severity encoding
-  snprintf(SBuf, sizeof(SBuf), "%s**", Tmp);
-  SBuf[strlen(SBuf)-2] = '\0';
-  SBuf[strlen(SBuf)+1] = Severity;
+  snprintf(SBuf, sizeof(SBuf), "%s*", Tmp);
+  SBuf[strlen(SBuf)-1] = '\0'; 		// new string terminiation replaces '*'
+  SBuf[strlen(SBuf)+1] = Severity;	// Severity after new string termination
 
   if (Tmp != ErrorString) free(Tmp);
@@ -174,9 +174,9 @@
   // Terminate if not successful
   if (!EvidenceServer::ServiceOK(&Config)) {
-    State(FATAL, "Configuration server unreachable, can't get '%s'", Item.c_str());
+    Message(FATAL, "Configuration server unreachable, can't get '%s'", Item.c_str());
   }
 
   if (strlen(Result) == 0) {
-    if (Default == NULL) State(FATAL, "Missing configuration data '%s'", Item.c_str());
+    if (Default == NULL) Message(FATAL, "Missing configuration data '%s'", Item.c_str());
 	Result = (char *) Default;
   }
@@ -214,5 +214,5 @@
 
   // If invoked twice, call exit()
-  ThisServer->State(ThisServer->WARN, "Signal handler called again, invoking exit() (signal %d)", Signal);
+  ThisServer->Message(ThisServer->WARN, "Signal handler called again, invoking exit() (signal %d)", Signal);
   exit(EXIT_FAILURE);
 }
@@ -253,9 +253,10 @@
   else snprintf(Msg, sizeof(Msg), "Terminate() called without an active exception");
 
-  ThisServer->State(FATAL, Msg);
+  ThisServer->Message(FATAL, Msg);
 }
 
 
 // Translates DIMInfo to string (memory has to be freed by caller)
+// Static method: it cannot report memory allocation errors via Message()
 char *EvidenceServer::ToString(DimInfo *Item) {
 
@@ -355,6 +356,6 @@
 
 // Marker for history buffer
-const int EvidenceHistory::WrapMark[] = {0, -1};
-const int EvidenceHistory::EndMark[] = {0, 0};
+const struct EvidenceHistory::Item EvidenceHistory::WrapMark = {0, -1, {}};
+const struct EvidenceHistory::Item EvidenceHistory::EndMark = {0, 0, {}};
 
 // Constructor
@@ -392,21 +393,18 @@
 
 // Returns next item in history buffer
-bool EvidenceHistory::Next(int &Time, int &Size, void *&Data) {
-
-  if (Buffer == NULL) return false;
+const struct EvidenceHistory::Item *EvidenceHistory::Next() {
+
+  if (Buffer == NULL) return NULL;
 
   // Check for wrap around
-  if (memcmp(Buffer+Offset, WrapMark, sizeof(WrapMark)) == 0) Offset = 4;
+  if (memcmp(Pointer, &WrapMark, sizeof(WrapMark)) == 0) Pointer = (struct Item *) (Buffer + 4);
   
   // Check if at end of ring buffer
-  if (memcmp(Buffer+Offset, EndMark, sizeof(EndMark)) == 0) return false;
-
-  Time = *(int *) (Buffer + Offset);
-  Size = *(int *) (Buffer + Offset + sizeof(int));
-  Data = Buffer + Offset + 2*sizeof(int);
-
-  Offset += *((int *) (Buffer + Offset) + 1) + 2*sizeof(int);
-
-  return true;
+  if (memcmp(Pointer, &EndMark, sizeof(EndMark)) == 0) return NULL;
+
+  const struct Item *Ret = Pointer;
+  Pointer = (struct Item *) ((char *) (Pointer + 1) + Pointer->Size);
+
+  return Ret;
 }
 
@@ -414,4 +412,4 @@
 void EvidenceHistory::Rewind() {
 
-  if (Buffer != NULL) Offset = *(int *) Buffer;
-}
+  if (Buffer != NULL) Pointer = (struct Item *) (Buffer + (*(int *) Buffer));
+}
Index: Evidence/Evidence.h
===================================================================
--- Evidence/Evidence.h	(revision 213)
+++ Evidence/Evidence.h	(revision 216)
@@ -63,7 +63,7 @@
 	~EvidenceServer();
 
-	enum StateType {INFO=0, WARN=1, ERROR=2, FATAL=3};
+	enum MessageType {INFO=0, WARN=1, ERROR=2, FATAL=3};
 
-	void State(StateType, const char *, ...);
+	void Message(MessageType, const char *, ...);
 	void SetStdOut(char *);
 	char* GetConfig(std::string, const char * = NULL);
@@ -75,20 +75,28 @@
 };
 
-class EvidenceHistory: public DimClient {
+class EvidenceHistory {
 
-  static const int WrapMark[];
-  static const int EndMark[];
+  public:  
+  	struct Item {
+	  int Time;
+	  int Size;
+	  char Data[]; // Size bytes
+	} __attribute__((packed));
 
-  std::string Name;
-  char *Buffer;
-  int BufferSize;
-  int Offset;
-  
+	static const struct Item WrapMark;
+	static const struct Item EndMark;
+
+  private:
+	std::string Name;
+	char *Buffer;
+	int BufferSize;
+	struct Item *Pointer;
+	
   public:
 	EvidenceHistory(std::string);
-	~EvidenceHistory();
-	
+	~EvidenceHistory();	
+
 	bool GetHistory();
-	bool Next(int &, int &, void *&);
+	const struct Item *Next();
 	void Rewind();
 };
Index: Evidence/readme.txt
===================================================================
--- Evidence/readme.txt	(revision 213)
+++ Evidence/readme.txt	(revision 216)
@@ -31,5 +31,5 @@
 			yet in memory, reading from history file is tried. Improved error handling of
 			history files.
-			
+28/5/2010	Changed name of 'State' service to 'Message' to better reflect its functionality. Added client information to log file entries.			
 
 
