provide an api for a separate object to monitor changes of the state of the alarm destination.

This commit is contained in:
Richard Frith-Macdonald 2020-07-16 13:35:39 +01:00
parent 5311f2bd64
commit 25826e9236
3 changed files with 186 additions and 30 deletions

View file

@ -44,7 +44,7 @@
* for a long time or raise an exception.
* </p>
*/
@protocol EcAlarmDestination
@protocol EcAlarmDestination <NSObject>
/** 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 <NSObject>
- (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.
* </p>
*/
@interface EcAlarmDestination : NSObject <EcAlarmDestination>
@interface EcAlarmDestination : NSObject
<EcAlarmDestination,EcAlarmMonitor>
{
NSRecursiveLock *_alarmLock;
NSMutableArray *_alarmQueue;
@ -96,10 +109,19 @@
NSString *_host;
NSString *_name;
id<EcAlarmDestination> _destination;
id<EcAlarmMonitor> _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.<br />
* 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<EcAlarmDestination>) setDestination: (id<EcAlarmDestination>)destination;
/** Sets the monitoring object to which state changes are sent.<br />
* If nil this turns off monitoring.<br />
* The monitoring object is retained by the receiver.<br />
* Returns the previously set monitor.
*/
- (id<EcAlarmMonitor>) setMonitor: (id<EcAlarmMonitor>)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

View file

@ -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<EcAlarmDestination>)[(id)destination retain];
_destination = RETAIN(destination);
[_alarmLock unlock];
return (id<EcAlarmDestination>)[old autorelease];
return AUTORELEASE(old);
}
- (id<EcAlarmMonitor>) setMonitor: (id<EcAlarmMonitor>)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];
}
}

View file

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