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 |