📄 table_dataset.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>static netsnmp_data_list *auto_tables;typedef struct data_set_tables_s { netsnmp_table_data_set *table_set;} data_set_tables;typedef struct data_set_cache_s { void *data; size_t data_len;} data_set_cache;#define STATE_ACTION 1#define STATE_COMMIT 2#define STATE_UNDO 3#define STATE_FREE 4typedef struct newrow_stash_s { netsnmp_table_row *newrow; int state; int created; int deleted;} newrow_stash;/** @defgroup table_dataset table_dataset * Helps you implement a table with automatted storage. * @ingroup table_data * * This helper is obsolete. If you are writing a new module, please * consider using the table_dataset2 helper instead. * * This handler helps you implement a table where all the data is * expected to be stored within the agent itself and not in some * external storage location. It handles all MIB requests including * GETs, GETNEXTs and SETs. It's possible to simply create a table * without actually ever defining a handler to be called when SNMP * requests come in. To use the data, you can either attach a * sub-handler that merely uses/manipulates the data further when * requests come in, or you can loop through it externally when it's * actually needed. This handler is most useful in cases where a * table is holding configuration data for something which gets * triggered via another event. * * NOTE NOTE NOTE: This helper isn't complete and is likely to change * somewhat over time. Specifically, the way it stores data * internally may change drastically. * * @{ */voidnetsnmp_init_table_dataset(void) {#ifndef NETSNMP_DISABLE_MIB_LOADING register_app_config_handler("table", netsnmp_config_parse_table_set, NULL, "tableoid");#endif /* NETSNMP_DISABLE_MIB_LOADING */ register_app_config_handler("add_row", netsnmp_config_parse_add_row, NULL, "table_name indexes... values...");}/* ================================== * * Data Set API: Table maintenance * * ================================== *//** Create a netsnmp_table_data_set structure given a table_data definition */netsnmp_table_data_set *netsnmp_create_table_data_set(const char *table_name){ netsnmp_table_data_set *table_set = SNMP_MALLOC_TYPEDEF(netsnmp_table_data_set); if (!table_set) return NULL; table_set->table = netsnmp_create_table_data(table_name); return table_set;}/** clones a dataset row, including all data. */netsnmp_table_row *netsnmp_table_data_set_clone_row(netsnmp_table_row *row){ netsnmp_table_data_set_storage *data, **newrowdata; netsnmp_table_row *newrow; if (!row) return NULL; newrow = netsnmp_table_data_clone_row(row); if (!newrow) return NULL; data = (netsnmp_table_data_set_storage *) row->data; if (data) { for (newrowdata = (netsnmp_table_data_set_storage **) &(newrow->data); data; newrowdata = &((*newrowdata)->next), data = data->next) { memdup((u_char **) newrowdata, (u_char *) data, sizeof(netsnmp_table_data_set_storage)); if (!*newrowdata) { netsnmp_table_dataset_delete_row(newrow); return NULL; } if (data->data.voidp) { memdup((u_char **) & ((*newrowdata)->data.voidp), (u_char *) data->data.voidp, data->data_len); if (!(*newrowdata)->data.voidp) { netsnmp_table_dataset_delete_row(newrow); return NULL; } } } } return newrow;}/** deletes a single dataset table data. * returns the (possibly still good) next pointer of the deleted data object. */NETSNMP_INLINE netsnmp_table_data_set_storage *netsnmp_table_dataset_delete_data(netsnmp_table_data_set_storage *data){ netsnmp_table_data_set_storage *nextPtr = NULL; if (data) { nextPtr = data->next; SNMP_FREE(data->data.voidp); } SNMP_FREE(data); return nextPtr;}/** deletes all the data from this node and beyond in the linked list */NETSNMP_INLINE voidnetsnmp_table_dataset_delete_all_data(netsnmp_table_data_set_storage *data){ while (data) { data = netsnmp_table_dataset_delete_data(data); }}/** deletes all the data from this node and beyond in the linked list */NETSNMP_INLINE voidnetsnmp_table_dataset_delete_row(netsnmp_table_row *row){ netsnmp_table_data_set_storage *data; if (!row) return; data = netsnmp_table_data_delete_row(row); netsnmp_table_dataset_delete_all_data(data);}/** adds a new row to a dataset table */NETSNMP_INLINE voidnetsnmp_table_dataset_add_row(netsnmp_table_data_set *table, netsnmp_table_row *row){ if (!table) return; netsnmp_table_data_add_row(table->table, row);}/** adds a new row to a dataset table */NETSNMP_INLINE voidnetsnmp_table_dataset_replace_row(netsnmp_table_data_set *table, netsnmp_table_row *origrow, netsnmp_table_row *newrow){ if (!table) return; netsnmp_table_data_replace_row(table->table, origrow, newrow);}/** removes a row from the table, but doesn't delete/free the column values */NETSNMP_INLINE voidnetsnmp_table_dataset_remove_row(netsnmp_table_data_set *table, netsnmp_table_row *row){ if (!table) return; netsnmp_table_data_remove_and_delete_row(table->table, row);}/** removes a row from the table and then deletes it (and all its data) */NETSNMP_INLINE voidnetsnmp_table_dataset_remove_and_delete_row(netsnmp_table_data_set *table, netsnmp_table_row *row){ netsnmp_table_data_set_storage *data; if (!table) return; data = (netsnmp_table_data_set_storage *) netsnmp_table_data_remove_and_delete_row(table->table, row); netsnmp_table_dataset_delete_all_data(data);}/* ================================== * * Data Set API: Default row operations * * ================================== *//** creates a new row from an existing defined default set */netsnmp_table_row *netsnmp_table_data_set_create_row_from_defaults (netsnmp_table_data_set_storage *defrow){ netsnmp_table_row *row; row = netsnmp_create_table_data_row(); if (!row) return NULL; for (; defrow; defrow = defrow->next) { netsnmp_set_row_column(row, defrow->column, defrow->type, defrow->data.voidp, defrow->data_len); if (defrow->writable) netsnmp_mark_row_column_writable(row, defrow->column, 1); } return row;}/** adds a new default row to a table_set. * Arguments should be the table_set, column number, variable type and * finally a 1 if it is allowed to be writable, or a 0 if not. If the * default_value field is not NULL, it will be used to populate new * valuse in that column fro newly created rows. It is copied into the * storage template (free your calling argument). * * returns SNMPERR_SUCCESS or SNMPERR_FAILURE */intnetsnmp_table_set_add_default_row(netsnmp_table_data_set *table_set, unsigned int column, int type, int writable, void *default_value, size_t default_value_len){ netsnmp_table_data_set_storage *new_col, *ptr, *pptr; if (!table_set) return SNMPERR_GENERR; /* * double check */ new_col = netsnmp_table_data_set_find_column(table_set->default_row, column); if (new_col != NULL) { if (new_col->type == type && new_col->writable == writable) return SNMPERR_SUCCESS; return SNMPERR_GENERR; } new_col = SNMP_MALLOC_TYPEDEF(netsnmp_table_data_set_storage); new_col->type = type; new_col->writable = writable; new_col->column = column; if (default_value) { memdup((u_char **) & (new_col->data.voidp), (u_char *) default_value, default_value_len); new_col->data_len = default_value_len; } if (table_set->default_row == NULL) table_set->default_row = new_col; else { /* sort in order just because (needed for add_row support) */ for (ptr = table_set->default_row, pptr = NULL; ptr; pptr = ptr, ptr = ptr->next) { if (ptr->column > column) { new_col->next = ptr; if (pptr) pptr->next = new_col; else table_set->default_row = new_col; return SNMPERR_SUCCESS; } } if (pptr) pptr->next = new_col; else snmp_log(LOG_ERR,"Shouldn't have gotten here: table_dataset/add_row"); } return SNMPERR_SUCCESS;}/** adds multiple data column definitions to each row. Functionally, * this is a wrapper around calling netsnmp_table_set_add_default_row * repeatedly for you. */void#if HAVE_STDARG_Hnetsnmp_table_set_multi_add_default_row(netsnmp_table_data_set *tset, ...)#elsenetsnmp_table_set_multi_add_default_row(va_dcl ) va_dcl#endif{ va_list debugargs; unsigned int column; int type, writable; void *data; size_t data_len;#if HAVE_STDARG_H va_start(debugargs, tset);#else netsnmp_table_data_set *tset; va_start(debugargs); tset = va_arg(debugargs, netsnmp_table_data_set *);#endif while ((column = va_arg(debugargs, unsigned int)) != 0) { type = va_arg(debugargs, int); writable = va_arg(debugargs, int); data = va_arg(debugargs, void *); data_len = va_arg(debugargs, size_t); netsnmp_table_set_add_default_row(tset, column, type, writable, data, data_len); } va_end(debugargs);}/* ================================== * * Data Set API: MIB maintenance * * ================================== *//** Given a netsnmp_table_data_set definition, create a handler for it */netsnmp_mib_handler *netsnmp_get_table_data_set_handler(netsnmp_table_data_set *data_set){ netsnmp_mib_handler *ret = NULL; if (!data_set) { snmp_log(LOG_INFO, "netsnmp_get_table_data_set_handler(NULL) called\n"); return NULL; } ret = netsnmp_create_handler(TABLE_DATA_SET_NAME, netsnmp_table_data_set_helper_handler); if (ret) { ret->flags |= MIB_HANDLER_AUTO_NEXT; ret->myvoid = (void *) data_set; } return ret;}/** register a given data_set at a given oid (specified in the netsnmp_handler_registration pointer). The reginfo->handler->access_method *may* be null if the call doesn't ever want to be called for SNMP operations.*/intnetsnmp_register_table_data_set(netsnmp_handler_registration *reginfo, netsnmp_table_data_set *data_set, netsnmp_table_registration_info *table_info){ if (NULL == table_info) { /* * allocate the table if one wasn't allocated */ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info); } if (NULL == table_info->indexes && data_set->table->indexes_template) { /* * copy the indexes in */ table_info->indexes = snmp_clone_varbind(data_set->table->indexes_template); } if ((!table_info->min_column || !table_info->max_column) && (data_set->default_row)) { /* * determine min/max columns */ unsigned int mincol = 0xffffffff, maxcol = 0; netsnmp_table_data_set_storage *row; for (row = data_set->default_row; row; row = row->next) { mincol = SNMP_MIN(mincol, row->column); maxcol = SNMP_MAX(maxcol, row->column); } if (!table_info->min_column) table_info->min_column = mincol; if (!table_info->max_column) table_info->max_column = maxcol; } netsnmp_inject_handler(reginfo, netsnmp_get_table_data_set_handler(data_set)); return netsnmp_register_table_data(reginfo, data_set->table, table_info);}newrow_stash *netsnmp_table_data_set_create_newrowstash (netsnmp_table_data_set *datatable, netsnmp_table_request_info *table_info){ newrow_stash *newrowstash = NULL; netsnmp_table_row *newrow = NULL; newrowstash = SNMP_MALLOC_TYPEDEF(newrow_stash); newrowstash->created = 1; newrow = netsnmp_table_data_set_create_row_from_defaults (datatable->default_row); newrow->indexes = snmp_clone_varbind(table_info->indexes); newrowstash->newrow = newrow;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -