Trouble with iterator

Joshua Tolley <[email protected]>
Newsgroups gmane.network.net-snmp.user
Message-ID <20090531043856.GI15201@eddie>
The agent I'm writing uses mib2c.iterator.conf, and creates fairly
straightforward C as expected. I fix a couple of syntax errors and fill in a
few of the details the mib2c configuration needs, and in the
initialize_table_<my table> function, I create several items using the linked
list system mib2c generated for me. Log messages I've sprinkled throughout the
get_first_data_point, get_next_data_point, and other similar functions
demonstrate that the linked list is correctly populated, and remains correctly
populated throughout the life of the agent, as expected. However, when I try
to walk the table with snmpwalk, it only ever returns one element in the
table. What's more, it never shows me any of the values of the three index
columns I have on the table. I can't help but think these problems are
related. Attached are the relevant section of the MIB I'm implementing, as
well as the two source files from mib2c, with my modifications, should anyone
care to peek inside. Many thanks, in advance, for any light shed...

 - Josh / eggyknap

------------------------------------------------------------------------------
Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT 
is a gathering of tech-side developers & brand creativity professionals. Meet
the minds behind Google Creative Lab, Visual Complexity, Processing, & 
iPhoneDevCamp as they present alongside digital heavyweights like Barbarian 
Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com

_______________________________________________
Net-snmp-users mailing list
[email protected]
Please see the following page to unsubscribe or change other options:
https://lists.sourceforge.net/lists/listinfo/net-snmp-users
pg_amop.mib (text/plain, 2.2 KB)
pgsqlPgAmopTable		OBJECT-TYPE
	SYNTAX		SEQUENCE OF pgsqlPgAmopEntry
	MAX-ACCESS	not-accessible
	STATUS		current
	DESCRIPTION
		"The catalog pg_amop stores information about operators associated with index access method operator classes. There is one row for each operator that is a member of an operator class."
	::= { pgsqlCatalogTables 3 }

pgsqlPgAmopEntry		OBJECT-TYPE
	SYNTAX		PgsqlPgAmopEntry
	MAX-ACCESS	not-accessible
	STATUS		current
	DESCRIPTION
		"pg_amop entry"
	INDEX  { pgsnmpdConnID, rdbmsDbIndex, pgsqlPgAmopEntryOID }
	::= { pgsqlPgAmopTable 1 }

PgsqlPgAmopEntry ::=
	SEQUENCE {
		pgsqlPgAmopEntryOID		INTEGER,
		pgsqlPgAmopAmopfamily		INTEGER,
		pgsqlPgAmopAmoplefttype		INTEGER,
		pgsqlPgAmopAmoprighttype		INTEGER,
		pgsqlPgAmopAmopstrategy		INTEGER,
		pgsqlPgAmopAmopreqcheck		TruthValue,
		pgsqlPgAmopAmopopr		INTEGER,
		pgsqlPgAmopAmopmethod		INTEGER
	}

pgsqlPgAmopEntryOID			OBJECT-TYPE
	SYNTAX		INTEGER
	MAX-ACCESS	not-accessible
	STATUS		current
	DESCRIPTION
		"OID of this entry"
	::= { pgsqlPgAmopEntry 1 }

pgsqlPgAmopAmopfamily			OBJECT-TYPE
	SYNTAX		INTEGER
	MAX-ACCESS	read-only
	STATUS		current
	DESCRIPTION
		"The operator family this entry is for"
	::= { pgsqlPgAmopEntry 2 }

pgsqlPgAmopAmoplefttype			OBJECT-TYPE
	SYNTAX		INTEGER
	MAX-ACCESS	read-only
	STATUS		current
	DESCRIPTION
		"Left-hand input data type of operator"
	::= { pgsqlPgAmopEntry 3 }

pgsqlPgAmopAmoprighttype			OBJECT-TYPE
	SYNTAX		INTEGER
	MAX-ACCESS	read-only
	STATUS		current
	DESCRIPTION
		"Right-hand input data type of operator"
	::= { pgsqlPgAmopEntry 4 }

pgsqlPgAmopAmopstrategy			OBJECT-TYPE
	SYNTAX		INTEGER
	MAX-ACCESS	read-only
	STATUS		current
	DESCRIPTION
		"Operator strategy number"
	::= { pgsqlPgAmopEntry 5 }

pgsqlPgAmopAmopreqcheck			OBJECT-TYPE
	SYNTAX		TruthValue
	MAX-ACCESS	read-only
	STATUS		current
	DESCRIPTION
		"Index hit must be rechecked"
	::= { pgsqlPgAmopEntry 6 }

pgsqlPgAmopAmopopr			OBJECT-TYPE
	SYNTAX		INTEGER
	MAX-ACCESS	read-only
	STATUS		current
	DESCRIPTION
		"OID of the operator"
	::= { pgsqlPgAmopEntry 7 }

pgsqlPgAmopAmopmethod			OBJECT-TYPE
	SYNTAX		INTEGER
	MAX-ACCESS	read-only
	STATUS		current
	DESCRIPTION
		"Index access method operator family is for"
	::= { pgsqlPgAmopEntry 8 }


---------------------------------------
pgsqlPgAmopTable.c (text/x-csrc, 11.8 KB)
/*
 * Note: this file originally auto-generated by mib2c using
 *  : mib2c.iterate.conf 15999 2007-03-25 22:32:02Z dts12 $
 */

#include "pgsnmpd.h"
#include "pgsqlPgAmopTable.h"

void fill_pgsqlPgAmopTable(void);

/** Initializes the pgsqlPgAmopTable module */
void
init_pgsqlPgAmopTable(void)
{
  /* here we initialize all the tables we're planning on supporting */
    initialize_table_pgsqlPgAmopTable();
}

  /* TODO: "Determine the first/last column names" */

/** Initialize the pgsqlPgAmopTable table by defining its contents and how it's structured */
void
initialize_table_pgsqlPgAmopTable(void)
{
    static oid pgsqlPgAmopTable_oid[] = {1,3,6,1,4,1,27645,1,2,3};
    size_t pgsqlPgAmopTable_oid_len   = OID_LENGTH(pgsqlPgAmopTable_oid);
    netsnmp_handler_registration    *reg;
    netsnmp_iterator_info           *iinfo;
    netsnmp_table_registration_info *table_info;

    reg = netsnmp_create_handler_registration(
              "pgsqlPgAmopTable",     pgsqlPgAmopTable_handler,
              pgsqlPgAmopTable_oid, pgsqlPgAmopTable_oid_len,
              HANDLER_CAN_RONLY
              );

    table_info = SNMP_MALLOC_TYPEDEF( netsnmp_table_registration_info );
    netsnmp_table_helper_add_indexes(table_info,
                           ASN_OCTET_STR,  /* index: pgsnmpdConnID */
                           ASN_INTEGER,  /* index: rdbmsDbIndex */
                           ASN_INTEGER,  /* index: pgsqlPgAmopEntryOID */
                           0);
    table_info->min_column = COLUMN_PGSQLPGAMOPAMOPFAMILY;
    table_info->max_column = COLUMN_PGSQLPGAMOPAMOPMETHOD;
    
    iinfo = SNMP_MALLOC_TYPEDEF( netsnmp_iterator_info );
    iinfo->get_first_data_point = pgsqlPgAmopTable_get_first_data_point;
    iinfo->get_next_data_point  = pgsqlPgAmopTable_get_next_data_point;
    iinfo->table_reginfo        = table_info;
    
    netsnmp_register_table_iterator( reg, iinfo );

    /* Initialise the contents of the table here */
    fill_pgsqlPgAmopTable();
}

#define CONNID_LEN 255

    /* Typical data structure for a row entry */
struct pgsqlPgAmopTable_entry {
    /* Index values */
    u_char pgsnmpdConnID[CONNID_LEN];
    size_t pgsnmpdConnID_len;
    long rdbmsDbIndex;
    long pgsqlPgAmopEntryOID;

    /* Column values */
    long pgsqlPgAmopAmopfamily;
    long pgsqlPgAmopAmoplefttype;
    long pgsqlPgAmopAmoprighttype;
    int  pgsqlPgAmopAmopstrategy;
    int  pgsqlPgAmopAmopreqcheck;
    long pgsqlPgAmopAmopopr;
    long pgsqlPgAmopAmopmethod;

    /* Illustrate using a simple linked list */
    int   valid;
    struct pgsqlPgAmopTable_entry *next;
};

struct pgsqlPgAmopTable_entry  *pgsqlPgAmopTable_head = NULL;

/* Quiet compiler */
struct pgsqlPgAmopTable_entry *
pgsqlPgAmopTable_createEntry(
                 char* pgsnmpdConnID,
                 size_t pgsnmpdConnID_len,
                 long  rdbmsDbIndex,
                 long  pgsqlPgAmopEntryOID
                );
void
pgsqlPgAmopTable_removeEntry( struct pgsqlPgAmopTable_entry *entry );

/* create a new row in the (unsorted) table */
struct pgsqlPgAmopTable_entry *
pgsqlPgAmopTable_createEntry(
                 char* pgsnmpdConnID,
                 size_t pgsnmpdConnID_len,
                 long  rdbmsDbIndex,
                 long  pgsqlPgAmopEntryOID
                ) {
    struct pgsqlPgAmopTable_entry *entry;

    entry = SNMP_MALLOC_TYPEDEF(struct pgsqlPgAmopTable_entry);
    if (!entry)
        return NULL;

    /*memset(entry->pgsnmpdConnID, 0, CONNID_LEN); */
    memcpy(entry->pgsnmpdConnID, pgsnmpdConnID, pgsnmpdConnID_len);
    entry->pgsnmpdConnID_len = pgsnmpdConnID_len;
    entry->rdbmsDbIndex = rdbmsDbIndex;
    entry->pgsqlPgAmopEntryOID = pgsqlPgAmopEntryOID;

    entry->next = pgsqlPgAmopTable_head;
    pgsqlPgAmopTable_head = entry;
    return entry;
}

/* remove a row from the table */
void
pgsqlPgAmopTable_removeEntry( struct pgsqlPgAmopTable_entry *entry ) {
    struct pgsqlPgAmopTable_entry *ptr, *prev;

    if (!entry)
        return;    /* Nothing to remove */

    for ( ptr  = pgsqlPgAmopTable_head, prev = NULL;
          ptr != NULL;
          prev = ptr, ptr = ptr->next ) {
        if ( ptr == entry )
            break;
    }
    if ( !ptr )
        return;    /* Can't find it */

    if ( prev == NULL )
        pgsqlPgAmopTable_head = ptr->next;
    else
        prev->next = ptr->next;

    SNMP_FREE( entry );   /* XXX - release any other internal resources */
}

void fill_pgsqlPgAmopTable(void) {
    PGresult *pg_db_query;
    int resultCount, i;
    struct pgsqlPgAmopTable_entry *entry;
    char pgsnmpdConnID[112] = "Default conn ID";
    size_t pgsnmpdConnID_len = strlen(pgsnmpdConnID) + 1;
    long rdbmsDbIndex = 1;

    snmp_log(LOG_INFO, "Initializing pgsqlPgAmopTable\n");
    if (PQstatus(dbconn) == CONNECTION_OK) {
        pg_db_query = PQexec(dbconn, "SELECT oid::INTEGER, amopfamily::INTEGER, amoplefttype::INTEGER, amoprighttype::INTEGER, amopstrategy, amopreqcheck, amopopr::INTEGER , amopmethod::INTEGER FROM pg_amop ORDER BY 1 ASC");
    }
    else {
        snmp_log(LOG_ERR, "Can't get connected to database\n");
        return;
        /* TODO: I should signal MFD_RESOURCE_UNAVAILABLE somehow, here */
    }

    if (PQresultStatus(pg_db_query) != PGRES_TUPLES_OK) {
        snmp_log(LOG_ERR, "Didn't get any results from the database\n");
        PQclear(pg_db_query);
        return;
        /* TODO: I should signal MFD_RESOURCE_UNAVAILABLE somehow, here */
    }
    resultCount = PQntuples(pg_db_query);
    for (i = 0; i < resultCount; i++) {
        entry = pgsqlPgAmopTable_createEntry(pgsnmpdConnID, pgsnmpdConnID_len,
                 rdbmsDbIndex, atol(PQgetvalue(pg_db_query, i, 0)));
        entry->pgsqlPgAmopAmopfamily    = atol(PQgetvalue(pg_db_query, i, 1));
        entry->pgsqlPgAmopAmoplefttype  = atol(PQgetvalue(pg_db_query, i, 2));
        entry->pgsqlPgAmopAmoprighttype = atol(PQgetvalue(pg_db_query, i, 3));
        entry->pgsqlPgAmopAmopstrategy  = atoi(PQgetvalue(pg_db_query, i, 4));
        entry->pgsqlPgAmopAmopreqcheck  = atoi(PQgetvalue(pg_db_query, i, 5));
        entry->pgsqlPgAmopAmopopr       = atol(PQgetvalue(pg_db_query, i, 6));
        entry->pgsqlPgAmopAmopmethod    = atol(PQgetvalue(pg_db_query, i, 7));
    }
    snmp_log(LOG_INFO, "Finished initializing pgsqlPgAmopTable with %d entries\n", resultCount);
}

/* Example iterator hook routines - using 'get_next' to do most of the work */
netsnmp_variable_list *
pgsqlPgAmopTable_get_first_data_point(void **my_loop_context,
                          void **my_data_context,
                          netsnmp_variable_list *put_index_data,
                          netsnmp_iterator_info *mydata)
{
    *my_loop_context = pgsqlPgAmopTable_head;
    return pgsqlPgAmopTable_get_next_data_point(my_loop_context, my_data_context,
                                    put_index_data,  mydata );
}

netsnmp_variable_list *
pgsqlPgAmopTable_get_next_data_point(void **my_loop_context,
                          void **my_data_context,
                          netsnmp_variable_list *put_index_data,
                          netsnmp_iterator_info *mydata)
{
    struct pgsqlPgAmopTable_entry *entry = (struct pgsqlPgAmopTable_entry *)*my_loop_context;
    netsnmp_variable_list *idx = put_index_data;

    if ( entry ) {
        snmp_set_var_value( idx, entry->pgsnmpdConnID, sizeof(entry->pgsnmpdConnID) );
        idx = idx->next_variable;
        snmp_set_var_typed_integer( idx, ASN_INTEGER, entry->rdbmsDbIndex );
        idx = idx->next_variable;
        snmp_set_var_typed_integer( idx, ASN_INTEGER, entry->pgsqlPgAmopEntryOID );
        idx = idx->next_variable;
        *my_data_context = (void *)entry;
        *my_loop_context = (void *)entry->next;
        return put_index_data;
    } else {
        return NULL;
    }
}


/** handles requests for the pgsqlPgAmopTable table */
int
pgsqlPgAmopTable_handler(
    netsnmp_mib_handler               *handler,
    netsnmp_handler_registration      *reginfo,
    netsnmp_agent_request_info        *reqinfo,
    netsnmp_request_info              *requests) {

    netsnmp_request_info       *request;
    netsnmp_table_request_info *table_info;
    struct pgsqlPgAmopTable_entry          *table_entry;

    switch (reqinfo->mode) {
        /*
         * Read-support (also covers GetNext requests)
         */
    case MODE_GET:
        for (request=requests; request; request=request->next) {
            table_entry = (struct pgsqlPgAmopTable_entry *)
                              netsnmp_extract_iterator_context(request);
            table_info  =     netsnmp_extract_table_info(      request);
    
            switch (table_info->colnum) {
            case COLUMN_PGSQLPGAMOPAMOPFAMILY:
                if ( !table_entry ) {
                    netsnmp_set_request_error(reqinfo, request,
                                              SNMP_NOSUCHINSTANCE);
                    continue;
                }
                snmp_set_var_typed_integer( request->requestvb, ASN_INTEGER,
                                            table_entry->pgsqlPgAmopAmopfamily);
                break;
            case COLUMN_PGSQLPGAMOPAMOPLEFTTYPE:
                if ( !table_entry ) {
                    netsnmp_set_request_error(reqinfo, request,
                                              SNMP_NOSUCHINSTANCE);
                    continue;
                }
                snmp_set_var_typed_integer( request->requestvb, ASN_INTEGER,
                                            table_entry->pgsqlPgAmopAmoplefttype);
                break;
            case COLUMN_PGSQLPGAMOPAMOPRIGHTTYPE:
                if ( !table_entry ) {
                    netsnmp_set_request_error(reqinfo, request,
                                              SNMP_NOSUCHINSTANCE);
                    continue;
                }
                snmp_set_var_typed_integer( request->requestvb, ASN_INTEGER,
                                            table_entry->pgsqlPgAmopAmoprighttype);
                break;
            case COLUMN_PGSQLPGAMOPAMOPSTRATEGY:
                if ( !table_entry ) {
                    netsnmp_set_request_error(reqinfo, request,
                                              SNMP_NOSUCHINSTANCE);
                    continue;
                }
                snmp_set_var_typed_integer( request->requestvb, ASN_INTEGER,
                                            table_entry->pgsqlPgAmopAmopstrategy);
                break;
            case COLUMN_PGSQLPGAMOPAMOPREQCHECK:
                if ( !table_entry ) {
                    netsnmp_set_request_error(reqinfo, request,
                                              SNMP_NOSUCHINSTANCE);
                    continue;
                }
                snmp_set_var_typed_integer( request->requestvb, ASN_INTEGER,
                                            table_entry->pgsqlPgAmopAmopreqcheck);
                break;
            case COLUMN_PGSQLPGAMOPAMOPOPR:
                if ( !table_entry ) {
                    netsnmp_set_request_error(reqinfo, request,
                                              SNMP_NOSUCHINSTANCE);
                    continue;
                }
                snmp_set_var_typed_integer( request->requestvb, ASN_INTEGER,
                                            table_entry->pgsqlPgAmopAmopopr);
                break;
            case COLUMN_PGSQLPGAMOPAMOPMETHOD:
                if ( !table_entry ) {
                    netsnmp_set_request_error(reqinfo, request,
                                              SNMP_NOSUCHINSTANCE);
                    continue;
                }
                snmp_set_var_typed_integer( request->requestvb, ASN_INTEGER,
                                            table_entry->pgsqlPgAmopAmopmethod);
                break;
            default:
                netsnmp_set_request_error(reqinfo, request,
                                          SNMP_NOSUCHOBJECT);
                break;
            }
        }
        break;

    }
    return SNMP_ERR_NOERROR;
}
pgsqlPgAmopTable.h (text/x-chdr, 938 B)
/*
 * Note: this file originally auto-generated by mib2c using
 *  : mib2c.iterate.conf 15999 2007-03-25 22:32:02Z dts12 $
 */
#ifndef PGSQLPGAMOPTABLE_H
#define PGSQLPGAMOPTABLE_H

/* function declarations */
void init_pgsqlPgAmopTable(void);
void initialize_table_pgsqlPgAmopTable(void);
Netsnmp_Node_Handler pgsqlPgAmopTable_handler;
Netsnmp_First_Data_Point  pgsqlPgAmopTable_get_first_data_point;
Netsnmp_Next_Data_Point   pgsqlPgAmopTable_get_next_data_point;

/* column number definitions for table pgsqlPgAmopTable */
       #define COLUMN_PGSQLPGAMOPENTRYOID		1
       #define COLUMN_PGSQLPGAMOPAMOPFAMILY		2
       #define COLUMN_PGSQLPGAMOPAMOPLEFTTYPE		3
       #define COLUMN_PGSQLPGAMOPAMOPRIGHTTYPE		4
       #define COLUMN_PGSQLPGAMOPAMOPSTRATEGY		5
       #define COLUMN_PGSQLPGAMOPAMOPREQCHECK		6
       #define COLUMN_PGSQLPGAMOPAMOPOPR		7
       #define COLUMN_PGSQLPGAMOPAMOPMETHOD		8
#endif /* PGSQLPGAMOPTABLE_H */
signature.asc (application/pgp-signature, 197 B)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAkoiCeAACgkQRiRfCGf1UMNlnQCeMtYnypco4SShoUXWivFpPWMe
KasAnjvUhAESupLhUlC92A8Qky61AHK8
=oLVo
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.