Source File modules/nh/nh.c

    1    | /***************************************
    2    |   $Revision: 1.6 $
    3    |
    4    |   Status: NOT REVUED, NOT TESTED
    5    |
    6    |  Author(s):       Andrei Robachevsky
    7    |
    8    |   ******************/ /******************
    9    |   Modification History:
    10   |         andrei (10/04/2000) Created.
    11   |   ******************/ /******************
    12   |   Copyright (c) 2000                              RIPE NCC
    13   |
    14   |   All Rights Reserved
    15   |
    16   |   Permission to use, copy, modify, and distribute this software and its
    17   |   documentation for any purpose and without fee is hereby granted,
    18   |   provided that the above copyright notice appear in all copies and that
    19   |   both that copyright notice and this permission notice appear in
    20   |   supporting documentation, and that the name of the author not be
    21   |   used in advertising or publicity pertaining to distribution of the
    22   |   software without specific, written prior permission.
    23   |
    24   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
    25   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
    26   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
    27   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
    28   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    29   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    30   |  ***************************************/
    31   | #include <glib.h>
    32   | #include <stdio.h>
    33   | #include <strings.h>
    34   | #include <glib.h>
    35   | #include <stdlib.h>
    36   | #include <ctype.h>
    37   | #include <unistd.h>
    38   |
    39   | #include "nh.h"
    40   | #include <stubs.h>
    41   |
    42   | /*+ String sizes +*/
    43   | #define STR_S   63
    44   | #define STR_M   255
    45   | #define STR_L   1023
    46   | #define STR_XL  4095
    47   | #define STR_XXL 16383
    48   | #define STR_XXXL 65535
    49   |
    50   | /*
    51   | CREATE TABLE nic_hdl (
    52   |   thread_id(11) DEFAULT '0' NOT NULL,
    53   |   range_id int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
    54   |   range_start int(10) DEFAULT '0' NOT NULL,
    55   |   range_end int(10) DEFAULT '0' NOT NULL,
    56   |   space char(4) DEFAULT '' NOT NULL,
    57   |   source char(10) DEFAULT '' NOT NULL,
    58   |   PRIMARY KEY (range_id, range_start, range_end)
    59   | );
    60   |
    61   | */
    62   |
    63   | #define get_min_range(prange, sql_connection) get_range(MIN_NIC_ID, prange, sql_connection)
    64   | static long get_range(long nic_id, range_t *prange, SQ_connection_t *sql_connection);
    65   | static long update_range(long range_id, range_t *p_newrange, SQ_connection_t *sql_connection, int commit_now);
    66   | static long create_range(range_t *p_range, SQ_connection_t *sql_connection, int commit_now);
    67   |
    68   | /************************************************************
    69   | * int NH_convert()                                          *
    70   | *                                                           *
    71   | * Converts space & nic_id into a database nic-handle        *
    72   | *                                                           *
    73   | *                                                           *
    74   | * Returns:                                                  *
    75   | * The size of the nic_handle in characters                  *
    76   | *                                                           *
    77   | ************************************************************/
    78   | int NH_convert(char *nic, nic_handle_t *nh_ptr)
    79   | {
    80   |   /* Check for special cases */
    81   |   /* Is is and AUTO nic-handle ? */
    82   |   if(nh_ptr->nic_id == AUTO_NIC_ID) return(-1);
    83   |   if(nh_ptr->space) nic+=sprintf(nic, "%s", nh_ptr->space);
    84   |   /* No nic-id ? */
    85   |   if(nh_ptr->nic_id != NULL_NIC_ID) nic+=sprintf(nic, "%ld", nh_ptr->nic_id);
    86   |   /* No source ? */
    87   |   if (nh_ptr->source) sprintf(nic, "%s", nh_ptr->source);
    88   |   return(1);
    89   | }
    90   |
    91   | /************************************************************
    92   | * int NH_parse()                                            *
    93   | *                                                           *
    94   | * Parse a nic handle as supplied by DBupdate                *
    95   | * The format is: <space>[<nic_id>|*][SOURCE]                *
    96   | * Also extracts nic_id and space for regular nic-handles    *
    97   | *                                                           *
    98   | * Acceptable format is:                                     *
    99   | * [A-Z][A-Z]*[1-9][0-9]*(-[A-Z][A-Z]*)?                     *
    100  | *                                                           *
    101  | * Returns:                                                  *
    102  | * >0 - success                                              *
    103  | *  0 - AUTO NIC                                             *
    104  | * -1  - error (not defined and processed yet)               *
    105  | *                                                           *
    106  | ************************************************************/
    107  | int NH_parse(char *nic, nic_handle_t **nh_ptr_ptr)
    108  | {
    109  | char *ptr;
    110  | int res = 1;
    111  | nic_handle_t *nh_ptr;
    112  |
    113  |      if(!(nh_ptr=calloc(1, sizeof(nic_handle_t)))) die;
    114  |
    115  |      ptr=nic;
    116  |
    117  |      /* extract space */
    118  |      while(isalpha((int)*ptr))ptr++;
    119  |      if(!(nh_ptr->space=malloc(ptr-nic+1))) die;
    120  |      strncpy(nh_ptr->space, nic, ptr-nic); *(nh_ptr->space+(ptr-nic))='\0';
    121  |
    122  |      /* If there are no digits, then this is no nic-hdl */
    123  |      /* We reserve NULL_NIC_ID for such pretty identifiers */
    124  |      if(*ptr == '\0') {
    125  |        nh_ptr->nic_id=NULL_NIC_ID;
    126  |        nh_ptr->source=NULL;
    127  |      }
    128  |      else {
    129  |        /* Check if it is and AUTO nic */
    130  |        if (*ptr == '*') {
    131  | 	       /* For AUTO nic_id we reserve AUTO_NIC_ID */
    132  | 	       nh_ptr->nic_id=AUTO_NIC_ID;
    133  | 	       res=0;
    134  | 	       ptr++;
    135  |        } else {
    136  |          nic=ptr;
    137  | 	 /* convert digits (if any) and store first invalid characted in ptr */
    138  |          nh_ptr->nic_id=(int)strtol(nic, &ptr, 10);
    139  | 	 /* Check if there were any digits at all */
    140  | 	 if(ptr == nic) nh_ptr->nic_id=NULL_NIC_ID;
    141  |        }
    142  |        /* check if there is any suffix */
    143  |        if (*ptr == '\0') nh_ptr->source=NULL;
    144  |        /* Copy suffix into source */
    145  |        else {
    146  | 	 if(!(nh_ptr->source=malloc(strlen(ptr)+1))) die;
    147  | 	 strcpy(nh_ptr->source, ptr);
    148  |        }
    149  |      }
    150  |      *nh_ptr_ptr=nh_ptr;
    151  |      return(res);
    152  | }
    153  |
    154  |
    155  |
    156  | /************************************************************
    157  | * int NH_check()                                            *
    158  | *                                                           *
    159  | * Check a NIC handle in the repository                      *
    160  | *                                                           *
    161  | *                                                           *
    162  | * Returns:                                                  *
    163  | *  1 - success                                              *
    164  | *  0 - error(nic_id exists or space is fully occupied)      *
    165  | * -1 - error (f.e. more than one object with the same PK)   *
    166  | *                                                           *
    167  | ************************************************************/
    168  | int NH_check(nic_handle_t *nh_ptr, SQ_connection_t *sql_connection)
    169  | {
    170  | range_t range;
    171  | long range_id;
    172  | long nic_id=nh_ptr->nic_id;
    173  |
    174  |
    175  |   range.space=nh_ptr->space;
    176  |   if(nh_ptr->source)range.source=nh_ptr->source; else range.source="";
    177  |
    178  |   if (nic_id == AUTO_NIC_ID) {
    179  |   /* NIC handle is an AUTO one */
    180  |   /* get first range (with min range_end) for a given space */
    181  |    range_id = get_min_range(&range, sql_connection);
    182  |    if(range_id<0)  return(-1); /* in case of an error */
    183  |
    184  |    if ( range_id==0 ) {
    185  |   /* Nothing found */
    186  |   /* Allocate a hic-hdl in a new space with the first range {0-1} in it*/
    187  |  	nic_id=1;
    188  |    } else {
    189  |       if ( range.end == MAX_NIC_ID ) return(0); /* space is fully occupied  */
    190  |       /* attach to range and may be join with next */
    191  |        nic_id = range.end+1;
    192  |    }
    193  |   }
    194  | /* if not AUTO */
    195  |   else {
    196  |     range_id = get_range(nic_id, &range, sql_connection);
    197  |     if(range_id <0)  return(-1); /* in case of an error */
    198  |     if(range_id!=0)  return(0); /* this nic_id already exists */
    199  |   }
    200  |   nh_ptr->nic_id=nic_id;
    201  |  return(1);
    202  | }
    203  |
    204  | /************************************************************
    205  | * long NH_free()                                             *
    206  | *                                                           *
    207  | * Delete a NIC handle from the repository                   *
    208  | *                                                           *
    209  | * To finalize changes make commit/rollback                  *
    210  | *                                                           *
    211  | * Returns:                                                  *
    212  | *  1 - success                                              *
    213  | *  0 - error (range is not founnd)                          *
    214  | * -1 - error (f.e. more than one object with the same PK)   *
    215  | *                                                           *
    216  | ************************************************************/
    217  | int NH_free(nic_handle_t *nh_ptr, SQ_connection_t *sql_connection, int commit_now)
    218  | {
    219  | range_t range;
    220  | long range_id;
    221  | int old_start;
    222  | long nic_id=nh_ptr->nic_id;
    223  |
    224  |
    225  |   range.space=nh_ptr->space;
    226  |   if(nh_ptr->source)range.source=nh_ptr->source; else range.source="";
    227  |
    228  |   /* Search for the range containing the nic-handle */
    229  |   range_id = get_range(nic_id, &range, sql_connection);
    230  |   /* If range is not found or an error occcured - return */
    231  |   if(range_id==0) { return(0); }
    232  |   if(range_id<0)  { return(-1); }
    233  |
    234  |   if(nic_id == range.start) {
    235  |   /* update range start and may be detele range and space */
    236  |    range.start+=1;
    237  |    range_id=update_range(range_id, &range, sql_connection, commit_now);
    238  |    if(range_id<=0) {  return(-1); }
    239  |   }
    240  |   else if(nic_id == range.end) {
    241  |   /* update range end and may be detele range and space */
    242  |          range.end-=1;
    243  |          range_id=update_range(range_id, &range, sql_connection, commit_now);
    244  | 	 if(range_id<=0) {  return(-1); }
    245  |   }
    246  |   else {
    247  |        /* split the range into two */
    248  |        /* shrink the old one */
    249  |          old_start=range.start;
    250  |          range.start=nic_id+1;
    251  |          range_id=update_range(range_id, &range, sql_connection, commit_now);
    252  | 	 if(range_id<=0) { return(-1); }
    253  |        /* create a new one */
    254  |          range.start=old_start;
    255  |          range.end=nic_id-1;
    256  |          range_id=create_range(&range, sql_connection, commit_now);
    257  | 	 if(range_id<=0) {  return(-1); }
    258  |   }
    259  |
    260  |   return(1);
    261  | }
    262  |
    263  |
    264  | /************************************************************
    265  | * int NH_register()                                         *
    266  | *                                                           *
    267  | * Get a NIC handle from the repository                      *
    268  | *                                                           *
    269  | *                                                           *
    270  | * Returns:                                                  *
    271  | * 1 - success                                               *
    272  | * 0  - nic_id already exists or space is fully occupied     *
    273  | * -1 - error (f.e. more than one object with the same PK)   *
    274  | *                                                           *
    275  | ************************************************************/
    276  | int NH_register(nic_handle_t *nh_ptr, SQ_connection_t *sql_connection, int commit_now)
    277  | {
    278  | range_t range;
    279  | long range_id;
    280  | long nic_id=nh_ptr->nic_id;
    281  |
    282  |
    283  |
    284  |
    285  |  /* Yiu should check for nh first for AUTO nic-handles */
    286  |   if (nic_id == AUTO_NIC_ID) { return(0); };
    287  |
    288  |   range.space=nh_ptr->space;
    289  |   if(nh_ptr->source)range.source=nh_ptr->source; else range.source="";
    290  |
    291  |   range_id = get_range(nic_id, &range, sql_connection);
    292  |   if(range_id <0)  { return(-1); } /* in case of an error */
    293  |   if(range_id!=0)  { return(0); } /* this nic_id already exists */
    294  |
    295  |   /* check if we can attach to existing next range */
    296  |   range_id = get_range(nic_id+1, &range, sql_connection);
    297  |   if(range_id <0)  { return(-1); } /* in case of an error */
    298  |
    299  |     if( range_id>0 ) {
    300  |     /* attach to range and may be join with previous */
    301  |      range.start-=1;
    302  |      range_id=update_range(range_id, &range, sql_connection, commit_now);
    303  |      if(range_id<=0) { return(-1); }
    304  |     }
    305  |     else {
    306  |      /* check if we can attach to existing previous range */
    307  |       if(nic_id>0) range_id = get_range(nic_id-1, &range, sql_connection);
    308  |       else range_id=0; /* there is no previous range in this case (nic_id==0) */
    309  |       if(range_id <0)  { return(-1); } /* in case of an error */
    310  |       if( range_id>0 ) {
    311  |       /* attach to range and may be join with next */
    312  |        range.end+=1;
    313  |        range_id=update_range(range_id, &range, sql_connection, commit_now);
    314  |        if(range_id<=0) { return(-1); }
    315  |       }
    316  |       else {
    317  |        /* If we cannot attach to any existing range - create new {nic_id-nic_id} */
    318  |        range.end=range.start=nic_id;
    319  |        range_id=create_range(&range, sql_connection, commit_now);
    320  |        if(range_id <=0)  { return(-1); } /* in case of an error */
    321  |       }
    322  |     }
    323  |  return(1);
    324  | }
    325  |
    326  | /*
    327  |  Free nic_handle_t structure
    328  |  */
    329  | void free_nh(nic_handle_t *nh_ptr)
    330  | {
    331  |  if(nh_ptr){
    332  |    if(nh_ptr->space)free(nh_ptr->space);
    333  |    if(nh_ptr->source)free(nh_ptr->source);
    334  |    free(nh_ptr);
    335  |  }
    336  | }
    337  |
    338  |
    339  | /************************************************************
    340  | * long get_range()                                          *
    341  | *                                                           *
    342  | * Searches for the range of the space containing            *
    343  | * the specified nic_id                                      *
    344  | *                                                           *
    345  | * To request to search for the firt (min) range, nic_id     *
    346  | * should be set to MIN_NIC_ID                               *
    347  | *                                                           *
    348  | * Returns:                                                  *
    349  | * >0 - range exists, returns range_id                       *
    350  | * 0  - range does not exist                                 *
    351  | * -1 - DB error (f.e. more than one object with the same PK)*
    352  | *                                                           *
    353  | * **********************************************************/
    354  | static long get_range(long nic_id, range_t *prange, SQ_connection_t *sql_connection)
    355  | {
    356  | SQ_result_set_t *sql_result;
    357  | SQ_row_t *sql_row;
    358  | char *sql_str;
    359  | GString *query;
    360  | long range_id=0;
    361  | int sql_err;
    362  |
    363  |  if ((query = g_string_sized_new(STR_L)) == NULL){
    364  |   fprintf(stderr, "E: cannot allocate gstring\n");
    365  |   return(-1);
    366  |  }
    367  |
    368  | /* Define row numbers in the result of the query */
    369  | #define RANGE_ID 0
    370  | #define RANGE_START 1
    371  | #define RANGE_END 2
    372  |
    373  |  if (nic_id==MIN_NIC_ID) {
    374  |   /* requesting the first (min) range */
    375  |   g_string_sprintf(query, "SELECT range_id, range_start, range_end "
    376  |                           "FROM nic_hdl "
    377  |                           "WHERE space='%s' "
    378  | 			  "AND source='%s' "
    379  |                           "AND (range_start=0 "
    380  |                           "OR  range_start=1) ",
    381  | 			  prange->space, prange->source);
    382  |  } else {
    383  |
    384  |   g_string_sprintf(query, "SELECT range_id, range_start, range_end "
    385  |                           "FROM nic_hdl "
    386  |                           "WHERE space='%s' "
    387  | 			  "AND source='%s' "
    388  |                           "AND range_start<=%ld "
    389  |                           "AND range_end>=%ld ",
    390  | 			  prange->space, prange->source, nic_id, nic_id);
    391  |  }
    392  |
    393  | /* execute query */
    394  | /* fprintf(stderr, "get_range[%s]\n", query->str); */
    395  |  sql_err=SQ_execute_query(sql_connection, query->str, &sql_result);
    396  |  g_string_free(query, TRUE);
    397  |
    398  |  if(sql_err) {
    399  |    fprintf(stderr,"ERROR: %s\n", SQ_error(sql_connection));
    400  |    return(-1);
    401  |  }
    402  |
    403  |  if ((sql_row = SQ_row_next(sql_result)) != NULL) {
    404  | /* Object exists */
    405  |    sql_str = SQ_get_column_string(sql_result, sql_row, RANGE_ID);
    406  |    if (sql_str != NULL) {
    407  |      range_id = atol(sql_str);
    408  |      free(sql_str);
    409  |    }
    410  |    sql_str = SQ_get_column_string(sql_result, sql_row, RANGE_START);
    411  |    if (sql_str != NULL) {
    412  |      prange->start = atoi(sql_str);
    413  |      free(sql_str);
    414  |    }
    415  |    sql_str = SQ_get_column_string(sql_result, sql_row, RANGE_END);
    416  |    if (sql_str != NULL) {
    417  |      prange->end = atoi(sql_str);
    418  |      free(sql_str);
    419  |    }
    420  |
    421  | /* We must process all the rows of the result */
    422  | /* otherwise we'll have them as part of the next qry */
    423  |    while ( (sql_row = SQ_row_next(sql_result)) != NULL) range_id=-1;
    424  |  } else
    425  |       range_id=0;  // object does not exist
    426  |
    427  |  if(sql_result)SQ_free_result(sql_result);
    428  |  return(range_id);
    429  | }
    430  |
    431  |
    432  |
    433  |
    434  | /************************************************************
    435  | * long update_range()                                       *
    436  | *                                                           *
    437  | * Updates the range by changing the boundaries              *
    438  | * Deletes the range if nothing left                         *
    439  | * Merges with neighbor ranges if there is no gap between    *
    440  | *                                                           *
    441  | * We never update range. We create a new one with specified *
    442  | * limits and mark old one(s) for deletion, so that we can   *
    443  | * make commit/rollback properly. This is possible as the    *
    444  | * primary keys are (range_id, range_start, range_end)       *
    445  | *                                                           *
    446  | * To finalize changes make commit/rollback                  *
    447  | *                                                           *
    448  | * Returns:                                                  *
    449  | * >0 - returns range_id on success                          *
    450  | * -1 - error (f.e. more than one object with the same PK)   *
    451  | *                                                           *
    452  | ************************************************************/
    453  |
    454  | static long update_range(long range_id, range_t *p_newrange, SQ_connection_t *sql_connection, int commit_now)
    455  | {
    456  | GString *query;
    457  | range_t range;
    458  | long prev_range_id, next_range_id;
    459  | int num;
    460  | int sql_err;
    461  |
    462  | /* Allocate memory */
    463  |  if ((query = g_string_sized_new(STR_L)) == NULL){
    464  |   fprintf(stderr, "E: cannot allocate gstring\n");
    465  |   return(-1);
    466  |  }
    467  |
    468  | /* Do range check */
    469  |  if (( p_newrange->end > MAX_RANGE ) || ( p_newrange->start < MIN_RANGE )) return(-1);
    470  |
    471  | /* Check if the range collapses */
    472  |  if ( p_newrange->end < p_newrange->start ) {
    473  |  /* then delete the range */
    474  |  /* Do this by marking the range for deletion for further commit/rollback */
    475  |   if(commit_now)
    476  |    g_string_sprintf(query, "DELETE FROM nic_hdl "
    477  |                            "WHERE range_id=%ld ",
    478  |                             range_id);
    479  |   else
    480  |    g_string_sprintf(query, "UPDATE nic_hdl SET thread_id=%d "
    481  |                            "WHERE range_id=%ld ",
    482  | 			    NH_DELETE, range_id);
    483  |
    484  | /*   fprintf(stderr, "update_range[%s]\n", query->str); */
    485  |    sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
    486  |    if(sql_err) {
    487  |     /* An error occured */
    488  |     g_string_free(query, TRUE);
    489  |     return(-1);
    490  |    }
    491  |    num = mysql_affected_rows(sql_connection);
    492  |    /* this should not happen */
    493  |    if(num==0) die;
    494  |
    495  |  }
    496  |  else {
    497  |   /* update the range for the same space/source */
    498  |   range.space=p_newrange->space;
    499  |   range.source=p_newrange->source;
    500  |   /* Check if we can join with previous range of the same space */
    501  |   prev_range_id=get_range(p_newrange->start-1, &range, sql_connection);
    502  |   /* Check if such range exists and it is not ours (this happens when we are shrinking */
    503  |   if((prev_range_id>0) && (prev_range_id!=range_id)) {
    504  |    /* acquire the previous range */
    505  |    /* mark it for deletion for commit/rollback */
    506  |    if(commit_now)
    507  |       g_string_sprintf(query, "DELETE FROM nic_hdl "
    508  |                               "WHERE range_id=%ld ",
    509  |                                prev_range_id);
    510  |    else
    511  |       g_string_sprintf(query, "UPDATE nic_hdl SET thread_id=%d "
    512  |                               "WHERE range_id=%ld ",
    513  | 			       NH_DELETE, prev_range_id);
    514  |
    515  |
    516  |
    517  | /*    fprintf(stderr, "update_range[%s]\n", query->str); */
    518  |    sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
    519  |    if(sql_err) {
    520  |     /* An error occured */
    521  |     g_string_free(query, TRUE);
    522  |     return(-1);
    523  |    }
    524  |    num = mysql_affected_rows(sql_connection);
    525  |    /* this should not happen */
    526  |    if(num==0) die;
    527  |
    528  |    /* expand the boundaries */
    529  |    p_newrange->start=range.start;
    530  |   }
    531  |
    532  | /* Check if we can join with next range of the same space */
    533  |   next_range_id=get_range(p_newrange->end+1, &range, sql_connection);
    534  |   /* Check if such range exists and it is not ours (this happens when we are shrinking) */
    535  |   if((next_range_id>0) && (next_range_id!=range_id)) {
    536  |    /* acquire the next range */
    537  |    /* mark it for deletion for commit/rollback */
    538  |    if(commit_now)
    539  |      g_string_sprintf(query, "DELETE FROM nic_hdl "
    540  |                              "WHERE range_id=%ld ",
    541  |                               next_range_id);
    542  |    else
    543  |      g_string_sprintf(query, "UPDATE nic_hdl SET thread_id=%d "
    544  |                              "WHERE range_id=%ld ",
    545  | 			      NH_DELETE, next_range_id);
    546  |
    547  |
    548  |
    549  | /*   fprintf(stderr, "update_range[%s]\n", query->str); */
    550  |    sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
    551  |    if(sql_err) {
    552  |     /* An error occured */
    553  |     g_string_free(query, TRUE);
    554  |     return(-1);
    555  |    }
    556  |    num = mysql_affected_rows(sql_connection);
    557  |    /* this should not happen */
    558  |    if(num==0) die;
    559  |
    560  |    /* expand the boundaries */
    561  |    p_newrange->end=range.end;
    562  |   }
    563  |
    564  | /* Now make a larger range. Mark current for deletion and new for commit/rollback */
    565  |   if(commit_now)
    566  |    g_string_sprintf(query, "UPDATE nic_hdl "
    567  |                            "SET range_start=%ld, range_end=%ld "
    568  | 			   "WHERE range_id=%ld",
    569  |                            p_newrange->start, p_newrange->end, range_id);
    570  |   else {
    571  |
    572  |    g_string_sprintf(query, "UPDATE nic_hdl SET thread_id=%d "
    573  |                            "WHERE range_id=%ld ",
    574  | 			   NH_DELETE, range_id);
    575  | /*   fprintf(stderr, "update_range[%s]\n", query->str); */
    576  |    sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
    577  |    if(sql_err) {
    578  |     /* An error occured */
    579  |     g_string_free(query, TRUE);
    580  |     return(-1);
    581  |    }
    582  |    num = mysql_affected_rows(sql_connection);
    583  |    /* this should not happen */
    584  |    if(num==0) die;
    585  |
    586  |    g_string_sprintf(query, "INSERT nic_hdl "
    587  |                            "SET thread_id=%d, range_id=%ld, space='%s', source='%s', range_start=%ld, range_end=%ld ",
    588  |                            NH_INSERT, range_id, p_newrange->space, p_newrange->source, p_newrange->start, p_newrange->end);
    589  |   }
    590  |
    591  | /*   fprintf(stderr, "update_range[%s]\n", query->str); */
    592  |    sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
    593  |    if(sql_err) {
    594  |     /* An error occured */
    595  |     g_string_free(query, TRUE);
    596  |     return(-1);
    597  |    }
    598  |    num = mysql_affected_rows(sql_connection);
    599  |    /* this should not happen */
    600  |    if(num==0) die;
    601  |  } /* update the range */
    602  |
    603  |  g_string_free(query, TRUE);
    604  |  return (range_id);
    605  | }
    606  |
    607  | /************************************************************
    608  | * long create_range()                                       *
    609  | *                                                           *
    610  | * Creates a new range in a given name space                 *
    611  | *                                                           *
    612  | * To finalize changes make commit/rollback                  *
    613  | *                                                           *
    614  | * Returns:                                                  *
    615  | * >0 - returns range_id on success                          *
    616  | * -1 - error (f.e. more than one object with the same PK)   *
    617  | *                                                           *
    618  | ************************************************************/
    619  |
    620  | static long create_range(range_t *p_range, SQ_connection_t *sql_connection, int commit_now)
    621  | {
    622  | GString *query;
    623  | int sql_err, num;
    624  |
    625  |  /* Allocate memory */
    626  |  if ((query = g_string_sized_new(STR_L)) == NULL){
    627  |   fprintf(stderr, "E: cannot allocate gstring\n");
    628  |   return(-1);
    629  |  }
    630  |
    631  |  if(commit_now)
    632  |   g_string_sprintf(query, "INSERT nic_hdl "
    633  |                           "SET thread_id=0, space='%s', source='%s', range_start=%ld, range_end=%ld ",
    634  |                            p_range->space, p_range->source, p_range->start, p_range->end);
    635  |  else
    636  |   g_string_sprintf(query, "INSERT nic_hdl "
    637  |                           "SET thread_id=%d, space='%s', source='%s', range_start=%ld, range_end=%ld ",
    638  |                            NH_INSERT, p_range->space, p_range->source, p_range->start, p_range->end);
    639  |
    640  | /* fprintf(stderr, "create_range[%s]\n", query->str); */
    641  |  sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
    642  |  g_string_free(query, TRUE);
    643  |
    644  |    if(sql_err) {
    645  |     /* An error occured */
    646  |     return(-1);
    647  |    }
    648  |    num = mysql_affected_rows(sql_connection);
    649  |    /* this should not happen */
    650  |    if(num==0) die;
    651  |  return(mysql_insert_id(sql_connection));
    652  | }
    653  |
    654  |
    655  | /************************************************************
    656  | * int NH_comrol()                                           *
    657  | *                                                           *
    658  | * Commits or rolls back changes to NHR                      *
    659  | *                                                           *
    660  | *                                                           *
    661  | * Returns:                                                  *
    662  | * >0 - success                                              *
    663  | * -1 - SQL error                                            *
    664  | *                                                           *
    665  | ************************************************************/
    666  |
    667  | int NH_comrol(SQ_connection_t *sql_connection, int thread_ins, int thread_del)
    668  | {
    669  | GString *query;
    670  | int sql_err;
    671  |
    672  |  /* Allocate memory */
    673  |  if ((query = g_string_sized_new(STR_L)) == NULL){
    674  |   fprintf(stderr, "E: cannot allocate gstring\n");
    675  |   return(-1);
    676  |  }
    677  |
    678  |   g_string_sprintf(query, "DELETE FROM nic_hdl "
    679  | 			  "WHERE thread_id=%d ",
    680  |                           thread_del);
    681  |
    682  | /* fprintf(stderr, "create_range[%s]\n", query->str); */
    683  |  sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
    684  |  if(sql_err) {
    685  |     /* An error occured */
    686  |     g_string_free(query, TRUE);
    687  |     fprintf(stderr,"ERROR: %s\n", SQ_error(sql_connection));
    688  |     die;
    689  |  }
    690  |
    691  |  g_string_sprintf(query, "UPDATE nic_hdl "
    692  |                          "SET thread_id=0 "
    693  | 			 "WHERE thread_id=%d ",
    694  |                           thread_ins);
    695  |
    696  | /* fprintf(stderr, "create_range[%s]\n", query->str); */
    697  |  sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
    698  |  g_string_free(query, TRUE);
    699  |
    700  |  if(sql_err) {
    701  |     /* An error occured */
    702  |    fprintf(stderr,"ERROR: %s\n", SQ_error(sql_connection));
    703  |    die;
    704  |  }
    705  |
    706  |  return(1);
    707  |
    708  | }
    709  |
    710  |