table_array.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:30k
- /*
- * table_array.c
- * $Id: table_array.c,v 5.23.2.1 2004/12/10 03:39:39 rstory Exp $
- */
- #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/table.h>
- #include <net-snmp/agent/table_array.h>
- #include <net-snmp/library/container.h>
- #include <net-snmp/library/snmp_assert.h>
- #if HAVE_DMALLOC_H
- #include <dmalloc.h>
- #endif
- /*
- * snmp.h:#define SNMP_MSG_INTERNAL_SET_BEGIN -1
- * snmp.h:#define SNMP_MSG_INTERNAL_SET_RESERVE1 0
- * snmp.h:#define SNMP_MSG_INTERNAL_SET_RESERVE2 1
- * snmp.h:#define SNMP_MSG_INTERNAL_SET_ACTION 2
- * snmp.h:#define SNMP_MSG_INTERNAL_SET_COMMIT 3
- * snmp.h:#define SNMP_MSG_INTERNAL_SET_FREE 4
- * snmp.h:#define SNMP_MSG_INTERNAL_SET_UNDO 5
- */
- static const char *mode_name[] = {
- "Reserve 1",
- "Reserve 2",
- "Action",
- "Commit",
- "Free",
- "Undo"
- };
- /*
- * PRIVATE structure for holding important info for each table.
- */
- typedef struct table_container_data_s {
- /** registration info for the table */
- netsnmp_table_registration_info *tblreg_info;
- /** container for the table rows */
- netsnmp_container *table;
- /*
- * mutex_type lock;
- */
- /** do we want to group rows with the same index
- * together when calling callbacks? */
- int group_rows;
- /** callbacks for this table */
- netsnmp_table_array_callbacks *cb;
- } table_container_data;
- /** @defgroup table_array table_array: Helps you implement a table when data can be stored locally. The data is stored in a sorted array, using a binary search for lookups.
- * @ingroup table
- *
- * The table_array handler is used (automatically) in conjuntion
- * with the @link table table@endlink handler. It is primarily
- * intended to be used with the mib2c configuration file
- * mib2c.array-user.conf.
- *
- * The code generated by mib2c is useful when you have control of
- * the data for each row. If you cannot control when rows are added
- * and deleted (or at least be notified of changes to row data),
- * then this handler is probably not for you.
- *
- * This handler makes use of callbacks (function pointers) to
- * handle various tasks. Code is generated for each callback,
- * but will need to be reviewed and flushed out by the user.
- *
- * NOTE NOTE NOTE: Once place where mib2c is somewhat lacking
- * is with regards to tables with external indices. If your
- * table makes use of one or more external indices, please
- * review the generated code very carefully for comments
- * regarding external indices.
- *
- * NOTE NOTE NOTE: This helper, the API and callbacks are still
- * being tested and may change.
- *
- * The generated code will define a structure for storage of table
- * related data. This structure must be used, as it contains the index
- * OID for the row, which is used for keeping the array sorted. You can
- * add addition fields or data to the structure for your own use.
- *
- * The generated code will also have code to handle SNMP-SET processing.
- * If your table does not support any SET operations, simply comment
- * out the #define <PREFIX>_SET_HANDLING (where <PREFIX> is your
- * table name) in the header file.
- *
- * SET processing modifies the row in-place. The duplicate_row
- * callback will be called to save a copy of the original row.
- * In the event of a failure before the commite phase, the
- * row_copy callback will be called to restore the original row
- * from the copy.
- *
- * Code will be generated to handle row creation. This code may be
- * disabled by commenting out the #define <PREFIX>_ROW_CREATION
- * in the header file.
- *
- * If your table contains a RowStatus object, by default the
- * code will not allow object in an active row to be modified.
- * To allow active rows to be modified, remove the comment block
- * around the #define <PREFIX>_CAN_MODIFY_ACTIVE_ROW in the header
- * file.
- *
- * Code will be generated to maintain a secondary index for all
- * rows, stored in a binary tree. This is very useful for finding
- * rows by a key other than the OID index. By default, the functions
- * for maintaining this tree will be based on a character string.
- * NOTE: this will likely be made into a more generic mechanism,
- * using new callback methods, in the near future.
- *
- * The generated code contains many TODO comments. Make sure you
- * check each one to see if it applies to your code. Examples include
- * checking indices for syntax (ranges, etc), initializing default
- * values in newly created rows, checking for row activation and
- * deactivation requirements, etc.
- *
- * @{
- */
- /**********************************************************************
- **********************************************************************
- * *
- * *
- * PUBLIC Registration functions *
- * *
- * *
- **********************************************************************
- **********************************************************************/
- /** register specified callbacks for the specified table/oid. If the
- group_rows parameter is set, the row related callbacks will be
- called once for each unique row index. Otherwise, each callback
- will be called only once, for all objects.
- */
- int
- netsnmp_table_container_register(netsnmp_handler_registration *reginfo,
- netsnmp_table_registration_info *tabreg,
- netsnmp_table_array_callbacks *cb,
- netsnmp_container *container,
- int group_rows)
- {
- table_container_data *tad = SNMP_MALLOC_TYPEDEF(table_container_data);
- if (!tad)
- return SNMPERR_GENERR;
- tad->tblreg_info = tabreg; /* we need it too, but it really is not ours */
- if (!cb) {
- snmp_log(LOG_ERR, "table_array registration with no callbacksn" );
- return SNMPERR_GENERR;
- }
- /*
- * check for required callbacks
- */
- if ((cb->can_set &&
- ((NULL==cb->duplicate_row) || (NULL==cb->delete_row) ||
- (NULL==cb->row_copy)) )) {
- snmp_log(LOG_ERR, "table_array registration with incomplete "
- "callback structure.n");
- return SNMPERR_GENERR;
- }
- if (NULL==container)
- tad->table = netsnmp_container_find("table_array");
- else
- tad->table = container;
- if (NULL==container->compare)
- container->compare = netsnmp_compare_netsnmp_index;
- if (NULL==container->ncompare)
- container->ncompare = netsnmp_ncompare_netsnmp_index;
-
- tad->cb = cb;
- reginfo->handler->myvoid = tad;
- return netsnmp_register_table(reginfo, tabreg);
- }
- /** find the handler for the table_array helper. */
- netsnmp_mib_handler *
- netsnmp_find_table_array_handler(netsnmp_handler_registration *reginfo)
- {
- netsnmp_mib_handler *mh;
- if (!reginfo)
- return NULL;
- mh = reginfo->handler;
- while (mh) {
- if (mh->access_method == netsnmp_table_array_helper_handler)
- break;
- mh = mh->next;
- }
- return mh;
- }
- /** find the context data used by the table_array helper */
- netsnmp_container *
- netsnmp_extract_array_context(netsnmp_request_info *request)
- {
- return netsnmp_request_get_list_data(request, TABLE_ARRAY_NAME);
- }
- /** this function is called to validate RowStatus transitions. */
- int
- netsnmp_table_array_check_row_status(netsnmp_table_array_callbacks *cb,
- netsnmp_request_group *ag,
- long *rs_new, long *rs_old)
- {
- netsnmp_index *row_ctx;
- netsnmp_index *undo_ctx;
- if (!ag || !cb)
- return SNMPERR_GENERR;
- row_ctx = ag->existing_row;
- undo_ctx = ag->undo_info;
-
- /*
- * xxx-rks: revisit row delete scenario
- */
- if (row_ctx) {
- /*
- * either a new row, or change to old row
- */
- /*
- * is it set to active?
- */
- if (RS_IS_GOING_ACTIVE(*rs_new)) {
- /*
- * is it ready to be active?
- */
- if ((NULL==cb->can_activate) ||
- cb->can_activate(undo_ctx, row_ctx, ag))
- *rs_new = RS_ACTIVE;
- else
- return SNMP_ERR_INCONSISTENTVALUE;
- } else {
- /*
- * not going active
- */
- if (undo_ctx) {
- /*
- * change
- */
- if (RS_IS_ACTIVE(*rs_old)) {
- /*
- * check pre-reqs for deactivation
- */
- if (cb->can_deactivate &&
- !cb->can_deactivate(undo_ctx, row_ctx, ag)) {
- return SNMP_ERR_INCONSISTENTVALUE;
- }
- }
- } else {
- /*
- * new row
- */
- }
- if (*rs_new != RS_DESTROY) {
- if ((NULL==cb->can_activate) ||
- cb->can_activate(undo_ctx, row_ctx, ag))
- *rs_new = RS_NOTINSERVICE;
- else
- *rs_new = RS_NOTREADY;
- } else {
- if (cb->can_delete && !cb->can_delete(undo_ctx, row_ctx, ag)) {
- return SNMP_ERR_INCONSISTENTVALUE;
- }
- ag->row_deleted = 1;
- }
- }
- } else {
- /*
- * check pre-reqs for delete row
- */
- if (cb->can_delete && !cb->can_delete(undo_ctx, row_ctx, ag)) {
- return SNMP_ERR_INCONSISTENTVALUE;
- }
- }
- return SNMP_ERR_NOERROR;
- }
- /** @} */
- #ifndef DOXYGEN_SHOULD_SKIP_THIS
- /**********************************************************************
- **********************************************************************
- **********************************************************************
- **********************************************************************
- * *
- * *
- * *
- * *
- * EVERYTHING BELOW THIS IS PRIVATE IMPLEMENTATION DETAILS. *
- * *
- * *
- * *
- * *
- **********************************************************************
- **********************************************************************
- **********************************************************************
- **********************************************************************/
- /**********************************************************************
- **********************************************************************
- * *
- * *
- * Structures, Utility/convenience functions *
- * *
- * *
- **********************************************************************
- **********************************************************************/
- /*
- * context info for SET requests
- */
- typedef struct set_context_s {
- netsnmp_agent_request_info *agtreq_info;
- table_container_data *tad;
- int status;
- } set_context;
- static void
- release_netsnmp_request_group(netsnmp_index *g, void *v)
- {
- netsnmp_request_group_item *tmp;
- netsnmp_request_group *group = (netsnmp_request_group *) g;
- if (!g)
- return;
- while (group->list) {
- tmp = group->list;
- group->list = tmp->next;
- free(tmp);
- }
- free(group);
- }
- static void
- release_netsnmp_request_groups(void *vp)
- {
- netsnmp_container *c = (netsnmp_container*)vp;
- CONTAINER_FOR_EACH(c, (netsnmp_container_obj_func*)
- release_netsnmp_request_group, NULL);
- CONTAINER_FREE(c);
- }
- void
- build_new_oid(netsnmp_handler_registration *reginfo,
- netsnmp_table_request_info *tblreq_info,
- netsnmp_index *row, netsnmp_request_info *current)
- {
- oid coloid[MAX_OID_LEN];
- int coloid_len;
- if (!tblreq_info || !reginfo || !row || !current)
- return;
- coloid_len = reginfo->rootoid_len + 2;
- memcpy(coloid, reginfo->rootoid, reginfo->rootoid_len * sizeof(oid));
- /** table.entry */
- coloid[reginfo->rootoid_len] = 1;
- /** table.entry.column */
- coloid[reginfo->rootoid_len + 1] = tblreq_info->colnum;
- /** table.entry.column.index */
- memcpy(&coloid[reginfo->rootoid_len + 2], row->oids,
- row->len * sizeof(oid));
- snmp_set_var_objid(current->requestvb, coloid,
- reginfo->rootoid_len + 2 + row->len);
- }
- /**********************************************************************
- **********************************************************************
- * *
- * *
- * GET procession functions *
- * *
- * *
- **********************************************************************
- **********************************************************************/
- int
- process_get_requests(netsnmp_handler_registration *reginfo,
- netsnmp_agent_request_info *agtreq_info,
- netsnmp_request_info *requests,
- table_container_data * tad)
- {
- int rc = SNMP_ERR_NOERROR;
- netsnmp_request_info *current;
- netsnmp_index *row = NULL;
- netsnmp_table_request_info *tblreq_info;
- netsnmp_variable_list *var;
- /*
- * Loop through each of the requests, and
- * try to find the appropriate row from the container.
- */
- for (current = requests; current; current = current->next) {
- var = current->requestvb;
- DEBUGMSGTL(("table_array:get",
- " process_get_request oid:"));
- DEBUGMSGOID(("table_array:get", var->name,
- var->name_length));
- DEBUGMSG(("table_array:get", "n"));
- /*
- * skip anything that doesn't need processing.
- */
- if (current->processed != 0) {
- DEBUGMSGTL(("table_array:get", "already processedn"));
- continue;
- }
- /*
- * Get pointer to the table information for this request. This
- * information was saved by table_helper_handler. When
- * debugging, we double check a few assumptions. For example,
- * the table_helper_handler should enforce column boundaries.
- */
- tblreq_info = netsnmp_extract_table_info(current);
- netsnmp_assert(tblreq_info->colnum <= tad->tblreg_info->max_column);
- if ((agtreq_info->mode == MODE_GETNEXT) ||
- (agtreq_info->mode == MODE_GETBULK)) {
- /*
- * find the row
- */
- row = netsnmp_table_index_find_next_row(tad->table, tblreq_info);
- if (!row) {
- /*
- * no results found.
- *
- * xxx-rks: how do we skip this entry for the next handler,
- * but still allow it a chance to hit another handler?
- */
- DEBUGMSGTL(("table_array:get", "no row foundn"));
- netsnmp_set_request_error(agtreq_info, current,
- SNMP_ENDOFMIBVIEW);
- continue;
- }
- /*
- * * if data was found, make sure it has the column we want
- */
- /* xxx-rks: add suport for sparse tables */
- /*
- * build new oid
- */
- build_new_oid(reginfo, tblreq_info, row, current);
- } /** GETNEXT/GETBULK */
- else {
- netsnmp_index index;
- index.oids = tblreq_info->index_oid;
- index.len = tblreq_info->index_oid_len;
- row = CONTAINER_FIND(tad->table, &index);
- if (!row) {
- DEBUGMSGTL(("table_array:get", "no row foundn"));
- netsnmp_set_request_error(agtreq_info, current,
- SNMP_NOSUCHINSTANCE);
- continue;
- }
- } /** GET */
- /*
- * get the data
- */
- rc = tad->cb->get_value(current, row, tblreq_info);
- } /** for ( ... requests ... ) */
- return rc;
- }
- /**********************************************************************
- **********************************************************************
- * *
- * *
- * SET procession functions *
- * *
- * *
- **********************************************************************
- **********************************************************************/
- void
- group_requests(netsnmp_agent_request_info *agtreq_info,
- netsnmp_request_info *requests,
- netsnmp_container *request_group, table_container_data * tad)
- {
- netsnmp_table_request_info *tblreq_info;
- netsnmp_variable_list *var;
- netsnmp_index *row, *tmp, index;
- netsnmp_request_info *current;
- netsnmp_request_group *g;
- netsnmp_request_group_item *i;
- for (current = requests; current; current = current->next) {
- var = current->requestvb;
- /*
- * skip anything that doesn't need processing.
- */
- if (current->processed != 0) {
- DEBUGMSGTL(("table_array:group",
- "already processedn"));
- continue;
- }
- /*
- * 3.2.1 Setup and paranoia
- * *
- * * Get pointer to the table information for this request. This
- * * information was saved by table_helper_handler. When
- * * debugging, we double check a few assumptions. For example,
- * * the table_helper_handler should enforce column boundaries.
- */
- row = NULL;
- tblreq_info = netsnmp_extract_table_info(current);
- netsnmp_assert(tblreq_info->colnum <= tad->tblreg_info->max_column);
- /*
- * search for index
- */
- index.oids = tblreq_info->index_oid;
- index.len = tblreq_info->index_oid_len;
- tmp = CONTAINER_FIND(request_group, &index);
- if (tmp) {
- DEBUGMSGTL(("table_array:group",
- " existing group:"));
- DEBUGMSGOID(("table_array:group", index.oids,
- index.len));
- DEBUGMSG(("table_array:group", "n"));
- g = (netsnmp_request_group *) tmp;
- i = SNMP_MALLOC_TYPEDEF(netsnmp_request_group_item);
- i->ri = current;
- i->tri = tblreq_info;
- i->next = g->list;
- g->list = i;
- /** xxx-rks: store map of colnum to request */
- continue;
- }
- DEBUGMSGTL(("table_array:group", " new group"));
- DEBUGMSGOID(("table_array:group", index.oids,
- index.len));
- DEBUGMSG(("table_array:group", "n"));
- g = SNMP_MALLOC_TYPEDEF(netsnmp_request_group);
- i = SNMP_MALLOC_TYPEDEF(netsnmp_request_group_item);
- g->list = i;
- g->table = tad->table;
- i->ri = current;
- i->tri = tblreq_info;
- /** xxx-rks: store map of colnum to request */
- /*
- * search for row. all changes are made to the original row,
- * later, we'll make a copy in undo_info before we start processing.
- */
- row = g->existing_row = CONTAINER_FIND(tad->table, &index);
- if (!g->existing_row) {
- if (!tad->cb->create_row) {
- if(MODE_IS_SET(agtreq_info->mode))
- netsnmp_set_request_error(agtreq_info, current,
- SNMP_ERR_NOTWRITABLE);
- else
- netsnmp_set_request_error(agtreq_info, current,
- SNMP_NOSUCHINSTANCE);
- free(g);
- free(i);
- continue;
- }
- /** use undo_info temporarily */
- row = g->existing_row = tad->cb->create_row(&index);
- if (!row) {
- /* xxx-rks : parameter to create_row to allow
- * for better error reporting. */
- netsnmp_set_request_error(agtreq_info, current,
- SNMP_ERR_GENERR);
- free(g);
- free(i);
- continue;
- }
- g->row_created = 1;
- }
- g->index.oids = row->oids;
- g->index.len = row->len;
- CONTAINER_INSERT(request_group, g);
- } /** for( current ... ) */
- }
- static void
- process_set_group(netsnmp_index *o, void *c)
- {
- /* xxx-rks: should we continue processing after an error?? */
- set_context *context = (set_context *) c;
- netsnmp_request_group *ag = (netsnmp_request_group *) o;
- int rc = SNMP_ERR_NOERROR;
- switch (context->agtreq_info->mode) {
- case MODE_SET_RESERVE1:/** -> SET_RESERVE2 || SET_FREE */
- /*
- * if not a new row, save undo info
- */
- if (ag->row_created == 0) {
- if (context->tad->cb->duplicate_row)
- ag->undo_info = context->tad->cb->duplicate_row(ag->existing_row);
- else
- ag->undo_info = NULL;
- if (NULL == ag->undo_info) {
- rc = SNMP_ERR_RESOURCEUNAVAILABLE;
- break;
- }
- }
-
- if (context->tad->cb->set_reserve1)
- context->tad->cb->set_reserve1(ag);
- break;
- case MODE_SET_RESERVE2:/** -> SET_ACTION || SET_FREE */
- if (context->tad->cb->set_reserve2)
- context->tad->cb->set_reserve2(ag);
- break;
- case MODE_SET_ACTION:/** -> SET_COMMIT || SET_UNDO */
- if (context->tad->cb->set_action)
- context->tad->cb->set_action(ag);
- break;
- case MODE_SET_COMMIT:/** FINAL CHANCE ON SUCCESS */
- if (ag->row_created == 0) {
- /*
- * this is an existing row, has it been deleted?
- */
- if (ag->row_deleted == 1) {
- DEBUGMSGT((TABLE_ARRAY_NAME, "action: deleting rown"));
- if (CONTAINER_REMOVE(ag->table, ag->existing_row) != 0) {
- rc = SNMP_ERR_COMMITFAILED;
- break;
- }
- }
- } else if (ag->row_deleted == 0) {
- /*
- * new row (that hasn't been deleted) should be inserted
- */
- DEBUGMSGT((TABLE_ARRAY_NAME, "action: inserting rown"));
- if (CONTAINER_INSERT(ag->table, ag->existing_row) != 0) {
- rc = SNMP_ERR_COMMITFAILED;
- break;
- }
- }
- if (context->tad->cb->set_commit)
- context->tad->cb->set_commit(ag);
- /** no more use for undo_info, so free it */
- if (ag->undo_info) {
- context->tad->cb->delete_row(ag->undo_info);
- ag->undo_info = NULL;
- }
- #if 0
- /* XXX-rks: finish row cooperative notifications
- * if the table has requested it, send cooperative notifications
- * for row operations.
- */
- if (context->tad->notifications) {
- if (ag->undo_info) {
- if (!ag->existing_row)
- netsnmp_monitor_notify(EVENT_ROW_DEL);
- else
- netsnmp_monitor_notify(EVENT_ROW_MOD);
- }
- else
- netsnmp_monitor_notify(EVENT_ROW_ADD);
- }
- #endif
- if ((ag->row_created == 0) && (ag->row_deleted == 1)) {
- context->tad->cb->delete_row(ag->existing_row);
- ag->existing_row = NULL;
- }
- break;
- case MODE_SET_FREE:/** FINAL CHANCE ON FAILURE */
- if (context->tad->cb->set_free)
- context->tad->cb->set_free(ag);
- /** no more use for undo_info, so free it */
- if (ag->row_created == 1) {
- if (context->tad->cb->delete_row)
- context->tad->cb->delete_row(ag->existing_row);
- ag->existing_row = NULL;
- }
- else {
- if (context->tad->cb->delete_row)
- context->tad->cb->delete_row(ag->undo_info);
- ag->undo_info = NULL;
- }
- break;
- case MODE_SET_UNDO:/** FINAL CHANCE ON FAILURE */
- /*
- * status already set - don't change it now
- */
- if (context->tad->cb->set_undo)
- context->tad->cb->set_undo(ag);
- /*
- * no more use for undo_info, so free it
- */
- if (ag->row_created == 0) {
- /*
- * restore old values
- */
- context->tad->cb->row_copy(ag->existing_row, ag->undo_info);
- context->tad->cb->delete_row(ag->undo_info);
- ag->undo_info = NULL;
- }
- else {
- context->tad->cb->delete_row(ag->existing_row);
- ag->existing_row = NULL;
- }
- break;
- default:
- snmp_log(LOG_ERR, "unknown mode processing SET for "
- "netsnmp_table_array_helper_handlern");
- rc = SNMP_ERR_GENERR;
- break;
- }
-
- if (rc)
- netsnmp_set_request_error(context->agtreq_info,
- ag->list->ri, rc);
-
- }
- int
- process_set_requests(netsnmp_agent_request_info *agtreq_info,
- netsnmp_request_info *requests,
- table_container_data * tad, char *handler_name)
- {
- set_context context;
- netsnmp_container *request_group;
- /*
- * create and save structure for set info
- */
- request_group = (netsnmp_container*) netsnmp_agent_get_list_data
- (agtreq_info, handler_name);
- if (request_group == NULL) {
- netsnmp_data_list *tmp;
- request_group = netsnmp_container_find("request_group:"
- "table_container");
- request_group->compare = netsnmp_compare_netsnmp_index;
- request_group->ncompare = netsnmp_ncompare_netsnmp_index;
- DEBUGMSGTL(("table_array", "Grouping requests by oidn"));
- tmp = netsnmp_create_data_list(handler_name,
- request_group,
- release_netsnmp_request_groups);
- netsnmp_agent_add_list_data(agtreq_info, tmp);
- /*
- * group requests.
- */
- group_requests(agtreq_info, requests, request_group, tad);
- }
- /*
- * process each group one at a time
- */
- context.agtreq_info = agtreq_info;
- context.tad = tad;
- context.status = SNMP_ERR_NOERROR;
- CONTAINER_FOR_EACH(request_group,
- (netsnmp_container_obj_func*)process_set_group,
- &context);
- return context.status;
- }
- /**********************************************************************
- **********************************************************************
- * *
- * *
- * netsnmp_table_array_helper_handler() *
- * *
- * *
- **********************************************************************
- **********************************************************************/
- int
- netsnmp_table_array_helper_handler(netsnmp_mib_handler *handler,
- netsnmp_handler_registration *reginfo,
- netsnmp_agent_request_info *agtreq_info,
- netsnmp_request_info *requests)
- {
- /*
- * First off, get our pointer from the handler. This
- * lets us get to the table registration information we
- * saved in get_table_array_handler(), as well as the
- * container where the actual table data is stored.
- */
- int rc = SNMP_ERR_NOERROR;
- table_container_data *tad = (table_container_data *)handler->myvoid;
- if (agtreq_info->mode < 0 || agtreq_info->mode > 5) {
- DEBUGMSGTL(("table_array", "Mode %d, Got request:n",
- agtreq_info->mode));
- } else {
- DEBUGMSGTL(("table_array", "Mode %s, Got request:n",
- mode_name[agtreq_info->mode]));
- }
- if (MODE_IS_SET(agtreq_info->mode)) {
- /*
- * netsnmp_mutex_lock(&tad->lock);
- */
- rc = process_set_requests(agtreq_info, requests,
- tad, handler->handler_name);
- /*
- * netsnmp_mutex_unlock(&tad->lock);
- */
- } else
- rc = process_get_requests(reginfo, agtreq_info, requests, tad);
- if (rc != SNMP_ERR_NOERROR) {
- DEBUGMSGTL(("table_array", "processing returned rc %dn", rc));
- }
-
- /*
- * Now we've done our processing. If there is another handler below us,
- * call them.
- */
- if (handler->next) {
- rc = netsnmp_call_next_handler(handler, reginfo, agtreq_info, requests);
- if (rc != SNMP_ERR_NOERROR) {
- DEBUGMSGTL(("table_array", "next handler returned rc %dn", rc));
- }
- }
-
- return rc;
- }
- #endif /** DOXYGEN_SHOULD_SKIP_THIS */