~ubuntu-branches/ubuntu/trusty/net-snmp/trusty

« back to all changes in this revision

Viewing changes to agent/object_monitor.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-09-13 12:06:21 UTC
  • Revision ID: james.westby@ubuntu.com-20040913120621-g952ntonlleihcvm
Tags: upstream-5.1.1
ImportĀ upstreamĀ versionĀ 5.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * object_monitor.c
 
3
 *
 
4
 * $Id: object_monitor.c,v 1.6 2002/07/23 19:02:56 rstory Exp $
 
5
 *
 
6
 * functions and data structures for cooperating code to monitor objects.
 
7
 *
 
8
 * WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
 
9
 * WARNING!                                                       WARNING!
 
10
 * WARNING!                                                       WARNING!
 
11
 * WARNING!         This code is under active development         WARNING!
 
12
 * WARNING!         and is subject to change at any time.         WARNING!
 
13
 * WARNING!                                                       WARNING!
 
14
 * WARNING!                                                       WARNING!
 
15
 * WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
 
16
 */
 
17
 
 
18
#include <net-snmp/net-snmp-config.h>
 
19
#include <net-snmp/net-snmp-includes.h>
 
20
#include <net-snmp/agent/net-snmp-agent-includes.h>
 
21
#include <net-snmp/library/container.h>
 
22
#include <net-snmp/library/snmp_assert.h>
 
23
 
 
24
#include "net-snmp/agent/object_monitor.h"
 
25
 
 
26
#if ! defined TRUE
 
27
#  define TRUE 1
 
28
#elsif TRUE != 1
 
29
error "TRUE != 1"
 
30
#endif
 
31
/**************************************************************************
 
32
 *
 
33
 * Private data structures
 
34
 *
 
35
 **************************************************************************/
 
36
    /*
 
37
     * individual callback info for an object
 
38
     */
 
39
    typedef struct monitor_info_s {
 
40
 
 
41
   /** priority for this callback */
 
42
    int             priority;
 
43
 
 
44
   /** handler that registred to watch this object */
 
45
    netsnmp_mib_handler *watcher;
 
46
 
 
47
   /** events that the watcher cares about */
 
48
    unsigned int    events;
 
49
 
 
50
   /** callback function */
 
51
    netsnmp_object_monitor_callback *cb;
 
52
 
 
53
   /** pointer to data from the watcher */
 
54
    void           *watcher_data;
 
55
 
 
56
    struct monitor_info_s *next;
 
57
 
 
58
} monitor_info;
 
59
 
 
60
/*
 
61
 * list of watchers for a given object
 
62
 */
 
63
typedef struct watcher_list_s {
 
64
 
 
65
   /** netsnmp_index must be first! */
 
66
    netsnmp_index  monitored_object;
 
67
 
 
68
    monitor_info   *head;
 
69
 
 
70
} watcher_list;
 
71
 
 
72
/*
 
73
 * temp holder for ordered list of callbacks
 
74
 */
 
75
typedef struct callback_placeholder_s {
 
76
 
 
77
    monitor_info   *mi;
 
78
    netsnmp_monitor_callback_header *cbh;
 
79
 
 
80
    struct callback_placeholder_s *next;
 
81
 
 
82
} callback_placeholder;
 
83
 
 
84
 
 
85
/**************************************************************************
 
86
 *
 
87
 * 
 
88
 *
 
89
 **************************************************************************/
 
90
 
 
91
/*
 
92
 * local statics
 
93
 */
 
94
static char     need_init = 1;
 
95
static netsnmp_container *monitored_objects = NULL;
 
96
static netsnmp_monitor_callback_header *callback_pending_list;
 
97
static callback_placeholder *callback_ready_list;
 
98
 
 
99
/*
 
100
 * local prototypes
 
101
 */
 
102
static watcher_list *find_watchers(oid * object, size_t oid_len);
 
103
static int      insert_watcher(oid *, size_t, monitor_info *);
 
104
static int      check_registered(unsigned int event, oid * o, int o_l,
 
105
                                 watcher_list ** pWl, monitor_info ** pMi);
 
106
static void     move_pending_to_ready(void);
 
107
 
 
108
 
 
109
/**************************************************************************
 
110
 *
 
111
 * Public functions
 
112
 *
 
113
 **************************************************************************/
 
114
 
 
115
/*
 
116
 * 
 
117
 */
 
118
void
 
119
netsnmp_monitor_init(void)
 
120
{
 
121
    if (!need_init)
 
122
        return;
 
123
 
 
124
    callback_pending_list = NULL;
 
125
    callback_ready_list = NULL;
 
126
 
 
127
    monitored_objects = netsnmp_container_get("object_monitor:binary_array");
 
128
    if (NULL != monitored_objects)
 
129
        need_init = 0;
 
130
    monitored_objects->compare = netsnmp_compare_netsnmp_index;
 
131
    monitored_objects->ncompare = netsnmp_ncompare_netsnmp_index;
 
132
    
 
133
    return;
 
134
}
 
135
 
 
136
 
 
137
/**************************************************************************
 
138
 *
 
139
 * Registration functions
 
140
 *
 
141
 **************************************************************************/
 
142
 
 
143
/**
 
144
 * Register a callback for the specified object.
 
145
 *
 
146
 * @param object  pointer to the OID of the object to monitor.
 
147
 * @param oid_len length of the OID pointed to by object.
 
148
 * @param priority the priority to associate with this callback. A
 
149
 *                 higher number indicates higher priority. This
 
150
 *                 allows multiple callbacks for the same object to
 
151
 *                 coordinate the order in which they are called. If
 
152
 *                 two callbacks register with the same priority, the
 
153
 *                 order is undefined.
 
154
 * @param events  the events which the callback is interested in.
 
155
 * @param watcher_data pointer to data that will be supplied to the
 
156
 *                     callback method when an event occurs.
 
157
 * @param cb pointer to the function to be called when an event occurs.
 
158
 *
 
159
 * NOTE: the combination of the object, priority and watcher_data must
 
160
 *       be unique, as they are the parameters for unregistering a
 
161
 *       callback.
 
162
 *
 
163
 * @return SNMPERR_NOERR registration was successful
 
164
 * @return SNMPERR_MALLOC memory allocation failed
 
165
 * @return SNMPERR_VALUE the combination of the object, priority and
 
166
 *                        watcher_data is not unique.
 
167
 */
 
168
int
 
169
netsnmp_monitor_register(oid * object, size_t oid_len, int priority,
 
170
                         unsigned int events, void *watcher_data,
 
171
                         netsnmp_object_monitor_callback * cb)
 
172
{
 
173
    monitor_info   *mi;
 
174
    int             rc;
 
175
 
 
176
    netsnmp_assert(need_init == 0);
 
177
 
 
178
    mi = calloc(1, sizeof(monitor_info));
 
179
    if (NULL == mi)
 
180
        return SNMPERR_MALLOC;
 
181
 
 
182
    mi->priority = priority;
 
183
    mi->events = events;
 
184
    mi->watcher_data = watcher_data;
 
185
    mi->cb = cb;
 
186
 
 
187
    rc = insert_watcher(object, oid_len, mi);
 
188
    if (rc != SNMPERR_SUCCESS)
 
189
        free(mi);
 
190
 
 
191
    return rc;
 
192
}
 
193
 
 
194
/**
 
195
 * Unregister a callback for the specified object.
 
196
 *
 
197
 * @param object  pointer to the OID of the object to monitor.
 
198
 * @param oid_len length of the OID pointed to by object.
 
199
 * @param priority the priority to associate with this callback.
 
200
 * @param watcher_data pointer to data that was supplied when the
 
201
 *                     callback was registered.
 
202
 * @param cb pointer to the function to be called when an event occurs.
 
203
 */
 
204
int
 
205
netsnmp_monitor_unregister(oid * object, size_t oid_len, int priority,
 
206
                           void *wd, netsnmp_object_monitor_callback * cb)
 
207
{
 
208
    monitor_info   *mi, *last;
 
209
 
 
210
    watcher_list   *wl = find_watchers(object, oid_len);
 
211
    if (NULL == wl)
 
212
        return SNMPERR_GENERR;
 
213
 
 
214
    last = NULL;
 
215
    mi = wl->head;
 
216
    while (mi) {
 
217
        if ((mi->cb == cb) && (mi->priority == priority) &&
 
218
            (mi->watcher_data == wd))
 
219
            break;
 
220
        last = mi;
 
221
        mi = mi->next;
 
222
    }
 
223
 
 
224
    if (NULL == mi)
 
225
        return SNMPERR_GENERR;
 
226
 
 
227
    if (NULL == last)
 
228
        wl->head = mi->next;
 
229
    else
 
230
        last->next = mi->next;
 
231
 
 
232
    if (NULL == wl->head) {
 
233
        CONTAINER_REMOVE(monitored_objects, wl);
 
234
        free(wl->monitored_object.oids);
 
235
        free(wl);
 
236
    }
 
237
 
 
238
    free(mi);
 
239
 
 
240
    return SNMPERR_SUCCESS;
 
241
}
 
242
 
 
243
/**************************************************************************
 
244
 *
 
245
 * object monitor functions
 
246
 *
 
247
 **************************************************************************/
 
248
 
 
249
/**
 
250
 * Notifies the object monitor of an event.
 
251
 *
 
252
 * The object monitor funtions will save the callback information
 
253
 * until all varbinds in the current PDU have been processed and
 
254
 * a response has been sent. At that time, the object monitor will
 
255
 * determine if there are any watchers monitoring for the event.
 
256
 *
 
257
 * NOTE: the actual type of the callback structure may vary. The
 
258
 *       object monitor functions require only that the start of
 
259
 *       the structure match the netsnmp_monitor_callback_header
 
260
 *       structure. It is up to the watcher and monitored objects
 
261
 *       to agree on the format of other data.
 
262
 *
 
263
 * @param cbh pointer to a callback header.
 
264
 */
 
265
void
 
266
netsnmp_notify_monitor(netsnmp_monitor_callback_header * cbh)
 
267
{
 
268
 
 
269
    netsnmp_assert(need_init == 0);
 
270
 
 
271
    /*
 
272
     * put processing of until response has been sent
 
273
     */
 
274
    cbh->private = callback_pending_list;
 
275
    callback_pending_list = cbh;
 
276
 
 
277
    return;
 
278
}
 
279
 
 
280
/**
 
281
 * check to see if a registration exists for an object/event combination
 
282
 *
 
283
 * @param event the event type to check for
 
284
 * @param o     the oid to check for
 
285
 * @param o_l   the length of the oid
 
286
 *
 
287
 * @returns TRUE(1) if a callback is registerd
 
288
 * @returns FALSE(0) if no callback is registered
 
289
 */
 
290
int
 
291
netsnmp_monitor_check_registered(int event, oid * o, int o_l)
 
292
{
 
293
    return check_registered(event, o, o_l, NULL, NULL);
 
294
}
 
295
 
 
296
/**
 
297
 * Process all pending callbacks
 
298
 *
 
299
 * NOTE: this method is not in the public header, as it should only be
 
300
 *       called in one place, in the agent.
 
301
 */
 
302
void
 
303
netsnmp_monitor_process_callbacks(void)
 
304
{
 
305
    netsnmp_assert(need_init == 0);
 
306
    netsnmp_assert(NULL == callback_ready_list);
 
307
 
 
308
    if (NULL == callback_pending_list) {
 
309
        DEBUGMSGT(("object_monitor", "No callbacks to process"));
 
310
        return;
 
311
    }
 
312
 
 
313
    DEBUGMSG(("object_monitor", "Checking for registered " "callbacks."));
 
314
 
 
315
    /*
 
316
     * move an pending notification which has a registered watcher to the
 
317
     * ready list. Free any other notifications.
 
318
     */
 
319
    move_pending_to_ready();
 
320
 
 
321
    /*
 
322
     * call callbacks
 
323
     */
 
324
    while (callback_ready_list) {
 
325
 
 
326
        /*
 
327
         * pop off the first item
 
328
         */
 
329
        callback_placeholder *current_cbr;
 
330
        current_cbr = callback_ready_list;
 
331
        callback_ready_list = current_cbr->next;
 
332
 
 
333
        /*
 
334
         * setup, then call callback
 
335
         */
 
336
        current_cbr->cbh->watcher_data = current_cbr->mi->watcher_data;
 
337
        current_cbr->cbh->priority = current_cbr->mi->priority;
 
338
        (*current_cbr->mi->cb) (current_cbr->cbh);
 
339
 
 
340
        /*
 
341
         * release memory (don't free current_cbr->mi)
 
342
         */
 
343
        if (--(current_cbr->cbh->refs) == 0) {
 
344
            free(current_cbr->cbh->monitored_object.oids);
 
345
            free(current_cbr->cbh);
 
346
        }
 
347
        free(current_cbr);
 
348
 
 
349
        /*
 
350
         * check for any new pending notifications
 
351
         */
 
352
        move_pending_to_ready();
 
353
 
 
354
    }
 
355
 
 
356
    netsnmp_assert(callback_ready_list == NULL);
 
357
    netsnmp_assert(callback_pending_list = NULL);
 
358
 
 
359
    return;
 
360
}
 
361
 
 
362
/**************************************************************************
 
363
 *
 
364
 * COOPERATIVE helpers
 
365
 *
 
366
 **************************************************************************/
 
367
/**
 
368
 * Notifies the object monitor of a cooperative event.
 
369
 *
 
370
 * This convenience function will build a
 
371
 * @link netsnmp_monitor_callback_header@endlink and call
 
372
 * @link netsnmp_notify_monitor@endlink.
 
373
 *
 
374
 * @param event the event type
 
375
 * @param object pointer to the oid of the object sending the event
 
376
 * @param len    the lenght of the oid
 
377
 * @param oid_steal set to true if the function may keep the pointer
 
378
 *                  to the memory (and free it later). set to false
 
379
 *                  to make the function allocate and copy the oid.
 
380
 * @param object_info pointer to data supplied by the object for
 
381
 *                    the callback. This pointer must remain valid,
 
382
 *                    will be provided to each callback registered
 
383
 *                    for the object (i.e. it will not be copied or
 
384
 *                    freed).
 
385
 */
 
386
void
 
387
netsnmp_notify_cooperative(int event, oid * o, size_t o_len, char o_steal,
 
388
                           void *object_info)
 
389
{
 
390
    netsnmp_monitor_callback_cooperative *cbh;
 
391
 
 
392
    netsnmp_assert(need_init == 0);
 
393
 
 
394
    cbh = SNMP_MALLOC_TYPEDEF(netsnmp_monitor_callback_cooperative);
 
395
    if (NULL == cbh) {
 
396
        snmp_log(LOG_ERR, "could not allocate memory for "
 
397
                 "cooperative callback");
 
398
        return;
 
399
    }
 
400
 
 
401
    cbh->hdr.event = event;
 
402
    cbh->hdr.object_info = object_info;
 
403
    cbh->hdr.monitored_object.len = o_len;
 
404
 
 
405
    if (o_steal) {
 
406
        cbh->hdr.monitored_object.oids = o;
 
407
    } else {
 
408
        cbh->hdr.monitored_object.oids = snmp_duplicate_objid(o, o_len);
 
409
    }
 
410
 
 
411
    netsnmp_notify_monitor((netsnmp_monitor_callback_header *) cbh);
 
412
}
 
413
 
 
414
#ifndef DOXYGEN_SHOULD_IGNORE_THIS
 
415
/*************************************************************************
 
416
 *************************************************************************
 
417
 *************************************************************************
 
418
 * WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
 
419
 * WARNING!                                                       WARNING!
 
420
 * WARNING!                                                       WARNING!
 
421
 * WARNING!         This code is under active development         WARNING!
 
422
 * WARNING!         and is subject to change at any time.         WARNING!
 
423
 * WARNING!                                                       WARNING!
 
424
 * WARNING!                                                       WARNING!
 
425
 * WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
 
426
 *************************************************************************
 
427
 *************************************************************************
 
428
 *************************************************************************
 
429
 */
 
430
static watcher_list *
 
431
find_watchers(oid * object, size_t oid_len)
 
432
{
 
433
    netsnmp_index oah;
 
434
 
 
435
    oah.oids = object;
 
436
    oah.len = oid_len;
 
437
 
 
438
    return (watcher_list *)CONTAINER_FIND(monitored_objects, &oah);
 
439
}
 
440
 
 
441
static int
 
442
insert_watcher(oid * object, size_t oid_len, monitor_info * mi)
 
443
{
 
444
    watcher_list   *wl = find_watchers(object, oid_len);
 
445
    int             rc = SNMPERR_SUCCESS;
 
446
 
 
447
    if (NULL != wl) {
 
448
 
 
449
        monitor_info   *last, *current;
 
450
 
 
451
        netsnmp_assert(wl->head != NULL);
 
452
 
 
453
        last = NULL;
 
454
        current = wl->head;
 
455
        while (current) {
 
456
            if (mi->priority == current->priority) {
 
457
                /*
 
458
                 * check for duplicate
 
459
                 */
 
460
                if (mi->watcher_data == current->watcher_data)
 
461
                    return SNMPERR_VALUE; /** duplicate! */
 
462
            } else if (mi->priority > current->priority) {
 
463
                break;
 
464
            }
 
465
            last = current;
 
466
            current = current->next;
 
467
        }
 
468
        if (NULL == last) {
 
469
            mi->next = wl->head;
 
470
            wl->head = mi;
 
471
        } else {
 
472
            mi->next = last->next;
 
473
            last->next = mi;
 
474
        }
 
475
    } else {
 
476
 
 
477
        /*
 
478
         * first watcher for this oid; set up list
 
479
         */
 
480
        wl = SNMP_MALLOC_TYPEDEF(watcher_list);
 
481
        if (NULL == wl)
 
482
            return SNMPERR_MALLOC;
 
483
 
 
484
        /*
 
485
         * copy index oid
 
486
         */
 
487
        wl->monitored_object.len = oid_len;
 
488
        wl->monitored_object.oids = malloc(sizeof(oid) * oid_len);
 
489
        if (NULL == wl->monitored_object.oids) {
 
490
            free(wl);
 
491
            return SNMPERR_MALLOC;
 
492
        }
 
493
        memcpy(wl->monitored_object.oids, object, sizeof(oid) * oid_len);
 
494
 
 
495
        /*
 
496
         * add watcher, and insert into array
 
497
         */
 
498
        wl->head = mi;
 
499
        mi->next = NULL;
 
500
        rc = CONTAINER_INSERT(monitored_objects, wl);
 
501
        if (rc) {
 
502
            free(wl->monitored_object.oids);
 
503
            free(wl);
 
504
            return rc;
 
505
        }
 
506
    }
 
507
    return rc;
 
508
}
 
509
 
 
510
/**
 
511
 * @internal
 
512
 * check to see if a registration exists for an object/event combination
 
513
 *
 
514
 * @param event the event type to check for
 
515
 * @param o     the oid to check for
 
516
 * @param o_l   the length of the oid
 
517
 * @param pWl   if a pointer to a watcher_list pointer is supplied,
 
518
 *              upon return the watcher list pointer will be set to
 
519
 *              the watcher list for the object, or NULL if there are
 
520
 *              no watchers for the object.
 
521
 * @param pMi   if a pointer to a monitor_info pointer is supplied,
 
522
 *              upon return the pointer will be set to the first
 
523
 *              monitor_info object for the specified event.
 
524
 *
 
525
 * @returns TRUE(1) if a callback is registerd
 
526
 * @returns FALSE(0) if no callback is registered
 
527
 */
 
528
static int
 
529
check_registered(unsigned int event, oid * o, int o_l,
 
530
                 watcher_list ** pWl, monitor_info ** pMi)
 
531
{
 
532
    watcher_list   *wl;
 
533
    monitor_info   *mi;
 
534
 
 
535
    netsnmp_assert(need_init == 0);
 
536
 
 
537
    /*
 
538
     * check to see if anyone has registered for callbacks
 
539
     * for the object.
 
540
     */
 
541
    wl = find_watchers(o, o_l);
 
542
    if (pWl)
 
543
        *pWl = wl;
 
544
    if (NULL == wl)
 
545
        return 0;
 
546
 
 
547
    /*
 
548
     * check if any watchers are watching for this specific event
 
549
     */
 
550
    for (mi = wl->head; mi; mi = mi->next) {
 
551
 
 
552
        if (mi->events & event) {
 
553
            if (pMi)
 
554
                *pMi = mi;
 
555
            return TRUE;
 
556
        }
 
557
    }
 
558
 
 
559
    return 0;
 
560
}
 
561
 
 
562
/**
 
563
 *@internal
 
564
 */
 
565
inline void
 
566
insert_ready(callback_placeholder * new_cbr)
 
567
{
 
568
    callback_placeholder *current_cbr, *last_cbr;
 
569
 
 
570
    /*
 
571
     * insert in callback ready list
 
572
     */
 
573
    last_cbr = NULL;
 
574
    current_cbr = callback_ready_list;
 
575
    while (current_cbr) {
 
576
 
 
577
        if (new_cbr->mi->priority > current_cbr->mi->priority)
 
578
            break;
 
579
 
 
580
        last_cbr = current_cbr;
 
581
        current_cbr = current_cbr->next;
 
582
    }
 
583
    if (NULL == last_cbr) {
 
584
        new_cbr->next = callback_ready_list;
 
585
        callback_ready_list = new_cbr;
 
586
    } else {
 
587
        new_cbr->next = last_cbr->next;
 
588
        last_cbr->next = new_cbr;
 
589
    }
 
590
}
 
591
 
 
592
/**
 
593
 *@internal
 
594
 *
 
595
 * move an pending notification which has a registered watcher to the
 
596
 * ready list. Free any other notifications.
 
597
 */
 
598
static void
 
599
move_pending_to_ready(void)
 
600
{
 
601
    /*
 
602
     * check to see if anyone has registered for callbacks
 
603
     * for each object.
 
604
     */
 
605
    while (callback_pending_list) {
 
606
 
 
607
        watcher_list   *wl;
 
608
        monitor_info   *mi;
 
609
        netsnmp_monitor_callback_header *cbp;
 
610
 
 
611
        /*
 
612
         * pop off first item
 
613
         */
 
614
        cbp = callback_pending_list;
 
615
        callback_pending_list = cbp->private; /** next */
 
616
 
 
617
        if (0 == check_registered(cbp->event, cbp->monitored_object.oids,
 
618
                                  cbp->monitored_object.len, &wl,
 
619
                                  &mi)) {
 
620
 
 
621
            /*
 
622
             * nobody watching, free memory
 
623
             */
 
624
            free(cbp);
 
625
            continue;
 
626
        }
 
627
 
 
628
        /*
 
629
         * Found at least one; check the rest of the list and
 
630
         * save callback for processing
 
631
         */
 
632
        for (; mi; mi = mi->next) {
 
633
 
 
634
            callback_placeholder *new_cbr;
 
635
 
 
636
            if (0 == (mi->events & cbp->event))
 
637
                continue;
 
638
 
 
639
            /*
 
640
             * create temprory placeholder.
 
641
             *
 
642
             * I hate to allocate memory here, as I'd like this code to
 
643
             * be fast and lean. But I don't have time to think of another
 
644
             * solution os this will have to do for now.
 
645
             *
 
646
             * I need a list of monitor_info (mi) objects for each
 
647
             * callback which has registered for the event, and want
 
648
             * that list sorted by the priority required by the watcher.
 
649
             */
 
650
            new_cbr = SNMP_MALLOC_TYPEDEF(callback_placeholder);
 
651
            if (NULL == new_cbr) {
 
652
                snmp_log(LOG_ERR, "malloc failed, callback dropped.");
 
653
                continue;
 
654
            }
 
655
            new_cbr->cbh = cbp;
 
656
            new_cbr->mi = mi;
 
657
            ++cbp->refs;
 
658
 
 
659
            /*
 
660
             * insert in callback ready list
 
661
             */
 
662
            insert_ready(new_cbr);
 
663
 
 
664
        } /** end mi loop */
 
665
    } /** end cbp loop */
 
666
 
 
667
    netsnmp_assert(callback_pending_list == NULL);
 
668
}
 
669
 
 
670
 
 
671
#if defined TESTING_OBJECT_MONITOR
 
672
/**************************************************************************
 
673
 *
 
674
 * (untested) TEST CODE
 
675
 *
 
676
 */
 
677
void
 
678
dummy_callback(netsnmp_monitor_callback_header * cbh)
 
679
{
 
680
    printf("Callback received.\n");
 
681
}
 
682
 
 
683
void
 
684
dump_watchers(netsnmp_index *oah, void *)
 
685
{
 
686
    watcher_list   *wl = (watcher_list *) oah;
 
687
    netsnmp_monitor_callback_header *cbh = wl->head;
 
688
 
 
689
    printf("Watcher List for OID ");
 
690
    print_objid(wl->hdr->oids, wl->hdr->len);
 
691
    printf("\n");
 
692
 
 
693
    while (cbh) {
 
694
 
 
695
        printf("Priority = %d;, Events = %d; Watcher Data = 0x%x\n",
 
696
               cbh->priority, cbh->events, cbh->watcher_data);
 
697
 
 
698
        cbh = cbh->private;
 
699
    }
 
700
}
 
701
 
 
702
void
 
703
main(int argc, char **argv)
 
704
{
 
705
 
 
706
    oid             object[3] = { 1, 3, 6 };
 
707
    int             object_len = 3;
 
708
    int             rc;
 
709
 
 
710
    /*
 
711
     * init
 
712
     */
 
713
    netsnmp_monitor_init();
 
714
 
 
715
    /*
 
716
     * insert an object
 
717
     */
 
718
    rc = netsnmp_monitor_register(object, object_len, 0,
 
719
                                  EVENT_ROW_ADD, (void *) 0xdeadbeef,
 
720
                                  dummy_callback);
 
721
    printf("insert an object: %d\n", rc);
 
722
 
 
723
    /*
 
724
     * insert same object, new priority
 
725
     */
 
726
    netsnmp_monitor_register(object, object_len, 10,
 
727
                             EVENT_ROW_ADD, (void *) 0xdeadbeef,
 
728
                             dummy_callback);
 
729
    printf("insert same object, new priority: %d\n", rc);
 
730
 
 
731
    /*
 
732
     * insert same object, same priority, new data
 
733
     */
 
734
    netsnmp_monitor_register(object, object_len, 10,
 
735
                             EVENT_ROW_ADD, (void *) 0xbeefdead,
 
736
                             dummy_callback);
 
737
    printf("insert same object, same priority, new data: %d\n", rc);
 
738
 
 
739
    /*
 
740
     * insert same object, same priority, same data
 
741
     */
 
742
    netsnmp_monitor_register(object, object_len, 10,
 
743
                             EVENT_ROW_ADD, (void *) 0xbeefdead,
 
744
                             dummy_callback);
 
745
    printf("insert same object, same priority, new data: %d\n", rc);
 
746
 
 
747
 
 
748
    /*
 
749
     * dump table
 
750
     */
 
751
    CONTAINER_FOR_EACH(monitored_objects, dump_watchers, NULL);
 
752
}
 
753
#endif /** defined TESTING_OBJECT_MONITOR */
 
754
 
 
755
#endif /** DOXYGEN_SHOULD_IGNORE_THIS */