## 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] */