Source File nh/nh.c

    1    | /***************************************
    2    |   $Revision: 1.16 $
    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,2001,2002                    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   |
    32   | #include "rip.h"
    33   |
    34   | #include <glib.h>
    35   | #include <stdio.h>
    36   | #include <strings.h>
    37   | #include <glib.h>
    38   | #include <stdlib.h>
    39   | #include <ctype.h>
    40   | #include <unistd.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   | * Returns:                                                  *
    74   | * The newly allocated string containing nic handle          *
    75   | * The string should be freed when no longer used            *
    76   | *                                                           *
    77   | * NULL in case of failure                                   *
    78   | *                                                           *
    79   | ************************************************************/
    80   | char *NH_convert(nic_handle_t *nh_ptr)
    81   | {
    82   |  char *nic_id=NULL;
    83   |  char *nic_components[4];
    84   |  char *nic_handle;
    85   |  int nc=0;
    86   |   /* Check for special cases */
    87   |   /* Is is and AUTO nic-handle ? */
    88   |   if(nh_ptr->nic_id == AUTO_NIC_ID) return(NULL);
    89   |   if(nh_ptr->space) {
    90   | 	  nic_components[nc]=nh_ptr->space; nc++;
    91   |   }
    92   |   /* No nic-id ? */
    93   |   if(nh_ptr->nic_id != NULL_NIC_ID) {
    94   | 	  nic_id = g_strdup_printf("%ld", nh_ptr->nic_id);
    95   | 	  nic_components[nc]=nic_id; nc++;
    96   |   }
    97   |
    98   |   /* No source ? */
    99   |   if (nh_ptr->source) {
    100  | 	  nic_components[nc]=nh_ptr->source; nc++;
    101  |   }
    102  |   nic_components[nc]=NULL;
    103  |   nic_handle = g_strjoinv(NULL, nic_components);
    104  |   UT_free(nic_id);
    105  |   return(nic_handle);
    106  | }
    107  |
    108  | /************************************************************
    109  | * int NH_parse()                                            *
    110  | *                                                           *
    111  | * Parse a nic handle as supplied by DBupdate                *
    112  | * The format is: <space>[<nic_id>|*][SOURCE]                *
    113  | * Also extracts nic_id and space for regular nic-handles    *
    114  | *                                                           *
    115  | * Acceptable format is:                                     *
    116  | * [A-Z][A-Z]*[1-9][0-9]*(-[A-Z][A-Z]*)?                     *
    117  | *                                                           *
    118  | * Returns:                                                  *
    119  | * >0 - success                                              *
    120  | *  0 - AUTO NIC                                             *
    121  | * -1  - error                                               *
    122  | *                                                           *
    123  | ************************************************************/
    124  | int NH_parse(const char *nic, nic_handle_t **nh_ptr_ptr)
    125  | {
    126  | const char *ptr;
    127  | int res = 1;
    128  | nic_handle_t *nh_ptr;
    129  |
    130  |      *nh_ptr_ptr=NULL;
    131  |      if(!(nh_ptr=UT_calloc(1, sizeof(nic_handle_t)))) die;
    132  |
    133  |      ptr=nic;
    134  |
    135  |      /* extract space */
    136  |      while(isalpha((int)*ptr))ptr++;
    137  |
    138  |      /* sanity check - space <=4 characters */
    139  |      if((ptr-nic)>MAX_NH_SPACE_LENGTH) {
    140  |        UT_free(nh_ptr);
    141  |        return(-1);
    142  |      }
    143  |
    144  |      if(!(nh_ptr->space=UT_malloc(ptr-nic+1))) die;
    145  |      strncpy(nh_ptr->space, nic, ptr-nic); *(nh_ptr->space+(ptr-nic))='\0';
    146  |
    147  |      /* If there are no digits, then this is no nic-hdl */
    148  |      /* We reserve NULL_NIC_ID for such pretty identifiers */
    149  |      if(*ptr == '\0') {
    150  |        nh_ptr->nic_id=NULL_NIC_ID;
    151  |        nh_ptr->source=NULL;
    152  |      }
    153  |      else {
    154  |        /* Check if it is and AUTO nic */
    155  |        if (*ptr == '*') {
    156  | 	       /* For AUTO nic_id we reserve AUTO_NIC_ID */
    157  | 	       nh_ptr->nic_id=AUTO_NIC_ID;
    158  | 	       res=0;
    159  | 	       ptr++;
    160  |        } else {
    161  |          nic=ptr;
    162  | 	 /* convert digits (if any) and store first invalid characted in ptr */
    163  |          if(isdigit((int)*nic)){
    164  |              nh_ptr->nic_id=(int)strtol(nic, (char **)&ptr, 10);
    165  |          } else {
    166  | 	     /* There were no digits at all */
    167  | 	     nh_ptr->nic_id=NULL_NIC_ID;
    168  |          }
    169  |        }
    170  |        /* sanity check - if the ID does not exeed NH_MAX_ID */
    171  |        if(nh_ptr->nic_id > MAX_NIC_ID) {
    172  |          if(nh_ptr) {
    173  |            UT_free(nh_ptr->space);UT_free(nh_ptr);
    174  |          }
    175  |          return(-1);
    176  |        }
    177  |        /* check if there is any suffix */
    178  |        if (*ptr == '\0') nh_ptr->source=NULL;
    179  |        /* Copy suffix into source */
    180  |        else {
    181  |          /* sanity check - suffix does not exceed the length */
    182  |          if(strlen(ptr)>MAX_NH_SOURCE_LENGTH) {
    183  |              if(nh_ptr){
    184  |                UT_free(nh_ptr->space);UT_free(nh_ptr);
    185  |              }
    186  |              return(-1);
    187  |          }
    188  | 	 if(!(nh_ptr->source=UT_malloc(strlen(ptr)+1))) die;
    189  | 	 strcpy(nh_ptr->source, ptr);
    190  |        }
    191  |      }
    192  |      *nh_ptr_ptr=nh_ptr;
    193  |      return(res);
    194  | }
    195  |
    196  |
    197  |
    198  | /************************************************************
    199  | * int NH_check()                                            *
    200  | *                                                           *
    201  | * Check a NIC handle in the repository                      *
    202  | *                                                           *
    203  | *                                                           *
    204  | * Returns:                                                  *
    205  | *  1 - success                                              *
    206  | *  0 - error(nic_id exists or space is fully occupied)      *
    207  | * -1 - error (f.e. more than one object with the same PK)   *
    208  | *                                                           *
    209  | ************************************************************/
    210  | int NH_check(nic_handle_t *nh_ptr, SQ_connection_t *sql_connection)
    211  | {
    212  | range_t range;
    213  | long range_id;
    214  | long nic_id=nh_ptr->nic_id;
    215  |
    216  |
    217  |   range.space=nh_ptr->space;
    218  |   if(nh_ptr->source)range.source=nh_ptr->source; else range.source="";
    219  |
    220  |   if (nic_id == AUTO_NIC_ID) {
    221  |   /* NIC handle is an AUTO one */
    222  |   /* get first range (with min range_end) for a given space */
    223  |    range_id = get_min_range(&range, sql_connection);
    224  |    if(range_id<0)  return(-1); /* in case of an error */
    225  |
    226  |    if ( range_id==0 ) {
    227  |   /* Nothing found */
    228  |   /* Allocate a hic-hdl in a new space with the first range {0-1} in it*/
    229  |  	nic_id=1;
    230  |    } else {
    231  |       if ( range.end == MAX_NIC_ID ) return(0); /* space is fully occupied  */
    232  |       /* attach to range and may be join with next */
    233  |        nic_id = range.end+1;
    234  |    }
    235  |   }
    236  | /* if not AUTO */
    237  |   else {
    238  |     range_id = get_range(nic_id, &range, sql_connection);
    239  |     if(range_id <0)  return(-1); /* in case of an error */
    240  |     if(range_id!=0)  return(0); /* this nic_id already exists */
    241  |   }
    242  |   nh_ptr->nic_id=nic_id;
    243  |  return(1);
    244  | }
    245  |
    246  | /************************************************************
    247  | * long NH_free()                                             *
    248  | *                                                           *
    249  | * Delete a NIC handle from the repository                   *
    250  | *                                                           *
    251  | * To finalize changes make commit/rollback                  *
    252  | *                                                           *
    253  | * Returns:                                                  *
    254  | *  1 - success                                              *
    255  | *  0 - error (range is not founnd)                          *
    256  | * -1 - error (f.e. more than one object with the same PK)   *
    257  | *                                                           *
    258  | ************************************************************/
    259  | int NH_free(nic_handle_t *nh_ptr, SQ_connection_t *sql_connection, int commit_now)
    260  | {
    261  | range_t range;
    262  | long range_id;
    263  | int old_start;
    264  | long nic_id=nh_ptr->nic_id;
    265  |
    266  |
    267  |   range.space=nh_ptr->space;
    268  |   if(nh_ptr->source)range.source=nh_ptr->source; else range.source="";
    269  |
    270  |   /* Search for the range containing the nic-handle */
    271  |   range_id = get_range(nic_id, &range, sql_connection);
    272  |   /* If range is not found or an error occcured - return */
    273  |   if(range_id==0) { return(0); }
    274  |   if(range_id<0)  { return(-1); }
    275  |
    276  |   if(nic_id == range.start) {
    277  |   /* update range start and may be detele range and space */
    278  |    range.start+=1;
    279  |    range_id=update_range(range_id, &range, sql_connection, commit_now);
    280  |    if(range_id<=0) {  return(-1); }
    281  |   }
    282  |   else if(nic_id == range.end) {
    283  |   /* update range end and may be detele range and space */
    284  |          range.end-=1;
    285  |          range_id=update_range(range_id, &range, sql_connection, commit_now);
    286  | 	 if(range_id<=0) {  return(-1); }
    287  |   }
    288  |   else {
    289  |        /* split the range into two */
    290  |        /* shrink the old one */
    291  |          old_start=range.start;
    292  |          range.start=nic_id+1;
    293  |          range_id=update_range(range_id, &range, sql_connection, commit_now);
    294  | 	 if(range_id<=0) { return(-1); }
    295  |        /* create a new one */
    296  |          range.start=old_start;
    297  |          range.end=nic_id-1;
    298  |          range_id=create_range(&range, sql_connection, commit_now);
    299  | 	 if(range_id<=0) {  return(-1); }
    300  |   }
    301  |
    302  |   return(1);
    303  | }
    304  |
    305  |
    306  | /************************************************************
    307  | * int NH_register()                                         *
    308  | *                                                           *
    309  | * Get a NIC handle from the repository                      *
    310  | *                                                           *
    311  | *                                                           *
    312  | * Returns:                                                  *
    313  | * 1 - success                                               *
    314  | * 0  - nic_id already exists or space is fully occupied     *
    315  | * -1 - error (f.e. more than one object with the same PK)   *
    316  | *                                                           *
    317  | ************************************************************/
    318  | int NH_register(nic_handle_t *nh_ptr, SQ_connection_t *sql_connection, int commit_now)
    319  | {
    320  | range_t range;
    321  | long range_id;
    322  | long nic_id=nh_ptr->nic_id;
    323  |
    324  |
    325  |
    326  |
    327  |  /* Yiu should check for nh first for AUTO nic-handles */
    328  |   if (nic_id == AUTO_NIC_ID) { return(0); };
    329  |
    330  |   range.space=nh_ptr->space;
    331  |   if(nh_ptr->source)range.source=nh_ptr->source; else range.source="";
    332  |
    333  |   range_id = get_range(nic_id, &range, sql_connection);
    334  |   if(range_id <0)  { return(-1); } /* in case of an error */
    335  |   if(range_id!=0)  { return(0); } /* this nic_id already exists */
    336  |
    337  |   /* check if we can attach to existing next range */
    338  |   range_id = get_range(nic_id+1, &range, sql_connection);
    339  |   if(range_id <0)  { return(-1); } /* in case of an error */
    340  |
    341  |     if( range_id>0 ) {
    342  |     /* attach to range and may be join with previous */
    343  |      range.start-=1;
    344  |      range_id=update_range(range_id, &range, sql_connection, commit_now);
    345  |      if(range_id<=0) { return(-1); }
    346  |     }
    347  |     else {
    348  |      /* check if we can attach to existing previous range */
    349  |       if(nic_id>0) range_id = get_range(nic_id-1, &range, sql_connection);
    350  |       else range_id=0; /* there is no previous range in this case (nic_id==0) */
    351  |       if(range_id <0)  { return(-1); } /* in case of an error */
    352  |       if( range_id>0 ) {
    353  |       /* attach to range and may be join with next */
    354  |        range.end+=1;
    355  |        range_id=update_range(range_id, &range, sql_connection, commit_now);
    356  |        if(range_id<=0) { return(-1); }
    357  |       }
    358  |       else {
    359  |        /* If we cannot attach to any existing range - create new {nic_id-nic_id} */
    360  |        range.end=range.start=nic_id;
    361  |        range_id=create_range(&range, sql_connection, commit_now);
    362  |        if(range_id <=0)  { return(-1); } /* in case of an error */
    363  |       }
    364  |     }
    365  |  return(1);
    366  | }
    367  |
    368  | /*
    369  |  Free nic_handle_t structure
    370  |  */
    371  | void free_nh(nic_handle_t *nh_ptr)
    372  | {
    373  |  if(nh_ptr){
    374  |    if(nh_ptr->space) UT_free(nh_ptr->space);
    375  |    if(nh_ptr->source) UT_free(nh_ptr->source);
    376  |    UT_free(nh_ptr);
    377  |  }
    378  | }
    379  |
    380  |
    381  | /************************************************************
    382  | * long get_range()                                          *
    383  | *                                                           *
    384  | * Searches for the range of the space containing            *
    385  | * the specified nic_id                                      *
    386  | *                                                           *
    387  | * To request to search for the firt (min) range, nic_id     *
    388  | * should be set to MIN_NIC_ID                               *
    389  | *                                                           *
    390  | * Returns:                                                  *
    391  | * >0 - range exists, returns range_id                       *
    392  | * 0  - range does not exist                                 *
    393  | * -1 - DB error (f.e. more than one object with the same PK)*
    394  | *                                                           *
    395  | * **********************************************************/
    396  | static long get_range(long nic_id, range_t *prange, SQ_connection_t *sql_connection)
    397  | {
    398  | SQ_result_set_t *sql_result;
    399  | SQ_row_t *sql_row;
    400  | char *sql_str;
    401  | GString *query;
    402  | long range_id=0;
    403  | int sql_err;
    404  |
    405  |  query = g_string_sized_new(STR_L);
    406  |
    407  | /* Define row numbers in the result of the query */
    408  | #define RANGE_ID 0
    409  | #define RANGE_START 1
    410  | #define RANGE_END 2
    411  |
    412  |  if (nic_id==MIN_NIC_ID) {
    413  |   /* requesting the first (min) range */
    414  |   g_string_sprintf(query, "SELECT range_id, range_start, range_end "
    415  |                           "FROM nic_hdl "
    416  |                           "WHERE space='%s' "
    417  | 			  "AND source='%s' "
    418  |                           "AND (range_start=0 "
    419  |                           "OR  range_start=1) ",
    420  | 			  prange->space, prange->source);
    421  |  } else {
    422  |
    423  |   g_string_sprintf(query, "SELECT range_id, range_start, range_end "
    424  |                           "FROM nic_hdl "
    425  |                           "WHERE space='%s' "
    426  | 			  "AND source='%s' "
    427  |                           "AND range_start<=%ld "
    428  |                           "AND range_end>=%ld ",
    429  | 			  prange->space, prange->source, nic_id, nic_id);
    430  |  }
    431  |
    432  | /* execute query */
    433  | /* fprintf(stderr, "get_range[%s]\n", query->str); */
    434  |  sql_err=SQ_execute_query(sql_connection, query->str, &sql_result);
    435  |  g_string_free(query, TRUE);
    436  |
    437  |  if(sql_err) {
    438  |    fprintf(stderr,"ERROR: %s\n", SQ_error(sql_connection));
    439  |    return(-1);
    440  |  }
    441  |
    442  |  if ((sql_row = SQ_row_next(sql_result)) != NULL) {
    443  | /* Object exists */
    444  |    sql_str = SQ_get_column_string(sql_result, sql_row, RANGE_ID);
    445  |    if (sql_str != NULL) {
    446  |      range_id = atol(sql_str);
    447  |      UT_free(sql_str);
    448  |    }
    449  |    sql_str = SQ_get_column_string(sql_result, sql_row, RANGE_START);
    450  |    if (sql_str != NULL) {
    451  |      prange->start = atoi(sql_str);
    452  |      UT_free(sql_str);
    453  |    }
    454  |    sql_str = SQ_get_column_string(sql_result, sql_row, RANGE_END);
    455  |    if (sql_str != NULL) {
    456  |      prange->end = atoi(sql_str);
    457  |      UT_free(sql_str);
    458  |    }
    459  |
    460  | /* We must process all the rows of the result */
    461  | /* otherwise we'll have them as part of the next qry */
    462  |    while ( (sql_row = SQ_row_next(sql_result)) != NULL) range_id=-1;
    463  |  } else
    464  |       range_id=0;  // object does not exist
    465  |
    466  |  if(sql_result)SQ_free_result(sql_result);
    467  |  return(range_id);
    468  | }
    469  |
    470  |
    471  |
    472  |
    473  | /************************************************************
    474  | * long update_range()                                       *
    475  | *                                                           *
    476  | * Updates the range by changing the boundaries              *
    477  | * Deletes the range if nothing left                         *
    478  | * Merges with neighbor ranges if there is no gap between    *
    479  | *                                                           *
    480  | * We never update range. We create a new one with specified *
    481  | * limits and mark old one(s) for deletion, so that we can   *
    482  | * make commit/rollback properly. This is possible as the    *
    483  | * primary keys are (range_id, range_start, range_end)       *
    484  | *                                                           *
    485  | * To finalize changes make commit/rollback                  *
    486  | *                                                           *
    487  | * Returns:                                                  *
    488  | * >0 - returns range_id on success                          *
    489  | * -1 - error (f.e. more than one object with the same PK)   *
    490  | *                                                           *
    491  | ************************************************************/
    492  |
    493  | static long update_range(long range_id, range_t *p_newrange, SQ_connection_t *sql_connection, int commit_now)
    494  | {
    495  | GString *query;
    496  | range_t range;
    497  | long prev_range_id, next_range_id;
    498  | int num;
    499  | int sql_err;
    500  |
    501  |  query = g_string_sized_new(STR_L);
    502  |
    503  | /* Do range check */
    504  |  if (( p_newrange->end > MAX_RANGE ) || ( p_newrange->start < MIN_RANGE )) return(-1);
    505  |
    506  | /* Check if the range collapses */
    507  |  if ( p_newrange->end < p_newrange->start ) {
    508  |  /* then delete the range */
    509  |  /* Do this by marking the range for deletion for further commit/rollback */
    510  |   if(commit_now)
    511  |    g_string_sprintf(query, "DELETE FROM nic_hdl "
    512  |                            "WHERE range_id=%ld ",
    513  |                             range_id);
    514  |   else
    515  |    g_string_sprintf(query, "UPDATE nic_hdl SET thread_id=%d "
    516  |                            "WHERE range_id=%ld ",
    517  | 			    NH_DELETE, range_id);
    518  |
    519  | /*   fprintf(stderr, "update_range[%s]\n", query->str); */
    520  |    sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
    521  |    if(sql_err) {
    522  |     /* An error occured */
    523  |     g_string_free(query, TRUE);
    524  |     return(-1);
    525  |    }
    526  |    num = SQ_get_affected_rows(sql_connection);
    527  |    /* this should not happen */
    528  |    if(num==0) die;
    529  |
    530  |  }
    531  |  else {
    532  |   /* update the range for the same space/source */
    533  |   range.space=p_newrange->space;
    534  |   range.source=p_newrange->source;
    535  |   /* Check if we can join with previous range of the same space */
    536  |   prev_range_id=get_range(p_newrange->start-1, &range, sql_connection);
    537  |   /* Check if such range exists and it is not ours (this happens when we are shrinking */
    538  |   if((prev_range_id>0) && (prev_range_id!=range_id)) {
    539  |    /* acquire the previous range */
    540  |    /* mark it for deletion for commit/rollback */
    541  |    if(commit_now)
    542  |       g_string_sprintf(query, "DELETE FROM nic_hdl "
    543  |                               "WHERE range_id=%ld ",
    544  |                                prev_range_id);
    545  |    else
    546  |       g_string_sprintf(query, "UPDATE nic_hdl SET thread_id=%d "
    547  |                               "WHERE range_id=%ld ",
    548  | 			       NH_DELETE, prev_range_id);
    549  |
    550  |
    551  |
    552  | /*    fprintf(stderr, "update_range[%s]\n", query->str); */
    553  |    sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
    554  |    if(sql_err) {
    555  |     /* An error occured */
    556  |     g_string_free(query, TRUE);
    557  |     return(-1);
    558  |    }
    559  |    num = SQ_get_affected_rows(sql_connection);
    560  |    /* this should not happen */
    561  |    if(num==0) die;
    562  |
    563  |    /* expand the boundaries */
    564  |    p_newrange->start=range.start;
    565  |   }
    566  |
    567  | /* Check if we can join with next range of the same space */
    568  |   next_range_id=get_range(p_newrange->end+1, &range, sql_connection);
    569  |   /* Check if such range exists and it is not ours (this happens when we are shrinking) */
    570  |   if((next_range_id>0) && (next_range_id!=range_id)) {
    571  |    /* acquire the next range */
    572  |    /* mark it for deletion for commit/rollback */
    573  |    if(commit_now)
    574  |      g_string_sprintf(query, "DELETE FROM nic_hdl "
    575  |                              "WHERE range_id=%ld ",
    576  |                               next_range_id);
    577  |    else
    578  |      g_string_sprintf(query, "UPDATE nic_hdl SET thread_id=%d "
    579  |                              "WHERE range_id=%ld ",
    580  | 			      NH_DELETE, next_range_id);
    581  |
    582  |
    583  |
    584  | /*   fprintf(stderr, "update_range[%s]\n", query->str); */
    585  |    sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
    586  |    if(sql_err) {
    587  |     /* An error occured */
    588  |     g_string_free(query, TRUE);
    589  |     return(-1);
    590  |    }
    591  |    num = SQ_get_affected_rows(sql_connection);
    592  |    /* this should not happen */
    593  |    if(num==0) die;
    594  |
    595  |    /* expand the boundaries */
    596  |    p_newrange->end=range.end;
    597  |   }
    598  |
    599  | /* Now make a larger range. Mark current for deletion and new for commit/rollback */
    600  |   if(commit_now)
    601  |    g_string_sprintf(query, "UPDATE nic_hdl "
    602  |                            "SET range_start=%ld, range_end=%ld "
    603  | 			   "WHERE range_id=%ld",
    604  |                            p_newrange->start, p_newrange->end, range_id);
    605  |   else {
    606  |
    607  |    g_string_sprintf(query, "UPDATE nic_hdl SET thread_id=%d "
    608  |                            "WHERE range_id=%ld ",
    609  | 			   NH_DELETE, range_id);
    610  | /*   fprintf(stderr, "update_range[%s]\n", query->str); */
    611  |    sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
    612  |    if(sql_err) {
    613  |     /* An error occured */
    614  |     g_string_free(query, TRUE);
    615  |     return(-1);
    616  |    }
    617  |    num = SQ_get_affected_rows(sql_connection);
    618  |    /* this should not happen */
    619  |    if(num==0) die;
    620  |
    621  |    g_string_sprintf(query, "INSERT nic_hdl "
    622  |                            "SET thread_id=%d, range_id=%ld, space='%s', source='%s', range_start=%ld, range_end=%ld ",
    623  |                            NH_INSERT, range_id, p_newrange->space, p_newrange->source, p_newrange->start, p_newrange->end);
    624  |   }
    625  |
    626  | /*   fprintf(stderr, "update_range[%s]\n", query->str); */
    627  |    sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
    628  |    if(sql_err) {
    629  |     /* An error occured */
    630  |     g_string_free(query, TRUE);
    631  |     return(-1);
    632  |    }
    633  |    num = SQ_get_affected_rows(sql_connection);
    634  |    /* this should not happen */
    635  |    if(num==0) die;
    636  |  } /* update the range */
    637  |
    638  |  g_string_free(query, TRUE);
    639  |  return (range_id);
    640  | }
    641  |
    642  | /************************************************************
    643  | * long create_range()                                       *
    644  | *                                                           *
    645  | * Creates a new range in a given name space                 *
    646  | *                                                           *
    647  | * To finalize changes make commit/rollback                  *
    648  | *                                                           *
    649  | * Returns:                                                  *
    650  | * >0 - returns range_id on success                          *
    651  | * -1 - error (f.e. more than one object with the same PK)   *
    652  | *                                                           *
    653  | ************************************************************/
    654  |
    655  | static long create_range(range_t *p_range, SQ_connection_t *sql_connection, int commit_now)
    656  | {
    657  | GString *query;
    658  | int sql_err, num;
    659  | long range_id;
    660  |
    661  |  query = g_string_sized_new(STR_L);
    662  |
    663  |  /* get the next range_id */
    664  |  /* XXX we cannot use autoincrement with MyISAM tables */
    665  |  /* XXX because they keep the max inserted id even if  */
    666  |  /* XXX it was deleted later, thus causing gaps we don't want */
    667  |
    668  |  range_id=SQ_get_max_id(sql_connection, "range_id", "nic_hdl") +1;
    669  |
    670  |  if(commit_now)
    671  |   g_string_sprintf(query, "INSERT nic_hdl "
    672  |                           "SET thread_id=0,  range_id=%ld, space='%s', source='%s', range_start=%ld, range_end=%ld ",
    673  |                            range_id, p_range->space, p_range->source, p_range->start, p_range->end);
    674  |  else
    675  |   g_string_sprintf(query, "INSERT nic_hdl "
    676  |                           "SET thread_id=%d, range_id=%ld, space='%s', source='%s', range_start=%ld, range_end=%ld ",
    677  |                            NH_INSERT, range_id, p_range->space, p_range->source, p_range->start, p_range->end);
    678  |
    679  | /* fprintf(stderr, "create_range[%s]\n", query->str); */
    680  |  sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
    681  |  g_string_free(query, TRUE);
    682  |
    683  |    if(sql_err) {
    684  |     /* An error occured */
    685  |     return(-1);
    686  |    }
    687  |    num = SQ_get_affected_rows(sql_connection);
    688  |    /* this should not happen */
    689  |    if(num==0) die;
    690  |  return(range_id);
    691  | }
    692  |
    693  |
    694  | /************************************************************
    695  | * int NH_comrol()                                           *
    696  | *                                                           *
    697  | * Commits or rolls back changes to NHR                      *
    698  | *                                                           *
    699  | *                                                           *
    700  | * Returns:                                                  *
    701  | * >0 - success                                              *
    702  | * -1 - SQL error                                            *
    703  | *                                                           *
    704  | ************************************************************/
    705  |
    706  | int NH_comrol(SQ_connection_t *sql_connection, int thread_ins, int thread_del)
    707  | {
    708  | GString *query;
    709  | int sql_err;
    710  |
    711  |  query = g_string_sized_new(STR_L);
    712  |
    713  |   g_string_sprintf(query, "DELETE FROM nic_hdl "
    714  | 			  "WHERE thread_id=%d ",
    715  |                           thread_del);
    716  |
    717  | /* fprintf(stderr, "create_range[%s]\n", query->str); */
    718  |  sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
    719  |  if(sql_err) {
    720  |     /* An error occured */
    721  |     g_string_free(query, TRUE);
    722  |     fprintf(stderr,"ERROR: %s\n", SQ_error(sql_connection));
    723  |     die;
    724  |  }
    725  |
    726  |  g_string_sprintf(query, "UPDATE nic_hdl "
    727  |                          "SET thread_id=0 "
    728  | 			 "WHERE thread_id=%d ",
    729  |                           thread_ins);
    730  |
    731  | /* fprintf(stderr, "create_range[%s]\n", query->str); */
    732  |  sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
    733  |  g_string_free(query, TRUE);
    734  |
    735  |  if(sql_err) {
    736  |     /* An error occured */
    737  |    fprintf(stderr,"ERROR: %s\n", SQ_error(sql_connection));
    738  |    die;
    739  |  }
    740  |
    741  |  return(1);
    742  |
    743  | }
    744  |
    745  |