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