finally in sync with archive
[bcm963xx.git] / userapps / opensource / net-snmp / agent / object_monitor.c
diff --git a/userapps/opensource/net-snmp/agent/object_monitor.c b/userapps/opensource/net-snmp/agent/object_monitor.c
deleted file mode 100755 (executable)
index c4c0318..0000000
+++ /dev/null
@@ -1,755 +0,0 @@
-/*
- * object_monitor.c
- *
- * $Id: object_monitor.c,v 1.6.2.1 2003/03/14 17:37:07 rstory Exp $
- *
- * functions and data structures for cooperating code to monitor objects.
- *
- * WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
- * WARNING!                                                       WARNING!
- * WARNING!                                                       WARNING!
- * WARNING!         This code is under active development         WARNING!
- * WARNING!         and is subject to change at any time.         WARNING!
- * WARNING!                                                       WARNING!
- * WARNING!                                                       WARNING!
- * WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
- */
-
-#include <net-snmp/net-snmp-config.h>
-#include <net-snmp/net-snmp-includes.h>
-#include <net-snmp/agent/net-snmp-agent-includes.h>
-#include <net-snmp/library/container.h>
-#include <net-snmp/library/snmp_assert.h>
-
-#include "net-snmp/agent/object_monitor.h"
-
-#if ! defined TRUE
-#  define TRUE 1
-#elsif TRUE != 1
-error "TRUE != 1"
-#endif
-/**************************************************************************
- *
- * Private data structures
- *
- **************************************************************************/
-    /*
-     * individual callback info for an object
-     */
-    typedef struct monitor_info_s {
-
-   /** priority for this callback */
-    int             priority;
-
-   /** handler that registred to watch this object */
-    netsnmp_mib_handler *watcher;
-
-   /** events that the watcher cares about */
-    unsigned int    events;
-
-   /** callback function */
-    netsnmp_object_monitor_callback *cb;
-
-   /** pointer to data from the watcher */
-    void           *watcher_data;
-
-    struct monitor_info_s *next;
-
-} monitor_info;
-
-/*
- * list of watchers for a given object
- */
-typedef struct watcher_list_s {
-
-   /** netsnmp_index must be first! */
-    netsnmp_index  monitored_object;
-
-    monitor_info   *head;
-
-} watcher_list;
-
-/*
- * temp holder for ordered list of callbacks
- */
-typedef struct callback_placeholder_s {
-
-    monitor_info   *mi;
-    netsnmp_monitor_callback_header *cbh;
-
-    struct callback_placeholder_s *next;
-
-} callback_placeholder;
-
-
-/**************************************************************************
- *
- * 
- *
- **************************************************************************/
-
-/*
- * local statics
- */
-static char     need_init = 1;
-static netsnmp_container *monitored_objects = NULL;
-static netsnmp_monitor_callback_header *callback_pending_list;
-static callback_placeholder *callback_ready_list;
-
-/*
- * local prototypes
- */
-static watcher_list *find_watchers(oid * object, size_t oid_len);
-static int      insert_watcher(oid *, size_t, monitor_info *);
-static int      check_registered(unsigned int event, oid * o, int o_l,
-                                 watcher_list ** pWl, monitor_info ** pMi);
-static void     move_pending_to_ready(void);
-
-
-/**************************************************************************
- *
- * Public functions
- *
- **************************************************************************/
-
-/*
- * 
- */
-void
-netsnmp_monitor_init(void)
-{
-    if (!need_init)
-        return;
-
-    callback_pending_list = NULL;
-    callback_ready_list = NULL;
-
-    monitored_objects = netsnmp_container_get("object_monitor:binary_array");
-    if (NULL != monitored_objects)
-        need_init = 0;
-    monitored_objects->compare = netsnmp_compare_netsnmp_index;
-    monitored_objects->ncompare = netsnmp_ncompare_netsnmp_index;
-    
-    return;
-}
-
-
-/**************************************************************************
- *
- * Registration functions
- *
- **************************************************************************/
-
-/**
- * Register a callback for the specified object.
- *
- * @param object  pointer to the OID of the object to monitor.
- * @param oid_len length of the OID pointed to by object.
- * @param priority the priority to associate with this callback. A
- *                 higher number indicates higher priority. This
- *                 allows multiple callbacks for the same object to
- *                 coordinate the order in which they are called. If
- *                 two callbacks register with the same priority, the
- *                 order is undefined.
- * @param events  the events which the callback is interested in.
- * @param watcher_data pointer to data that will be supplied to the
- *                     callback method when an event occurs.
- * @param cb pointer to the function to be called when an event occurs.
- *
- * NOTE: the combination of the object, priority and watcher_data must
- *       be unique, as they are the parameters for unregistering a
- *       callback.
- *
- * @return SNMPERR_NOERR registration was successful
- * @return SNMPERR_MALLOC memory allocation failed
- * @return SNMPERR_VALUE the combination of the object, priority and
- *                        watcher_data is not unique.
- */
-int
-netsnmp_monitor_register(oid * object, size_t oid_len, int priority,
-                         unsigned int events, void *watcher_data,
-                         netsnmp_object_monitor_callback * cb)
-{
-    monitor_info   *mi;
-    int             rc;
-
-    netsnmp_assert(need_init == 0);
-
-    mi = calloc(1, sizeof(monitor_info));
-    if (NULL == mi)
-        return SNMPERR_MALLOC;
-
-    mi->priority = priority;
-    mi->events = events;
-    mi->watcher_data = watcher_data;
-    mi->cb = cb;
-
-    rc = insert_watcher(object, oid_len, mi);
-    if (rc != SNMPERR_SUCCESS)
-        free(mi);
-
-    return rc;
-}
-
-/**
- * Unregister a callback for the specified object.
- *
- * @param object  pointer to the OID of the object to monitor.
- * @param oid_len length of the OID pointed to by object.
- * @param priority the priority to associate with this callback.
- * @param watcher_data pointer to data that was supplied when the
- *                     callback was registered.
- * @param cb pointer to the function to be called when an event occurs.
- */
-int
-netsnmp_monitor_unregister(oid * object, size_t oid_len, int priority,
-                           void *wd, netsnmp_object_monitor_callback * cb)
-{
-    monitor_info   *mi, *last;
-
-    watcher_list   *wl = find_watchers(object, oid_len);
-    if (NULL == wl)
-        return SNMPERR_GENERR;
-
-    last = NULL;
-    mi = wl->head;
-    while (mi) {
-        if ((mi->cb == cb) && (mi->priority == priority) &&
-            (mi->watcher_data == wd))
-            break;
-        last = mi;
-        mi = mi->next;
-    }
-
-    if (NULL == mi)
-        return SNMPERR_GENERR;
-
-    if (NULL == last)
-        wl->head = mi->next;
-    else
-        last->next = mi->next;
-
-    if (NULL == wl->head) {
-        CONTAINER_REMOVE(monitored_objects, wl);
-        free(wl->monitored_object.oids);
-        free(wl);
-    }
-
-    free(mi);
-
-    return SNMPERR_SUCCESS;
-}
-
-/**************************************************************************
- *
- * object monitor functions
- *
- **************************************************************************/
-
-/**
- * Notifies the object monitor of an event.
- *
- * The object monitor funtions will save the callback information
- * until all varbinds in the current PDU have been processed and
- * a response has been sent. At that time, the object monitor will
- * determine if there are any watchers monitoring for the event.
- *
- * NOTE: the actual type of the callback structure may vary. The
- *       object monitor functions require only that the start of
- *       the structure match the netsnmp_monitor_callback_header
- *       structure. It is up to the watcher and monitored objects
- *       to agree on the format of other data.
- *
- * @param cbh pointer to a callback header.
- */
-void
-netsnmp_notify_monitor(netsnmp_monitor_callback_header * cbh)
-{
-
-    netsnmp_assert(need_init == 0);
-
-    /*
-     * put processing of until response has been sent
-     */
-    cbh->private = callback_pending_list;
-    callback_pending_list = cbh;
-
-    return;
-}
-
-/**
- * check to see if a registration exists for an object/event combination
- *
- * @param event the event type to check for
- * @param o     the oid to check for
- * @param o_l   the length of the oid
- *
- * @returns TRUE(1) if a callback is registerd
- * @returns FALSE(0) if no callback is registered
- */
-int
-netsnmp_monitor_check_registered(int event, oid * o, int o_l)
-{
-    return check_registered(event, o, o_l, NULL, NULL);
-}
-
-/**
- * Process all pending callbacks
- *
- * NOTE: this method is not in the public header, as it should only be
- *       called in one place, in the agent.
- */
-void
-netsnmp_monitor_process_callbacks(void)
-{
-    netsnmp_assert(need_init == 0);
-    netsnmp_assert(NULL == callback_ready_list);
-
-    if (NULL == callback_pending_list) {
-        DEBUGMSGT(("object_monitor", "No callbacks to process"));
-        return;
-    }
-
-    DEBUGMSG(("object_monitor", "Checking for registered " "callbacks."));
-
-    /*
-     * move an pending notification which has a registered watcher to the
-     * ready list. Free any other notifications.
-     */
-    move_pending_to_ready();
-
-    /*
-     * call callbacks
-     */
-    while (callback_ready_list) {
-
-        /*
-         * pop off the first item
-         */
-        callback_placeholder *current_cbr;
-        current_cbr = callback_ready_list;
-        callback_ready_list = current_cbr->next;
-
-        /*
-         * setup, then call callback
-         */
-        current_cbr->cbh->watcher_data = current_cbr->mi->watcher_data;
-        current_cbr->cbh->priority = current_cbr->mi->priority;
-        (*current_cbr->mi->cb) (current_cbr->cbh);
-
-        /*
-         * release memory (don't free current_cbr->mi)
-         */
-        if (--(current_cbr->cbh->refs) == 0) {
-            free(current_cbr->cbh->monitored_object.oids);
-            free(current_cbr->cbh);
-        }
-        free(current_cbr);
-
-        /*
-         * check for any new pending notifications
-         */
-        move_pending_to_ready();
-
-    }
-
-    netsnmp_assert(callback_ready_list == NULL);
-    netsnmp_assert(callback_pending_list = NULL);
-
-    return;
-}
-
-/**************************************************************************
- *
- * COOPERATIVE helpers
- *
- **************************************************************************/
-/**
- * Notifies the object monitor of a cooperative event.
- *
- * This convenience function will build a
- * @link netsnmp_monitor_callback_header@endlink and call
- * @link netsnmp_notify_monitor@endlink.
- *
- * @param event the event type
- * @param object pointer to the oid of the object sending the event
- * @param len    the lenght of the oid
- * @param oid_steal set to true if the function may keep the pointer
- *                  to the memory (and free it later). set to false
- *                  to make the function allocate and copy the oid.
- * @param object_info pointer to data supplied by the object for
- *                    the callback. This pointer must remain valid,
- *                    will be provided to each callback registered
- *                    for the object (i.e. it will not be copied or
- *                    freed).
- */
-void
-netsnmp_notify_cooperative(int event, oid * o, size_t o_len, char o_steal,
-                           void *object_info)
-{
-    netsnmp_monitor_callback_cooperative *cbh;
-
-    netsnmp_assert(need_init == 0);
-
-    cbh = SNMP_MALLOC_TYPEDEF(netsnmp_monitor_callback_cooperative);
-    if (NULL == cbh) {
-        snmp_log(LOG_ERR, "could not allocate memory for "
-                 "cooperative callback");
-        return;
-    }
-
-    cbh->hdr.event = event;
-    cbh->hdr.object_info = object_info;
-    cbh->hdr.monitored_object.len = o_len;
-
-    if (o_steal) {
-        cbh->hdr.monitored_object.oids = o;
-    } else {
-        cbh->hdr.monitored_object.oids = snmp_duplicate_objid(o, o_len);
-    }
-
-    netsnmp_notify_monitor((netsnmp_monitor_callback_header *) cbh);
-}
-
-#ifndef DOXYGEN_SHOULD_IGNORE_THIS
-/*************************************************************************
- *************************************************************************
- *************************************************************************
- * WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
- * WARNING!                                                       WARNING!
- * WARNING!                                                       WARNING!
- * WARNING!         This code is under active development         WARNING!
- * WARNING!         and is subject to change at any time.         WARNING!
- * WARNING!                                                       WARNING!
- * WARNING!                                                       WARNING!
- * WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
- *************************************************************************
- *************************************************************************
- *************************************************************************
- */
-static watcher_list *
-find_watchers(oid * object, size_t oid_len)
-{
-    netsnmp_index oah;
-
-    oah.oids = object;
-    oah.len = oid_len;
-
-    return (watcher_list *)CONTAINER_FIND(monitored_objects, &oah);
-}
-
-static int
-insert_watcher(oid * object, size_t oid_len, monitor_info * mi)
-{
-    watcher_list   *wl = find_watchers(object, oid_len);
-    int             rc = SNMPERR_SUCCESS;
-
-    if (NULL != wl) {
-
-        monitor_info   *last, *current;
-
-        netsnmp_assert(wl->head != NULL);
-
-        last = NULL;
-        current = wl->head;
-        while (current) {
-            if (mi->priority == current->priority) {
-                /*
-                 * check for duplicate
-                 */
-                if (mi->watcher_data == current->watcher_data)
-                    return SNMPERR_VALUE; /** duplicate! */
-            } else if (mi->priority > current->priority) {
-                break;
-            }
-            last = current;
-            current = current->next;
-        }
-        if (NULL == last) {
-            mi->next = wl->head;
-            wl->head = mi;
-        } else {
-            mi->next = last->next;
-            last->next = mi;
-        }
-    } else {
-
-        /*
-         * first watcher for this oid; set up list
-         */
-        wl = SNMP_MALLOC_TYPEDEF(watcher_list);
-        if (NULL == wl)
-            return SNMPERR_MALLOC;
-
-        /*
-         * copy index oid
-         */
-        wl->monitored_object.len = oid_len;
-        wl->monitored_object.oids = malloc(sizeof(oid) * oid_len);
-        if (NULL == wl->monitored_object.oids) {
-            free(wl);
-            return SNMPERR_MALLOC;
-        }
-        memcpy(wl->monitored_object.oids, object, sizeof(oid) * oid_len);
-
-        /*
-         * add watcher, and insert into array
-         */
-        wl->head = mi;
-        mi->next = NULL;
-        rc = CONTAINER_INSERT(monitored_objects, wl);
-        if (rc) {
-            free(wl->monitored_object.oids);
-            free(wl);
-            return rc;
-        }
-    }
-    return rc;
-}
-
-/**
- * @internal
- * check to see if a registration exists for an object/event combination
- *
- * @param event the event type to check for
- * @param o     the oid to check for
- * @param o_l   the length of the oid
- * @param pWl   if a pointer to a watcher_list pointer is supplied,
- *              upon return the watcher list pointer will be set to
- *              the watcher list for the object, or NULL if there are
- *              no watchers for the object.
- * @param pMi   if a pointer to a monitor_info pointer is supplied,
- *              upon return the pointer will be set to the first
- *              monitor_info object for the specified event.
- *
- * @returns TRUE(1) if a callback is registerd
- * @returns FALSE(0) if no callback is registered
- */
-static int
-check_registered(unsigned int event, oid * o, int o_l,
-                 watcher_list ** pWl, monitor_info ** pMi)
-{
-    watcher_list   *wl;
-    monitor_info   *mi;
-
-    netsnmp_assert(need_init == 0);
-
-    /*
-     * check to see if anyone has registered for callbacks
-     * for the object.
-     */
-    wl = find_watchers(o, o_l);
-    if (pWl)
-        *pWl = wl;
-    if (NULL == wl)
-        return 0;
-
-    /*
-     * check if any watchers are watching for this specific event
-     */
-    for (mi = wl->head; mi; mi = mi->next) {
-
-        if (mi->events & event) {
-            if (pMi)
-                *pMi = mi;
-            return TRUE;
-        }
-    }
-
-    return 0;
-}
-
-/**
- *@internal
- */
-NETSNMP_INLINE void
-insert_ready(callback_placeholder * new_cbr)
-{
-    callback_placeholder *current_cbr, *last_cbr;
-
-    /*
-     * insert in callback ready list
-     */
-    last_cbr = NULL;
-    current_cbr = callback_ready_list;
-    while (current_cbr) {
-
-        if (new_cbr->mi->priority > current_cbr->mi->priority)
-            break;
-
-        last_cbr = current_cbr;
-        current_cbr = current_cbr->next;
-    }
-    if (NULL == last_cbr) {
-        new_cbr->next = callback_ready_list;
-        callback_ready_list = new_cbr;
-    } else {
-        new_cbr->next = last_cbr->next;
-        last_cbr->next = new_cbr;
-    }
-}
-
-/**
- *@internal
- *
- * move an pending notification which has a registered watcher to the
- * ready list. Free any other notifications.
- */
-static void
-move_pending_to_ready(void)
-{
-    /*
-     * check to see if anyone has registered for callbacks
-     * for each object.
-     */
-    while (callback_pending_list) {
-
-        watcher_list   *wl;
-        monitor_info   *mi;
-        netsnmp_monitor_callback_header *cbp;
-
-        /*
-         * pop off first item
-         */
-        cbp = callback_pending_list;
-        callback_pending_list = cbp->private; /** next */
-
-        if (0 == check_registered(cbp->event, cbp->monitored_object.oids,
-                                  cbp->monitored_object.len, &wl,
-                                  &mi)) {
-
-            /*
-             * nobody watching, free memory
-             */
-            free(cbp);
-            continue;
-        }
-
-        /*
-         * Found at least one; check the rest of the list and
-         * save callback for processing
-         */
-        for (; mi; mi = mi->next) {
-
-            callback_placeholder *new_cbr;
-
-            if (0 == (mi->events & cbp->event))
-                continue;
-
-            /*
-             * create temprory placeholder.
-             *
-             * I hate to allocate memory here, as I'd like this code to
-             * be fast and lean. But I don't have time to think of another
-             * solution os this will have to do for now.
-             *
-             * I need a list of monitor_info (mi) objects for each
-             * callback which has registered for the event, and want
-             * that list sorted by the priority required by the watcher.
-             */
-            new_cbr = SNMP_MALLOC_TYPEDEF(callback_placeholder);
-            if (NULL == new_cbr) {
-                snmp_log(LOG_ERR, "malloc failed, callback dropped.");
-                continue;
-            }
-            new_cbr->cbh = cbp;
-            new_cbr->mi = mi;
-            ++cbp->refs;
-
-            /*
-             * insert in callback ready list
-             */
-            insert_ready(new_cbr);
-
-        } /** end mi loop */
-    } /** end cbp loop */
-
-    netsnmp_assert(callback_pending_list == NULL);
-}
-
-
-#if defined TESTING_OBJECT_MONITOR
-/**************************************************************************
- *
- * (untested) TEST CODE
- *
- */
-void
-dummy_callback(netsnmp_monitor_callback_header * cbh)
-{
-    printf("Callback received.\n");
-}
-
-void
-dump_watchers(netsnmp_index *oah, void *)
-{
-    watcher_list   *wl = (watcher_list *) oah;
-    netsnmp_monitor_callback_header *cbh = wl->head;
-
-    printf("Watcher List for OID ");
-    print_objid(wl->hdr->oids, wl->hdr->len);
-    printf("\n");
-
-    while (cbh) {
-
-        printf("Priority = %d;, Events = %d; Watcher Data = 0x%x\n",
-               cbh->priority, cbh->events, cbh->watcher_data);
-
-        cbh = cbh->private;
-    }
-}
-
-void
-main(int argc, char **argv)
-{
-
-    oid             object[3] = { 1, 3, 6 };
-    int             object_len = 3;
-    int             rc;
-
-    /*
-     * init
-     */
-    netsnmp_monitor_init();
-
-    /*
-     * insert an object
-     */
-    rc = netsnmp_monitor_register(object, object_len, 0,
-                                  EVENT_ROW_ADD, (void *) 0xdeadbeef,
-                                  dummy_callback);
-    printf("insert an object: %d\n", rc);
-
-    /*
-     * insert same object, new priority
-     */
-    netsnmp_monitor_register(object, object_len, 10,
-                             EVENT_ROW_ADD, (void *) 0xdeadbeef,
-                             dummy_callback);
-    printf("insert same object, new priority: %d\n", rc);
-
-    /*
-     * insert same object, same priority, new data
-     */
-    netsnmp_monitor_register(object, object_len, 10,
-                             EVENT_ROW_ADD, (void *) 0xbeefdead,
-                             dummy_callback);
-    printf("insert same object, same priority, new data: %d\n", rc);
-
-    /*
-     * insert same object, same priority, same data
-     */
-    netsnmp_monitor_register(object, object_len, 10,
-                             EVENT_ROW_ADD, (void *) 0xbeefdead,
-                             dummy_callback);
-    printf("insert same object, same priority, new data: %d\n", rc);
-
-
-    /*
-     * dump table
-     */
-    CONTAINER_FOR_EACH(monitored_objects, dump_watchers, NULL);
-}
-#endif /** defined TESTING_OBJECT_MONITOR */
-
-#endif /** DOXYGEN_SHOULD_IGNORE_THIS */