On fre, 2007-06-15 at 11:47 +0200, Magnus Fromreide wrote:
> Yes, the main problem seems to be the containers. It might be that I
> expect things that they never intended to provide but the word makes me
> expect something along the line of the C++ associative containers and I
> also expect the iterators to have C++-like properties but they most
> certainly don't have that.
>
> > > Please disregard the sysORTable patch for now, as I am working on a new
> > > one without iterators.
> >
> > I'll make an alternative suggestion.
> > Give me a couple of days, and I'll try to convert your iterator-based code
> > into an equivalent tdata-based version. Comparing the two should help
> > you get a better grasp of how these two approaches relate.
>
> I am actually doing that myself as I think that is the way to understand
> something, so unless you wish to make an alternative suggestion there is
> no need, but if you do I will probably compare both versions and try to
> understand the differences in design choises.
>
> What I really would appreciate is if someone could review my finished
> code once it is done.
Attached is my new try.
The part that I am least satisfied with is the index allocataion - I am
convinced that there should be a way to do better than O(^2) for it but
I fail to see it. I could obviously drop the requirement of stable
indices but that doesn't feel right either.
/MF
Index: README.agent-mibs
===================================================================
--- README.agent-mibs (revision 16702)
+++ README.agent-mibs (working copy)
@@ -40,6 +40,7 @@
G scalar group helper
W watched scalar
M mfd
+ C container table
Platform Keys
------------------
@@ -65,7 +66,7 @@
SNMPv2-MIB
system.?.0 A 3.2 O mibII/system_mib.c
.sysORLastChange.0 A 5.5 W mibII/sysORTable.c
- sysORTable A 3.4 O mibII/sysORTable.c
+ sysORTable A 5.5 C mibII/sysORTable.c
snmp.*.0 A 3.2 O mibII/snmp_mib.c
setSerialNo.0 A 5.0 W mibII/setSerialNo.c
Index: agent/mibgroup/mibII/sysORTable.c
===================================================================
--- agent/mibgroup/mibII/sysORTable.c (revision 16702)
+++ agent/mibgroup/mibII/sysORTable.c (working copy)
@@ -11,22 +11,14 @@
#else
#include <strings.h>
#endif
+#include <stddef.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include <net-snmp/agent/agent_callbacks.h>
-#include "struct.h"
-#include "util_funcs.h"
#include "sysORTable.h"
-#include "snmpd.h"
-#ifdef USING_AGENTX_SUBAGENT_MODULE
-#include "agentx/subagent.h"
-#include "agentx/client.h"
-#endif
-
-
static int
_register_sysOR_callback(int majorID, int minorID,
void *serverarg, void *clientarg);
@@ -37,25 +29,98 @@
_unregister_sysOR_by_session_callback(int majorID, int minorID,
void *serverarg, void *clientarg);
-static u_long sysORLastChange;
-static struct sysORTable *table = NULL;
-static int numEntries = 0;
+typedef struct sysOREntry_s {
+ netsnmp_index OR_idx;
+ char *OR_descr;
+ oid *OR_oid;
+ size_t OR_oidlen;
+ u_long OR_uptime;
+ netsnmp_session *OR_sess;
+} sysOREntry;
-/*
- * define the structure we're going to ask the agent to register our
- * information at
- */
-struct variable1 sysORTable_variables[] = {
- {SYSORTABLEID, ASN_OBJECT_ID, RONLY, var_sysORTable, 1, {2}},
- {SYSORTABLEDESCR, ASN_OCTET_STR, RONLY, var_sysORTable, 1, {3}},
- {SYSORTABLEUPTIME, ASN_TIMETICKS, RONLY, var_sysORTable, 1, {4}}
-};
+static void
+free_sysOREntry(void *data, void *context)
+{
+ sysOREntry* entry = data;
+ free(entry->OR_oid);
+ free(entry->OR_descr);
+ free(entry->OR_idx.oids);
+ free(entry);
+}
-/*
- * Define the OID pointer to the top of the mib tree that we're
- * registering underneath
- */
-oid sysORTable_variables_oid[] = { SNMP_OID_MIB2, 1, 9, 1 };
+#define COLUMN_SYSORINDEX 1
+#define COLUMN_SYSORID 2
+#define COLUMN_SYSORDESCR 3
+#define COLUMN_SYSORUPTIME 4
+
+static u_long sysORLastChange;
+static netsnmp_container *table;
+static oid sysORNextIndex = 1;
+
+static int
+init_table(void)
+{
+ if (table != NULL)
+ return 0;
+
+ table = netsnmp_container_find("sysORTable:table_container");
+
+ if (table == NULL)
+ return -1;
+
+ table->container_name = strdup("sysORTable");
+ if (table->container_name == NULL) {
+ CONTAINER_FREE(table);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+sysORTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+ netsnmp_request_info *request;
+
+ switch (reqinfo->mode) {
+ case MODE_GET:
+ for (request = requests; request; request = request->next) {
+ sysOREntry* entry =
+ (sysOREntry *)netsnmp_container_table_extract_context(request);
+
+ if (!entry) {
+ netsnmp_set_request_error(
+ reqinfo, request, SNMP_NOSUCHINSTANCE);
+ continue;
+ }
+
+ switch (netsnmp_extract_table_info(request)->colnum) {
+ case COLUMN_SYSORID:
+ snmp_set_var_typed_value(
+ request->requestvb, ASN_OBJECT_ID,
+ (u_char *)entry->OR_oid, entry->OR_oidlen * sizeof(oid));
+ break;
+ case COLUMN_SYSORDESCR:
+ snmp_set_var_typed_value(
+ request->requestvb, ASN_OCTET_STR,
+ (u_char *)entry->OR_descr, strlen(entry->OR_descr));
+ break;
+ case COLUMN_SYSORUPTIME:
+ snmp_set_var_typed_integer(
+ request->requestvb, ASN_TIMETICKS, entry->OR_uptime);
+ break;
+ default:
+ netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
+ break;
+ }
+ }
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
#ifdef USING_MIBII_SYSTEM_MIB_MODULE
extern oid system_module_oid[];
extern int system_module_oid_len;
@@ -65,11 +130,27 @@
void
init_sysORTable(void)
{
+ DEBUGMSGTL(("mibII/sysORTable", "init_sysORTable\n"));
oid sysORLastChange_oid[] = { SNMP_OID_MIB2, 1, 8 };
- /*
- * register ourselves with the agent to handle our mib tree
- */
+ oid sysORTable_oid[] = { SNMP_OID_MIB2, 1, 9 };
+ netsnmp_table_registration_info *table_info =
+ SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
+
+ init_table();
+
+ if (table_info == NULL || table == NULL) {
+ free(table_info);
+ CONTAINER_FREE(table);
+ return;
+ }
+
+ netsnmp_table_helper_add_indexes(table_info,
+ ASN_INTEGER, /** index: sysORIndex */
+ 0);
+ table_info->min_column = COLUMN_SYSORID;
+ table_info->max_column = COLUMN_SYSORUPTIME;
+
netsnmp_register_watched_scalar(
netsnmp_create_handler_registration(
"mibII/sysORLastChange", NULL,
@@ -79,21 +160,11 @@
&sysORLastChange, sizeof(u_long),
ASN_TIMETICKS, WATCHER_FIXED_SIZE));
-#ifdef USING_AGENTX_SUBAGENT_MODULE
- if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) == MASTER_AGENT)
- (void) register_mib_priority("mibII/sysORTable",
- (struct variable *)
- sysORTable_variables,
- sizeof(struct variable1),
- sizeof(sysORTable_variables) /
- sizeof(struct variable1),
- sysORTable_variables_oid,
- sizeof(sysORTable_variables_oid) /
- sizeof(oid), 1);
- else
-#endif
- REGISTER_MIB("mibII/sysORTable", sysORTable_variables, variable1,
- sysORTable_variables_oid);
+ netsnmp_container_table_register(
+ netsnmp_create_handler_registration(
+ "mibII/sysORTable", sysORTable_handler,
+ sysORTable_oid, OID_LENGTH(sysORTable_oid), HANDLER_CAN_RONLY),
+ table_info, table, TABLE_CONTAINER_KEY_NETSNMP_INDEX);
snmp_register_callback(SNMP_CALLBACK_APPLICATION,
SNMPD_CALLBACK_REQ_REG_SYSOR,
@@ -114,105 +185,126 @@
#endif
}
- /*********************
- *
- * System specific implementation functions
- *
- *********************/
-
-u_char *
-var_sysORTable(struct variable *vp,
- oid * name,
- size_t * length,
- int exact, size_t * var_len, WriteMethod ** write_method)
+void
+shutdown_sysORTable(void)
{
- unsigned long i = 0;
- static unsigned long ret;
- struct sysORTable *ptr = table;
-
- if (header_simple_table
- (vp, name, length, exact, var_len, write_method, numEntries))
- return NULL;
-
- for (i = 1; ptr != NULL && i < name[*length - 1]; ptr = ptr->next, i++) {
- DEBUGMSGTL(("mibII/sysORTable", "sysORTable -- %lu != %lu\n",
- i, name[*length - 1]));
- }
- if (ptr == NULL) {
- DEBUGMSGTL(("mibII/sysORTable", "sysORTable -- no match: %lu\n",
- i));
- return NULL;
- }
- DEBUGMSGTL(("mibII/sysORTable", "sysORTable -- match: %lu\n", i));
-
- switch (vp->magic) {
- case SYSORTABLEID:
- *var_len = ptr->OR_oidlen * sizeof(ptr->OR_oid[0]);
- return (u_char *) ptr->OR_oid;
-
- case SYSORTABLEDESCR:
- *var_len = strlen(ptr->OR_descr);
- return (u_char *) ptr->OR_descr;
-
- case SYSORTABLEUPTIME:
- ret = netsnmp_timeval_uptime(&ptr->OR_uptime);
- return (u_char *) & ret;
-
- default:
- DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_sysORTable\n",
- vp->magic));
- }
- return NULL;
+ DEBUGMSGTL(("mibII/sysORTable", "shutdown_sysORTable\n"));
+ init_table();
+ CONTAINER_CLEAR(table, &free_sysOREntry, NULL);
}
-
int
register_sysORTable_sess(oid * oidin,
size_t oidlen,
const char *descr, netsnmp_session * ss)
{
- struct sysORTable *ptr, **nptr;
- struct register_sysOR_parameters reg_sysOR_parms;
+ sysOREntry *entry;
- DEBUGMSGTL(("mibII/sysORTable", "sysORTable registering: "));
+ DEBUGMSGTL(("mibII/sysORTable", "registering: "));
DEBUGMSGOID(("mibII/sysORTable", oidin, oidlen));
- DEBUGMSG(("mibII/sysORTable", "\n"));
+ DEBUGMSG(("mibII/sysORTable", ", session %p\n", ss));
- ptr = (struct sysORTable *) malloc(sizeof(struct sysORTable));
- if (ptr == NULL) {
+ init_table();
+
+ entry = calloc(1, sizeof(sysOREntry));
+ if (entry == NULL) {
+ DEBUGMSGTL(("mibII/sysORTable", "Failed to allocate new entry\n"));
return SYS_ORTABLE_REGISTRATION_FAILED;
}
- ptr->OR_descr = (char *) strdup(descr);
- if (ptr->OR_descr == NULL) {
- free(ptr);
+
+ entry->OR_idx.oids = malloc(sizeof(oid));
+ if (entry->OR_idx.oids == NULL) {
+ DEBUGMSGTL(("mibII/sysORTable", "Failed to allocate new index\n"));
+ free(entry);
return SYS_ORTABLE_REGISTRATION_FAILED;
}
- ptr->OR_oidlen = oidlen;
- ptr->OR_oid = (oid *) malloc(sizeof(oid) * oidlen);
- if (ptr->OR_oid == NULL) {
- free(ptr->OR_descr);
- free(ptr);
+ entry->OR_descr = (char *) strdup(descr);
+ if (entry->OR_descr == NULL) {
+ DEBUGMSGTL(("mibII/sysORTable",
+ "Failed to allocate new sysORDescr\n"));
+ free(entry->OR_idx.oids);
+ free(entry);
return SYS_ORTABLE_REGISTRATION_FAILED;
}
- memcpy(ptr->OR_oid, oidin, sizeof(oid) * oidlen);
- gettimeofday(&(ptr->OR_uptime), NULL);
- sysORLastChange = netsnmp_get_agent_uptime();
- ptr->OR_sess = ss;
- ptr->next = NULL;
- numEntries++;
+ entry->OR_oid = (oid *) malloc(sizeof(oid) * oidlen);
+ if (entry->OR_oid == NULL) {
+ DEBUGMSGTL(("mibII/sysORTable", "Failed to allocate new sysORID\n"));
+ free(entry->OR_idx.oids);
+ free(entry->OR_descr);
+ free(entry);
+ return SYS_ORTABLE_REGISTRATION_FAILED;
+ }
- /* add this entry to the end of the chained list */
- nptr = &table;
- while (*nptr != NULL)
- nptr = &((*nptr)->next);
- *nptr = ptr;
+ entry->OR_idx.len = 1;
+ {
+ const oid firstNext = sysORNextIndex;
+ netsnmp_iterator* it = CONTAINER_ITERATOR(table);
- reg_sysOR_parms.name = oidin;
- reg_sysOR_parms.namelen = oidlen;
- reg_sysOR_parms.descr = descr;
- snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
- SNMPD_CALLBACK_REG_SYSOR, ®_sysOR_parms);
+ DEBUGMSGTL(("mibII/sysORTable", "firstNext = %u\n", firstNext));
+ do {
+ const sysOREntry* value;
+ const oid cur = sysORNextIndex;
+
+ DEBUGMSGTL(("mibII/sysORTable", "cur = %u\n", cur));
+
+ if (sysORNextIndex == SNMP_MIN(MAX_SUBID, 2147483647UL))
+ sysORNextIndex = 1;
+ else
+ ++sysORNextIndex;
+
+ DEBUGMSGTL(("mibII/sysORTable", "sysORNextIndex = %u\n",
+ sysORNextIndex));
+
+ for (value = it->curr(it);
+ value && *value->OR_idx.oids < cur;
+ value = ITERATOR_NEXT(it)) {
+ DEBUGMSGTL(("mibII/sysORTable", "*value->OR_idx.oids = %u\n",
+ *value->OR_idx.oids));
+ }
+
+ if (value && *value->OR_idx.oids == cur) {
+ if (sysORNextIndex < cur)
+ it->reset(it);
+ } else {
+ *entry->OR_idx.oids = cur;
+ break;
+ }
+ } while (firstNext != sysORNextIndex);
+
+ ITERATOR_RELEASE(it);
+
+ if(firstNext == sysORNextIndex) {
+ DEBUGMSGTL(("mibII/sysORTable",
+ "Failed to locate a free index\n"));
+ free(entry->OR_oid);
+ free(entry->OR_idx.oids);
+ free(entry->OR_descr);
+ free(entry);
+ return SYS_ORTABLE_REGISTRATION_FAILED;
+ }
+ }
+
+ memcpy(entry->OR_oid, oidin, sizeof(oid) * oidlen);
+ entry->OR_oidlen = oidlen;
+ entry->OR_sess = ss;
+
+ DEBUGMSGTL(("mibII/sysORTable", "sysORTable registered as sysOREntry.%u\n",
+ *entry->OR_idx.oids));
+
+ CONTAINER_INSERT(table, entry);
+
+ entry->OR_uptime = sysORLastChange = netsnmp_get_agent_uptime();
+
+ {
+ struct register_sysOR_parameters reg_sysOR_parms;
+ reg_sysOR_parms.name = oidin;
+ reg_sysOR_parms.namelen = oidlen;
+ reg_sysOR_parms.descr = descr;
+ snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
+ SNMPD_CALLBACK_REG_SYSOR, ®_sysOR_parms);
+ }
+
return SYS_ORTABLE_REGISTERED_OK;
}
@@ -222,48 +314,44 @@
return register_sysORTable_sess(oidin, oidlen, descr, NULL);
}
-
-
int
unregister_sysORTable_sess(oid * oidin,
size_t oidlen, netsnmp_session * ss)
{
- struct sysORTable *ptr, *prev = NULL, *next;
- int found = SYS_ORTABLE_NO_SUCH_REGISTRATION;
- struct register_sysOR_parameters reg_sysOR_parms;
+ sysOREntry *value;
+ netsnmp_iterator* it = CONTAINER_ITERATOR(table);
+
DEBUGMSGTL(("mibII/sysORTable", "sysORTable unregistering: "));
DEBUGMSGOID(("mibII/sysORTable", oidin, oidlen));
- DEBUGMSG(("mibII/sysORTable", "\n"));
+ DEBUGMSG(("mibII/sysORTable", ", session %p\n", ss));
- for (ptr = table; ptr; ptr = next)
- {
- next = ptr->next;
- if (ptr->OR_sess == ss &&
- (snmp_oid_compare(oidin, oidlen, ptr->OR_oid, ptr->OR_oidlen) == 0))
- {
- if (prev == NULL)
- table = ptr->next;
- else
- prev->next = ptr->next;
+ while ((value = ITERATOR_NEXT(it))) {
+ if (value->OR_sess == ss &&
+ snmp_oid_compare(oidin, oidlen,
+ value->OR_oid, value->OR_oidlen) == 0) {
+ CONTAINER_REMOVE(table, value);
+ free_sysOREntry(value, NULL);
- free(ptr->OR_oid);
- free(ptr->OR_descr);
- free(ptr);
- numEntries--;
+ DEBUGMSGTL(("mibII/sysORTable", "unregistering successfull"));
+
sysORLastChange = netsnmp_get_agent_uptime();
- found = SYS_ORTABLE_UNREGISTERED_OK;
- break;
- } else
- prev = ptr;
+ {
+ struct register_sysOR_parameters reg_sysOR_parms;
+ reg_sysOR_parms.name = oidin;
+ reg_sysOR_parms.namelen = oidlen;
+ snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
+ SNMPD_CALLBACK_UNREG_SYSOR,
+ ®_sysOR_parms);
+ }
+ ITERATOR_RELEASE(it);
+ return SYS_ORTABLE_UNREGISTERED_OK;
+ }
}
- reg_sysOR_parms.name = oidin;
- reg_sysOR_parms.namelen = oidlen;
- snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
- SNMPD_CALLBACK_UNREG_SYSOR, ®_sysOR_parms);
-
- return found;
+ DEBUGMSGTL(("mibII/sysORTable", "unregistering failed"));
+ ITERATOR_RELEASE(it);
+ return SYS_ORTABLE_NO_SUCH_REGISTRATION;
}
@@ -273,29 +361,35 @@
return unregister_sysORTable_sess(oidin, oidlen, NULL);
}
+
void
unregister_sysORTable_by_session(netsnmp_session * ss)
{
- struct sysORTable *ptr, *prev = NULL, *next;
+ sysOREntry *value;
+ int any_unregistered = 0;
- for (ptr = table; ptr; ptr = next)
- {
- next = ptr->next;
- if (((ss->flags & SNMP_FLAGS_SUBSESSION) && ptr->OR_sess == ss) ||
- (!(ss->flags & SNMP_FLAGS_SUBSESSION) && ptr->OR_sess &&
- ptr->OR_sess->subsession == ss)) {
- if (prev == NULL)
- table = next;
- else
- prev->next = next;
- free(ptr->OR_oid);
- free(ptr->OR_descr);
- free(ptr);
- numEntries--;
- sysORLastChange = netsnmp_get_agent_uptime();
- } else
- prev = ptr;
+ DEBUGMSGTL(("mibII/sysORTable",
+ "sysORTable unregistering session %p\n", ss));
+
+ netsnmp_iterator* it = CONTAINER_ITERATOR(table);
+ while ((value = ITERATOR_NEXT(it))) {
+ if (((ss->flags & SNMP_FLAGS_SUBSESSION) && value->OR_sess == ss) ||
+ (!(ss->flags & SNMP_FLAGS_SUBSESSION) && value->OR_sess &&
+ value->OR_sess->subsession == ss)) {
+ CONTAINER_REMOVE(table, value);
+ DEBUGMSGTL(("mibII/sysORTable", " "));
+ DEBUGMSGOID(("mibII/sysORTable", value->OR_oid, value->OR_oidlen));
+ DEBUGMSG(("mibII/sysORTable", "\n"));
+ free_sysOREntry(value, NULL);
+ any_unregistered = 1;
+ }
}
+ ITERATOR_RELEASE(it);
+ if (any_unregistered)
+ sysORLastChange = netsnmp_get_agent_uptime();
+
+ DEBUGMSGTL(("mibII/sysORTable",
+ "sysORTable unregistering session %p done\n", ss));
}
static int
@@ -329,4 +423,3 @@
parms->OR_oidlen,
parms->OR_sess);
}
-
Index: agent/mibgroup/mibII/sysORTable.h
===================================================================
--- agent/mibgroup/mibII/sysORTable.h (revision 16702)
+++ agent/mibgroup/mibII/sysORTable.h (working copy)
@@ -1,44 +1,27 @@
-/*
- * Template MIB group interface - sysORTable.h
- *
- */
#ifndef _MIBGROUP_SYSORTABLE_H
#define _MIBGROUP_SYSORTABLE_H
-config_require(util_funcs)
-config_require(mibII/system_mib)
+struct sysORTable {
+ const char *OR_descr;
+ oid *OR_oid;
+ size_t OR_oidlen;
+ netsnmp_session *OR_sess;
+};
- struct sysORTable {
- char *OR_descr;
- oid *OR_oid;
- size_t OR_oidlen;
- struct timeval OR_uptime;
- netsnmp_session *OR_sess;
- struct sysORTable *next;
- };
+struct register_sysOR_parameters {
+ oid *name;
+ int namelen;
+ const char *descr;
+};
- struct register_sysOR_parameters {
- oid *name;
- int namelen;
- const char *descr;
- };
+extern void init_sysORTable(void);
+extern int register_sysORTable(oid *, size_t, const char *);
+extern int unregister_sysORTable(oid *, size_t);
+extern int register_sysORTable_sess(oid *, size_t, const char *,
+ netsnmp_session *);
+extern int unregister_sysORTable_sess(oid *, size_t, netsnmp_session *);
+extern void unregister_sysORTable_by_session(netsnmp_session *);
- extern void init_sysORTable(void);
- extern FindVarMethod var_sysORTable;
- extern FindVarMethod var_sysORLastChange;
- extern int register_sysORTable(oid *, size_t, const char *);
- extern int unregister_sysORTable(oid *, size_t);
- extern int register_sysORTable_sess(oid *, size_t, const char *,
- netsnmp_session *);
- extern int unregister_sysORTable_sess(oid *, size_t,
- netsnmp_session *);
- extern void unregister_sysORTable_by_session(netsnmp_session *);
-
-#define SYSORTABLEINDEX 1
-#define SYSORTABLEID 2
-#define SYSORTABLEDESCR 3
-#define SYSORTABLEUPTIME 4
-
#define SYS_ORTABLE_REGISTERED_OK 0
#define SYS_ORTABLE_REGISTRATION_FAILED -1
#define SYS_ORTABLE_UNREGISTERED_OK 0
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Net-snmp-coders mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/net-snmp-coders