Source File modules/nh/nh.c

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