comments in-line below

On 2015-02-11 15:59, David Mandelberg wrote:
> From: David Mandelberg <dmand...@bbn.com>
> 
> Use the schema introduced in the previous set of commits when querying
> rpki-rtr data from the database. Additionally, change how rpki-rtr
> data is queried during Serial and Reset Queries to significantly
> improve performance with large rtr_incremental or rtr_full tables.
> 
> NOTE: This is one of a series of commits to use the updated schema.
> It is the last in the series to update the non-test code, so the code
> should be working now, but the tests will still fail.
> 
> addresses [#5] and [#7]
> ---
>  lib/db/clients/rtr.c | 446 
> +++++++++++++++++++++++++++------------------------
>  lib/db/prep-stmt.c   |  18 ++-
>  2 files changed, 246 insertions(+), 218 deletions(-)
> 
> diff --git a/lib/db/clients/rtr.c b/lib/db/clients/rtr.c
> index c19702e..0527482 100644
> --- a/lib/db/clients/rtr.c
> +++ b/lib/db/clients/rtr.c
> @@ -23,26 +23,65 @@
>  
>  
>  struct query_state {
> -    uint32_t ser_num;           // ser_num to search for first row to send
> -    uint64_t first_row;         // first row to send.  zero-based
> -    int bad_ser_num;            // neither the given ser_num, nor its
> -                                // successor, exist
> -    int data_sent;              // true if a pdu has been created for this
> -                                // serial/reset query
> -    int no_new_data;            // the given ser_num exists, but its 
> successor 
> -                                // does not
> -    int not_ready;              // no valid ser_nums exist, yet
> -    uint16_t session;           // the session_id number
> +    /**
> +        @brief Serial number to search for first row to send.

nit: This line and the rest of this structure has tab/spaces mismatch
vs. rest of file.

> +    */
> +    uint32_t ser_num;
> +
> +    /**
> +        @brief The last row that we sent.
> +    */
> +    struct last_row {

nit: no need to name this structure -- you can do struct {...}

> +        /**
> +            @brief False if there was a previous row, true if this is
> +                the first time.
> +
> +            If this is true, the values in the remaining fields are
> +            unspecified.
> +        */
> +        uint8_t first_time;

should have type unsigned char (type of MYSQL_TYPE_TINY)

> +
> +        uint32_t asn;

should have type unsigned int (type of MYSQL_TYPE_LONG)

> +
> +        /**
> +            @brief Length of #prefix, either 4 for IPv4 or 16 for IPv6.
> +        */
> +        uint8_t prefix_family_length;
> +
> +        uint8_t prefix[16];

should have type unsigned char[] (type of MYSQL_TYPE_BLOB)

> +
> +        uint8_t prefix_length;

should have type unsigned char (type of MYSQL_TYPE_TINY)

> +
> +        uint8_t prefix_max_length;

should have type unsigned char (type of MYSQL_TYPE_TINY)

> +    } first_row;

Why is this called first_row when the name of the struct is last_row?
Don't you mean:
    struct last_row {...} last_row
or:
    struct first_row {...} first_row?

> +
> +    /**
> +        @brief Neither the given ser_num, nor its successor, exist.
> +    */
> +    int bad_ser_num;
> +
> +    /**
> +        @brief True if a pdu has been created for this serial/reset query.
> +    */
> +    int data_sent;
> +
> +    /**
> +        @brief The given ser_num exists, but its successor does not.
> +    */
> +    int no_new_data;
> +
> +    /**
> +        @brief No valid ser_nums exist, yet.
> +    */
> +    int not_ready;
> +
> +    /**
> +        @brief The session_id number.
> +    */
> +    uint16_t session;
>  };
>  
>  
> -static const size_t IPADDR_STR_LEN = ((INET6_ADDRSTRLEN > INET_ADDRSTRLEN) ? 
> INET6_ADDRSTRLEN : INET_ADDRSTRLEN) + 1 +  // '/'
> -    3 +                         // prefix length
> -    1 +                         // '('
> -    3 +                         // max length
> -    1;                          // ')'
> -
> -
>  
> /**=============================================================================
>  
> ------------------------------------------------------------------------------*/
>  int db_rtr_get_session_id(
> @@ -476,164 +515,42 @@ static int readSerNumAsCurrent(
>  
>  
>  
> /**=============================================================================
> - * @param field_str has the format:  <address>/<length>[(<max_length>)]
> - * It originates from a database field `ip_addr' and gets null terminated
> - *     before being passed to this function.
> - * @return 0 on success or an error code on failure.
> -------------------------------------------------------------------------------*/
> -static int parseIpaddr(
> -    sa_family_t * family,
> -    struct in_addr *addr4,
> -    struct in6_addr *addr6,
> -    uint8_t * prefix_len,
> -    uint8_t * max_len,
> -    const char field_str[])
> -{
> -    char ip_txt[INET_ADDRSTRLEN >
> -                INET6_ADDRSTRLEN ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN];
> -    size_t i;
> -    int chars_consumed;
> -
> -    if (field_str[0] == '\0')
> -    {
> -        LOG(LOG_ERR, "empty field string");
> -        return -1;
> -    }
> -
> -    // copy IP field
> -    for (i = 0;
> -         field_str[i] != '\0' && field_str[i] != '/' && i < sizeof(ip_txt);
> -         ++i)
> -    {
> -        ip_txt[i] = field_str[i];
> -    }
> -    if (field_str[i] == '\0')
> -    {
> -        LOG(LOG_ERR, "no prefix length present");
> -        return -1;
> -    }
> -    else if (field_str[i] == '/')
> -    {
> -        ip_txt[i] = '\0';
> -        ++i;
> -    }
> -    else
> -    {
> -        LOG(LOG_ERR, "IP address string too long");
> -        return -1;
> -    }
> -
> -    // parse IP field
> -    if (inet_pton(AF_INET, ip_txt, addr4) == 1)
> -    {
> -        *family = AF_INET;
> -    }
> -    else if (inet_pton(AF_INET6, ip_txt, addr6) == 1)
> -    {
> -        *family = AF_INET6;
> -    }
> -    else
> -    {
> -        LOG(LOG_ERR, "malformed IP address");
> -        return -1;
> -    }
> -
> -    // parse prefix length field
> -    if (sscanf(field_str + i, "%" SCNu8 "%n", prefix_len, &chars_consumed) < 
> 1)
> -    {
> -        LOG(LOG_ERR, "error parsing prefix length");
> -        return -1;
> -    }
> -    else
> -    {
> -        i += chars_consumed;
> -    }
> -
> -    // return early if there's no max length field
> -    if (field_str[i] == '\0')
> -    {
> -        *max_len = *prefix_len;
> -        return 0;
> -    }
> -
> -    // parse max length field
> -    if (field_str[i] == '(')
> -    {
> -        ++i;
> -    }
> -    else
> -    {
> -        LOG(LOG_ERR, "expecting `(' after the prefix length");
> -        return -1;
> -    }
> -
> -    if (sscanf(field_str + i, "%" SCNu8 "%n", max_len, &chars_consumed) < 1)
> -    {
> -        LOG(LOG_ERR, "error parsing max length");
> -        return -1;
> -    }
> -    else
> -    {
> -        i += chars_consumed;
> -    }
> -
> -    if (field_str[i] == '\0')
> -    {
> -        LOG(LOG_ERR, "truncated max length");
> -        return -1;
> -    }
> -    else if (field_str[i] != ')')
> -    {
> -        LOG(LOG_ERR, "garbage at end of max length field");
> -        return -1;
> -    }
> -    else
> -    {
> -        ++i;
> -    }
> -
> -    // done all parsing
> -
> -    if (field_str[i] != '\0')
> -    {
> -        LOG(LOG_ERR, "garbage at end");
> -        return -1;
> -    }
> -
> -    return 0;
> -}
> -
> -
> -/**=============================================================================
> + * @param[out] pdu PDU to fill in.
> + * @param[in] asn AS number.
> + * @param[in] prefix_data Raw prefix.
> + * @param[in] prefix_data_length Length of @p prefix_data. This must be 
> either

nit: please wrap at ~70 cols

> + *    4 (IPv4) or 16 (IPv6).
> + * @param[in] prefix_length Length in bits of the prefix. This must be >= 0, 
> and

nit: please wrap at ~70 cols
nit: it's unsigned, so how could it be < 0?

> + *    <= 32 for IPv4 or <= 128 for IPv6.
> + * @param[in] prefix_max_length Maximum prefix length, as from a ROA.
> + * @param[in] is_announce True for announcement, false for withdrawal.
>  
> ------------------------------------------------------------------------------*/
>  static int fillPduIpPrefix(
>      PDU * pdu,
>      uint32_t asn,
> -    char *ip_addr,
> +    uint8_t const * prefix_data,
> +    size_t prefix_data_length,
> +    uint8_t prefix_length,
> +    uint8_t prefix_max_length,
>      bool is_announce)
>  {
> -    sa_family_t family = 0;
> -    struct in_addr addr4;
> -    struct in6_addr addr6;
> -    uint8_t prefix_len;
> -    uint8_t max_prefix_len;
>      uint8_t flags = is_announce ? FLAG_WITHDRAW_ANNOUNCE : 0;
>  
> -    if (parseIpaddr(&family, &addr4, &addr6, &prefix_len, &max_prefix_len,
> -                    ip_addr))
> +    switch (prefix_data_length)
>      {
> -        LOG(LOG_ERR, "could not parse ip_addr");
> -        return -1;
> -    }
> +        case 4:
> +            fill_pdu_ipv4_prefix(pdu, flags, prefix_length,
> +                prefix_max_length, (struct in_addr const *)prefix_data, asn);

s_addr isn't guaranteed to be the first member of struct in_addr, and
the alignment of prefix_data might not be appropriate for struct
in_addr.  Should instead create a local struct in_addr and memcpy into
it's s_addr member.

> +            break;
>  
> -    if (family == AF_INET)
> -        fill_pdu_ipv4_prefix(pdu,
> -                             flags, prefix_len, max_prefix_len, &addr4, asn);
> -    else if (family == AF_INET6)
> -        fill_pdu_ipv6_prefix(pdu,
> -                             flags, prefix_len, max_prefix_len, &addr6, asn);
> -    else
> -        return -1;
> +        case 16:
> +            fill_pdu_ipv6_prefix(pdu, flags, prefix_length,
> +                prefix_max_length, (struct in6_addr const *)prefix_data, 
> asn);

s6_addr isn't guaranteed to be the first member of struct in6_addr,
and the alignment of prefix_data might not be appropriate for struct
in6_addr.  Should instead create a local struct in6_addr and memcpy
into it's s6_addr member.

> +            break;
> +
> +        default:
> +            return -1;
> +    }

Would be nice to use an address family type instead of assuming that
each address family has a different length.  Not sure if/when we'll
see another address family with the same length...

>  
>      return 0;
>  }
> @@ -658,9 +575,9 @@ int db_rtr_serial_query_init(
>          return -1;
>      }
>      state->ser_num = 0;
> -    state->first_row = 0;
> -    state->data_sent = 0;
> +    state->first_row.first_time = 1;
>      state->bad_ser_num = 0;
> +    state->data_sent = 0;
>      state->no_new_data = 0;
>      state->not_ready = 0;

It's OK/necesssary to not initialize state->session?

nit:  use a compound literal to replace all those lines:

    *state = (struct query_state){ .first_row.first_time = 1 };

>      *query_state = (void *)state;
> @@ -806,24 +723,55 @@ static int serial_query_do_query(
>      MYSQL_STMT *stmt =
>          conn->stmts[DB_CLIENT_TYPE_RTR][DB_PSTMT_RTR_SERIAL_QRY_GET_NEXT];
>  
> -    MYSQL_BIND bind_in[3];
> +    MYSQL_BIND bind_in[7];
>      memset(bind_in, 0, sizeof(bind_in));
>      // serial_num parameter
>      bind_in[0].buffer_type = MYSQL_TYPE_LONG;
>      bind_in[0].buffer = &(state->ser_num);
>      bind_in[0].is_unsigned = (my_bool) 1;
>      bind_in[0].is_null = (my_bool *) 0;
> -    // offset parameter
> -    bind_in[1].buffer_type = MYSQL_TYPE_LONGLONG;
> -    bind_in[1].buffer = &(state->first_row);
> -    bind_in[1].is_unsigned = (my_bool) 1;
> -    bind_in[1].is_null = (my_bool *) 0;
> -    // limit parameter
> +    // start-at-beginning parameter
> +    bind_in[1].buffer_type = MYSQL_TYPE_TINY;
> +    bind_in[1].buffer = &state->first_row.first_time;

state->first_row.first_time has type uint8_t, not unsigned char

> +    bind_in[1].is_unsigned = (my_bool)1;

nit: no need for casting (also below)

> +    bind_in[1].is_null = (my_bool *)0;

nit: NULL (also below)

> +    // asn parameter
>      bind_in[2].buffer_type = MYSQL_TYPE_LONG;
> -    size_t limit = max_rows - *num_pdus;
> -    bind_in[2].buffer = &limit;
> -    bind_in[2].is_unsigned = (my_bool) 1;
> -    bind_in[2].is_null = (my_bool *) 0;
> +    bind_in[2].buffer = &state->first_row.asn;

state->first_row.asn has type uint32_t, not unsigned int

> +    bind_in[2].is_unsigned = (my_bool)1;
> +    bind_in[2].is_null = (my_bool *)0;
> +    // prefix parameter
> +    bind_in[3].buffer_type = MYSQL_TYPE_BLOB;
> +    bind_in[3].buffer = &state->first_row.prefix;
> +    bind_in[3].buffer_length = sizeof(state->first_row.prefix);
> +    unsigned long prefix_family_length;
> +    if (state->first_row.first_time)
> +    {
> +        prefix_family_length = 0;
> +    }
> +    else
> +    {
> +        prefix_family_length = state->first_row.prefix_family_length;
> +    }
> +    bind_in[3].length = &prefix_family_length;
> +    bind_in[3].is_null = (my_bool *)0;

what about .is_unsigned?

> +    // prefix_length parameter
> +    bind_in[4].buffer_type = MYSQL_TYPE_TINY;
> +    bind_in[4].buffer = &state->first_row.prefix_length;

state->first_row.prefix_length has type uint8_t, not unsigned char

> +    bind_in[4].is_unsigned = (my_bool)1;
> +    bind_in[4].is_null = (my_bool *)0;
> +    // prefix_max_length parameter
> +    bind_in[5].buffer_type = MYSQL_TYPE_TINY;
> +    bind_in[5].buffer = &state->first_row.prefix_max_length;

state->first_row.prefix_max_length has type uint8_t, not unsigned char

> +    bind_in[5].is_unsigned = (my_bool)1;
> +    bind_in[5].is_null = (my_bool *)0;
> +    // limit parameter
> +    bind_in[6].buffer_type = MYSQL_TYPE_LONGLONG;
> +    uint64_t limit = max_rows - *num_pdus;

type should be unsigned long long, not uint64_t

> +    bind_in[6].buffer = &limit;
> +    bind_in[6].is_unsigned = (my_bool) 1;
> +    bind_in[6].is_null = (my_bool *) 0;

nit: use an initializer

> +
>  
>      if (mysql_stmt_bind_param(stmt, bind_in))
>      {
> @@ -839,23 +787,35 @@ static int serial_query_do_query(
>          return -1;
>      }
>  
> -    MYSQL_BIND bind_out[3];
> +    MYSQL_BIND bind_out[5];
>      uint32_t db_asn;
> -    char db_ip_addr[IPADDR_STR_LEN + 1];
> +    unsigned long db_prefix_family_length;
> +    uint8_t db_prefix[16];

should have type unsigned char[] (type of MYSQL_TYPE_BLOB)

> +    uint8_t db_prefix_length;

should have type unsigned char (type of MYSQL_TYPE_TINY)

> +    uint8_t db_prefix_max_length;

should have type unsigned char (type of MYSQL_TYPE_TINY)

>      int8_t db_is_announce;
>      memset(bind_out, 0, sizeof(bind_out));
>      // asn output
>      bind_out[0].buffer_type = MYSQL_TYPE_LONG;
>      bind_out[0].is_unsigned = (my_bool) 1;
>      bind_out[0].buffer = &db_asn;
> -    // ip_addr output
> -    bind_out[1].buffer_type = MYSQL_TYPE_STRING;
> -    bind_out[1].buffer_length = IPADDR_STR_LEN;
> -    bind_out[1].buffer = (char *)&db_ip_addr;
> -    // is_announce output
> +    // prefix output
> +    bind_out[1].buffer_type = MYSQL_TYPE_BLOB;
> +    bind_out[1].buffer_length = sizeof(db_prefix);
> +    bind_out[1].length = &db_prefix_family_length;
> +    bind_out[1].buffer = &db_prefix;

what about .is_unsigned?  I guess it's memset to 0.  Do you want that?
(The type of db_prefix is unsigned array.)

> +    // prefix_length output
>      bind_out[2].buffer_type = MYSQL_TYPE_TINY;
> -    bind_out[2].is_unsigned = (my_bool) 0;
> -    bind_out[2].buffer = &db_is_announce;
> +    bind_out[2].is_unsigned = (my_bool)1;
> +    bind_out[2].buffer = &db_prefix_length;
> +    // prefix_max_length output
> +    bind_out[3].buffer_type = MYSQL_TYPE_TINY;
> +    bind_out[3].is_unsigned = (my_bool)1;
> +    bind_out[3].buffer = &db_prefix_max_length;
> +    // is_announce output
> +    bind_out[4].buffer_type = MYSQL_TYPE_TINY;
> +    bind_out[4].is_unsigned = (my_bool) 0;
> +    bind_out[4].buffer = &db_is_announce;

nit: use an initializer

>  
>      if (mysql_stmt_bind_result(stmt, bind_out))
>      {
> @@ -880,15 +840,25 @@ static int serial_query_do_query(
>  
>      while ((ret = mysql_stmt_fetch(stmt)) == 0)
>      {
> -        if (fillPduIpPrefix(&((*_pdus)[*num_pdus]), db_asn, db_ip_addr, 
> db_is_announce  /* , 
> -                                                                             
>             * state->session */ ))
> +        if (fillPduIpPrefix(
> +            &((*_pdus)[*num_pdus]),
> +            db_asn,
> +            db_prefix, db_prefix_family_length,
> +            db_prefix_length, db_prefix_max_length,
> +            db_is_announce))
>          {
>              LOG(LOG_ERR, "could not create PDU_IPVx_PREFIX");
>              mysql_stmt_free_result(stmt);
>              return -1;
>          }
>          ++*num_pdus;
> -        ++state->first_row;
> +
> +        state->first_row.first_time = 0;
> +        state->first_row.asn = db_asn;
> +        state->first_row.prefix_family_length = db_prefix_family_length;
> +        memcpy(state->first_row.prefix, db_prefix, db_prefix_family_length);
> +        state->first_row.prefix_length = db_prefix_length;
> +        state->first_row.prefix_max_length = db_prefix_max_length;

It took me a little while to understand why this information is now
stored in state when it wasn't previously, so a comment (or at least
an explanation in the commit message) about how this all works would
be useful.

>      }
>      if (ret != 0 && ret != MYSQL_NO_DATA)
>      {
> @@ -946,7 +916,7 @@ static int serial_query_post_query(
>      {                           // db has sn for this sn_prev
>          *is_done = 0;
>          state->ser_num = next_ser_num;
> -        state->first_row = 0;
> +        state->first_row.first_time = 1;
>          return 0;
>      }
>      else if (ret == GET_SERNUM_NONE)
> @@ -1063,7 +1033,7 @@ int db_rtr_reset_query_init(
>          return -1;
>      }
>      state->ser_num = 0;
> -    state->first_row = 0;
> +    state->first_row.first_time = 1;
>      state->bad_ser_num = 0;
>      state->data_sent = 0;
>      state->no_new_data = 0;
> @@ -1162,24 +1132,54 @@ ssize_t db_rtr_reset_query_get_next(
>  
>      MYSQL_STMT *stmt =
>          conn->stmts[DB_CLIENT_TYPE_RTR][DB_PSTMT_RTR_RESET_QRY_GET_NEXT];
> -    MYSQL_BIND bind_in[3];
> +    MYSQL_BIND bind_in[7];
>      memset(bind_in, 0, sizeof(bind_in));
>      // serial_num parameter
>      bind_in[0].buffer_type = MYSQL_TYPE_LONG;
>      bind_in[0].buffer = &(state->ser_num);
>      bind_in[0].is_unsigned = (my_bool) 1;
>      bind_in[0].is_null = (my_bool *) 0;
> -    // offset parameter
> -    bind_in[1].buffer_type = MYSQL_TYPE_LONGLONG;
> -    bind_in[1].buffer = &(state->first_row);
> -    bind_in[1].is_unsigned = (my_bool) 1;
> -    bind_in[1].is_null = (my_bool *) 0;
> -    // limit parameter
> +    // start-at-beginning parameter
> +    bind_in[1].buffer_type = MYSQL_TYPE_TINY;
> +    bind_in[1].buffer = &state->first_row.first_time;
> +    bind_in[1].is_unsigned = (my_bool)1;
> +    bind_in[1].is_null = (my_bool *)0;
> +    // asn parameter
>      bind_in[2].buffer_type = MYSQL_TYPE_LONG;
> -    size_t limit = max_rows - num_pdus;
> -    bind_in[2].buffer = &limit;
> -    bind_in[2].is_unsigned = (my_bool) 1;
> -    bind_in[2].is_null = (my_bool *) 0;
> +    bind_in[2].buffer = &state->first_row.asn;
> +    bind_in[2].is_unsigned = (my_bool)1;
> +    bind_in[2].is_null = (my_bool *)0;
> +    // prefix parameter
> +    bind_in[3].buffer_type = MYSQL_TYPE_BLOB;
> +    bind_in[3].buffer = &state->first_row.prefix;
> +    bind_in[3].buffer_length = sizeof(state->first_row.prefix);
> +    unsigned long prefix_family_length;
> +    if (state->first_row.first_time)
> +    {
> +        prefix_family_length = 0;
> +    }
> +    else
> +    {
> +        prefix_family_length = state->first_row.prefix_family_length;
> +    }
> +    bind_in[3].length = &prefix_family_length;
> +    bind_in[3].is_null = (my_bool *)0;
> +    // prefix_length parameter
> +    bind_in[4].buffer_type = MYSQL_TYPE_TINY;
> +    bind_in[4].buffer = &state->first_row.prefix_length;
> +    bind_in[4].is_unsigned = (my_bool)1;
> +    bind_in[4].is_null = (my_bool *)0;
> +    // prefix_max_length parameter
> +    bind_in[5].buffer_type = MYSQL_TYPE_TINY;
> +    bind_in[5].buffer = &state->first_row.prefix_max_length;
> +    bind_in[5].is_unsigned = (my_bool)1;
> +    bind_in[5].is_null = (my_bool *)0;
> +    // limit parameter
> +    bind_in[6].buffer_type = MYSQL_TYPE_LONGLONG;
> +    uint64_t limit = max_rows - num_pdus;
> +    bind_in[6].buffer = &limit;
> +    bind_in[6].is_unsigned = (my_bool) 1;
> +    bind_in[6].is_null = (my_bool *) 0;

~50 lines of almost purely identical code makes me sad.

>  
>      if (mysql_stmt_bind_param(stmt, bind_in))
>      {
> @@ -1199,18 +1199,30 @@ ssize_t db_rtr_reset_query_get_next(
>          return -1;
>      }
>  
> -    MYSQL_BIND bind_out[2];
> +    MYSQL_BIND bind_out[4];
>      uint32_t db_asn;
> -    char db_ip_addr[IPADDR_STR_LEN + 1];
> +    unsigned long db_prefix_family_length;
> +    uint8_t db_prefix[16];
> +    uint8_t db_prefix_length;
> +    uint8_t db_prefix_max_length;
>      memset(bind_out, 0, sizeof(bind_out));
>      // asn output
>      bind_out[0].buffer_type = MYSQL_TYPE_LONG;
>      bind_out[0].is_unsigned = 1;
>      bind_out[0].buffer = &db_asn;
> -    // ip_addr output
> -    bind_out[1].buffer_type = MYSQL_TYPE_STRING;
> -    bind_out[1].buffer_length = IPADDR_STR_LEN;
> -    bind_out[1].buffer = (char *)&db_ip_addr;
> +    // prefix output
> +    bind_out[1].buffer_type = MYSQL_TYPE_BLOB;
> +    bind_out[1].buffer_length = sizeof(db_prefix);
> +    bind_out[1].length = &db_prefix_family_length;
> +    bind_out[1].buffer = &db_prefix;
> +    // prefix_length output
> +    bind_out[2].buffer_type = MYSQL_TYPE_TINY;
> +    bind_out[2].is_unsigned = (my_bool)1;
> +    bind_out[2].buffer = &db_prefix_length;
> +    // prefix_max_length output
> +    bind_out[3].buffer_type = MYSQL_TYPE_TINY;
> +    bind_out[3].is_unsigned = (my_bool)1;
> +    bind_out[3].buffer = &db_prefix_max_length;

and this is also almost identical to an above hunk of code (with
similar issues)

>  
>      if (mysql_stmt_bind_result(stmt, bind_out))
>      {
> @@ -1240,8 +1252,12 @@ ssize_t db_rtr_reset_query_get_next(
>      int ret;
>      while ((ret = mysql_stmt_fetch(stmt)) == 0)
>      {
> -        if (fillPduIpPrefix(&((*_pdus)[num_pdus]), db_asn, db_ip_addr, 1     
>    /* , 
> -                                                                             
>     * state->session */ ))
> +        if (fillPduIpPrefix(
> +            &((*_pdus)[num_pdus]),
> +            db_asn,
> +            db_prefix, db_prefix_family_length,
> +            db_prefix_length, db_prefix_max_length,
> +            1))

more nearly identical code

>          {
>              LOG(LOG_ERR, "could not create PDU_IPVx_PREFIX");
>              mysql_stmt_free_result(stmt);
> @@ -1250,7 +1266,13 @@ ssize_t db_rtr_reset_query_get_next(
>              return -1;
>          }
>          ++num_pdus;
> -        ++state->first_row;
> +
> +        state->first_row.first_time = 0;
> +        state->first_row.asn = db_asn;
> +        state->first_row.prefix_family_length = db_prefix_family_length;
> +        memcpy(state->first_row.prefix, db_prefix, db_prefix_family_length);
> +        state->first_row.prefix_length = db_prefix_length;
> +        state->first_row.prefix_max_length = db_prefix_max_length;

more nearly identical code

-Richard

>      }
>      if (ret != 0 && ret != MYSQL_NO_DATA)
>      {
> diff --git a/lib/db/prep-stmt.c b/lib/db/prep-stmt.c
> index 214a9a6..a7a778d 100644
> --- a/lib/db/prep-stmt.c
> +++ b/lib/db/prep-stmt.c
> @@ -27,14 +27,20 @@ static const char *_queries_rtr[] = {
>          " from rtr_update " " where serial_num=?",
>  
>      // DB_PSTMT_RTR_SERIAL_QRY_GET_NEXT
> -    "select asn, ip_addr, is_announce "
> -        " from rtr_incremental "
> -        " where serial_num=? " " order by asn, ip_addr " " limit ?, ?",
> +    "select asn, prefix, prefix_length, prefix_max_length, is_announce "
> +    " from rtr_incremental "
> +    " where serial_num=? "
> +    "  and (? or (asn, prefix, prefix_length, prefix_max_length) > (?, ?, ?, 
> ?)) "
> +    " order by asn, prefix, prefix_length, prefix_max_length "
> +    " limit ?",
>  
>      // DB_PSTMT_RTR_RESET_QRY_GET_NEXT
> -    "select asn, ip_addr "
> -        " from rtr_full "
> -        " where serial_num=? " " order by asn, ip_addr " " limit ?, ?",
> +    "select asn, prefix, prefix_length, prefix_max_length "
> +    " from rtr_full "
> +    " where serial_num=? "
> +    "  and (? or (asn, prefix, prefix_length, prefix_max_length) > (?, ?, ?, 
> ?)) "
> +    " order by asn, prefix, prefix_length, prefix_max_length "
> +    " limit ?",
>  
>      // DB_PSTMT_RTR_COUNT_SESSION
>      "select count(*) from rtr_session",
> 


------------------------------------------------------------------------------
_______________________________________________
rpstir-devel mailing list
rpstir-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rpstir-devel

Reply via email to