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.26 $
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,2000,2001 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
33 #include "rip.h"
34
35 static
36 er_ret_t
37 make_sql2pack(SQ_result_set_t *result, SQ_row_t *row,
/* [<][>][^][v][top][bottom][index][help] */
38 rp_upd_pack_t *pack, rp_attr_t attr, ip_space_t space,
39 int colcount)
40 {
41 er_ret_t conv = RP_OK;
42 rp_uni_t *uniptr = &(pack->uni);
43 char *idptr; /* initially set to the 0'th column */
44 char *col[5];
45 unsigned i;
46
47 dieif(colcount>5); /* size of the col array */
48
49 for(i=0; i<colcount; i++) {
50 col[i] = SQ_get_column_string_nocopy(result, row, i);
51 if (col[i] == NULL) {
52 die;
53 }
54 }
55
56 idptr = col[0];
57
58 pack->type = attr;
59 pack->d.origin = NULL;
60 switch( attr ) {
61 case A_IN:
62 /*
63 read 0-2 from inetnum
64 0 - objectid
65 1 - begin
66 2 - end
67 */
68 uniptr->space = IP_V4;
69 conv = IP_rang_f2b_v4( &(uniptr->u.in), col[1], col[2] );
70 break;
71 case A_RT:
72 /*
73 read 0-3 from route
74 0 - objectid
75 1 - prefix
76 2 - prefix_length
77 3 - origin
78 */
79 uniptr->space = IP_V4;
80 if( NOERR(conv = IP_pref_f2b_v4( &(uniptr->u.rt), col[1], col[2] ))) {
81 pack->d.origin = UT_strdup(col[3]);
82 }
83 break;
84 case A_DN:
85 if( space == IP_V4 ) {
86 /*
87 read 0-3 from inaddr
88 0 - objectid
89 1 - prefix
90 2 - prefix_length
91 3 - domain
92 */
93 conv = IP_pref_f2b_v4( &(uniptr->u.rt), col[1], col[2] );
94 uniptr->space = IP_pref_b2_space( &(uniptr->u.rt) );
95 pack->d.domain = UT_strdup(col[3]);
96 }
97 else {
98 /* read 0-4 from ip6int
99 0 - objectid
100 1 - msb
101 2 - lsb
102 3 - prefix_length
103 4 - domain
104 */
105 conv = IP_pref_f2b_v6( &(uniptr->u.rt), col[1], col[2], col[3] );
106 uniptr->space = IP_pref_b2_space( &(uniptr->u.rt) );
107
108 pack->d.domain = UT_strdup(col[4]);
109 }
110 break;
111 case A_I6:
112 /*
113 read 0-3 from inaddr
114 0 - objectid
115 1 - msb
116 2 - lsb
117 3 - prefix_length
118 */
119 conv = IP_pref_f2b_v6( &(uniptr->u.rt), col[1], col[2], col[3]);
120 uniptr->space = IP_pref_b2_space( &(uniptr->u.rt) );
121 break;
122 default:
123 /* die; / * shouldn't have got here */
124 conv = IP_INVARG;
125 }
126
127 if( sscanf(idptr, "%lu", &(pack->key) ) < 1 ) {
128 conv = IP_INVARG;
129 }
130
131
132 for(i=0; i<colcount; i++) {
133 /* wr_free(col[i]);*/ ;
134 }
135
136 return conv;
137 }
138
139 static
140 er_ret_t
141 RP_sql_load_attr_space( rp_attr_t attr, ip_space_t space,
/* [<][>][^][v][top][bottom][index][help] */
142 rp_regid_t reg_id, SQ_connection_t *con
143 )
144 {
145 SQ_row_t *row;
146 SQ_result_set_t *result;
147 int objnr=0;
148 rx_tree_t *mytree;
149 rp_upd_pack_t pack;
150 int colcount;
151 int sizedebug = ER_is_traced(FAC_RP, ASP_RP_LOAD_DET);
152 char *v4 = DF_attrcode_radix_load_v4(attr);
153 char *v6 = DF_attrcode_radix_load_v6(attr);
154 char *vu = (space == IP_V4) ? v4 : v6;
155 char *srcnam = ca_get_srcname(reg_id);
156 const char *attr_code;
157 char *activity;
158
159 dieif( vu == NULL /* loading query undefined */ );
160 #if 0
161 if( attr==A_IN && space==IP_V4 ) {
162 vu = "SELECT object_id,begin_in,end_in FROM inetnum WHERE thread_id = 0 AND begin_in >= 3238002688 AND end_in < 3254779904 ";
163 }
164 #endif
165
166 dieif( RP_tree_get ( &mytree, reg_id, space, attr ) != RP_OK );
167
168 ER_inf_va(FAC_RP, ASP_RP_LOAD_DET, "loading using %s", vu);
169 ER_dbg_va(FAC_RP, ASP_RP_LOAD_DET, "size before query = %x", sbrk(0));
170
171 attr_code = DF_get_attribute_code(attr);
172 activity = UT_malloc(strlen(srcnam) + strlen(attr_code) + 32);
173 sprintf(activity, "%s/%s, query ", srcnam, attr_code);
174 TA_setactivity(activity);
175 TA_increment();
176
177 if ( SQ_execute_query(con, vu, &result) == -1 ) {
178 fprintf(stderr, "ERROR %d: %s\n", SQ_errno(con), SQ_error(con));
179 die;
180 }
181 else {
182 colcount = SQ_get_column_count(result);
183
184 ER_dbg_va(FAC_RP, ASP_RP_LOAD_DET,
185 "size after query = %x; columns = %d", sbrk(0), colcount);
186
187 /* LOCKED when created, so no need to acquire lock here */
188
189 while ( (row = SQ_row_next(result)) != NULL
190 && SQ_errno(con) == 0 ) {
191
192 dieif( ! NOERR(make_sql2pack(result, row, &pack, attr, space,
193 colcount)) );
194
195 if( ! NOERR(RP_pack_node_l(RX_OPER_CRE, &pack, mytree))) {
196 fprintf(stderr,"%d:\t%ld\n", objnr, pack.key);
197 die;
198 }
199
200 /* free allocated memory */
201 if( pack.d.origin != NULL ) {
202 UT_free(pack.d.origin);
203 pack.d.origin = NULL;
204 }
205
206 objnr++;
207
208 if( sizedebug ) {
209 ER_dbg_va(FAC_RP, ASP_RP_LOAD_DET, "size after object %d = %x",
210 objnr, sbrk(0));
211 }
212
213 if( objnr % 1000 == 0 ) {
214
215 sprintf(activity, "%s/%s, %d done ",
216 srcnam, attr_code, objnr);
217 TA_setactivity(activity);
218 }
219 }
220 /* XXX UNLOCK */
221 TH_release_write_lockw( &(mytree->rwlock) );
222 }
223
224 if( SQ_errno(con) == 0 ) {
225 SQ_free_result(result);
226 } else {
227 die;
228 }
229
230 ER_inf_va(FAC_RP, ASP_RP_LOAD_GEN, "loaded %d objects into %s", objnr,
231 DF_get_attribute_code(attr) );
232
233 UT_free(activity);
234 UT_free(srcnam);
235 return RP_OK;
236 }
237
238 er_ret_t
239 RP_sql_load_reg(rp_regid_t reg_id)
/* [<][>][^][v][top][bottom][index][help] */
240 {
241
242 er_ret_t err;
243 SQ_connection_t *con;
244 char *dbhost = ca_get_srcdbmachine(reg_id);
245 char *dbname = ca_get_srcdbname(reg_id);
246 char *dbuser = ca_get_srcdbuser(reg_id);
247 char *dbpass = ca_get_srcdbpassword(reg_id);
248 char *srcnam = ca_get_srcname(reg_id);
249 unsigned dbport = ca_get_srcdbport(reg_id);
250
251 TA_add( 0, "rx load");
252
253 con = SQ_get_connection( dbhost, dbport, dbname, dbuser, dbpass );
254
255 dieif ( SQ_execute_query(con, "LOCK TABLES "
256 "route READ, inetnum READ, inet6num READ, "
257 "inaddr_arpa READ, domain READ, ip6int READ ",
258 NULL) == -1 );
259
260 do {
261 if( !NOERR(err=RP_sql_load_attr_space( A_RT, IP_V4, reg_id, con))) {
262 break;
263 }
264 if( !NOERR(err=RP_sql_load_attr_space( A_IN, IP_V4, reg_id, con))) {
265 break;
266 }
267 if( !NOERR(err=RP_sql_load_attr_space( A_I6, IP_V6, reg_id, con))) {
268 break;
269 }
270 if( !NOERR(err=RP_sql_load_attr_space( A_DN, IP_V4, reg_id, con))) {
271 break;
272 }
273 if( !NOERR(err=RP_sql_load_attr_space( A_DN, IP_V6, reg_id, con))) {
274 break;
275 }
276 /* CONSTCOND */
277 } while(0);
278
279 dieif ( SQ_execute_query(con, "UNLOCK TABLES", NULL) == -1 );
280
281 /* Close connection */
282 SQ_close_connection(con);
283
284 TA_delete();
285
286 /* free junk */
287 UT_free(dbhost);
288 UT_free(dbname);
289 UT_free(dbuser);
290 UT_free(dbpass);
291 UT_free(srcnam);
292 return err;
293 }
294
295
296 /*
297 load the tree from an ascii file (short attr names).
298 mainly for testing...
299 */
300 er_ret_t
301 RP_asc_load(char *filename, int maxobj, int operation,
/* [<][>][^][v][top][bottom][index][help] */
302 rp_regid_t reg_id)
303 {
304 er_ret_t err;
305 FILE *fp;
306 char buf[1024];
307 char fulltext[65536];
308 int objnr = 0;
309 unsigned len, oldlen=0, ranlen;
310 char rangstr[IP_RANGSTR_MAX];
311 int parsed = 0;
312 int eor; /* end of record */
313
314
315 if( (fp = fopen(filename,"r")) == NULL ) {
316 perror(filename);
317 die;
318 }
319
320 do {
321 fgets(buf, 128, fp);
322
323 eor = ( strlen(buf) <= 1 || feof(fp) );
324
325 if( strlen(buf) > 1 ) {
326 len = strlen(buf);
327 dieif( oldlen+len+1 > 65536 ); /* object too long */
328 memcpy( fulltext+oldlen, buf, len);
329 oldlen+=len;
330
331 fulltext[oldlen]=0;
332 }
333
334 if( eor ) { /* end of object: put into the database. */
335 parsed++;
336
337 /* see if it was just some whitespace junk and nothing more */
338 if( *fulltext==0 ) {
339 continue; /* discard */
340 }
341
342 /* check if it's a radix object */
343 do {
344 char attrname[3];
345 A_Type_t attrcode;
346
347 if( fulltext[0] == '*' && fulltext[3] == ':' ) {
348 strncpy(attrname, fulltext+1, 2);
349 attrname[2]=0;
350
351 if(strcmp(attrname, "XX") == 0 ) {
352 /* object deleted */
353 break;
354 }
355
356 if( (attrcode = DF_attribute_code2type( attrname )) == -1 ) {
357 fprintf(stderr,"discarding a non-object:\n%s\n", fulltext);
358 break;
359 }
360
361 if( DF_attrcode_has_radix_lookup(attrcode) == 0 ) {
362 /* no interest to radix */
363 break;
364 }
365
366 /* copy and translate the range */
367 ranlen = index(fulltext+5,'\n')-fulltext-5;
368 strncpy(rangstr, fulltext+5, ranlen);
369 rangstr[ranlen]=0;
370
371 if( NOERR(err=RP_asc_node(operation, rangstr, attrcode, reg_id,
372 fulltext, strlen(fulltext)+1, 0L )) ) {
373 objnr++;
374 }
375 else {
376 die; /* error putting into the radix tree */
377 return err;
378 }
379
380 }
381 /* CONSTCOND */
382 } while(0);
383
384 *fulltext=0;
385 oldlen=0;
386 }
387 }
388 while(!feof(fp) && objnr<maxobj);
389
390 return RP_OK;
391 }