tests/rx/rx_test.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. CO_get_query_logging
  2. CO_get_query_logfile
  3. put_inet_sql
  4. put_route_sql
  5. put_inetnums
  6. put_prefixes
  7. main

#include <rxroutines.h>
#include <iproutines.h>
#include <stdio.h>
#include <memwrap.h>
#include <numconv.h>

#include "mysql_driver.h"

#define RIPE_REG 17

#define MY_TREE_FAM RX_FAM_IN

#define STR_L 1023

#define HOST "rowan.ripe.net"
#define DATABASE_PORT 3306
#define DATABASE "RIPE"
#define USER "dbint"
#define PASSWD "reimp"
#define QUERY_IN "select * from inetnum where in_id > "
#define QUERY_RT "select * from route where rt_id > "

int Query_logging=0;
char *Query_logfile="stdout";

int CO_get_query_logging() {
/* [<][>][^][v][top][bottom][index][help] */
  return Query_logging;
} /* CO_get_query_logging() */

char *CO_get_query_logfile() {
/* [<][>][^][v][top][bottom][index][help] */
  return Query_logfile;
} /* CO_get_query_logfile() */

void put_inet_sql(rx_tree_t *mytree, char * startobj, int maxobj )
/* [<][>][^][v][top][bottom][index][help] */
{
  SQ_row_t *row;
  int retrieved_objects=0;

  SQ_connection_t *con;
  SQ_result_set_t *result;

  int objnr=1;
  int brk=0;

  char qry[1024];

  /* Make connection */
  con = SQ_get_connection(HOST, DATABASE_PORT, DATABASE, USER, PASSWD);

  //  compose the query

  strcpy(qry, QUERY_IN);
  strcat(qry, startobj);

  fprintf(stderr,"the query is: \n%s\n", qry);

  result = SQ_execute_query(con, qry); 
  
  if (result == NULL) {
    fprintf(stderr, "ERROR %d: %s\n", SQ_errno(con), SQ_error(con));
  }
  else {
    while ( (row = SQ_row_next(result)) != NULL 
            && objnr<=maxobj) {

      ip_range_t myrang;
      rx_dataleaf_t *leafptr;
      unsigned in_id;
      char *col[4];
      int i;
      
      memset(&myrang, 0, sizeof(ip_range_t));
      myrang.begin.space =  myrang.end.space = IP_V4;
      

      for(i=0; i<4; i++) {
        col[i] = SQ_get_column_string( row, i);
        if (col[i] == NULL) {
          die;
        }
      }

      // get the data: range and payload (id and netname)
      
      // begin of range
      //      if( sscanf(col[1], "%u", &myrang.begin.words[0] ) < 1 ) {
      if( ut_dec_2_uns(col[1], &myrang.begin.words[0] ) < 0 ) {
        die;
      }
      free(col[1]);

      // end of range
      //      if( sscanf(col[2], "%u", &myrang.end.words[0] ) < 1 ) {
      if( ut_dec_2_uns(col[2], &myrang.end.words[0] ) < 0 ) {
          die;
      }
      free(col[2]);
      
      // payload
      if( wr_calloc( (void **)& leafptr, sizeof(rx_dataleaf_t), 1) 
          != UT_OK) {
        die;
      }
      
      // fulltext id
      //      if( sscanf(col[0], "%u", &in_id ) < 1 ) {
      if( ut_dec_2_uns(col[0], &in_id ) < 0 ) {
        die;
      }
      free(col[0]);
      leafptr->data_key = in_id;

      // netname - already allocated in SQ_get_column_string, 
      // just save the pointer
      leafptr->data_ptr = col[3];
      leafptr->data_len = strlen(col[3])+1;

      if( RX_inum_node( RX_OPER_CRE, &myrang, mytree, leafptr ) != RX_OK ) {
        fprintf(stderr,"%d:\t%d\t%s\n", objnr, in_id, col[3]);
        die;
      }
 
      objnr++;
    }
  }
  SQ_free_result(result);

  /* Close connection */
  SQ_close_connection(con);

}


void put_route_sql(rx_tree_t *mytree, char * startobj, int maxobj )
/* [<][>][^][v][top][bottom][index][help] */
{
  SQ_row_t *row;
  int retrieved_objects=0;

  SQ_connection_t *con;
  SQ_result_set_t *result;

  int objnr=1;
  int brk=0;

  char qry[1024];

  /* Make connection */
  con = SQ_get_connection(HOST, DATABASE_PORT, DATABASE, USER, PASSWD);

  //  compose the query

  strcpy(qry, QUERY_RT);
  strcat(qry, startobj);

  fprintf(stderr,"the query is: \n%s\n", qry);

  result = SQ_execute_query(con, qry); 
  
  if (result == NULL) {
    fprintf(stderr, "ERROR %d: %s\n", SQ_errno(con), SQ_error(con));
  }
  else {
    while ( (row = SQ_row_next(result)) != NULL 
            && objnr<=maxobj) {

      ip_prefix_t mypref;
      rx_dataleaf_t *leafptr;
      int rt_id;
      char *col[4];
      int i;
      
      memset(&mypref, 0, sizeof(ip_prefix_t));
      mypref.ip.space = IP_V4;

      for(i=0; i<4; i++) {
        col[i] = SQ_get_column_string( row, i);
        if (col[i] == NULL) {
          die;
        }
      }

      // get the data: prefix and payload (id and origin)
      
      // prefix ip
      if( sscanf(col[1], "%u", &mypref.ip.words[0] ) < 1 ) {
        die;
      }
      free(col[1]);

      // prefix length
      if( sscanf(col[2], "%u", &mypref.bits ) < 1 ) {
        die;
      }
      free(col[2]);
      
      // payload: goes into a dataleaf
      if( wr_calloc( (void **)& leafptr, sizeof(rx_dataleaf_t), 1) 
          != UT_OK) {
        die;
      }
      
      // fulltext id
      if( sscanf(col[0], "%u", &rt_id ) < 1 ) {
        die;
      }
      free(col[0]);
      leafptr->data_key = rt_id;

      // origin - already allocated in SQ_get_column_string, 
      // just save the pointer
      leafptr->data_ptr = col[3];
      leafptr->data_len = strlen(col[3])+1;

      if( RX_bin_node( RX_OPER_CRE, &mypref, mytree, leafptr ) != RX_OK ) {
        fprintf(stderr,"%d:\t%d\t%s\n", objnr, rt_id, col[3]);
        die;
      }
 
      objnr++;
    }
  }
  SQ_free_result(result);

  /* Close connection */
  SQ_close_connection(con);

}


void put_inetnums(rx_tree_t *mytree, FILE *fp, int maxobj)
/* [<][>][^][v][top][bottom][index][help] */
{
  char buf[1024];
  char *fulltext=NULL;
  int objnr = 0;
  int len, oldlen=0;
  int cnt;
  int ranlen;
  char rangstr[IP_RANGSTR_MAX];
  rx_dataleaf_t *leafptr;
  er_ret_t err;

  while(!feof(fp) && objnr<maxobj) {
    fgets(buf, 128, fp);

    if(strlen(buf)>1) {
      len = strlen(buf);
      if( wr_realloc( (void **)& fulltext, fulltext, len+oldlen + 1) 
          != UT_OK) {
        die;
      }
      memcpy( fulltext+oldlen, buf, len);
      oldlen+=len;
      
      fulltext[oldlen]=0;
    }
    else {
      // end of object: put into the database.

      // see if it was just some whitespace junk and nothing more
      if( fulltext==NULL ) {
        continue;  // discard
      }

      // but check if it's an object first :)
      if( strncmp(fulltext, "*in: ", 5) != 0 ) {
        fprintf(stderr,"discarding a non-object:\n%s\n", fulltext);
        wr_free(fulltext);
      }
      else {
        int rang_ok;

        // copy and translate the range
        ranlen = index(fulltext+5,'\n')-fulltext-5;
        strncpy(rangstr, fulltext+5, ranlen);
        rangstr[ranlen]=0;

        if (RX_asc_node( RX_OPER_CRE, rangstr, 
                         RIPE_REG, IP_V4, MY_TREE_FAM, fulltext ) == RX_OK ) {
          objnr++;
        }
        else {
          die; // error putting into the radix tree
        }
      }

      fulltext=NULL;
      oldlen=0;
    }
  }
}


void put_prefixes(rx_tree_t *mytree, FILE *fp, int maxobj)
/* [<][>][^][v][top][bottom][index][help] */
{
  char buf[1024];
  char *fulltext=NULL;
  int objnr = 0;
  int len, oldlen=0;
  int preflen;
  char pref[IP_PREFSTR_MAX];
  ip_prefix_t mypref;
  rx_dataleaf_t *leafptr;
  

  while(!feof(fp) && objnr<maxobj) {
    fgets(buf, 128, fp);

    if(strlen(buf)>1) {
      len = strlen(buf);
      if( wr_realloc( (void **)& fulltext, fulltext, len+oldlen + 1) 
          != UT_OK) {
        die;
      }
      memcpy( fulltext+oldlen, buf, len);
      oldlen+=len;
      
      fulltext[oldlen]=0;
    }
    else {
      // end of object: put into the database.

      // see if it was just some whitespace junk and nothing more
      if( fulltext==NULL ) {
        continue;  // discard
      }

      // but check if it's an object first :)
      if( strncmp(fulltext, "*rt: ", 5) != 0 ) {
        fprintf(stderr,"discarding a non-object:\n%s\n", fulltext);
        wr_free(fulltext);
      }
      else {
        // copy and translate the prefix
        preflen = index(fulltext+5,'\n')-fulltext-5;
        strncpy(pref, fulltext+5, preflen);
        pref[preflen]=0;

        if( RX_asc_node( RX_OPER_CRE, pref, 
                         RIPE_REG, IP_V4, MY_TREE_FAM, fulltext ) == RX_OK ) {
          objnr++;
        }
      }
      fulltext=NULL;
      oldlen=0;
    }
  }
}

int main(int argc, char **argv)
/* [<][>][^][v][top][bottom][index][help] */
{
  ip_prefix_t mypref;
  rx_tree_t  *mytree;
  ip_prefix_t *querypref;
  GList    *datlist, *qitem, *preflist;
  int maxline=0;
  char buf[1024];
  er_path_t erlogstr;
  FILE *fp;
  int i, par_a, par_b=0, search_mode;
  char pref[IP_PREFSTR_MAX];
  er_ret_t err;
  int cnt;
  char *key;

  
  
  ER_init(argc, argv);

  erlogstr.fdes = stderr;
  erlogstr.asp  = 0;
  erlogstr.sev  = ER_SEV_W;
  erlogstr.mode = ER_M_SEVCHAR | ER_M_TEXTLONG ;

  ER_setpath(& erlogstr);  

  puts("creating a tree...");

  IP_pref_e2b(&mypref, "0.0.0.0/0");


  


  if (RX_space_cre(RIPE_REG, IP_V4, MY_TREE_FAM, "0.0.0.0/0",
                   RX_MEM_RAMONLY, RX_SUB_NONE) != RX_OK)
    puts("error!!!");
  
  rx_space_list();
  fputs("-----------------------------------------------------------------\n",
        stderr);
  if( RX_get_tree ( &mytree, RIPE_REG, IP_V4, MY_TREE_FAM) != RX_OK ) {
    die;
  }  
  
#if 0

  if( argc<3 ) {
    fputs("arguments:  number_of_lines  filename", stderr);
    die;
  } else {
    maxline = atoi(argv[1]);
    if( (fp = fopen(argv[2],"r")) == NULL ) {
      perror(argv[0]);
      die; 
    }
    else
      {
        put_inetnums(mytree, fp, maxline);
        //  put_prefixes(mytree, fp, maxline);
      }
  }
  

#else


  if( argc!=3 ) {
    fputs("arguments: startobj number_of_lines", stderr);
    die;
  } else {
    maxline = atoi(argv[2]);
    put_inet_sql(mytree, argv[1], maxline);
  }

#endif

  rx_space_list();

  // consistency check
  
  if( mytree->num_nodes > 0 ) {
    fprintf(stderr, "tree consistency check: ");

    cnt = rx_walk_tree(mytree->top_ptr, NULL, RX_WALK_CNTGLU, 
                       255, 0, 0, NULL, &err);
    if( cnt != mytree->num_nodes ) {
      fprintf(stderr,
              " %d nodes instead of %d found\n",
              cnt, mytree->num_nodes);
    } 
    else {
      fprintf(stderr, "OK\n");
    }
  }

  // exit(0);

  // rx_tree_print( mytree );

  // change the loglevel
  erlogstr.asp  = ASP_RX_SRCH_DET | ASP_RX_STKBLD_DET;
  ER_setpath(& erlogstr);

  
  // search
  while(!feof(stdin)) {
    printf("\nsearch> ");
    fgets(buf, 128, stdin);

    par_a=1;
    key = buf;
    
    if( *key == '\0' ) {
      continue;
    }

    // chop \n
    *index(buf,'\n') = '\0';

    if( strcmp(key, "exit") == 0 ) {
      exit(0);
    }
    
    if( strncmp(key, "show ", 5) == 0 ) {
      int depth;
      extern er_ret_t rx_walk_hook_printnode();
      
      key+=5;

      /* tree inspection */
      if( strncmp(key, "tree", 4) == 0 ) {
        // show tree <n>,  default n = 255
        key+=4;
        if( sscanf(key, "%d", &depth) < 1 ) {
          depth = 255;
        }
        
        rx_walk_tree(mytree->top_ptr, rx_walk_hook_printnode, 
                     RX_WALK_CNTGLU,  // print also glue nodes
                     depth, 0, 0, NULL, &err);

        /* err will be handled below */
        printf("got status %x\n", err);
        ER_perror(FAC_RX, err);

        continue;
      }      
    }
    else {

      /* ordinary query */

      /* take switches */
      if( *key=='-' ) {
        switch( *(++key) ) {
        case 'd':
          search_mode = RX_SRCH_EXLESS;     // default
          break;
        case 'e':
          search_mode = RX_SRCH_EXACT;
          break;
        case 'm':
          search_mode = RX_SRCH_MORE;
          key++;
          if(  ! isdigit( *key ) ) {
            puts("invalid syntax");
            continue;
          } else {
            sscanf( key, "%d", &par_a);
          }
          break;
        case 'l':
          search_mode = RX_SRCH_LESS;
          key++;
          if(  ! isdigit( *key ) ) {
            puts("invalid syntax");
            continue;
          } else {
            sscanf( key, "%d", &par_a);
          }
          break;
        case 'r':
          search_mode = RX_SRCH_RANG;
          key++;
          if( ! isdigit( *key ) ) {
            puts("invalid syntax");
            continue;
          }
          else {
            sscanf( key, "%d", &par_a);
          }
          break;
        case 's':
          search_mode = RX_SRCH_DBLS;
          key++;
          if(  ! isdigit( *key ) ) {
            puts("invalid syntax");
            continue;
          } else {
            sscanf( key, "%d", &par_a);
          }
          break;
        }
        
        if( (key=index(buf, ' ')) == NULL ) {
          // empty query
          continue;
        }
        else {
          key++;
        }
        
      } 
      else {
        search_mode = RX_SRCH_EXLESS;          // default search mode
      }
      
      // zero the datlist (the one for answers). 
      datlist = NULL;
      
      err = RX_asc_search(search_mode,  par_a, par_b, key, 
                          RIPE_REG, IP_V4, MY_TREE_FAM, &datlist, RX_ANS_ALL);
    }

    printf("got status %x\n", err);
    
    ER_perror(FAC_RX, err);

    switch( err ) {
    case RX_OK:

      puts("### answers:");
      
      for(i=0; i<g_list_length(datlist); i++) {
        rx_datcpy_t *datcpy = g_list_nth_data(datlist, i);
        char rangstr[IP_RANGSTR_MAX];
        
        if( MY_TREE_FAM == RX_FAM_IN ) {
          if(IP_rang_b2a( &(datcpy->leafcpy.iprange), rangstr, IP_RANGSTR_MAX) 
             != IP_OK ) {
            die;
          }
          if( datcpy->leafcpy.composed ) {
            strcat(rangstr, "  \tc");
          }
        } else {
          rangstr[0] = '\0';
        }

        printf("\n%d: [%u]\t%s\n%s",i, datcpy->leafcpy.data_key,
               rangstr, (char *) datcpy->leafcpy.data_ptr );
        wr_free(datcpy->leafcpy.data_ptr );
      }
      
      g_list_foreach(datlist, rx_free_list_element, NULL);
      g_list_free(datlist);

      break;
    case IP_INVARG:
      fputs("conversion error", stderr);
      break;
    default:
      die;
    }
  }
  return 0;
}

/* [<][>][^][v][top][bottom][index][help] */