I found the following code in netsnmp_table_iterator_helper_handler:
/* if sorted, pass in a hint */
if (iinfo->flags & NETSNMP_ITERATOR_FLAG_SORTED) {
callback_loop_context = table_info;
}
This caught my eye because it looks like it is intended to allow a
get_first_data_point function to examine the index data in the
netsnmp_table_request_info and return the correct index data right
away instead of returning the first index and requiring a sequential
search using get_next_data_point. I have a table handler that is
using NETSNMP_ITERATOR_FLAG_SORTED, and I am interested in an easy way
to make the handler more efficient, so I figured I'd try using this
hint as an optimization.
Using the hint appeared to work great, but then one of my test scripts
noticed a problem: GetNext requests for the table had been broken.
What I saw is that snmpwalk would find all the rows for the first
column (eg. col1.1, col1.2, col1.3), but then would only return the
last row for all subsequent columns in the table (col2.3, col3.3,
col4.3, etc).
This problem happens because netsnmp_table_iterator_helper_handler
always passes in the hint, even after hitting the end of a row and
then restarting iteration for the next column. The
get_first_data_point function is called twice for a GetNext request
when the requested OID is the last index in the table: the first call
ends up hitting the end of the row without finding a value to return,
so then netsnmp_table_iterator_helper_handler sets table_info->colnum
to the next valid column, and calls the get_first_data_point function
a second time. The correct thing to return from this second call is
the first index of the table, but since the hint is being passed in
which the index value from the request, my code would return that
index value (since it was found in the underlying data structure) and
things would break.
I believe the correct thing to do would be for
netsnmp_table_iterator_helper_handler to not pass in the hint after
changing table_info->colnum. I've attached a patch that fixes the
problem that I'm seeing. I'd appreciated it if someone who is
familiar with this code would review the patch and let me know if
there is some obvious problem with this approach before I submit it to
the patch tracking system.
Being able to use this hint gives a large increase in efficiency.
Regular use of table_iterator has cost O( columns * rows^2 ). Setting
NETSNMP_ITERATOR_FLAG_SORTED reduces the number of calls to
get_next_data_point required for a full table walk to half of what is
required without the flag set, but doesn't change the big-O cost.
Using the hint results in constant-time access to any element in the
table, so it reduces the number of get_next_data_point calls down to
O( columns * rows ).
Nathan
--- agent/helpers/table_iterator.c.orig 2006-08-25 05:13:02.000000000 -0700
+++ agent/helpers/table_iterator.c 2008-03-05 23:39:39.000000000 -0800
@@ -392,6 +392,7 @@
int oldmode = 0;
netsnmp_iterator_info *iinfo;
int notdone;
+ int hintok = 0;
netsnmp_request_info *request, *reqtmp = NULL;
netsnmp_variable_list *index_search = NULL;
netsnmp_variable_list *free_this_index_search = NULL;
@@ -493,6 +494,7 @@
if (!request->processed)
request_count++;
notdone = 1;
+ hintok = 1;
while(notdone) {
notdone = 0;
@@ -534,7 +536,7 @@
}
/* if sorted, pass in a hint */
- if (iinfo->flags & NETSNMP_ITERATOR_FLAG_SORTED) {
+ if (hintok && (iinfo->flags & NETSNMP_ITERATOR_FLAG_SORTED)) {
callback_loop_context = table_info;
}
index_search =
@@ -710,7 +712,8 @@
break;
} else {
table_info->colnum = nc;
- notdone = 1;
+ hintok = 0;
+ notdone = 1;
}
}
}
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
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