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.24 $
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 #include "ca_configFns.h"
36 #include "ca_dictionary.h"
37 #include "ca_macros.h"
38 #include "ca_srcAttribs.h"
39 #include "ta.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 unsigned 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 char *srcnam = ca_get_srcname(reg_id);
169 char activity[64];
170
171 dieif( vu == NULL /* loading query undefined */ );
172 #if 0
173 if( attr==A_IN && space==IP_V4 ) {
174 vu = "SELECT object_id,begin_in,end_in FROM inetnum WHERE thread_id = 0 AND begin_in >= 3238002688 AND end_in < 3254779904 ";
175 }
176 #endif
177
178 dieif( RP_tree_get ( &mytree, reg_id, space, attr ) != RP_OK );
179
180 ER_inf_va(FAC_RP, ASP_RP_LOAD_DET, "loading using %s", vu);
181 ER_dbg_va(FAC_RP, ASP_RP_LOAD_DET, "size before query = %x", sbrk(0));
182
183 sprintf(activity, "%s/%s, query ", srcnam, DF_get_attribute_code(attr));
184 TA_setactivity(activity);
185 TA_increment();
186
187 if ( SQ_execute_query(con, vu, &result) == -1 ) {
188 fprintf(stderr, "ERROR %d: %s\n", SQ_errno(con), SQ_error(con));
189 die;
190 }
191 else {
192 colcount = SQ_get_column_count(result);
193
194 ER_dbg_va(FAC_RP, ASP_RP_LOAD_DET,
195 "size after query = %x; columns = %d", sbrk(0), colcount);
196
197 /* LOCKED when created, so no need to acquire lock here */
198
199 while ( (row = SQ_row_next(result)) != NULL
200 && SQ_errno(con) == 0 ) {
201
202 dieif( ! NOERR(make_sql2pack(result, row, &pack, attr, space,
203 colcount)) );
204
205 if( ! NOERR(RP_pack_node_l(RX_OPER_CRE, &pack, mytree))) {
206 fprintf(stderr,"%d:\t%ld\n", objnr, pack.key);
207 die;
208 }
209
210 /* free allocated memory */
211 if( pack.d.origin != NULL ) {
212 wr_free(pack.d.origin);
213 pack.d.origin = NULL;
214 }
215
216 objnr++;
217
218 if( sizedebug ) {
219 ER_dbg_va(FAC_RP, ASP_RP_LOAD_DET, "size after object %d = %x",
220 objnr, sbrk(0));
221 }
222
223 if( objnr % 1000 == 0 ) {
224
225 sprintf(activity, "%s/%s, %d done ",
226 srcnam, DF_get_attribute_code(attr), objnr);
227 TA_setactivity(activity);
228 }
229 }
230 /* XXX UNLOCK */
231 TH_release_write_lockw( &(mytree->rwlock) );
232 }
233
234 if( SQ_errno(con) == 0 ) {
235 SQ_free_result(result);
236 } else {
237 die;
238 }
239
240 ER_inf_va(FAC_RP, ASP_RP_LOAD_GEN, "loaded %d objects into %s", objnr,
241 DF_get_attribute_code(attr) );
242
243 wr_free(srcnam);
244 return RP_OK;
245 }
246
247 er_ret_t
248 RP_sql_load_reg(rp_regid_t reg_id)
/* [<][>][^][v][top][bottom][index][help] */
249 {
250
251 er_ret_t err;
252 SQ_connection_t *con;
253 char *dbhost = ca_get_srcdbmachine(reg_id);
254 char *dbname = ca_get_srcdbname(reg_id);
255 char *dbuser = ca_get_srcdbuser(reg_id);
256 char *dbpass = ca_get_srcdbpassword(reg_id);
257 char *srcnam = ca_get_srcname(reg_id);
258 unsigned dbport = ca_get_srcdbport(reg_id);
259
260 TA_add( 0, "rx load");
261
262 con = SQ_get_connection( dbhost, dbport, dbname, dbuser, dbpass );
263
264 dieif ( SQ_execute_query(con, "LOCK TABLES "
265 "route READ, inetnum READ, inet6num READ, "
266 "inaddr_arpa READ, domain READ, ip6int READ ",
267 NULL) == -1 );
268
269 do {
270 if( !NOERR(err=RP_sql_load_attr_space( A_RT, IP_V4, reg_id, con))) {
271 break;
272 }
273 if( !NOERR(err=RP_sql_load_attr_space( A_IN, IP_V4, reg_id, con))) {
274 break;
275 }
276 if( !NOERR(err=RP_sql_load_attr_space( A_I6, IP_V6, reg_id, con))) {
277 break;
278 }
279 if( !NOERR(err=RP_sql_load_attr_space( A_DN, IP_V4, reg_id, con))) {
280 break;
281 }
282 if( !NOERR(err=RP_sql_load_attr_space( A_DN, IP_V6, reg_id, con))) {
283 break;
284 }
285 /* CONSTCOND */
286 } while(0);
287
288 dieif ( SQ_execute_query(con, "UNLOCK TABLES", NULL) == -1 );
289
290 /* Close connection */
291 SQ_close_connection(con);
292
293 TA_delete();
294
295 /* free junk */
296 wr_free(dbhost);
297 wr_free(dbname);
298 wr_free(dbuser);
299 wr_free(dbpass);
300 wr_free(srcnam);
301 return err;
302 }
303
304
305 /*
306 load the tree from an ascii file (short attr names).
307 mainly for testing...
308 */
309 er_ret_t
310 RP_asc_load(char *filename, int maxobj, int operation,
/* [<][>][^][v][top][bottom][index][help] */
311 rp_regid_t reg_id)
312 {
313 er_ret_t err;
314 FILE *fp;
315 char buf[1024];
316 char fulltext[65536];
317 int objnr = 0;
318 unsigned len, oldlen=0, ranlen;
319 char rangstr[IP_RANGSTR_MAX];
320 int parsed = 0;
321 int eor; /* end of record */
322
323
324 if( (fp = fopen(filename,"r")) == NULL ) {
325 perror(filename);
326 die;
327 }
328
329 do {
330 fgets(buf, 128, fp);
331
332 eor = ( strlen(buf) <= 1 || feof(fp) );
333
334 if( strlen(buf) > 1 ) {
335 len = strlen(buf);
336 dieif( oldlen+len+1 > 65536 ); /* object too long */
337 memcpy( fulltext+oldlen, buf, len);
338 oldlen+=len;
339
340 fulltext[oldlen]=0;
341 }
342
343 if( eor ) { /* end of object: put into the database. */
344 parsed++;
345
346 /* see if it was just some whitespace junk and nothing more */
347 if( *fulltext==0 ) {
348 continue; /* discard */
349 }
350
351 /* check if it's a radix object */
352 do {
353 char attrname[3];
354 A_Type_t attrcode;
355
356 if( fulltext[0] == '*' && fulltext[3] == ':' ) {
357 strncpy(attrname, fulltext+1, 2);
358 attrname[2]=0;
359
360 if(strcmp(attrname, "XX") == 0 ) {
361 /* object deleted */
362 break;
363 }
364
365 if( (attrcode = DF_attribute_code2type( attrname )) == -1 ) {
366 fprintf(stderr,"discarding a non-object:\n%s\n", fulltext);
367 break;
368 }
369
370 if( DF_attrcode_has_radix_lookup(attrcode) == 0 ) {
371 /* no interest to radix */
372 break;
373 }
374
375 /* copy and translate the range */
376 ranlen = index(fulltext+5,'\n')-fulltext-5;
377 strncpy(rangstr, fulltext+5, ranlen);
378 rangstr[ranlen]=0;
379
380 if( NOERR(err=RP_asc_node(operation, rangstr, attrcode, reg_id,
381 fulltext, strlen(fulltext)+1, 0L )) ) {
382 objnr++;
383 }
384 else {
385 die; /* error putting into the radix tree */
386 return err;
387 }
388
389 }
390 /* CONSTCOND */
391 } while(0);
392
393 *fulltext=0;
394 oldlen=0;
395 }
396 }
397 while(!feof(fp) && objnr<maxobj);
398
399 return RP_OK;
400 }