Index: Evidence/Alarm/Alarm.cc
===================================================================
--- Evidence/Alarm/Alarm.cc	(revision 128)
+++ Evidence/Alarm/Alarm.cc	(revision 142)
@@ -5,8 +5,10 @@
   - Checks periodically if all required servers are up
     (later it should try to start them if not)
-  - Listens to the 'Status' service of each server. The server state 
-    is published as a DIM service.
+  - Listens to the 'Status' service of each server.
+  - A text describing the state of all servers is published as DIM service.
+    The states are described in StateString[].
+  - A master alarm (indicating most severe of individual alarms) is published. 
     
-  Oliver Grimm, September 2009
+  Oliver Grimm, January 2010
 
 \********************************************************************/
@@ -14,4 +16,8 @@
 #define SERVER_NAME "Alarm"
 #include "../Evidence.h"
+
+#define SUMMARYSIZE 10000	// Bytes for alarm summary text
+
+const char* StateString[] = {"OK", "WARN", "ERROR", "FATAL", "UNAVAILABLE"};
 
 //
@@ -21,4 +27,5 @@
     
     DimStampedInfo **StatusService;
+
     void infoHandler();
 
@@ -26,9 +33,15 @@
     AlarmHandler();
     ~AlarmHandler();
-    
+
+	DimService *Summary, *Master;
+	
+	char *AlarmSummary;
+	int MasterAlarm;
+	int *State;    
     char **Server;
     unsigned int NumServers;
-    char *StateString;
-    char *ServerList;  
+    char *ServerList; 
+	
+	void UpdateAlarmSummary();
 }; 
 
@@ -36,5 +49,12 @@
 AlarmHandler::AlarmHandler(): EvidenceServer(SERVER_NAME) {
 
+  AlarmSummary = new char [SUMMARYSIZE];
+  MasterAlarm = 0;
+  
   char *ServerNames = GetConfig(SERVER_NAME " servers");
+
+  // Create DIM services
+  Summary = new DimService(SERVER_NAME"/Summary", AlarmSummary);
+  Master = new DimService(SERVER_NAME"/MasterAlarm", MasterAlarm);
 
   // Copy original list of servers to observe
@@ -53,4 +73,5 @@
   // Subscribe with handler to 'Status' service of all servers
   StatusService = new DimStampedInfo* [NumServers];
+  State = new int [NumServers];
   
   for (int i=0; i<NumServers; i++) {
@@ -58,12 +79,9 @@
     strcpy(Buffer, Server[i]);
     strcat(Buffer, "/Status");
-    StatusService[i] = new DimStampedInfo(Buffer, 0, this);
-    printf("Subscribed to %s\n", Buffer);
-    delete[] Buffer; 
+    StatusService[i] = new DimStampedInfo(Buffer, NO_LINK, this);
+    delete[] Buffer;
+	
+	State[i] = 0;
   }
-  
-  StateString = new char [NumServers+1];
-  for (int i=0; i<NumServers; i++) StateString[i] = '1';
-  StateString[NumServers] = '\0';
 }
 
@@ -73,28 +91,52 @@
   for (int i=0; i<NumServers; i++) delete StatusService[i];
   delete[] StatusService;
+  delete Master;
+  delete Summary;
+  delete[] State;
   delete[] Server;
   delete[] ServerList;
+  delete[] AlarmSummary;
 }
 
-// Print messages of status changes to screen
+// Print messages of status changes to screen and update status string
 void AlarmHandler::infoHandler() {
 
-  // Ignore empty messages
-  if (strlen(getInfo()->getString()) == 0) return;
-  
-  // Print message
-  time_t RawTime = getInfo()->getTimestamp();
-  struct tm *TM = localtime(&RawTime);
-  printf("%s (%02d:%02d:%02d): %s\n", getInfo()->getName(), TM->tm_hour,
-	TM->tm_min, TM->tm_sec, getInfo()->getString());
+  // Identify status service
+  for (int i=0; i<NumServers; i++) if (getInfo() == StatusService[i]) {
 
-  // Update status string
-  for (int i=0; i<NumServers; i++) {
-    if (strcmp(getInfo()->getName(),Server[i]) == 0) {
-      StateString[i] = '2';
-    }
+	// Ignore DIS_DNS (has no status service)
+	if (strcmp(getInfo()->getName(),"DIS_DNS/Status") == 0) return;
+	
+	// Update State if server is unavailable or with current severity of status  
+	if (getInfo()->getSize()==strlen(NO_LINK)+1 &&
+		strcmp(getInfo()->getString(), NO_LINK)==0) State[i] = 4;
+	else {
+	  State[i] = *(getInfo()->getString()+strlen(getInfo()->getString())+2);
+
+	  // Print message
+	  time_t RawTime = getInfo()->getTimestamp();
+	  struct tm *TM = localtime(&RawTime);
+	  printf("%s (%02d:%02d:%02d): %s\n", getInfo()->getName(), TM->tm_hour,
+		TM->tm_min, TM->tm_sec, getInfo()->getString());	  
+	}
+	UpdateAlarmSummary();
   }  
 }
 
+
+// Update alarm status summary
+void AlarmHandler::UpdateAlarmSummary() {
+  
+  int Offset = 0;
+  MasterAlarm = 0;
+   
+  for (int i=0; i<NumServers; i++) {
+    snprintf(AlarmSummary+Offset, SUMMARYSIZE-Offset, "%s: %s\n", Server[i], StateString[State[i]]);
+	Offset += strlen(AlarmSummary+Offset);
+	if (State[i] > MasterAlarm) MasterAlarm = State[i];
+  }
+  Summary->updateService();
+  Master->updateService();
+}
 
 //	    
@@ -113,8 +155,4 @@
   unsigned int Period = atoi(Alarm.GetConfig(SERVER_NAME " period"));
 
-  // Create DIM services
-  static DimService ServerState(SERVER_NAME"/State", Alarm.StateString);
-  static DimService ServerList(SERVER_NAME"/Servers", Alarm.ServerList);
-
   // Check periodically if servers are up
   while(!EvidenceServer::ExitRequest) {
@@ -125,12 +163,8 @@
         if (strcmp(ServerName, Alarm.Server[i]) == 0) Exists = true;
       }
-      if (!Exists) {
-        Alarm.Msg(Alarm.WARN, "Server %s unavailable", Alarm.Server[i]);
-	Alarm.StateString[i] = '0';
-      }
-      else if (Alarm.StateString[i] == '0') Alarm.StateString[i] = '1';
+      if (!Exists) Alarm.State[i] = 4;
     }
     
-    ServerState.updateService(Alarm.StateString);
+    Alarm.UpdateAlarmSummary();
     sleep(Period);
   }
