1 | /***************************************
2 | $Revision: 1.8 $
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_lock( &(mytree->rwlock) );
147 |
148 | err = RP_uni_node_l (mode, uni, mytree, data, datalen, key);
149 |
150 | /* UNLOCK */
151 | TH_release_write_lock( &(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 | }