modules/rp/rp_load.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- make_sql2pack
- RP_sql_load_attr_space
- RP_sql_load_reg
- RP_asc_load
1 /***************************************
2 $Revision: 1.20 $
3
4 Radix payload (rp) - user level functions for storing data in radix trees
5
6 rp_load = loading the radix trees with data on startup
7
8 Status: NOT REVIEWED, TESTED
9
10 Design and implementation by: Marek Bukowy
11
12 ******************/ /******************
13 Copyright (c) 1999 RIPE NCC
14
15 All Rights Reserved
16
17 Permission to use, copy, modify, and distribute this software and its
18 documentation for any purpose and without fee is hereby granted,
19 provided that the above copyright notice appear in all copies and that
20 both that copyright notice and this permission notice appear in
21 supporting documentation, and that the name of the author not be
22 used in advertising or publicity pertaining to distribution of the
23 software without specific, written prior permission.
24
25 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
26 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
27 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
28 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
29 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
30 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31 ***************************************/
32 #include <rp.h>
33 #include <mysql_driver.h>
34 #include <constants.h>
35
36 #include "ca_configFns.h"
37 #include "ca_dictSyms.h"
38 #include "ca_macros.h"
39 #include "ca_srcAttribs.h"
40
41 static
42 er_ret_t
43 make_sql2pack(SQ_result_set_t *result, SQ_row_t *row,
/* [<][>][^][v][top][bottom][index][help] */
44 rp_upd_pack_t *pack, rp_attr_t attr, ip_space_t space,
45 int colcount)
46 {
47 er_ret_t conv = RP_OK;
48 rp_uni_t *uniptr = &(pack->uni);
49 char *idptr; /* initially set to the 0'th column */
50 char *col[5];
51 int i;
52
53 dieif(colcount>5); /* size of the col array */
54
55 for(i=0; i<colcount; i++) {
56 col[i] = SQ_get_column_string_nocopy(result, row, i);
57 if (col[i] == NULL) {
58 die;
59 }
60 }
61
62 idptr = col[0];
63
64 pack->type = attr;
65 pack->d.origin = NULL;
66 switch( attr ) {
67 case A_IN:
68 /*
69 read 0-2 from inetnum
70 0 - objectid
71 1 - begin
72 2 - end
73 */
74 uniptr->space = IP_V4;
75 conv = IP_rang_f2b_v4( &(uniptr->u.in), col[1], col[2] );
76 break;
77 case A_RT:
78 /*
79 read 0-3 from route
80 0 - objectid
81 1 - prefix
82 2 - prefix_length
83 3 - origin
84 */
85 uniptr->space = IP_V4;
86 if( NOERR(conv = IP_pref_f2b_v4( &(uniptr->u.rt), col[1], col[2] ))) {
87 dieif(wr_malloc( (void **) &(pack->d.origin), strlen(col[3])+1)
88 != UT_OK);
89
90 strcpy(pack->d.origin, col[3]);
91 }
92 break;
93 case A_DN:
94 if( space == IP_V4 ) {
95 /*
96 read 0-3 from inaddr
97 0 - objectid
98 1 - prefix
99 2 - prefix_length
100 3 - domain
101 */
102 conv = IP_pref_f2b_v4( &(uniptr->u.rt), col[1], col[2] );
103 uniptr->space = IP_pref_b2_space( &(uniptr->u.rt) );
104 dieif(wr_malloc( (void **) &(pack->d.domain), strlen(col[3])+1)
105 != UT_OK);
106 strcpy(pack->d.domain, col[3]);
107 }
108 else {
109 /* read 0-4 from ip6int
110 0 - objectid
111 1 - msb
112 2 - lsb
113 3 - prefix_length
114 4 - domain
115 */
116 conv = IP_pref_f2b_v6( &(uniptr->u.rt), col[1], col[2], col[3] );
117 uniptr->space = IP_pref_b2_space( &(uniptr->u.rt) );
118
119 dieif(wr_malloc( (void **) &(pack->d.domain), strlen(col[4])+1)
120 != UT_OK);
121 strcpy(pack->d.domain, col[4]);
122 }
123 break;
124 case A_I6:
125 /*
126 read 0-3 from inaddr
127 0 - objectid
128 1 - msb
129 2 - lsb
130 3 - prefix_length
131 */
132 conv = IP_pref_f2b_v6( &(uniptr->u.rt), col[1], col[2], col[3]);
133 uniptr->space = IP_pref_b2_space( &(uniptr->u.rt) );
134 break;
135 default:
136 /* die; / * shouldn't have got here */
137 conv = IP_INVARG;
138 }
139
140 if( sscanf(idptr, "%lu", &(pack->key) ) < 1 ) {
141 conv = IP_INVARG;
142 }
143
144
145 for(i=0; i<colcount; i++) {
146 /* wr_free(col[i]);*/ ;
147 }
148
149 return conv;
150 }
151
152 static
153 er_ret_t
154 RP_sql_load_attr_space( rp_attr_t attr, ip_space_t space,
/* [<][>][^][v][top][bottom][index][help] */
155 rp_regid_t reg_id, SQ_connection_t *con
156 )
157 {
158 SQ_row_t *row;
159 SQ_result_set_t *result;
160 int objnr=0;
161 rx_tree_t *mytree;
162 rp_upd_pack_t pack;
163 int colcount;
164 int sizedebug = ER_is_traced(FAC_RP, ASP_RP_LOAD_DET);
165 char *v4 = DF_attrcode_radix_load_v4(attr);
166 char *v6 = DF_attrcode_radix_load_v6(attr);
167 char *vu = (space == IP_V4) ? v4 : v6;
168
169 dieif( vu == NULL /* loading query undefined */ );
170
171 dieif( RP_tree_get ( &mytree, reg_id, space, attr ) != RP_OK );
172
173 ER_inf_va(FAC_RP, ASP_RP_LOAD_DET, "loading using %s", vu);
174 ER_dbg_va(FAC_RP, ASP_RP_LOAD_DET, "size before query = %x", sbrk(0));
175
176 if ( SQ_execute_query(con, vu, &result) == -1 ) {
177 fprintf(stderr, "ERROR %d: %s\n", SQ_errno(con), SQ_error(con));
178 die;
179 }
180 else {
181 colcount = SQ_get_column_count(result);
182
183 ER_dbg_va(FAC_RP, ASP_RP_LOAD_DET,
184 "size after query = %x; columns = %d", sbrk(0), colcount);
185
186 /* LOCKED when created, so no need to acquire lock here */
187
188 while ( (row = SQ_row_next(result)) != NULL
189 && SQ_errno(con) == 0 ) {
190
191 dieif( ! NOERR(make_sql2pack(result, row, &pack, attr, space,
192 colcount)) );
193
194 if( ! NOERR(RP_pack_node_l(RX_OPER_CRE, &pack, mytree))) {
195 fprintf(stderr,"%d:\t%ld\n", objnr, pack.key);
196 die;
197 }
198
199 /* free allocated memory */
200 if( pack.d.origin != NULL ) {
201 wr_free(pack.d.origin);
202 pack.d.origin = NULL;
203 }
204
205 objnr++;
206
207 if( sizedebug ) {
208 ER_dbg_va(FAC_RP, ASP_RP_LOAD_DET, "size after object %d = %x",
209 objnr, sbrk(0));
210 }
211
212 }
213 /* XXX UNLOCK */
214 TH_release_write_lock( &(mytree->rwlock) );
215 }
216
217 if( SQ_errno(con) == 0 ) {
218 SQ_free_result(result);
219 } else {
220 die;
221 }
222
223 ER_inf_va(FAC_RP, ASP_RP_LOAD_GEN, "loaded %d objects into %s", objnr,
224 DF_get_attribute_code(attr) );
225
226
227 return RP_OK;
228 }
229
230 er_ret_t
231 RP_sql_load_reg(rp_regid_t reg_id)
/* [<][>][^][v][top][bottom][index][help] */
232 {
233
234 er_ret_t err;
235 SQ_connection_t *con;
236 char *dbhost = ca_get_srcdbmachine(reg_id);
237 char *dbname = ca_get_srcdbname(reg_id);
238 char *dbuser = ca_get_srcdbuser(reg_id);
239 char *dbpass = ca_get_srcdbpassword(reg_id);
240 char *srcnam = ca_get_srcname(reg_id);
241
242 con = SQ_get_connection( dbhost, ca_get_srcdbport(reg_id),
243 dbname, dbuser, dbpass );
244
245 dieif ( SQ_execute_query(con, "LOCK TABLES "
246 "route READ, inetnum READ, inet6num READ, "
247 "inaddr_arpa READ, domain READ, ip6int READ ",
248 NULL) == -1 );
249
250 do {
251 if( !NOERR(err=RP_sql_load_attr_space( A_RT, IP_V4, reg_id, con))) {
252 break;
253 }
254 if( !NOERR(err=RP_sql_load_attr_space( A_IN, IP_V4, reg_id, con))) {
255 break;
256 }
257 if( !NOERR(err=RP_sql_load_attr_space( A_I6, IP_V6, reg_id, con))) {
258 break;
259 }
260 if( !NOERR(err=RP_sql_load_attr_space( A_DN, IP_V4, reg_id, con))) {
261 break;
262 }
263 if( !NOERR(err=RP_sql_load_attr_space( A_DN, IP_V6, reg_id, con))) {
264 break;
265 }
266 /* CONSTCOND */
267 } while(0);
268
269 dieif ( SQ_execute_query(con, "UNLOCK TABLES", NULL) == -1 );
270
271 /* Close connection */
272 SQ_close_connection(con);
273
274 /* free junk */
275 wr_free(dbhost);
276 wr_free(dbname);
277 wr_free(dbuser);
278 wr_free(dbpass);
279 wr_free(srcnam);
280 return err;
281 }
282
283
284 /*
285 load the tree from an ascii file (short attr names).
286 mainly for testing...
287 */
288 er_ret_t
289 RP_asc_load(char *filename, int maxobj, int operation,
/* [<][>][^][v][top][bottom][index][help] */
290 rp_regid_t reg_id)
291 {
292 er_ret_t err;
293 FILE *fp;
294 char buf[1024];
295 char fulltext[65536];
296 int objnr = 0;
297 int len, oldlen=0;
298 int ranlen;
299 char rangstr[IP_RANGSTR_MAX];
300 int parsed = 0;
301 int eor; /* end of record */
302
303
304 if( (fp = fopen(filename,"r")) == NULL ) {
305 perror(filename);
306 die;
307 }
308
309 do {
310 fgets(buf, 128, fp);
311
312 eor = ( strlen(buf) <= 1 || feof(fp) );
313
314 if( strlen(buf) > 1 ) {
315 len = strlen(buf);
316 dieif( oldlen+len+1 > 65536 ); /* object too long */
317 memcpy( fulltext+oldlen, buf, len);
318 oldlen+=len;
319
320 fulltext[oldlen]=0;
321 }
322
323 if( eor ) { /* end of object: put into the database. */
324 parsed++;
325
326 /* see if it was just some whitespace junk and nothing more */
327 if( *fulltext==0 ) {
328 continue; /* discard */
329 }
330
331 /* check if it's a radix object */
332 do {
333 char attrname[3];
334 A_Type_t attrcode;
335
336 if( fulltext[0] == '*' && fulltext[3] == ':' ) {
337 strncpy(attrname, fulltext+1, 2);
338 attrname[2]=0;
339
340 if(strcmp(attrname, "XX") == 0 ) {
341 /* object deleted */
342 break;
343 }
344
345 if( (attrcode = DF_attribute_code2type( attrname )) == -1 ) {
346 fprintf(stderr,"discarding a non-object:\n%s\n", fulltext);
347 break;
348 }
349
350 if( DF_attrcode_has_radix_lookup(attrcode) == 0 ) {
351 /* no interest to radix */
352 break;
353 }
354
355 /* copy and translate the range */
356 ranlen = index(fulltext+5,'\n')-fulltext-5;
357 strncpy(rangstr, fulltext+5, ranlen);
358 rangstr[ranlen]=0;
359
360 if( NOERR(err=RP_asc_node(operation, rangstr, attrcode, reg_id,
361 fulltext, strlen(fulltext)+1, 0L )) ) {
362 objnr++;
363 }
364 else {
365 die; /* error putting into the radix tree */
366 return err;
367 }
368
369 }
370 /* CONSTCOND */
371 } while(0);
372
373 *fulltext=0;
374 oldlen=0;
375 }
376 }
377 while(!feof(fp) && objnr<maxobj);
378
379 return RP_OK;
380 }