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