⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 row_merge.c

📁 开发snmp的开发包有两个开放的SNMP开发库
💻 C
字号:
#include <net-snmp/net-snmp-config.h>#if HAVE_STRING_H#include <string.h>#else#include <strings.h>#endif#include <net-snmp/net-snmp-includes.h>#include <net-snmp/agent/net-snmp-agent-includes.h>#include <net-snmp/agent/row_merge.h>/** @defgroup row_merge row_merge *  Calls sub handlers with request for one row at a time. *  @ingroup utilities *  This helper splits a whole bunch of requests into chunks based on the row *  index that they refer to, and passes all requests for a given row to the lower handlers. *  This is useful for handlers that don't want to process multiple rows at the *  same time, but are happy to iterate through the request list for a single row. *  @{ *//** returns a row_merge handler that can be injected into a given *  handler chain.   */netsnmp_mib_handler *netsnmp_get_row_merge_handler(int prefix_len){    netsnmp_mib_handler *ret = NULL;    ret = netsnmp_create_handler("row_merge",                                  netsnmp_row_merge_helper_handler);    if (ret) {        ret->myvoid = (void *)(intptr_t)prefix_len;    }    return ret;}/** functionally the same as calling netsnmp_register_handler() but also * injects a row_merge handler at the same time for you. */intnetsnmp_register_row_merge(netsnmp_handler_registration *reginfo){    netsnmp_inject_handler(reginfo,		    netsnmp_get_row_merge_handler(reginfo->rootoid_len+1));    return netsnmp_register_handler(reginfo);}static void_rm_status_free(void *mem){    netsnmp_row_merge_status *rm_status = (netsnmp_row_merge_status*)mem;    if (NULL != rm_status->saved_requests)        free(rm_status->saved_requests);    if (NULL != rm_status->saved_status)        free(rm_status->saved_status);    free(mem);}/** retrieve row_merge_status */netsnmp_row_merge_status *netsnmp_row_merge_status_get(netsnmp_handler_registration *reginfo,                             netsnmp_agent_request_info *reqinfo,                             int create_missing){    netsnmp_row_merge_status *rm_status;    char buf[64];    int rc;    /*     * see if we've already been here     */    rc = snprintf(buf, sizeof(buf), "row_merge:%p", reginfo);    if ((-1 == rc) || (rc >= sizeof(buf))) {        snmp_log(LOG_ERR,"error creating key\n");        return NULL;    }        rm_status = netsnmp_agent_get_list_data(reqinfo, buf);    if ((NULL == rm_status) && create_missing) {        void *data_list;                rm_status = SNMP_MALLOC_TYPEDEF(netsnmp_row_merge_status);        if (NULL == rm_status) {            snmp_log(LOG_ERR,"error allocating memory\n");            return NULL;        }        data_list = netsnmp_create_data_list(buf, rm_status,                                             _rm_status_free);        if (NULL == data_list) {            free(rm_status);            return NULL;        }        netsnmp_agent_add_list_data(reqinfo, data_list);    }        return rm_status;}/** Determine if this is the first row * * returns 1 if this is the first row for this pass of the handler. */intnetsnmp_row_merge_status_first(netsnmp_handler_registration *reginfo,                               netsnmp_agent_request_info *reqinfo){    netsnmp_row_merge_status *rm_status;    /*     * find status     */    rm_status = netsnmp_row_merge_status_get(reginfo, reqinfo, 0);    if (NULL == rm_status)        return 0;    return (rm_status->count == 1) ? 1 : (rm_status->current == 1);}/** Determine if this is the last row * * returns 1 if this is the last row for this pass of the handler. */intnetsnmp_row_merge_status_last(netsnmp_handler_registration *reginfo,                              netsnmp_agent_request_info *reqinfo){    netsnmp_row_merge_status *rm_status;    /*     * find status     */    rm_status = netsnmp_row_merge_status_get(reginfo, reqinfo, 0);    if (NULL == rm_status)        return 0;    return (rm_status->count == 1) ? 1 :        (rm_status->current == rm_status->rows);}#define ROW_MERGE_WAITING 0#define ROW_MERGE_ACTIVE  1#define ROW_MERGE_DONE    2#define ROW_MERGE_HEAD    3/** Implements the row_merge handler */intnetsnmp_row_merge_helper_handler(netsnmp_mib_handler *handler,                                 netsnmp_handler_registration *reginfo,                                 netsnmp_agent_request_info *reqinfo,                                 netsnmp_request_info *requests){    netsnmp_request_info *request, **saved_requests;    char *saved_status;    netsnmp_row_merge_status *rm_status;    int i, j, ret, tail, count, final_rc = SNMP_ERR_NOERROR;    /*     * Use the prefix length as supplied during registration, rather     *  than trying to second-guess what the MIB implementer wanted.     */    int SKIP_OID = (int)(intptr_t)handler->myvoid;    DEBUGMSGTL(("helper:row_merge", "Got request (%d): ", SKIP_OID));    DEBUGMSGOID(("helper:row_merge", reginfo->rootoid, reginfo->rootoid_len));    DEBUGMSG(("helper:row_merge", "\n"));    /*     * find or create status     */    rm_status = netsnmp_row_merge_status_get(reginfo, reqinfo, 1);    /*     * Count the requests, and set up an array to keep     *  track of the original order.     */    for (count = 0, request = requests; request; request = request->next) {        DEBUGIF("helper:row_merge") {            DEBUGMSGTL(("helper:row_merge", "  got varbind: "));            DEBUGMSGOID(("helper:row_merge", request->requestvb->name,                         request->requestvb->name_length));            DEBUGMSG(("helper:row_merge", "\n"));        }        count++;    }    /*     * Optimization: skip all this if there is just one request     */    if(count == 1) {        rm_status->count = count;        if (requests->processed)            return SNMP_ERR_NOERROR;        return netsnmp_call_next_handler(handler, reginfo, reqinfo, requests);    }    /*     * we really should only have to do this once, instead of every pass.     * as a precaution, we'll do it every time, but put in some asserts     * to see if we have to.     */    /*     * if the count changed, re-do everything     */    if ((0 != rm_status->count) && (rm_status->count != count)) {        /*         * ok, i know next/bulk can cause this condition. Probably         * GET, too. need to rethink this mode counting. maybe         * add the mode to the rm_status structure? xxx-rks         */        if ((reqinfo->mode != MODE_GET) &&            (reqinfo->mode != MODE_GETNEXT) &&            (reqinfo->mode != MODE_GETBULK)) {            netsnmp_assert((NULL != rm_status->saved_requests) &&                           (NULL != rm_status->saved_status));        }        DEBUGMSGTL(("helper:row_merge", "count changed! do over...\n"));        SNMP_FREE(rm_status->saved_requests);        SNMP_FREE(rm_status->saved_status);                rm_status->count = 0;        rm_status->rows = 0;    }    if (0 == rm_status->count) {        /*         * allocate memory for saved structure         */        rm_status->saved_requests =            (netsnmp_request_info**)calloc(count+1,                                           sizeof(netsnmp_request_info*));        rm_status->saved_status = (char*)calloc(count,sizeof(char));    }    saved_status = rm_status->saved_status;    saved_requests = rm_status->saved_requests;    /*     * set up saved requests, and set any processed requests to done     */    i = 0;    for (request = requests; request; request = request->next, i++) {        if (request->processed) {            saved_status[i] = ROW_MERGE_DONE;            DEBUGMSGTL(("helper:row_merge", "  skipping processed oid: "));            DEBUGMSGOID(("helper:row_merge", request->requestvb->name,                         request->requestvb->name_length));            DEBUGMSG(("helper:row_merge", "\n"));        }        else            saved_status[i] = ROW_MERGE_WAITING;        if (0 != rm_status->count)            netsnmp_assert(saved_requests[i] == request);        saved_requests[i] = request;        saved_requests[i]->prev = NULL;    }    saved_requests[i] = NULL;    /*     * Note that saved_requests[count] is valid     *    (because of the 'count+1' in the calloc above),     * but NULL (since it's past the end of the list).     * This simplifies the re-linking later.     */    /*     * Work through the (unprocessed) requests in order.     * For each of these, search the rest of the list for any     *   matching indexes, and link them into a new list.     */    for (i=0; i<count; i++) {	if (saved_status[i] != ROW_MERGE_WAITING)	    continue;        if (0 == rm_status->count)            rm_status->rows++;        DEBUGMSGTL(("helper:row_merge", " row %d oid[%d]: ", rm_status->rows, i));        DEBUGMSGOID(("helper:row_merge", saved_requests[i]->requestvb->name,                     saved_requests[i]->requestvb->name_length));        DEBUGMSG(("helper:row_merge", "\n"));	saved_requests[i]->next = NULL;	saved_status[i] = ROW_MERGE_HEAD;	tail = i;        for (j=i+1; j<count; j++) {	    if (saved_status[j] != ROW_MERGE_WAITING)	        continue;            DEBUGMSGTL(("helper:row_merge", "? oid[%d]: ", j));            DEBUGMSGOID(("helper:row_merge",                         saved_requests[j]->requestvb->name,                         saved_requests[j]->requestvb->name_length));            if (!snmp_oid_compare(                    saved_requests[i]->requestvb->name+SKIP_OID,                    saved_requests[i]->requestvb->name_length-SKIP_OID,                    saved_requests[j]->requestvb->name+SKIP_OID,                    saved_requests[j]->requestvb->name_length-SKIP_OID)) {                DEBUGMSG(("helper:row_merge", " match\n"));                saved_requests[tail]->next = saved_requests[j];                saved_requests[j]->next    = NULL;                saved_requests[j]->prev = saved_requests[tail];	        saved_status[j] = ROW_MERGE_ACTIVE;	        tail = j;            }            else                DEBUGMSG(("helper:row_merge", " no match\n"));        }    }    /*     * not that we have a list for each row, call next handler...     */    if (0 == rm_status->count)        rm_status->count = count;    rm_status->current = 0;    for (i=0; i<count; i++) {	if (saved_status[i] != ROW_MERGE_HEAD)	    continue;        /*         * found the head of a new row,         * call the next handler with this list         */        rm_status->current++;        ret = netsnmp_call_next_handler(handler, reginfo, reqinfo,			                saved_requests[i]);        if (ret != SNMP_ERR_NOERROR) {            snmp_log(LOG_WARNING,                     "bad rc (%d) from next handler in row_merge\n", ret);            if (SNMP_ERR_NOERROR == final_rc)                final_rc = ret;        }    }    /*     * restore original linked list     */    for (i=0; i<count; i++) {	saved_requests[i]->next = saved_requests[i+1];        if (i>0)	    saved_requests[i]->prev = saved_requests[i-1];    }    return final_rc;}/**  *  initializes the row_merge helper which then registers a row_merge *  handler as a run-time injectable handler for configuration file *  use. */voidnetsnmp_init_row_merge(void){    netsnmp_register_handler_by_name("row_merge",                                     netsnmp_get_row_merge_handler(-1));}/**  @} */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -