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