Source File rp/rp_load.c

    1    | /***************************************
    2    |   $Revision: 1.27 $
    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,
    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,
    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)
    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,
    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  | }