## 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.9 $
       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   /* 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)
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     639 {
     640 GString *query;
     641 int sql_err, num;
     642 long range_id;
     643
     644  /* Allocate memory */
     645  if ((query = g_string_sized_new(STR_L)) == NULL){
     646   fprintf(stderr, "E: cannot allocate gstring\n");
     647   return(-1);
     648  }
     649
     650  /* get the next range_id */
     651  /* XXX we cannot use autoincrement with MyISAM tables */
     652  /* XXX because they keep the max inserted id even if  */
     653  /* XXX it was deleted later, thus causing gaps we don't want */
     654
     655  range_id=SQ_get_max_id(sql_connection, "range_id", "nic_hdl") +1;
     656
     657  if(commit_now)
     658   g_string_sprintf(query, "INSERT nic_hdl "
     659                           "SET thread_id=0,  range_id=%ld, space='%s', source='%s', range_start=%ld, range_end=%ld ",
     660                            range_id, p_range->space, p_range->source, p_range->start, p_range->end);
     661  else
     662   g_string_sprintf(query, "INSERT nic_hdl "
     663                           "SET thread_id=%d, range_id=%ld, space='%s', source='%s', range_start=%ld, range_end=%ld ",
     664                            NH_INSERT, range_id, p_range->space, p_range->source, p_range->start, p_range->end);
     665
     666 /* fprintf(stderr, "create_range[%s]\n", query->str); */
     667  sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
     668  g_string_free(query, TRUE);
     669
     670    if(sql_err) {
     671     /* An error occured */
     672     return(-1);
     673    }
     674    num = SQ_get_affected_rows(sql_connection);
     675    /* this should not happen */
     676    if(num==0) die;
     677  return(range_id);
     678 }
     679
     680
     681 /************************************************************
     682 * int NH_comrol()                                           *
     683 *                                                           *
     684 * Commits or rolls back changes to NHR                      *
     685 *                                                           *
     686 *                                                           *
     687 * Returns:                                                  *
     688 * >0 - success                                              *
     689 * -1 - SQL error                                            *
     690 *                                                           *
     691 ************************************************************/
     692
     693 int NH_comrol(SQ_connection_t *sql_connection, int thread_ins, int thread_del)
         /* [<][>][^][v][top][bottom][index][help] */
     694 {
     695 GString *query;
     696 int sql_err;
     697
     698  /* Allocate memory */
     699  if ((query = g_string_sized_new(STR_L)) == NULL){
     700   fprintf(stderr, "E: cannot allocate gstring\n");
     701   return(-1);
     702  }
     703
     704   g_string_sprintf(query, "DELETE FROM nic_hdl "
     705                           "WHERE thread_id=%d ",
     706                           thread_del);
     707
     708 /* fprintf(stderr, "create_range[%s]\n", query->str); */
     709  sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
     710  if(sql_err) {
     711     /* An error occured */
     712     g_string_free(query, TRUE);
     713     fprintf(stderr,"ERROR: %s\n", SQ_error(sql_connection));
     714     die;
     715  }
     716
     717  g_string_sprintf(query, "UPDATE nic_hdl "
     718                          "SET thread_id=0 "
     719                          "WHERE thread_id=%d ",
     720                           thread_ins);
     721
     722 /* fprintf(stderr, "create_range[%s]\n", query->str); */
     723  sql_err=SQ_execute_query(sql_connection, query->str, (SQ_result_set_t **)NULL);
     724  g_string_free(query, TRUE);
     725
     726  if(sql_err) {
     727     /* An error occured */
     728    fprintf(stderr,"ERROR: %s\n", SQ_error(sql_connection));
     729    die;
     730  }
     731
     732  return(1);
     733
     734 }
     735
     736

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