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