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 */