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 | }