1 | /*************************************** 2 | $Revision: 1.9 $ 3 | 4 | Radix payload (rp) - user level functions for storing data in radix trees 5 | 6 | rp_load = user level tree maintenance (knows about registries and attributes) 7 | 8 | Status: NOT REVIEWED, TESTED 9 | 10 | Design and implementation by: Marek Bukowy 11 | 12 | ******************/ /****************** 13 | Copyright (c) 1999,2000,2001,2002 RIPE NCC 14 | 15 | All Rights Reserved 16 | 17 | Permission to use, copy, modify, and distribute this software and its 18 | documentation for any purpose and without fee is hereby granted, 19 | provided that the above copyright notice appear in all copies and that 20 | both that copyright notice and this permission notice appear in 21 | supporting documentation, and that the name of the author not be 22 | used in advertising or publicity pertaining to distribution of the 23 | software without specific, written prior permission. 24 | 25 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 26 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL 27 | AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 28 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 29 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 30 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 31 | ***************************************/ 32 | 33 | #define RP_IMPL 34 | #include "rip.h" 35 | 36 | /***************************************************************************/ 37 | /*++++++++++++++ 38 | finds a tree matching the specified criteria(registry+space+family+tid). 39 | 40 | MT-note: locks/unlocks forest (still to be done) 41 | 42 | Returns: RX_OK or RX_NOTREE if no such tree can be found. 43 | +++++++++++*/ 44 | 45 | er_ret_t 46 | RP_tree_get ( rx_tree_t **treeptr, /*+ answer goes here, please +*/ 47 | rp_regid_t reg_id, /*+ id of the registry +*/ 48 | ip_space_t spc_id, /*+ type of space (ipv4/ipv6) +*/ 49 | rp_attr_t attr /*+ extra tree id (within the same reg/spc/fam +*/ 50 | ) 51 | 52 | { 53 | GList *elem; 54 | rp_tentry_t *trdef; 55 | /* lock the forest */ 56 | TH_acquire_read_lockw(&rx_forest_rwlock); 57 | elem = g_list_first(rx_forest); 58 | 59 | while( elem != NULL ) { 60 | trdef = elem->data; 61 | 62 | 63 | if( trdef->reg_id == reg_id 64 | && trdef->attr == attr 65 | && trdef->tree->space == spc_id ) { 66 | /* copy the value to user's data */ 67 | *treeptr = trdef->tree; 68 | ER_dbg_va(FAC_RP, ASP_RP_TREE_DET, 69 | "tree found at %08x -> %08x",trdef, trdef->tree); 70 | return RP_OK; 71 | } 72 | elem = g_list_next(elem); 73 | } 74 | 75 | *treeptr = NULL; /* set when NOT FOUND*/ 76 | TH_release_read_lockw(&rx_forest_rwlock); 77 | /* pthread_mutex_unlock(&rx_forest_mx);*/ 78 | return RP_NOTREE; 79 | } 80 | 81 | 82 | 83 | /*++++++++++++++++++++++++++++++++ 84 | put into LL of trees; handle alloc err ??? 85 | 86 | since other threads are supposed to be reading already, 87 | must create the tree locked and observe the forest mutex. 88 | ++++++++++++++++++++*/ 89 | er_ret_t 90 | RP_tree_add ( 91 | rp_regid_t reg_id, /*+ id of the registry +*/ 92 | rp_attr_t attr, /*+ extra tree id (within the same registry/space/family +*/ 93 | char *prefixstr, /*+ prefix the tree will cover (string) +*/ 94 | rx_mem_mt mem_mode, /* memory only, memory+sql, sql only +*/ 95 | rx_subtree_mt subtrees /*+ one of NONE, AUTO, HAND +*/ 96 | ) 97 | { 98 | er_ret_t err; 99 | rp_tentry_t *treedef; 100 | rx_tree_t *mytree; 101 | rx_tree_t *existree; 102 | rx_fam_t fam_id = RP_attr2fam( attr ); 103 | 104 | if( (err = RX_tree_cre(prefixstr, fam_id, mem_mode, subtrees, &mytree)) == RX_OK) { 105 | 106 | /* OK, see if there is a tree for this space already */ 107 | if( RP_tree_get(&existree, reg_id, mytree->space, attr) == RP_OK ) { 108 | /* In this case we need to delete and re-initialize it */ 109 | /* lock the tree for writing and leave it in the locked state for loading */ 110 | TH_acquire_write_lockw(&existree->rwlock); 111 | 112 | if( (err = RP_tree_del(existree)) == RP_OK){ 113 | /* Initialize the tree */ 114 | existree->num_nodes=0; 115 | } 116 | /* free the newly created tree */ 117 | UT_free(mytree); 118 | return err; 119 | } 120 | 121 | treedef = (rp_tentry_t *)UT_malloc(sizeof(rp_tentry_t)); 122 | 123 | treedef -> reg_id = reg_id; 124 | treedef -> attr = attr; 125 | treedef -> tree = mytree; 126 | 127 | /* add the tree to the forest in locked state */ 128 | TH_acquire_write_lockw( &(mytree->rwlock) ); 129 | 130 | /* Lock the forest */ 131 | TH_acquire_write_lockw(&rx_forest_rwlock); 132 | rx_forest = g_list_append (rx_forest, treedef); 133 | TH_release_write_lockw(&rx_forest_rwlock); 134 | } 135 | 136 | return err; 137 | } 138 | 139 | /*++++++++++++++ 140 | finds a tree and deletes its contents 141 | the tree itself is not deleted ! 142 | 143 | Returns: RX_OK or RX_NOTREE if no such tree can be found. 144 | +++++++++++*/ 145 | 146 | er_ret_t 147 | RP_tree_del ( rx_tree_t *tree ) 148 | { 149 | int cnt; 150 | 151 | if( tree->top_ptr != NULL ) { 152 | cnt = rx_delete_tree(tree, tree->top_ptr, 255, 0, 0, NULL); 153 | ER_inf_va(FAC_RP, ASP_RP_LOAD_GEN, 154 | "tree at %08x: %d nodes deleted", tree, cnt); 155 | if (cnt != tree->num_nodes){ 156 | ER_perror(FAC_RP, RP_NOYETI, 157 | "tree at %p: %d nodes deleted, should be %d", tree, cnt, tree->num_nodes); 158 | return RP_NOYETI; 159 | } 160 | } 161 | return RP_OK; 162 | } 163 | 164 | 165 | er_ret_t 166 | rp_init_attr_tree( rp_regid_t reg_id, rp_attr_t attr) 167 | { 168 | er_ret_t err; 169 | 170 | err = RP_OK; 171 | 172 | /* Some (DN) attributes are related to two trees */ 173 | if( RP_attr2spc(attr, IP_V4) ) { 174 | err=RP_tree_add(reg_id, attr, "0.0.0.0/0", 175 | RX_MEM_RAMONLY, RX_SUB_NONE); 176 | } 177 | 178 | if( RP_attr2spc(attr, IP_V6) ) { 179 | err=RP_tree_add(reg_id, attr, "0::/0", 180 | RX_MEM_RAMONLY, RX_SUB_NONE); 181 | } 182 | 183 | return err; 184 | } 185 | /***************************************************************************/ 186 | 187 | er_ret_t 188 | RP_init_trees( rp_regid_t reg_id ) 189 | { 190 | er_ret_t err; 191 | 192 | if( NOERR(err=rp_init_attr_tree(reg_id, A_IN)) 193 | && NOERR(err=rp_init_attr_tree(reg_id, A_RT)) 194 | && NOERR(err=rp_init_attr_tree(reg_id, A_I6)) 195 | && NOERR(err=rp_init_attr_tree(reg_id, A_DN)) ) { 196 | return RP_OK; 197 | } 198 | 199 | return err; 200 | } 201 | 202 | 203 | 204 |