1 | /*************************************** 2 | $Revision: 1.9 $ 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 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 <rp.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 | dieif( wr_calloc( (void **)& leafptr, sizeof(rx_dataleaf_t), 1) != UT_OK ); 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 | dieif( wr_malloc( (void **)& (leafptr->data_ptr), datalen) != UT_OK ); 56 | 57 | memcpy(leafptr->data_ptr, data, datalen); 58 | leafptr->data_len = datalen; 59 | } 60 | 61 | switch( mytree->family ) { 62 | case RX_FAM_IN: 63 | err = RX_in_node( mode, &(uni->u.in), mytree, leafptr ); 64 | break; 65 | case RX_FAM_RT: 66 | err = RX_rt_node( mode, &(uni->u.rt), mytree, leafptr ); 67 | break; 68 | default: 69 | die; 70 | err = RP_BADKEY; 71 | } 72 | 73 | if( mode != RX_OPER_CRE ) { 74 | wr_free(leafptr); 75 | } 76 | 77 | return err; 78 | } 79 | 80 | 81 | 82 | /*+ *************************************************************** 83 | 84 | MAIN FRONTEND FUNCTION 85 | 86 | 87 | finds tree, locks it. 88 | 89 | builds a dataleaf and puts into the node(s), 90 | calling rx_bin_node for every prefix. 91 | 92 | MT-note: locks/unlocks the tree. 93 | 94 | +++++++++++++++++*/ 95 | er_ret_t 96 | RP_uni_node ( rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/ 97 | rp_uni_t *uni, /*+ unified argument structure +*/ 98 | rp_attr_t attr, /*+ additional tree attribute +*/ 99 | rp_regid_t reg_id, /*+ id of the registry +*/ 100 | void *data, /*+ pointer to the payload +*/ 101 | unsigned datalen, /*+ length of the payload +*/ 102 | sql_key_t key /*+ the key to the SQL full-text +*/ 103 | ) 104 | { 105 | 106 | /* 107 | For creation of a new node: 108 | 109 | READ-LOCK THE FOREST 110 | 111 | get the root tree for this space (rx_get_tree) 112 | got it ? good. No ? error!!! 113 | 114 | Check if any of the prefixes spans more than one subtree... 115 | Check if they all exist already.. 116 | 117 | abort if any is missing 118 | 119 | UNLOCK THE FOREST 120 | 121 | **now start writing the data:** 122 | 123 | put *data* records in memory and sql table 124 | 125 | for all matchind [sub]trees (in order of the list) 126 | WRITE-LOCK the in-memory [sub]tree 127 | WRITE-LOCK the sql-table for it 128 | 129 | for(all prefixes in memory that match this tree) 130 | create a node in the tree pointing to the data 131 | rof 132 | UNLOCK the tree 133 | rof 134 | 135 | 136 | */ 137 | 138 | rx_tree_t *mytree; 139 | ip_space_t space = uni->space; 140 | er_ret_t err; 141 | 142 | 143 | dieif( RP_tree_get ( &mytree, reg_id, space, attr ) != RP_OK ); 144 | 145 | /* LOCK */ 146 | TH_acquire_write_lockw( &(mytree->rwlock) ); 147 | 148 | err = RP_uni_node_l (mode, uni, mytree, data, datalen, key); 149 | 150 | /* UNLOCK */ 151 | TH_release_write_lockw( &(mytree->rwlock) ); 152 | 153 | return err; 154 | } 155 | 156 | /*+ ********************************************************************* 157 | Ascii frontend - translates key according to attr and calls rx_uni_node. 158 | FOR TESTING PURPOSES ONLY 159 | ********************************************************************* +*/ 160 | er_ret_t 161 | RP_asc_node( rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/ 162 | char *rangstr, /*+ string prefix/range/IP/inaddr +*/ 163 | rp_attr_t attr, /*+ additional tree attribute +*/ 164 | rp_regid_t reg_id, /*+ id of the registry +*/ 165 | void *data, /*+ pointer to the payload +*/ 166 | unsigned datalen, /*+ length of the payload +*/ 167 | sql_key_t key /*+ the key to the SQL full-text +*/ 168 | ) 169 | { 170 | rp_uni_t uni; 171 | 172 | if( RP_asc2uni( rangstr, attr, &uni ) != IP_OK ) { 173 | ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, 174 | "can't understand the key, discarding the OBJECT."); 175 | return RP_BADKEY; 176 | } 177 | else { 178 | ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, 179 | "rx_asc_node: inserting object %s for attr %d reg %d \twith %d bytes at %x", 180 | rangstr, attr, reg_id, datalen, data); 181 | return RP_uni_node(mode, &uni, attr, reg_id, data, datalen, key); 182 | } 183 | } 184 | 185 | /***************************************************************************/ 186 | 187 | er_ret_t 188 | RP_pack_node(rx_oper_mt mode, 189 | rp_upd_pack_t *pack, 190 | rp_regid_t reg_id) /*+ id of the registry +*/ 191 | { 192 | char *rx_text = ""; 193 | unsigned len; 194 | rp_uni_t *uniptr; 195 | 196 | if(mode != RX_OPER_DEL) { 197 | rp_make_short(pack, &rx_text, &len); 198 | } 199 | 200 | uniptr = &(pack->uni); 201 | 202 | return RP_uni_node(mode, uniptr, pack->type, reg_id, rx_text, len, pack->key); 203 | } 204 | /***************************************************************************/ 205 | 206 | er_ret_t 207 | RP_pack_node_l(rx_oper_mt mode, 208 | rp_upd_pack_t *pack, 209 | rx_tree_t *mytree) 210 | { 211 | char *rx_text = ""; 212 | unsigned len; 213 | rp_uni_t *uniptr; 214 | 215 | if(mode != RX_OPER_DEL) { 216 | rp_make_short(pack, &rx_text, &len); 217 | } 218 | 219 | uniptr = &(pack->uni); 220 | 221 | return RP_uni_node_l(mode, uniptr, mytree, 222 | rx_text, strlen(rx_text)+1, pack->key); 223 | }