/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following functions.
- make_sql2pack
- RP_sql_load_attr_space
- RP_sql_load_reg
- RP_asc_load
1 /***************************************
2 $Revision: 1.28 $
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,2002 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 #ifndef NO_A_I6
268 if( !NOERR(err=RP_sql_load_attr_space( A_I6, IP_V6, reg_id, con))) {
269 break;
270 }
271 #endif
272 #ifndef NO_A_DN
273 if( !NOERR(err=RP_sql_load_attr_space( A_DN, IP_V4, reg_id, con))) {
274 break;
275 }
276 if( !NOERR(err=RP_sql_load_attr_space( A_DN, IP_V6, reg_id, con))) {
277 break;
278 }
279 #endif
280 /* CONSTCOND */
281 } while(0);
282
283 dieif ( SQ_execute_query(con, "UNLOCK TABLES", NULL) == -1 );
284
285 /* Close connection */
286 SQ_close_connection(con);
287
288 TA_delete();
289
290 /* free junk */
291 UT_free(dbhost);
292 UT_free(dbname);
293 UT_free(dbuser);
294 UT_free(dbpass);
295 UT_free(srcnam);
296 return err;
297 }
298
299
300 /*
301 load the tree from an ascii file (short attr names).
302 mainly for testing...
303 */
304 er_ret_t
305 RP_asc_load(char *filename, int maxobj, int operation,
/* [<][>][^][v][top][bottom][index][help] */
306 rp_regid_t reg_id)
307 {
308 er_ret_t err;
309 FILE *fp;
310 char buf[1024];
311 char fulltext[65536];
312 int objnr = 0;
313 unsigned len, oldlen=0, ranlen;
314 char rangstr[IP_RANGSTR_MAX];
315 int parsed = 0;
316 int eor; /* end of record */
317
318
319 if( (fp = fopen(filename,"r")) == NULL ) {
320 perror(filename);
321 die;
322 }
323
324 do {
325 fgets(buf, 128, fp);
326
327 eor = ( strlen(buf) <= 1 || feof(fp) );
328
329 if( strlen(buf) > 1 ) {
330 len = strlen(buf);
331 dieif( oldlen+len+1 > 65536 ); /* object too long */
332 memcpy( fulltext+oldlen, buf, len);
333 oldlen+=len;
334
335 fulltext[oldlen]=0;
336 }
337
338 if( eor ) { /* end of object: put into the database. */
339 parsed++;
340
341 /* see if it was just some whitespace junk and nothing more */
342 if( *fulltext==0 ) {
343 continue; /* discard */
344 }
345
346 /* check if it's a radix object */
347 do {
348 char attrname[3];
349 A_Type_t attrcode;
350
351 if( fulltext[0] == '*' && fulltext[3] == ':' ) {
352 strncpy(attrname, fulltext+1, 2);
353 attrname[2]=0;
354
355 if(strcmp(attrname, "XX") == 0 ) {
356 /* object deleted */
357 break;
358 }
359
360 if( (attrcode = DF_attribute_code2type( attrname )) == -1 ) {
361 fprintf(stderr,"discarding a non-object:\n%s\n", fulltext);
362 break;
363 }
364
365 if( DF_attrcode_has_radix_lookup(attrcode) == 0 ) {
366 /* no interest to radix */
367 break;
368 }
369
370 /* copy and translate the range */
371 ranlen = index(fulltext+5,'\n')-fulltext-5;
372 strncpy(rangstr, fulltext+5, ranlen);
373 rangstr[ranlen]=0;
374
375 if( NOERR(err=RP_asc_node(operation, rangstr, attrcode, reg_id,
376 fulltext, strlen(fulltext)+1, 0L )) ) {
377 objnr++;
378 }
379 else {
380 die; /* error putting into the radix tree */
381 return err;
382 }
383
384 }
385 /* CONSTCOND */
386 } while(0);
387
388 *fulltext=0;
389 oldlen=0;
390 }
391 }
392 while(!feof(fp) && objnr<maxobj);
393
394 return RP_OK;
395 }