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