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]; } }