diff --git a/EcAlarmDestination.h b/EcAlarmDestination.h
index 75a274b..f4b4e3f 100644
--- a/EcAlarmDestination.h
+++ b/EcAlarmDestination.h
@@ -44,7 +44,7 @@
* for a long time or raise an exception.
*
*/
-@protocol EcAlarmDestination
+@protocol EcAlarmDestination
/** Passes an alarm to the destination.
*/
@@ -66,6 +66,18 @@
@end
+/** These methods are called to inform an object monitoring the alarm
+ * destination about changes to its state.
+ */
+@protocol EcAlarmMonitor
+- (void) activePut: (EcAlarm*)alarm;
+- (void) activeRemove: (EcAlarm*)alarm;
+- (void) clearsPut: (EcAlarm*)alarm;
+- (void) clearsRemove: (EcAlarm*)alarm;
+- (void) managePut: (NSString*)name;
+- (void) manageRemove: (NSString*)name;
+@end
+
/**
@@ -81,7 +93,8 @@
* destination.
*
*/
-@interface EcAlarmDestination : NSObject
+@interface EcAlarmDestination : NSObject
+
{
NSRecursiveLock *_alarmLock;
NSMutableArray *_alarmQueue;
@@ -96,10 +109,19 @@
NSString *_host;
NSString *_name;
id _destination;
+ id _monitor;
NSArray *_backups;
BOOL _debug;
}
+/** Internal use only.
+ */
+- (void) activePut: (EcAlarm*)alarm;
+
+/** Internal use only.
+ */
+- (void) activeRemove: (EcAlarm*)alarm;
+
/** Passes an alarm to the destination by adding it to a queue of alarm
* events which will be processed in the receivers running thread.
*/
@@ -114,6 +136,18 @@
*/
- (NSArray*) backups;
+/** Returns an array containing all the latest cleared alarms.
+ */
+- (NSArray*) clears;
+
+/** Internal use only.
+ */
+- (void) clearsPut: (EcAlarm*)alarm;
+
+/** Internal use only.
+ */
+- (void) clearsRemove: (EcAlarm*)alarm;
+
/** Inform the destination of the existence of a managed object.
* This is an indicator of a 'cold start' of that object ... meaning that the
* object has just started up afresh, and all outstanding alarms for the object
@@ -150,6 +184,18 @@
*/
- (BOOL) isRunning;
+/** Returns an array containing the known managed objects.
+ */
+- (NSArray*) managed;
+
+/** Internal use only.
+ */
+- (void) managePut: (NSString*)name;
+
+/** Internal use only.
+ */
+- (void) manageRemove: (NSString*)name;
+
/** This method is called from -init in a secondary thread to start handling
* of alarms by the receiver. Do not call it yourself.
*/
@@ -188,6 +234,13 @@
*/
- (id) setDestination: (id)destination;
+/** Sets the monitoring object to which state changes are sent.
+ * If nil this turns off monitoring.
+ * The monitoring object is retained by the receiver.
+ * Returns the previously set monitor.
+ */
+- (id) setMonitor: (id)monitor;
+
/** Requests that the receiver's running thread should shut down. This method
* waits for a short while for the thread to shut down, but the process of
* shutting down is not guaranteed to have completed by the time the method
diff --git a/EcAlarmDestination.m b/EcAlarmDestination.m
index fac1239..b934835 100644
--- a/EcAlarmDestination.m
+++ b/EcAlarmDestination.m
@@ -56,6 +56,28 @@
@implementation EcAlarmDestination
+- (void) activePut: (EcAlarm*)alarm
+{
+ if (_monitor != self)
+ {
+ [_monitor activePut: alarm];
+ }
+ [_alarmLock lock];
+ [_alarmsActive addObject: alarm];
+ [_alarmLock unlock];
+}
+
+- (void) activeRemove: (EcAlarm*)alarm
+{
+ if (_monitor != self)
+ {
+ [_monitor activeRemove: alarm];
+ }
+ [_alarmLock lock];
+ [_alarmsActive removeObject: alarm];
+ [_alarmLock unlock];
+}
+
- (oneway void) alarm: (in bycopy EcAlarm*)event
{
if (NO == [event isKindOfClass: [EcAlarm class]])
@@ -187,22 +209,49 @@
return [a autorelease];
}
+- (NSArray*) clears
+{
+ NSArray *a;
+
+ [_alarmLock lock];
+ a = [_alarmsCleared allObjects];
+ [_alarmLock unlock];
+ return a;
+}
+
+- (void) clearsPut: (EcAlarm*)alarm
+{
+ if (_monitor != self)
+ {
+ [_monitor clearsPut: alarm];
+ }
+ [_alarmLock lock];
+ [_alarmsCleared addObject: alarm];
+ [_alarmLock unlock];
+}
+
+- (void) clearsRemove: (EcAlarm*)alarm
+{
+ if (_monitor != self)
+ {
+ [_monitor clearsRemove: alarm];
+ }
+ [_alarmLock lock];
+ [_alarmsCleared removeObject: alarm];
+ [_alarmLock unlock];
+}
+
- (void) dealloc
{
[self shutdown];
- [_backups release];
- [(id)_destination release];
- _destination = nil;
- [_alarmQueue release];
- _alarmQueue = nil;
- [_alarmsActive release];
- _alarmsActive = nil;
- [_alarmsCleared release];
- _alarmsCleared = nil;
- [_managedObjects release];
- _managedObjects = nil;
- [_alarmLock release];
- _alarmLock = nil;
+ DESTROY(_backups);
+ DESTROY(_destination);
+ DESTROY(_monitor);
+ DESTROY(_alarmQueue);
+ DESTROY(_alarmsActive);
+ DESTROY(_alarmsCleared);
+ DESTROY(_managedObjects);
+ DESTROY(_alarmLock);
[super dealloc];
}
@@ -325,6 +374,38 @@
return result;
}
+- (NSArray*) managed
+{
+ NSArray *a;
+
+ [_alarmLock lock];
+ a = [_managedObjects allObjects];
+ [_alarmLock unlock];
+ return a;
+}
+
+- (void) managePut: (NSString*)name
+{
+ if (_monitor != self)
+ {
+ [_monitor managePut: name];
+ }
+ [_alarmLock lock];
+ [_managedObjects addObject: name];
+ [_alarmLock unlock];
+}
+
+- (void) manageRemove: (NSString*)name
+{
+ if (_monitor != self)
+ {
+ [_monitor manageRemove: name];
+ }
+ [_alarmLock lock];
+ [_managedObjects removeObject: name];
+ [_alarmLock unlock];
+}
+
- (void) run
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
@@ -417,9 +498,27 @@
}
[_alarmLock lock];
old = (id)_destination;
- _destination = (id)[(id)destination retain];
+ _destination = RETAIN(destination);
[_alarmLock unlock];
- return (id)[old autorelease];
+ return AUTORELEASE(old);
+}
+
+- (id) setMonitor: (id)monitor
+{
+ id old;
+
+ if (nil != (id)monitor && NO == [(id)monitor
+ conformsToProtocol: @protocol(EcAlarmMonitor)])
+ {
+ [NSException raise: NSInvalidArgumentException
+ format: @"[%@-%@] arg does not conform to EcAlarmMonitor protocol",
+ NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
+ }
+ [_alarmLock lock];
+ old = (id)_monitor;
+ _monitor = RETAIN(monitor);
+ [_alarmLock unlock];
+ return AUTORELEASE(old);
}
- (void) shutdown
@@ -597,7 +696,7 @@
if (nil == [_managedObjects member: m])
{
- [_managedObjects addObject: m];
+ [self managePut: m];
[_alarmLock unlock];
[self domanageFwd: m];
[_alarmLock lock];
@@ -668,7 +767,7 @@
/* Alarm previously active ...
* remove old copy and forward clear.
*/
- [_alarmsActive removeObject: prev];
+ [self activeRemove: prev];
shouldForward = YES;
}
if (nil == [_alarmsCleared member: next])
@@ -676,7 +775,7 @@
/* Alarm not previously cleared ...
* add to cleared set and forward clear.
*/
- [_alarmsCleared addObject: next];
+ [self clearsPut: next];
shouldForward = YES;
}
}
@@ -685,7 +784,7 @@
/* If there was a previous version of the alarm
* cleared, remove that so it's re-raised.
*/
- [_alarmsCleared removeObject: next];
+ [self clearsRemove: next];
/* If the alarm is new or of changed severity,
* update the records and pass it on.
@@ -693,7 +792,7 @@
if (nil == prev || [next perceivedSeverity]
!= [prev perceivedSeverity])
{
- [_alarmsActive addObject: next];
+ [self activePut: next];
shouldForward = YES;
}
}
@@ -705,7 +804,7 @@
*/
if (nil == [_managedObjects member: m])
{
- [_managedObjects addObject: m];
+ [self managePut: m];
}
else
{
@@ -767,7 +866,7 @@
{
if ([[a managedObject] isEqual: m])
{
- [_alarmsActive removeObject: a];
+ [self activeRemove: a];
}
}
e = [[_alarmsCleared allObjects] objectEnumerator];
@@ -775,10 +874,10 @@
{
if ([[a managedObject] isEqual: m])
{
- [_alarmsCleared removeObject: a];
+ [self clearsRemove: a];
}
}
- [_managedObjects removeObject: m];
+ [self manageRemove: m];
}
}
diff --git a/EcAlarmSinkSNMP.m b/EcAlarmSinkSNMP.m
index b6aadd1..a1f4c70 100644
--- a/EcAlarmSinkSNMP.m
+++ b/EcAlarmSinkSNMP.m
@@ -1501,7 +1501,7 @@ objectsTable_handler(netsnmp_mib_handler *handler,
/* Remove from the ObjC table.
*/
- [_alarmsActive removeObject: alarm];
+ [self activeRemove: alarm];
/* Find and remove the SNMP table entry.
*/
@@ -1573,7 +1573,7 @@ objectsTable_handler(netsnmp_mib_handler *handler,
/* Remove from the ObjC table.
*/
[prev retain];
- [_alarmsActive removeObject: prev];
+ [self activeRemove: prev];
/* Find and remove the SNMP table entry.
*/
@@ -1607,6 +1607,7 @@ objectsTable_handler(netsnmp_mib_handler *handler,
if (NO == [managedObjects containsObject: m])
{
objectsTable_createEntry(m);
+ [self managePut: m];
[managedObjects addObject: m];
managedObjectsCount = [managedObjects count];
[self domanageFwd: m];
@@ -1630,7 +1631,7 @@ objectsTable_handler(netsnmp_mib_handler *handler,
else
{
prev = [[prev retain] autorelease];
- [_alarmsActive removeObject: prev];
+ [self activeRemove: prev];
row = (netsnmp_tdata_row*)[prev extra];
/* send the clear for the entry.
*/
@@ -1643,7 +1644,7 @@ objectsTable_handler(netsnmp_mib_handler *handler,
* and send new severity trap.
*/
setAlarmTableEntry(row, next);
- [_alarmsActive addObject: next];
+ [self activePut: next];
[alarmSink _trap: next forceClear: NO];
[self alarmFwd: next];
changed = YES;
@@ -1662,6 +1663,7 @@ objectsTable_handler(netsnmp_mib_handler *handler,
if (NO == [managedObjects containsObject: m])
{
objectsTable_createEntry(m);
+ [self managePut: m];
[managedObjects addObject: m];
managedObjectsCount = [managedObjects count];
changed = YES;
@@ -1694,6 +1696,7 @@ objectsTable_handler(netsnmp_mib_handler *handler,
}
row = netsnmp_tdata_row_next(objectsTable, row);
}
+ [self manageRemove: m];
[managedObjects removeObject: m];
if (YES == [m hasSuffix: @"_"])
{
@@ -1706,6 +1709,7 @@ objectsTable_handler(netsnmp_mib_handler *handler,
{
if (YES == [s hasPrefix: m])
{
+ [self manageRemove: s];
[managedObjects removeObject: s];
}
}