1 | /*************************************** 2 | $Revision: 1.13 $ 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; /*+ non-zero for composed inetnums 134 | equal to: the number of prefixes composing 135 | the range - minus 1 +*/ 136 | 137 | void *data_ptr; /*+ to in-memory immediate data +*/ 138 | int data_len; /*+ and its length +*/ 139 | 140 | sql_key_t data_key; /*+ key to the SQL full-text data record +*/ 141 | sql_key_t leaf_key; /*+ pointer to the SQL data leaf record +*/ 142 | } rx_dataleaf_t; 143 | 144 | /*+ 145 | The struct for radix nodes. 146 | 147 | Must contain prefix, parent, left/right child links in memory and sql, 148 | link to the sql version of the node. 149 | And of course data: pointer to a double linked list of rx_data_t's. 150 | +*/ 151 | 152 | typedef struct _rx_node_str { 153 | ip_prefix_t prefix; /*+ who am i. +*/ 154 | 155 | char glue; 156 | /*+ now this is an indicator for a node that it 157 | is not holding a real prefix, 158 | but is only a glue node +*/ 159 | 160 | GList *leaves_ptr; /*+ a double-linked list of rx_data_t structs 161 | the data leaves can be multiple at each node 162 | (due to a user error the inetnum ranges can 163 | overlap, due to multihoming or error routes 164 | can be duplicated ). 165 | So we link a dynamic thing here +*/ 166 | 167 | // sql_key_t leaves_key; 168 | /* "linked list" not needed in sql - 169 | the data leaves can be found in node_leaf 170 | table as those that have 171 | node_key in node_id */ 172 | 173 | struct _rx_node_str 174 | *parent_ptr, /*+ radix links in memory +*/ 175 | *child_ptr[2]; /*+ NULL means empty +*/ 176 | 177 | sql_key_t parent_key, /*+ radix links in SQL +*/ 178 | child_key[2]; /*+ zero means empty +*/ 179 | 180 | sql_key_t node_key; /*+ key of the corresponding SQL radix node +*/ 181 | 182 | } rx_node_t; 183 | 184 | 185 | /*+ 186 | rx_tree_t - defines a radix tree. 187 | 188 | includes a pointer(key) to the top node, 189 | 190 | names of the corresponding SQL tables 191 | (they can be generated automatically, 192 | but this is the place to store the result) 193 | Data_table is for data_key. 194 | Radix_table is for parent_id, right_id, left_id, node_id. 195 | Leaves_table is for leaves_key (double linked list in SQL). 196 | +*/ 197 | 198 | typedef struct _rx_tree_str { 199 | rx_regid_t reg_id; /*+ registry id +*/ 200 | ip_space_t space; /*+ one of IPv4, IPv6 +*/ 201 | rx_fam_t family; /*+ one of RT, IN +*/ 202 | 203 | rx_subtree_mt subtrees; /*+ one of NONE, AUTO, HAND +*/ 204 | rx_mem_mt mem_mode; /*+ where the tree will sit - SQL or RAM +*/ 205 | struct rx_tree_str 206 | *parent_tree; /*+ pointer to the parent tree +*/ 207 | 208 | ip_prefix_t prefix; /*+ of the IP space this tree covers +*/ 209 | 210 | int maxbits; /*+ max depth of this tree 211 | (depends on the space, so it is redundant)+*/ 212 | sql_tblnam_t data_table; 213 | sql_tblnam_t radix_table; 214 | sql_tblnam_t leaves_table; 215 | 216 | int num_nodes; /*+ number of nodes in tree - for assertions +*/ 217 | 218 | rx_node_t *top_ptr; /*+ pointer to the top node +*/ 219 | long top_key; /*+ the same in SQL +*/ 220 | 221 | rw_lock_t rwlock; /*+ per-tree reader/writer lock +*/ 222 | 223 | } rx_tree_t; 224 | 225 | 226 | /*+ this is a definition of a node copy used for: 227 | 228 | * stack elements returned from rx_stack_build, 229 | 230 | * answer elements from an rx_nod_search. 231 | 232 | It *must* hold pointers to the original locations of it (in terms of 233 | memory and SQL) so that one could actually modify the node... 234 | In SQL tree mode it holds also a copy of a node. 235 | This seems to be unnecessary for in-memory radix trees but is a must 236 | for sql ones. 237 | 238 | WARNING!!!!! The fact that pointers to tree and memory / SQL nodes are 239 | here is a subject to race condition. The location of the tree in the 240 | forest list and the node in memory must not change. 241 | 242 | +*/ 243 | 244 | typedef struct { 245 | rx_tree_t *tree; /*+ contains registry_id, space_id, sql table names +*/ 246 | rx_node_t *srcptr; 247 | sql_key_t srckey; 248 | rx_node_t cpy; /*+ filled in if the tree is kept in SQL only mode +*/ 249 | } rx_nodcpy_t; 250 | 251 | 252 | /*+ 253 | This represents one data leaf (by reference). It's used for returning data 254 | from rx_bin_search() to rx_asc_search(). 255 | +*/ 256 | typedef struct { 257 | sql_key_t srckey; 258 | rx_dataleaf_t *leafptr; 259 | } rx_datref_t; 260 | 261 | 262 | /*+ this is a structure used for returning the data from the search. 263 | It contains a copy of the dataleaf and a pointer to the source +*/ 264 | typedef struct { 265 | sql_key_t srckey; 266 | rx_dataleaf_t leafcpy; 267 | } rx_datcpy_t; 268 | 269 | 270 | typedef struct { 271 | rx_node_t *node; 272 | int code; 273 | int datatoo; 274 | rx_tree_t *tree; 275 | } rx_treecheck_t; 276 | 277 | /* 278 | * ----------------------------------------------------------------------- 279 | * 280 | * now, THIS is a scrap heap for things that MAY BE useful 281 | */ 282 | 283 | /* a definite pointer to an sql object: table name + key 284 | However, it might be nice to include the table TYPE so that one knows 285 | what data it holds :-) 286 | */ 287 | typedef struct { 288 | sql_tblnam_t name; 289 | sql_key_t key; 290 | } rx_sqlobj_t; 291 | 292 | 293 | typedef struct { 294 | GList **nodlist; 295 | rx_tree_t *tree; 296 | ip_prefix_t *prefix; 297 | } hook_addnode_userdat_t; 298 | 299 | /********************* P R O T O T Y P E S **********************/ 300 | 301 | 302 | void rx_free_list_element(void *cpy, void *trash); 303 | void RX_attach2forest(rx_tree_t *newtree); 304 | er_ret_t 305 | RX_tree_cre ( 306 | rx_regid_t reg_id, 307 | ip_space_t spc_id, 308 | rx_fam_t fam_id, 309 | char *prefixstr, 310 | rx_mem_mt mem_mode, // memory only, memory+sql, sql only 311 | rx_subtree_mt subtrees, // NONE, AUTO, HAND 312 | rx_tree_t **treeptr 313 | ); 314 | er_ret_t 315 | RX_get_tree ( rx_tree_t **treeptr, 316 | rx_regid_t reg_id, 317 | ip_space_t spc_id, 318 | rx_fam_t fam_id 319 | ); 320 | 321 | er_ret_t 322 | RX_bin_search ( 323 | rx_srch_mt search_mode, 324 | int par_a, 325 | int par_b, 326 | rx_tree_t *tree, // tree ptr 327 | ip_prefix_t *prefix, // binary prefix 328 | GList **datleaves, // data leaves go here 329 | int max_count 330 | ); 331 | er_ret_t 332 | RX_asc_search ( 333 | rx_srch_mt search_mode, 334 | int par_a, 335 | int par_b, 336 | char *key, /*+ search term: prefix/range/IP +*/ 337 | int reg_id, 338 | ip_space_t spc_id, /*+ space id, one of IPv4 IPv6. +*/ 339 | rx_fam_t fam_id, /*+ RX_FAM_RT or RX_FAM_IN +*/ 340 | GList **anslist, /*+ answers go here, please +*/ 341 | int max_count /*+ # of answers. +*/ 342 | ); 343 | 344 | er_ret_t 345 | RX_asc_node ( rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/ 346 | char *rangstr, /*+ string prefix/range/IP +*/ 347 | rx_regid_t reg_id, /*+ id of the registry +*/ 348 | ip_space_t spc_id, /*+ type of space (ipv4/ipv6) +*/ 349 | rx_fam_t fam_id, /*+ family of objects (route/inetnum) +*/ 350 | void *data /*+ pointer to the payload +*/ 351 | ); 352 | er_ret_t 353 | RX_bin_node ( 354 | rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/ 355 | ip_prefix_t *newpref, /*+ prefix of the node +*/ 356 | rx_tree_t *tree, /*+ pointer to the tree structure +*/ 357 | rx_dataleaf_t *dataleaf /*+ dataleaf to attach at the node +*/ 358 | ); 359 | 360 | er_ret_t 361 | RX_inum_node( rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/ 362 | ip_range_t *rang, /*+ range of IP addresses +*/ 363 | rx_tree_t *tree, /*+ pointer to the tree structure +*/ 364 | rx_dataleaf_t *leafptr /*+ dataleaf to attach at the node +*/ 365 | ); 366 | 367 | er_ret_t 368 | rx_build_stack(rx_nodcpy_t stack[], 369 | int *maxdepth, 370 | rx_tree_t *tree, 371 | ip_prefix_t *newpref, 372 | rx_stk_mt dmode 373 | ); 374 | 375 | er_ret_t 376 | rx_nod_search ( 377 | rx_srch_mt search_mode, 378 | int par_a, 379 | int par_b, 380 | /* see rx_asc_search() for explanation */ 381 | rx_tree_t *tree, // tree ptr 382 | ip_prefix_t *prefix, // binary prefix 383 | 384 | rx_nodcpy_t stack[], // stack==array of node_copies 385 | int stackcount, // number of element on the stack, 386 | // can come from a creat stack! 387 | 388 | GList **nodlist, // answers go here 389 | int max_count // max # of answers 390 | ); 391 | int 392 | rx_walk_tree(rx_node_t *node, 393 | er_ret_t (*func)(rx_node_t *node, int level, int nodecounter, 394 | void *userptr), 395 | rx_walk_mt walk_mode, 396 | int maxlevel, 397 | int level, 398 | int nodecounter, 399 | void *userptr, 400 | er_ret_t *err); 401 | 402 | 403 | 404 | er_ret_t rx_tree_print( sk_conn_st *condat,rx_tree_t *tree ); 405 | void rx_space_list(sk_conn_st *condat); 406 | void rx_nod_print( rx_node_t *node, char *buf, int maxchar ); 407 | void rx_stk_print( rx_nodcpy_t stack[], int stackdepth ); 408 | 409 | #undef EXTDEF 410 | #endif /* _RX_H */