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