modules/nh/nh.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. get_min_range
  2. NH_convert
  3. NH_parse
  4. NH_check
  5. NH_free
  6. NH_register
  7. free_nh
  8. get_range
  9. update_range
  10. create_range
  11. NH_comrol

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

/* [<][>][^][v][top][bottom][index][help] */