1 | /***************************************
2 | $Revision: 1.18 $
3 |
4 | Radix tree (rx). rxroutines.h - header file for radix tree handling module.
5 |
6 | Status: NOT REVUED, TESTED
7 |
8 | Design and implementation by: marek
9 |
10 | ******************/ /******************
11 | Copyright (c) 1999 RIPE NCC
12 |
13 | All Rights Reserved
14 |
15 | Permission to use, copy, modify, and distribute this software and its
16 | documentation for any purpose and without fee is hereby granted,
17 | provided that the above copyright notice appear in all copies and that
18 | both that copyright notice and this permission notice appear in
19 | supporting documentation, and that the name of the author not be
20 | used in advertising or publicity pertaining to distribution of the
21 | software without specific, written prior permission.
22 |
23 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
25 | AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
26 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
27 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
28 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29 | ***************************************/
30 |
31 | #ifndef _RX_H
32 | #define _RX_H
33 |
34 | #include <glib.h>
35 | #ifndef G_THREADS_ENABLED
36 | #error "GLib must be compiled with thread support enabled to be MT-Safe"
37 | #endif
38 |
39 | #include <pthread.h>
40 | #include <stubs.h>
41 |
42 | #include <memwrap.h>
43 | #include <stdio.h>
44 | #include <iproutines.h>
45 | #include <erroutines.h>
46 |
47 | #include "socket.h" /*condat*/
48 |
49 | #include "thread.h" /*rwlock*/
50 |
51 |
52 | typedef enum {
53 | RX_FAM_RT = 1,
54 | RX_FAM_IN = 2,
55 | RX_FAM_IP = 4
56 | } rx_fam_t;
57 |
58 |
59 | /*+ the node operation modes +*/
60 | typedef enum {
61 | RX_OPER_CRE = 1,
62 | RX_OPER_DEL
63 | } rx_oper_mt;
64 |
65 |
66 | /*+ stack building modes +*/
67 | typedef enum {
68 | RX_STK_CREAT = 1, /*+ - creation = all glue nodes, stop at first non-glue +*/
69 | RX_STK_QUERY_ALLNOD, /*+ - query = all glue nodes, stop when deep enough */
70 | RX_STK_QUERY_NOGLUE /*+ - query = no glue nodes, stop when deep enough */
71 | } rx_stk_mt;
72 |
73 | /*+ the search modes +*/
74 | typedef enum {
75 | RX_SRCH_CREAT = 1, /*+ special search - does not skip glue nodes +*/
76 | RX_SRCH_EXLESS, /*+ the default search +*/
77 | RX_SRCH_EXACT,
78 | RX_SRCH_LESS,
79 | RX_SRCH_MORE, /*+ more specific search +*/
80 | RX_SRCH_DBLS, /*+ special more spec: return only nodes with
81 | more than one data leaves +*/
82 | RX_SRCH_RANG /*+ more specific range search, RPSL style : ^n-m +*/
83 | } rx_srch_mt;
84 |
85 |
86 | /* constant to mean 'unlimited number of answers from a search' */
87 | #define RX_ANS_ALL (-1)
88 |
89 | #define RX_ALL_DEPTHS 255
90 |
91 |
92 | /*+ radix tree's memory modes -- not yet implemented +*/
93 | typedef enum {
94 | RX_MEM_RAMONLY,
95 | RX_MEM_RAMSQL,
96 | RX_MEM_SQLONLY
97 | } rx_mem_mt;
98 |
99 |
100 |
101 | /*+ subtree modes -- not yet implemented +*/
102 | typedef enum {
103 | RX_SUB_NONE,
104 | RX_SUB_AUTO,
105 | RX_SUB_HAND
106 | } rx_subtree_mt;
107 |
108 | /* modes for tree traversal (walk_tree) */
109 | typedef enum {
110 | RX_WALK_CNTGLU=1, /*+ default: count also glue nodes and make the level
111 | checking aware of them +*/
112 |
113 | RX_WALK_SKPGLU=2, /*+ only real nodes counted & watched in level checks +*/
114 |
115 | RX_WALK_PRFLEN=4, /*+ make level check a check for prefix length;
116 | still only non-glue nodes are counted +*/
117 | RX_WALK_REVERS=8 /*+ reverse the order of traversing the tree
118 | (first link 1 then 0) +*/
119 | } rx_walk_mt;
120 |
121 |
122 | /*+ A struct for data hooked via a double linked list at a radix node.
123 | Must uniquely define the object for lookups in the SQL tables and/or memory.
124 | Must also contain enough info to let the delete_node choose (and remove)
125 | the proper object from the (linked) list +*/
126 |
127 | typedef struct {
128 | ip_range_t iprange; /*+ for inetnums. empty for routes +*/
129 |
130 | char composed; /*+ non-zero for composed inetnums
131 | equal to: the number of prefixes composing
132 | the range - minus 1 +*/
133 |
134 | void *data_ptr; /*+ to in-memory immediate data +*/
135 | int data_len; /*+ and its length +*/
136 |
137 | sql_key_t data_key; /*+ key to the SQL full-text data record +*/
138 | sql_key_t leaf_key; /*+ pointer to the SQL data leaf record +*/
139 | } rx_dataleaf_t;
140 |
141 | /*+
142 | The struct for radix nodes.
143 |
144 | Must contain prefix, parent, left/right child links in memory and sql,
145 | link to the sql version of the node.
146 | And of course data: pointer to a double linked list of rx_data_t's.
147 | +*/
148 |
149 | typedef struct _rx_node_str {
150 | ip_prefix_t prefix; /*+ who am i. +*/
151 |
152 | char glue;
153 | /*+ now this is an indicator for a node that it
154 | is not holding a real prefix,
155 | but is only a glue node +*/
156 |
157 | GList *leaves_ptr; /*+ a double-linked list of rx_data_t structs
158 | the data leaves can be multiple at each node
159 | (due to a user error the inetnum ranges can
160 | overlap, due to multihoming or error routes
161 | can be duplicated ).
162 | So we link a dynamic thing here +*/
163 |
164 | /* sql_key_t leaves_key; */
165 | /* "linked list" not needed in sql -
166 | the data leaves can be found in node_leaf
167 | table as those that have
168 | node_key in node_id */
169 |
170 | struct _rx_node_str
171 | *parent_ptr, /*+ radix links in memory +*/
172 | *child_ptr[2]; /*+ NULL means empty +*/
173 |
174 | sql_key_t parent_key, /*+ radix links in SQL +*/
175 | child_key[2]; /*+ zero means empty +*/
176 |
177 | sql_key_t node_key; /*+ key of the corresponding SQL radix node +*/
178 |
179 | } rx_node_t;
180 |
181 |
182 | /*+
183 | rx_tree_t - defines a radix tree.
184 |
185 | includes a pointer(key) to the top node,
186 |
187 | names of the corresponding SQL tables
188 | (they can be generated automatically,
189 | but this is the place to store the result)
190 | Data_table is for data_key.
191 | Radix_table is for parent_id, right_id, left_id, node_id.
192 | Leaves_table is for leaves_key (double linked list in SQL).
193 | +*/
194 |
195 | typedef struct _rx_tree_str {
196 | ip_space_t space; /*+ one of IPv4, IPv6 +*/
197 | rx_fam_t family; /*+ one of RT, IN +*/
198 |
199 | rx_subtree_mt subtrees; /*+ one of NONE, AUTO, HAND +*/
200 | rx_mem_mt mem_mode; /*+ where the tree will sit - SQL or RAM +*/
201 | struct rx_tree_str
202 | *parent_tree; /*+ pointer to the parent tree +*/
203 |
204 | ip_prefix_t prefix; /*+ of the IP space this tree covers +*/
205 |
206 | int maxbits; /*+ max depth of this tree
207 | (depends on the space, so it is redundant)+*/
208 | sql_tblnam_t data_table;
209 | sql_tblnam_t radix_table;
210 | sql_tblnam_t leaves_table;
211 |
212 | int num_nodes; /*+ number of nodes in tree - for assertions +*/
213 |
214 | rx_node_t *top_ptr; /*+ pointer to the top node +*/
215 | long top_key; /*+ the same in SQL +*/
216 |
217 | rw_lock_t rwlock; /*+ per-tree reader/writer lock +*/
218 |
219 | } rx_tree_t;
220 |
221 |
222 | /*+ this is a definition of a node copy used for:
223 |
224 | * stack elements returned from rx_stack_build,
225 |
226 | * answer elements from an rx_nod_search.
227 |
228 | It *must* hold pointers to the original locations of it (in terms of
229 | memory and SQL) so that one could actually modify the node...
230 | In SQL tree mode it holds also a copy of a node.
231 | This seems to be unnecessary for in-memory radix trees but is a must
232 | for sql ones.
233 |
234 | WARNING!!!!! The fact that pointers to tree and memory / SQL nodes are
235 | here is a subject to race condition. The location of the tree in the
236 | forest list and the node in memory must not change.
237 |
238 | +*/
239 |
240 | typedef struct {
241 | rx_tree_t *tree; /*+ contains registry_id, space_id, sql table names +*/
242 | rx_node_t *srcptr;
243 | sql_key_t srckey;
244 | rx_node_t cpy; /*+ filled in if the tree is kept in SQL only mode +*/
245 | } rx_nodcpy_t;
246 |
247 |
248 | /*+
249 | This represents one data leaf (by reference). It's used for returning data
250 | from rx_bin_search() to rx_asc_search().
251 | +*/
252 | typedef struct {
253 | sql_key_t srckey;
254 | rx_dataleaf_t *leafptr;
255 | } rx_datref_t;
256 |
257 |
258 | /*+ this is a structure used for returning the data from the search.
259 | It contains a copy of the dataleaf and a pointer to the source +*/
260 | typedef struct {
261 | sql_key_t srckey;
262 | rx_dataleaf_t leafcpy;
263 | } rx_datcpy_t;
264 |
265 |
266 | typedef struct {
267 | rx_node_t *node;
268 | int code;
269 | int datatoo;
270 | rx_tree_t *tree;
271 | } rx_treecheck_t;
272 |
273 | /*
274 | * -----------------------------------------------------------------------
275 | *
276 | * now, THIS is a scrap heap for things that MAY BE useful
277 | */
278 |
279 | /* a definite pointer to an sql object: table name + key
280 | However, it might be nice to include the table TYPE so that one knows
281 | what data it holds :-)
282 | */
283 | typedef struct {
284 | sql_tblnam_t name;
285 | sql_key_t key;
286 | } rx_sqlobj_t;
287 |
288 |
289 | typedef struct {
290 | GList **nodlist;
291 | rx_tree_t *tree;
292 | ip_prefix_t *prefix;
293 | } hook_addnode_userdat_t;
294 |
295 | /********************* P R O T O T Y P E S **********************/
296 |
297 |
298 | void rx_free_list_element(void *cpy, void *trash);
299 |
300 |
301 |
302 | er_ret_t
303 | RX_treecheck( rx_tree_t *tree, int datatoo, rx_treecheck_t *errorfound);
304 |
305 | er_ret_t
306 | RX_tree_cre (
307 | char *prefixstr, /*+ prefix the tree will cover (string) +*/
308 | rx_fam_t fam_id,
309 | rx_mem_mt mem_mode, /* memory only, memory+sql, sql only +*/
310 | rx_subtree_mt subtrees, /*+ one of NONE, AUTO, HAND +*/
311 | rx_tree_t **treestore /* store the tree pointer here */
312 | );
313 |
314 | er_ret_t
315 | RX_bin_search (
316 | rx_srch_mt search_mode,
317 | int par_a,
318 | int par_b,
319 | rx_tree_t *tree, /* tree ptr */
320 | ip_prefix_t *prefix, /* binary prefix */
321 | GList **datleaves, /* data leaves go here */
322 | int max_count
323 | );
324 | er_ret_t
325 | RX_bin_node (
326 | rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/
327 | ip_prefix_t *newpref, /*+ prefix of the node +*/
328 | rx_tree_t *tree, /*+ pointer to the tree structure +*/
329 | rx_dataleaf_t *dataleaf /*+ dataleaf to attach at the node +*/
330 | );
331 | er_ret_t
332 | RX_rt_node (
333 | rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/
334 | ip_prefix_t *newpref, /*+ prefix of the node +*/
335 | rx_tree_t *tree, /*+ pointer to the tree structure +*/
336 | rx_dataleaf_t *dataleaf /*+ dataleaf to attach at the node +*/
337 | );
338 | er_ret_t
339 | RX_in_node( rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/
340 | ip_range_t *rang, /*+ range of IP addresses +*/
341 | rx_tree_t *tree, /*+ pointer to the tree structure +*/
342 | rx_dataleaf_t *leafptr /*+ dataleaf to attach at the node +*/
343 | );
344 | er_ret_t
345 | rx_build_stack(rx_nodcpy_t stack[],
346 | int *maxdepth,
347 | rx_tree_t *tree,
348 | ip_prefix_t *newpref,
349 | rx_stk_mt dmode
350 | );
351 |
352 | er_ret_t
353 | rx_nod_search (
354 | rx_srch_mt search_mode,
355 | int par_a,
356 | int par_b,
357 | /* see rx_asc_search() for explanation */
358 | rx_tree_t *tree, /* tree ptr */
359 | ip_prefix_t *prefix, /* binary prefix */
360 |
361 | rx_nodcpy_t stack[], /* stack==array of node_copies */
362 | int stackcount, /* number of element on the stack*/
363 | /* can be set in creat stack */
364 |
365 | GList **nodlist, /* answers go here */
366 | int max_count /* max # of answers */
367 | );
368 | int
369 | rx_walk_tree(rx_node_t *node,
370 | er_ret_t (*func)(rx_node_t *node, int level, int nodecounter,
371 | void *userptr),
372 | rx_walk_mt walk_mode,
373 | int maxlevel,
374 | int level,
375 | int nodecounter,
376 | void *userptr,
377 | er_ret_t *err);
378 | er_ret_t
379 | rx_preflist_search (
380 | rx_srch_mt search_mode,
381 | int par_a,
382 | int par_b,
383 | rx_tree_t *mytree,
384 | GList **preflist,
385 | GList **datlist
386 | );
387 | ip_rangesize_t
388 | rx_find_smallest_span( GList *datlist );
389 | er_ret_t
390 | rx_asc_append_datref(rx_datref_t *refptr, GList **anslist);
391 | er_ret_t
392 | rx_asc_process_datlist(
393 | rx_srch_mt search_mode,
394 | rx_fam_t fam_id,
395 | GList **datlist,
396 | ip_range_t *testrang,
397 | GList **anslist );
398 | er_ret_t
399 | rx_asc_make_preflist(
400 | rx_srch_mt search_mode,
401 | char *key,
402 | rx_fam_t fam_id,
403 | GList **preflist,
404 | ip_range_t *testrang,
405 | rx_srch_mt *first_pass_mode
406 | ) ;
407 |
408 | er_ret_t rx_tree_print( sk_conn_st *condat,rx_tree_t *tree );
409 | void rx_space_list(sk_conn_st *condat);
410 | void rx_nod_print( rx_node_t *node, char *buf, int maxchar );
411 | void rx_stk_print( rx_nodcpy_t stack[], int stackdepth );
412 |
413 | #undef EXTDEF
414 | #endif /* _RX_H */