diff options
Diffstat (limited to 'agent/mibgroup/disman/expr/expExpression.c')
-rw-r--r-- | agent/mibgroup/disman/expr/expExpression.c | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/agent/mibgroup/disman/expr/expExpression.c b/agent/mibgroup/disman/expr/expExpression.c new file mode 100644 index 0000000..aa618b7 --- /dev/null +++ b/agent/mibgroup/disman/expr/expExpression.c @@ -0,0 +1,365 @@ +/* + * DisMan Expression MIB: + * Core implementation of the expression handling behaviour + */ + +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> +#include "disman/expr/expExpression.h" +#include "disman/expr/expObject.h" + +netsnmp_tdata *expr_table_data; + + /* + * Initializes the container for the expExpression table, + * regardless of which module initialisation routine is called first. + */ +void +init_expr_table_data(void) +{ + DEBUGMSGTL(("disman:expr:init", "init expression container\n")); + if (!expr_table_data) { + expr_table_data = netsnmp_tdata_create_table("expExpressionTable", 0); + DEBUGMSGTL(("disman:expr:init", "create expression container (%x)\n", + expr_table_data)); + } +} + +/** Initialize the expExpression module */ +void +init_expExpression(void) +{ + init_expr_table_data(); +} + + + /* =================================================== + * + * APIs for maintaining the contents of the + * expression table container. + * + * =================================================== */ + +void +_mteExpr_dump(void) +{ + struct mteExpression *entry; + netsnmp_tdata_row *row; + int i = 0; + + for (row = netsnmp_tdata_row_first(expr_table_data); + row; + row = netsnmp_tdata_row_next(expr_table_data, row)) { + entry = (struct mteExpression *)row->data; + DEBUGMSGTL(("disman:expr:dump", "ExpressionTable entry %d: ", i)); + DEBUGMSGOID(("disman:expr:dump", row->oid_index.oids, row->oid_index.len)); + DEBUGMSG(("disman:expr:dump", "(%s, %s)", + row->indexes->val.string, + row->indexes->next_variable->val.string)); + DEBUGMSG(("disman:expr:dump", ": %x, %x\n", row, entry)); + i++; + } + DEBUGMSGTL(("disman:expr:dump", "ExpressionTable %d entries\n", i)); +} + + + +/* + * Create a new row in the expression table + */ +struct expExpression * +expExpression_createEntry(char *expOwner, char *expName, int fixed) +{ + netsnmp_tdata_row *row; + + row = expExpression_createRow(expOwner, expName, fixed); + return row ? (struct expExpression *)row->data : NULL; +} + + +netsnmp_tdata_row * +expExpression_createRow(char *expOwner, char *expName, int fixed) +{ + struct expExpression *entry; + netsnmp_tdata_row *row; + size_t expOwner_len = (expOwner) ? strlen(expOwner) : 0; + size_t expName_len = (expName) ? strlen(expName) : 0; + + /* + * Create the expExpression entry, and the + * (table-independent) row wrapper structure... + */ + entry = SNMP_MALLOC_TYPEDEF(struct expExpression); + if (!entry) + return NULL; + + row = netsnmp_tdata_create_row(); + if (!row) { + SNMP_FREE(entry); + return NULL; + } + row->data = entry; + + /* + * ... initialize this row with the indexes supplied + * and the default values for the row... + */ + if (expOwner) + memcpy(entry->expOwner, expOwner, expOwner_len); + netsnmp_tdata_row_add_index(row, ASN_OCTET_STR, + entry->expOwner, expOwner_len); + if (expName) + memcpy(entry->expName, expName, expName_len); + netsnmp_tdata_row_add_index(row, ASN_OCTET_STR, + entry->expName, expName_len); + + entry->expValueType = EXPVALTYPE_COUNTER; + entry->expErrorCount = 0; + if (fixed) + entry->flags |= EXP_FLAG_FIXED; + + /* + * ... and insert the row into the table container. + */ + netsnmp_tdata_add_row(expr_table_data, row); + DEBUGMSGTL(("disman:expr:table", "Expression entry created (%s, %s)\n", + expOwner, expName)); + return row; +} + +/* + * Remove a row from the expression table + */ +void +expExpression_removeEntry(netsnmp_tdata_row *row) +{ + struct expExpression *entry; + + if (!row) + return; /* Nothing to remove */ + entry = (struct expExpression *) + netsnmp_tdata_remove_and_delete_row(expr_table_data, row); + if (entry) { + /* expExpression_disable( entry ) */ + SNMP_FREE(entry); + } +} + + +struct expExpression * +expExpression_getFirstEntry( void ) +{ + return (struct expExpression *) + netsnmp_tdata_row_entry(netsnmp_tdata_row_first(expr_table_data)); +} + +struct expExpression * +expExpression_getNextEntry( char *owner, char *name ) +{ + netsnmp_variable_list owner_var, name_var; + + memset(&owner_var, 0, sizeof(netsnmp_variable_list)); + memset(&name_var, 0, sizeof(netsnmp_variable_list)); + snmp_set_var_typed_value( &owner_var, ASN_OCTET_STR, + (u_char*)owner, strlen(owner)); + snmp_set_var_typed_value( &name_var, ASN_OCTET_STR, + (u_char*)name, strlen(name)); + owner_var.next_variable = &name_var; + + return (struct expExpression *) + netsnmp_tdata_row_entry( + netsnmp_tdata_row_next_byidx(expr_table_data, &owner_var)); +} + +struct expExpression * +expExpression_getEntry( char *owner, char *name ) +{ + netsnmp_variable_list owner_var, name_var; + + memset(&owner_var, 0, sizeof(netsnmp_variable_list)); + memset(&name_var, 0, sizeof(netsnmp_variable_list)); + snmp_set_var_typed_value( &owner_var, ASN_OCTET_STR, + (u_char*)owner, strlen(owner)); + snmp_set_var_typed_value( &name_var, ASN_OCTET_STR, + (u_char*)name, strlen(name)); + owner_var.next_variable = &name_var; + + return (struct expExpression *) + netsnmp_tdata_row_entry( + netsnmp_tdata_row_get_byidx(expr_table_data, &owner_var)); +} + + + /* =================================================== + * + * APIs for evaluating an expression - data gathering + * + * =================================================== */ + + + +/* + * Gather the data necessary for evaluating an expression. + * + * This will retrieve *all* the data relevant for all + * instances of this expression, rather than just the + * just the values needed for expanding a given instance. + */ +void +expExpression_getData( unsigned int reg, void *clientarg ) +{ + struct expExpression *entry = (struct expExpression *)clientarg; + netsnmp_tdata_row *row; + netsnmp_variable_list *var; + int ret; + + if ( !entry && reg ) { + snmp_alarm_unregister( reg ); + return; + } + + if (( entry->expExpression[0] == '\0' ) || + !(entry->flags & EXP_FLAG_ACTIVE) || + !(entry->flags & EXP_FLAG_VALID)) + return; + + DEBUGMSGTL(("disman:expr:run", "Gathering expression data (%s, %s)\n", + entry->expOwner, entry->expName)); + + /* + * This routine can be called in two situations: + * - regularly by 'snmp_alarm' (reg != 0) + * (as part of ongoing delta-value sampling) + * - on-demand (reg == 0) + * (for evaluating a particular entry) + * + * If a regularly sampled expression (entry->alarm != 0) + * is invoked on-demand (reg == 0), then use the most + * recent sampled values, rather than retrieving them again. + */ + if ( !reg && entry->alarm ) + return; + + /* + * XXX - may want to implement caching for on-demand evaluation + * of non-regularly sampled expressions. + */ + + /* + * For a wildcarded expression, expExpressionPrefix is used + * to determine which object instances to retrieve. + * (For a non-wildcarded expression, we already know + * explicitly which object instances will be needed). + * + * If we walk this object here, then the results can be + * used to build the necessary GET requests for each + * individual parameter object (within expObject_getData) + * + * This will probably be simpler (and definitely more efficient) + * than walking the object instances separately and merging + * merging the results). + * + * NB: Releasing any old results is handled by expObject_getData. + * Assigning to 'entry->pvars' without first releasing the + * previous contents does *not* introduce a memory leak. + */ + if ( entry->expPrefix_len ) { + var = (netsnmp_variable_list *) + SNMP_MALLOC_TYPEDEF( netsnmp_variable_list ); + snmp_set_var_objid( var, entry->expPrefix, entry->expPrefix_len); + ret = netsnmp_query_walk( var, entry->session ); + DEBUGMSGTL(("disman:expr:run", "Walk returned %d\n", ret )); + entry->pvars = var; + } + + /* XXX - retrieve sysUpTime.0 value, and check for discontinuity */ + /* + entry->flags &= ~EXP_FLAG_SYSUT; + var = (netsnmp_variable_list *) + SNMP_MALLOC_TYPEDEF( netsnmp_variable_list ); + snmp_set_var_objid( var, sysUT_oid, sysUT_oid_len ); + netsnmp_query_get( var, entry->session ); + if ( *var->val.integer != entry->sysUpTime ) { + entry->flags |= EXP_FLAG_SYSUT; + entry->sysUpTime = *var->val.integer; + } + snmp_free_varbind(var); + */ + + /* + * Loop through the list of relevant objects, + * and retrieve the corresponding values. + */ + for ( row = expObject_getFirst( entry->expOwner, entry->expName ); + row; + row = expObject_getNext( row )) { + + /* XXX - may need to check whether owner/name still match */ + expObject_getData( entry, (struct expObject *)row->data); + } +} + + +void +expExpression_enable( struct expExpression *entry ) +{ + DEBUGMSG(("disman:expr:run", "Enabling %s\n", entry->expName)); + if (!entry) + return; + + if (entry->alarm) { + /* or explicitly call expExpression_disable ?? */ + snmp_alarm_unregister( entry->alarm ); + entry->alarm = 0; + } + + if (entry->expDeltaInterval) { + entry->alarm = snmp_alarm_register( + entry->expDeltaInterval, SA_REPEAT, + expExpression_getData, entry ); + expExpression_getData( entry->alarm, (void*)entry ); + } +} + +void +expExpression_disable( struct expExpression *entry ) +{ + if (!entry) + return; + + if (entry->alarm) { + snmp_alarm_unregister( entry->alarm ); + entry->alarm = 0; + /* Perhaps release any previous results ?? */ + } +} + + +long _expExpression_MaxCount = 0; +long _expExpression_countEntries(void) +{ + struct expExpression *entry; + netsnmp_tdata_row *row; + long count = 0; + + for (row = netsnmp_tdata_row_first(expr_table_data); + row; + row = netsnmp_tdata_row_next(expr_table_data, row)) { + entry = (struct expExpression *)row->data; + count += entry->count; + } + + return count; +} + +long expExpression_getNumEntries(int max) +{ + long count; + /* XXX - implement some form of caching ??? */ + count = _expExpression_countEntries(); + if ( count > _expExpression_MaxCount ) + _expExpression_MaxCount = count; + + return ( max ? _expExpression_MaxCount : count); +} |