$Revision: 1.30 $
Radix tree (rx). rx_search.c - functions to search nodes of the tree
Status: NOT REVUED, TESTED, COMPLETE
Design and implementation by: Marek Bukowy
Included Files
- #include <include/erroutines.h>
- #include <include/rxroutines.h>
builds a stack for this prefix, finds *nodes* in the stack
and appends *copies of the data leaves* to the LL of answers;
sorts by SQL object keys and uniq's the data
finds:
0 or 1 nodes for exact search
0 or 1 nodes for exless (0 if no less specific node found)
any number (incl. 0) for {more|less}-n specific
then copies the nodes/dataleaves to the answer structs and appends them
to the given LL. So, effectively, the number of answers can be
anything from 0 to infinity, because objects may be duplicate
even at the same node.
returns errcode.
algorithm:
builds stack[MAXBIT (==128)];
if( more/less-depth && par_a == 0)
run rx_nod_search, then
if(more spec) rx_nod_walk(maxdepth=n, append_to_LL() );
if(less spec) do { append(LL, stack[i]) } while(i-- && n--);
otherwise just set LL
The routine provides _at_least_ max_count answers.
It will *try* to stop after max_count as soon as possible
- but it's the higher level routine that should do the final cut.
er_ret_t RX_bin_search ( rx_srch_mt search_mode, int par_a, int par_b, rx_tree_t* tree, ip_prefix_t* prefix, GList** datleaves, int max_count )
helper: just appends the element pointed to by datref to anslist
er_ret_t rx_asc_append_datref ( rx_datref_t* refptr, GList** anslist )
inetnum / exact|exless specific :
optimise: (composed range)
perform a separate first pass, with just one exact search on one of
the composing prefixes - the object must be found if it's in the
database.
So a little cheat: remove all but one prefixes from preflist
and force a different search mode
er_ret_t rx_asc_make_preflist ( rx_srch_mt search_mode, char* key, rx_fam_t fam_id, GList** preflist, ip_range_t* testrang, rx_srch_mt* first_pass_mode )
rx_asc_process_datlist() - helper for rx_asc_search()
fetches the copies of objects from the radix tree into datlist
ASSUMES LOCKED TREE
the behaviour for a default inetnum (range) query is:
do an exact match;
if it fails, do an exless match on the encompassing prefix
for routes(prefixes):
do an exless match
So if it's the default search mode on an inetnum tree,
and the key is a range,
then an exact search is performed on one of the composing prefixes.
Then the resulting data leaves are checked for exact matching with
the range queried for.
Any dataleaves that do not match are discarded, and if none are left,
the procedure falls back to searching for the encompassing prefix.
(calculated in the smart_conv routine).
Add the dataleaf copies to the list of answers,
taking span into account
er_ret_t rx_asc_process_datlist ( rx_srch_mt search_mode, rx_fam_t fam_id, GList** datlist, ip_range_t* testrang, GList** anslist )
Descends the given tree following the last prefix bit to get [past]
the node with the given prefix.
It fills up a stack of COPIES of nodes, including glue nodes.
Then it also sets the number of elements on the stack:
set maxdepth to the position where a next one would be written
( = last + 1, or number of nodes pushed)
The dmodes:
RX_STK_QUERY_NOGLUE = (search exact/less spec) stop when
* the current prefix length >= newprefix length
* the current prefix does not match anymore
* do not add glue nodes
RX_STK_QUERY_ALLNOD = as above, except that the glue and data nodes are
treated equally (i.e. glue nodes are not skipped)
RX_STK_CREAT = descend until the next non-glue node past the one found
in exact mode (for creation)
er_ret_t rx_build_stack ( rx_nodcpy_t stack[], int* maxdepth, rx_tree_t* tree, ip_prefix_t* newpref, rx_stk_mt dmode )
this is a helper: goes through a datlist and returns the smallest
size of a range
ip_rangesize_t rx_find_smallest_span ( GList* datlist )
er_ret_t rx_nod_search ( rx_srch_mt search_mode, int par_a, int par_b, rx_tree_t* tree, ip_prefix_t* prefix, rx_nodcpy_t stack[], int stackcount, GList** nodlist, int max_count, void )
helper:
this routine goes through the list of prefixes and performs a bin_search
on each of them; attaches the results to datlist.
er_ret_t rx_preflist_search ( rx_srch_mt search_mode, int par_a, int par_b, rx_tree_t* mytree, GList** preflist, GList** datlist )
helper for the nod_search routine:
allocate a new node copy struct, copy the struct and add to nodlist
static er_ret_t rx_nod_append ( GList** nodlist, rx_nodcpy_t* element )
helper for DBLS lookup in rx_nod_search
adds a node to the list of answers.
static er_ret_t rx_walk_hook_adddoubles ( rx_node_t* node, int level, int nodecounter, void* userptr )
helper for MORE specific lookup in rx_nod_search
adds a node to the list of answers.
static er_ret_t rx_walk_hook_addnode ( rx_node_t* node, int level, int nodecounter, void* userptr )