1 | /*************************************** 2 | $Revision: 1.13 $ 3 | 4 | Radix tree (rx). rx_payload.c - functions to operate on user data 5 | (creation/deletion). 6 | 7 | Status: NOT REVUED, UNTESTED, INCOMPLETE 8 | 9 | Design and implementation by: Marek Bukowy 10 | 11 | ******************/ /****************** 12 | Copyright (c) 1999,2000,2001,2002 RIPE NCC 13 | 14 | All Rights Reserved 15 | 16 | Permission to use, copy, modify, and distribute this software and its 17 | documentation for any purpose and without fee is hereby granted, 18 | provided that the above copyright notice appear in all copies and that 19 | both that copyright notice and this permission notice appear in 20 | supporting documentation, and that the name of the author not be 21 | used in advertising or publicity pertaining to distribution of the 22 | software without specific, written prior permission. 23 | 24 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 25 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL 26 | AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 27 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 28 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 29 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 30 | ***************************************/ 31 | 32 | #include "rip.h" 33 | 34 | /*+ *************************************************************** 35 | assumes locked tree 36 | +*/ 37 | er_ret_t 38 | RP_uni_node_l ( rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/ 39 | rp_uni_t *uni, 40 | rx_tree_t *mytree, 41 | void *data, /*+ pointer to the payload +*/ 42 | unsigned datalen, /*+ length of the payload +*/ 43 | sql_key_t key /*+ the key to the SQL full-text +*/ 44 | ) 45 | { 46 | rx_dataleaf_t *leafptr; 47 | er_ret_t err; 48 | 49 | /* set the data leaf values*/ 50 | leafptr = (rx_dataleaf_t *)UT_calloc(1, sizeof(rx_dataleaf_t)); 51 | leafptr->data_key = key; /* also for deletion - it is used for finding the 52 | right dataleaf in the tree */ 53 | 54 | if( mode == RX_OPER_CRE ) { 55 | leafptr->data_ptr = UT_malloc(datalen); 56 | memcpy(leafptr->data_ptr, data, datalen); 57 | leafptr->data_len = datalen; 58 | } 59 | 60 | switch( mytree->family ) { 61 | case RX_FAM_IN: 62 | err = RX_in_node( mode, &(uni->u.in), mytree, leafptr ); 63 | break; 64 | case RX_FAM_RT: 65 | err = RX_rt_node( mode, &(uni->u.rt), mytree, leafptr ); 66 | break; 67 | default: 68 | die; 69 | err = RP_BADKEY; 70 | } 71 | 72 | if( mode != RX_OPER_CRE ) { 73 | UT_free(leafptr); 74 | } 75 | 76 | return err; 77 | } 78 | 79 | 80 | 81 | /*+ *************************************************************** 82 | 83 | MAIN FRONTEND FUNCTION 84 | 85 | 86 | finds tree, locks it. 87 | 88 | builds a dataleaf and puts into the node(s), 89 | calling rx_bin_node for every prefix. 90 | 91 | MT-note: locks/unlocks the tree. 92 | 93 | +++++++++++++++++*/ 94 | er_ret_t 95 | RP_uni_node ( rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/ 96 | rp_uni_t *uni, /*+ unified argument structure +*/ 97 | rp_attr_t attr, /*+ additional tree attribute +*/ 98 | rp_regid_t reg_id, /*+ id of the registry +*/ 99 | void *data, /*+ pointer to the payload +*/ 100 | unsigned datalen, /*+ length of the payload +*/ 101 | sql_key_t key /*+ the key to the SQL full-text +*/ 102 | ) 103 | { 104 | 105 | /* 106 | For creation of a new node: 107 | 108 | READ-LOCK THE FOREST 109 | 110 | get the root tree for this space (rx_get_tree) 111 | got it ? good. No ? error!!! 112 | 113 | Check if any of the prefixes spans more than one subtree... 114 | Check if they all exist already.. 115 | 116 | abort if any is missing 117 | 118 | UNLOCK THE FOREST 119 | 120 | **now start writing the data:** 121 | 122 | put *data* records in memory and sql table 123 | 124 | for all matchind [sub]trees (in order of the list) 125 | WRITE-LOCK the in-memory [sub]tree 126 | WRITE-LOCK the sql-table for it 127 | 128 | for(all prefixes in memory that match this tree) 129 | create a node in the tree pointing to the data 130 | rof 131 | UNLOCK the tree 132 | rof 133 | 134 | 135 | */ 136 | 137 | rx_tree_t *mytree; 138 | ip_space_t space = uni->space; 139 | er_ret_t err; 140 | 141 | 142 | dieif( RP_tree_get ( &mytree, reg_id, space, attr ) != RP_OK ); 143 | 144 | /* LOCK */ 145 | TH_acquire_write_lockw( &(mytree->rwlock) ); 146 | 147 | err = RP_uni_node_l (mode, uni, mytree, data, datalen, key); 148 | 149 | /* UNLOCK */ 150 | TH_release_write_lockw( &(mytree->rwlock) ); 151 | 152 | return err; 153 | } 154 | 155 | /*+ ********************************************************************* 156 | Ascii frontend - translates key according to attr and calls rx_uni_node. 157 | FOR TESTING PURPOSES ONLY 158 | ********************************************************************* +*/ 159 | er_ret_t 160 | RP_asc_node( rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/ 161 | char *rangstr, /*+ string prefix/range/IP/inaddr +*/ 162 | rp_attr_t attr, /*+ additional tree attribute +*/ 163 | rp_regid_t reg_id, /*+ id of the registry +*/ 164 | void *data, /*+ pointer to the payload +*/ 165 | unsigned datalen, /*+ length of the payload +*/ 166 | sql_key_t key /*+ the key to the SQL full-text +*/ 167 | ) 168 | { 169 | rp_uni_t uni; 170 | 171 | if( RP_asc2uni( rangstr, attr, &uni ) != IP_OK ) { 172 | ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, 173 | "can't understand the key, discarding the OBJECT."); 174 | return RP_BADKEY; 175 | } 176 | else { 177 | ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, 178 | "rx_asc_node: inserting object %s for attr %d reg %d \twith %d bytes at %x", 179 | rangstr, attr, reg_id, datalen, data); 180 | return RP_uni_node(mode, &uni, attr, reg_id, data, datalen, key); 181 | } 182 | } 183 | 184 | /***************************************************************************/ 185 | 186 | er_ret_t 187 | RP_pack_node(rx_oper_mt mode, 188 | rp_upd_pack_t *pack, 189 | rp_regid_t reg_id) /*+ id of the registry +*/ 190 | { 191 | char *rx_text = ""; 192 | unsigned len=0;/* doesn't matter for deletion */ 193 | rp_uni_t *uniptr; 194 | 195 | if(mode != RX_OPER_DEL) { 196 | rp_make_short(pack, &rx_text, &len); 197 | } 198 | 199 | uniptr = &(pack->uni); 200 | return RP_uni_node(mode, uniptr, pack->type, reg_id, 201 | rx_text, len+1, pack->key); 202 | } 203 | /***************************************************************************/ 204 | 205 | er_ret_t 206 | RP_pack_node_l(rx_oper_mt mode, 207 | rp_upd_pack_t *pack, 208 | rx_tree_t *mytree) 209 | { 210 | char *rx_text = ""; 211 | unsigned len=0;/* doesn't matter for deletion */ 212 | rp_uni_t *uniptr; 213 | 214 | if(mode != RX_OPER_DEL) { 215 | rp_make_short(pack, &rx_text, &len); 216 | } 217 | 218 | uniptr = &(pack->uni); 219 | 220 | return RP_uni_node_l(mode, uniptr, mytree, 221 | rx_text, strlen(rx_text)+1, pack->key); 222 | }