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