1 | /***************************************
2 | $Revision: 1.24 $
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 "sk.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 | #ifdef RX_IMPL_PRINT
87 | char *rx_srch_mode_text[]={
88 | "", /* begins with 1 */
89 | "CREAT",
90 | "EXLESS",
91 | "EXACT",
92 | "LESS",
93 | "MORE",
94 | "DBLS",
95 | "RANG"
96 | };
97 | #endif
98 |
99 | /* constant to mean 'unlimited number of answers from a search' */
100 | #define RX_ANS_ALL (-1)
101 |
102 | #define RX_ALL_DEPTHS 255
103 |
104 |
105 | /*+ radix tree's memory modes -- not yet implemented +*/
106 | typedef enum {
107 | RX_MEM_RAMONLY,
108 | RX_MEM_RAMSQL,
109 | RX_MEM_SQLONLY
110 | } rx_mem_mt;
111 |
112 |
113 |
114 | /*+ subtree modes -- not yet implemented +*/
115 | typedef enum {
116 | RX_SUB_NONE,
117 | RX_SUB_AUTO,
118 | RX_SUB_HAND
119 | } rx_subtree_mt;
120 |
121 | /* modes for tree traversal (walk_tree) */
122 | typedef enum {
123 | RX_WALK_CNTGLU=1, /*+ default: count also glue nodes and make the level
124 | checking aware of them +*/
125 |
126 | RX_WALK_SKPGLU=2, /*+ only real nodes counted & watched in level checks +*/
127 |
128 | RX_WALK_PRFLEN=4, /*+ make level check a check for prefix length;
129 | still only non-glue nodes are counted +*/
130 | RX_WALK_REVERS=8 /*+ reverse the order of traversing the tree
131 | (first link 1 then 0) +*/
132 | } rx_walk_mt;
133 |
134 |
135 | /*+ A struct for data hooked via a double linked list at a radix node.
136 | Must uniquely define the object for lookups in the SQL tables and/or memory.
137 | Must also contain enough info to let the delete_node choose (and remove)
138 | the proper object from the (linked) list +*/
139 |
140 | typedef struct {
141 | ip_range_t iprange; /*+ filled for all trees. Used in rp_search
142 | for determining exact matches (all trees)
143 | and to see if an address is in range
144 | (only IPv4 inetnum trees) +*/
145 | unsigned char preflen; /* to avoid arithmetics on IPv6 ranges,
146 | we have to store prefix length to
147 | determine the shortest object in search.
148 | This is filled in for all route trees
149 | */
150 |
151 | char composed; /*+ non-zero for composed inetnums
152 | equal to: the number of prefixes composing
153 | the range - minus 1 +*/
154 |
155 | void *data_ptr; /*+ to in-memory immediate data +*/
156 | unsigned data_len; /*+ and its length +*/
157 |
158 | sql_key_t data_key; /*+ key to the SQL full-text data record +*/
159 | sql_key_t leaf_key; /*+ pointer to the SQL data leaf record +*/
160 | } rx_dataleaf_t;
161 |
162 | /*+
163 | The struct for radix nodes.
164 |
165 | Must contain prefix, parent, left/right child links in memory and sql,
166 | link to the sql version of the node.
167 | And of course data: pointer to a double linked list of rx_data_t's.
168 | +*/
169 |
170 | typedef struct _rx_node_str {
171 | ip_prefix_t prefix; /*+ who am i. +*/
172 |
173 | char glue;
174 | /*+ now this is an indicator for a node that it
175 | is not holding a real prefix,
176 | but is only a glue node +*/
177 |
178 | GList *leaves_ptr; /*+ a double-linked list of rx_data_t structs
179 | the data leaves can be multiple at each node
180 | (due to a user error the inetnum ranges can
181 | overlap, due to multihoming or error routes
182 | can be duplicated ).
183 | So we link a dynamic thing here +*/
184 |
185 | /* sql_key_t leaves_key; */
186 | /* "linked list" not needed in sql -
187 | the data leaves can be found in node_leaf
188 | table as those that have
189 | node_key in node_id */
190 |
191 | struct _rx_node_str
192 | *parent_ptr, /*+ radix links in memory +*/
193 | *child_ptr[2]; /*+ NULL means empty +*/
194 |
195 | sql_key_t parent_key, /*+ radix links in SQL +*/
196 | child_key[2]; /*+ zero means empty +*/
197 |
198 | sql_key_t node_key; /*+ key of the corresponding SQL radix node +*/
199 |
200 | } rx_node_t;
201 |
202 |
203 | /*+
204 | rx_tree_t - defines a radix tree.
205 |
206 | includes a pointer(key) to the top node,
207 |
208 | names of the corresponding SQL tables
209 | (they can be generated automatically,
210 | but this is the place to store the result)
211 | Data_table is for data_key.
212 | Radix_table is for parent_id, right_id, left_id, node_id.
213 | Leaves_table is for leaves_key (double linked list in SQL).
214 | +*/
215 |
216 | typedef struct _rx_tree_str {
217 | ip_space_t space; /*+ one of IPv4, IPv6 +*/
218 | rx_fam_t family; /*+ one of RT, IN +*/
219 |
220 | rx_subtree_mt subtrees; /*+ one of NONE, AUTO, HAND +*/
221 | rx_mem_mt mem_mode; /*+ where the tree will sit - SQL or RAM +*/
222 | struct rx_tree_str
223 | *parent_tree; /*+ pointer to the parent tree +*/
224 |
225 | ip_prefix_t prefix; /*+ of the IP space this tree covers +*/
226 |
227 | int maxbits; /*+ max depth of this tree
228 | (depends on the space, so it is redundant)+*/
229 | sql_tblnam_t data_table;
230 | sql_tblnam_t radix_table;
231 | sql_tblnam_t leaves_table;
232 |
233 | int num_nodes; /*+ number of nodes in tree - for assertions +*/
234 |
235 | rx_node_t *top_ptr; /*+ pointer to the top node +*/
236 | long top_key; /*+ the same in SQL +*/
237 |
238 | rw_lock_t rwlock; /*+ per-tree reader/writer lock +*/
239 |
240 | } rx_tree_t;
241 |
242 |
243 | /*+ this is a definition of a node copy used for:
244 |
245 | * stack elements returned from rx_stack_build,
246 |
247 | * answer elements from an rx_nod_search.
248 |
249 | It *must* hold pointers to the original locations of it (in terms of
250 | memory and SQL) so that one could actually modify the node...
251 | In SQL tree mode it holds also a copy of a node.
252 | This seems to be unnecessary for in-memory radix trees but is a must
253 | for sql ones.
254 |
255 | WARNING!!!!! The fact that pointers to tree and memory / SQL nodes are
256 | here is a subject to race condition. The location of the tree in the
257 | forest list and the node in memory must not change.
258 |
259 | +*/
260 |
261 | typedef struct {
262 | rx_tree_t *tree; /*+ contains registry_id, space_id, sql table names +*/
263 | rx_node_t *srcptr;
264 | sql_key_t srckey;
265 | rx_node_t cpy; /*+ filled in if the tree is kept in SQL only mode +*/
266 | } rx_nodcpy_t;
267 |
268 |
269 | /*+
270 | This represents one data leaf (by reference). It's used for returning data
271 | from rx_bin_search() to rx_asc_search().
272 | +*/
273 | typedef struct {
274 | sql_key_t srckey;
275 | rx_dataleaf_t *leafptr;
276 | } rx_datref_t;
277 |
278 |
279 | /*+ this is a structure used for returning the data from the search.
280 | It contains a copy of the dataleaf and a pointer to the source +*/
281 | typedef struct {
282 | sql_key_t srckey;
283 | rx_dataleaf_t leafcpy;
284 | } rx_datcpy_t;
285 |
286 | typedef struct {
287 | rx_node_t *node;
288 | int code;
289 | int datatoo;
290 | rx_tree_t *tree;
291 | } rx_treecheck_t;
292 |
293 | /*
294 | * -----------------------------------------------------------------------
295 | *
296 | * now, THIS is a scrap heap for things that MAY BE useful
297 | */
298 |
299 | /* a definite pointer to an sql object: table name + key
300 | However, it might be nice to include the table TYPE so that one knows
301 | what data it holds :-)
302 | */
303 | typedef struct {
304 | sql_tblnam_t name;
305 | sql_key_t key;
306 | } rx_sqlobj_t;
307 |
308 |
309 | typedef struct {
310 | GList **nodlist;
311 | rx_tree_t *tree;
312 | ip_prefix_t *prefix;
313 | } hook_addnode_userdat_t;
314 |
315 | /********************* P R O T O T Y P E S **********************/
316 |
317 |
318 | void rx_free_list_element(void *cpy, void *trash);
319 |
320 |
321 |
322 | er_ret_t
323 | RX_treecheck( rx_tree_t *tree, int datatoo, rx_treecheck_t *errorfound);
324 |
325 | er_ret_t
326 | RX_tree_cre (
327 | char *prefixstr, /*+ prefix the tree will cover (string) +*/
328 | rx_fam_t fam_id,
329 | rx_mem_mt mem_mode, /* memory only, memory+sql, sql only +*/
330 | rx_subtree_mt subtrees, /*+ one of NONE, AUTO, HAND +*/
331 | rx_tree_t **treestore /* store the tree pointer here */
332 | );
333 |
334 | er_ret_t
335 | RX_bin_search (
336 | rx_srch_mt search_mode,
337 | int par_a,
338 | int par_b,
339 | rx_tree_t *tree, /* tree ptr */
340 | ip_prefix_t *prefix, /* binary prefix */
341 | GList **datleaves, /* data leaves go here */
342 | int max_count
343 | );
344 | er_ret_t
345 | rx_bin_node (
346 | rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/
347 | ip_prefix_t *newpref, /*+ prefix of the node +*/
348 | rx_tree_t *tree, /*+ pointer to the tree structure +*/
349 | rx_dataleaf_t *dataleaf /*+ dataleaf to attach at the node +*/
350 | );
351 | er_ret_t
352 | RX_rt_node (
353 | rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/
354 | ip_prefix_t *newpref, /*+ prefix of the node +*/
355 | rx_tree_t *tree, /*+ pointer to the tree structure +*/
356 | rx_dataleaf_t *dataleaf /*+ dataleaf to attach at the node +*/
357 | );
358 | er_ret_t
359 | RX_in_node( rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/
360 | ip_range_t *rang, /*+ range of IP addresses +*/
361 | rx_tree_t *tree, /*+ pointer to the tree structure +*/
362 | rx_dataleaf_t *leafptr /*+ dataleaf to attach at the node +*/
363 | );
364 | er_ret_t
365 | rx_build_stack(rx_nodcpy_t stack[],
366 | int *maxdepth,
367 | rx_tree_t *tree,
368 | ip_prefix_t *newpref,
369 | rx_stk_mt dmode
370 | );
371 |
372 | er_ret_t
373 | rx_nod_search (
374 | rx_srch_mt search_mode,
375 | int par_a,
376 | int par_b,
377 | /* see rx_asc_search() for explanation */
378 | rx_tree_t *tree, /* tree ptr */
379 | ip_prefix_t *prefix, /* binary prefix */
380 |
381 | rx_nodcpy_t stack[], /* stack==array of node_copies */
382 | int stackcount, /* number of element on the stack*/
383 | /* can be set in creat stack */
384 |
385 | GList **nodlist, /* answers go here */
386 | int max_count /* max # of answers */
387 | );
388 | int
389 | rx_walk_tree(rx_node_t *node,
390 | er_ret_t (*func)(rx_node_t *node, int level, int nodecounter,
391 | void *userptr),
392 | rx_walk_mt walk_mode,
393 | int maxlevel,
394 | int level,
395 | int nodecounter,
396 | void *userptr,
397 | er_ret_t *err);
398 |
399 |
400 | er_ret_t rx_tree_print( sk_conn_st *condat,rx_tree_t *tree );
401 | void rx_space_list(sk_conn_st *condat);
402 | void rx_nod_print( rx_node_t *node, char *buf, unsigned maxchar );
403 | void rx_stk_print( rx_nodcpy_t stack[], int stackdepth );
404 | const char *RX_text_srch_mode(rx_srch_mt mode);
405 | #undef EXTDEF
406 | #endif /* _RX_H */