On Wed, 2005-04-27 at 22:38, Toth, Gregory S wrote:
> We are in the transition process from 4.2.x to 5.0.6
> Doing scalars in 5.0.6 is fairly straightforward but the table
> implementation is very different.

Probably because there are now several different possible
alternatives, depending on the characteristics of your table.


> The output file from mib2c has two methods that appear to be roughly the
> same:
>    netsnmp_variable_list * xxxxxx_get_first_data_point(....) 
> And
>    netsnmp_variable_list * xxxxxx_get_next_data_point(....) 

OK - so you're working with the iterator helper.

The main thing to realise is that any table implementation faces
two basic tasks - identifying which row of the table is needed
for a given request, and then returning the appropriate column
value from that particular row.

With the v4 agent, the 'var_xxx' routine typically handled both
tasks.  Unless you used the 'header_simple_table' routine,
which took care of (most of) the first task - identifying the row.

With the v5 agent, the most basic "register_table_handler" approach
still leaves both tasks to the user-provided handler routine
(just weeding out some of the more obviously invalid requests).

All of the other helpers (data, dataset, container, iterator,
array_user, MfD, etc) take care of much of this first task - and
typically provide the user helper with the relevant row, leaving
it to return the appropriate column value.
  (The dataset helper takes care of this second task too, and
the array_user and MfD helpers don't use the same handler-based
structure of the rest of the agent toolkit).  But that's the
basic idea.


> My guess is that xxxxxx_get_first_data_point should return the objectID
> (in the netsnmp_variable_list) of the first element table element (1
> (column),1 (row)) for a 2 dimensional table and that given a object id
> in the "netsnmp_variable_list * put_index_data",
> xxxxxx_get_next_data_point(....) should return the object id of the next
> element (for example passing in the oid (1 (column),1 (row)) should
> possibly return the oid (1 (column),2 (row)).

Good guess, but not quite right.

These two routines are just concerned with determining the appropriate
*row* to use.  They're not interested in columns at all.
The 'get_first' routine should return some sort of pointer to the
first row of the table (and will only be called once). The 'get_next'
routine should take this pointer, and return the equivalent pointer
for the next row.  This will be called repeatedly until the agent
has walked through the full table.   At which point, the internal
iterator helper will decide which was the correct row, and call the
handler routine.  See my response to Emmanuel for a slightly fuller
description of this.


The other thing to realise is that these get_{first,next} routines
actually return *three* pointers.  One (the variable_list parameter)
is an indication of the index values for each row (so that the
iterator helper can decide which row is required).  Another (the
loop_context parameter) is a pointer to allow the get_next routine
to move on to the next row of the table.  The third (the data_context
parameter) is a separate pointer that will be passed to the main
handler, to retrieve the column values for that row.

It's often the case that the loop_context and data_context pointers
will be identical, but that's not necessarily always the case.
It's up to you how you pass information between the get_* hooks
(loop_context) and between these hook routines and the main
handler (data_context).


> If this is true, how do I set this in the 
> snmp_set_var_value(vptr, (u_char *) /* XXX: oidNumber data */ ,/* XXX:
>                        length of oidNumber data */ );
> Call?

This is used to set the index of the appropriate row in the array.

> For example if the object id of the (1,1) element in my array is
> "1.2.3.4.5.6.7.1", do I just do this:
> 
> oid  my_oid[] ={ 1,2,3,4,5,6,7,1};
> vptr = put_index_data;
> snmp_set_var_value(vptr,(u_char *)my_oid,8); 

No.
Try:
     long  this_index = 1;    // (1,x) elements
     vptr = put_index_data;
     snmp_set_var_value( vptr,  (u_char*)&this_index,
                                   sizeof(this_index));
     return put_index_data;

But you'd also need to set '*loop)context' and '*data_context'
appropriately.


> What is this my_loop_context, my_data_context supposed to be?
> Do I need them at all

Yes.  See above.


> With this code which I copied from vacm_context.c, it does not seem to
> do anything, should it?

>     *my_loop_context = context_ptr;
>     *my_data_context = context_ptr;

But it *is* doing something.
It's specifying (to both the get_next routine and the main
handler) that we're currently working with the first row of
the table, as returned by 'get_top_context_cache()'

Have a look at the 'get_next_context()' routine. It uses the
*loop_context parameter to move on to the next row of the table:

    context_ptr = (subtree_context_cache *) (*my_loop_context);
    context_ptr = context_ptr->next;
    *my_loop_context = context_ptr;

and pass this same entry to the handler:

    *my_data_context = context_ptr;
                                                                                
The vacm_context_handler then retrieves this data_context pointer,
and uses it to fulfil the SNMP request:

     context_ptr = (subtree_context_cache *)
            netsnmp_extract_iterator_context(requests);

OK?

Dave



-------------------------------------------------------
SF.Net email is sponsored by: Tell us your software development plans!
Take this survey and enter to win a one-year sub to SourceForge.net
Plus IDC's 2005 look-ahead and a copy of this survey
Click here to start!  http://www.idcswdc.com/cgi-bin/survey?id=105hix
_______________________________________________
Net-snmp-coders mailing list
Net-snmp-coders@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/net-snmp-coders

Reply via email to