modules/ud/ud_comrol.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- rollback
- commit
- delete
1 /***************************************
2 $Revision: 1.21 $
3
4 rollback(), commit(), delete() - rollback, commit update transaction, delete an object
5
6 Status: NOT REVUED, NOT TESTED
7
8 Author(s): Andrei Robachevsky
9
10 ******************/ /******************
11 Modification History:
12 andrei (17/01/2000) Created.
13 ******************/ /******************
14 Copyright (c) 2000 RIPE NCC
15
16 All Rights Reserved
17
18 Permission to use, copy, modify, and distribute this software and its
19 documentation for any purpose and without fee is hereby granted,
20 provided that the above copyright notice appear in all copies and that
21 both that copyright notice and this permission notice appear in
22 supporting documentation, and that the name of the author not be
23 used in advertising or publicity pertaining to distribution of the
24 software without specific, written prior permission.
25
26 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
28 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
29 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
30 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
31 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 ***************************************/
33 #include "ud.h"
34 #include "ud_int.h"
35 #include "ud_comrol.h"
36 #include "rp.h"
37
38 /************************************************************
39 * int rollback() *
40 * *
41 * Rolls back the transaction *
42 * *
43 * It locks all relevant tables and processes the rollback *
44 * General approach is to delete all new records related *
45 * to the transaction (thread_id==thread_ins) and clean up *
46 * old ones (thread_id==thread_upd) *
47 * *
48 ************************************************************/
49
50 int rollback(Transaction_t *tr) {
/* [<][>][^][v][top][bottom][index][help] */
51 GString *query;
52 long sequence_id;
53 int i, j;
54 int sql_err;
55
56 if(ACT_DELETE(tr->action)) return(0);
57
58 if ((query = g_string_sized_new(STR_XXL)) == NULL){
59 fprintf(stderr, "E: cannot allocate gstring\n");
60 tr->succeeded=0;
61 tr->error |= ERROR_U_MEM;
62 die; }
63
64 /* Lock all relevant tables */
65 g_string_sprintf(query, "LOCK TABLES %s WRITE,", DF_get_class_sql_table(tr->class_type));
66
67 for (i=0; tables[tr->class_type][i] != NULL; i++)
68 g_string_sprintfa(query, " %s WRITE,", tables[tr->class_type][i]);
69
70 for (i=TAB_START; tables[tr->class_type][i] != NULL; i++)
71 g_string_sprintfa(query, " %s WRITE,", tables[tr->class_type][i]);
72
73 g_string_sprintfa(query, " last WRITE, history WRITE ");
74
75 sql_err=SQ_execute_query(tr->sql_connection, query->str, NULL);
76
77 /*fprintf(stderr,"%s\n", query->str);*/
78
79
80 /* Process AUX and LEAF tables */
81 for (i=TAB_START; tables[tr->class_type][i] != NULL; i++) {
82 /* Delete what has been inserted */
83 g_string_sprintf(query, "DELETE FROM %s WHERE object_id=%ld AND thread_id=%d", tables[tr->class_type][i], tr->object_id, tr->thread_ins);
84 sql_err=SQ_execute_query(tr->sql_connection, query->str, NULL);
85
86 /* Normalize what has been updated/touched */
87 g_string_sprintf(query, "UPDATE %s SET thread_id=0 WHERE object_id=%ld AND thread_id=%d", tables[tr->class_type][i], tr->object_id, tr->thread_upd);
88 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
89 }
90
91 /* Process MAIN tables */
92 g_string_sprintf(query, "DELETE FROM %s WHERE object_id=%ld AND thread_id=%d",
93 DF_get_class_sql_table(tr->class_type), tr->object_id, tr->thread_ins);
94 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
95
96 /* This is needed only for objects with dummies, as they are updated with TR_UPDATE */
97 /* We use this tag when commiting the update to set dummy==0 */
98 /* XXX may be later this should be reconsidered */
99 g_string_sprintf(query, "UPDATE %s SET thread_id=0 WHERE object_id=%ld AND thread_id=%d",
100 DF_get_class_sql_table(tr->class_type), tr->object_id, tr->thread_upd);
101 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
102
103 /* Now tables that might be affected by dummies */
104 for(j=0; j < tr->ndummy; j++)
105 for (i=0; tables[tr->class_type][i] != NULL; i++) {
106 g_string_sprintf(query, "DELETE FROM %s WHERE object_id=%ld ", tables[tr->class_type][i], tr->dummy_id[j]);
107 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
108 }
109
110 /* if dummies have been created - get rid of them */
111 for(j=0; j < tr->ndummy; j++){
112 g_string_sprintf(query, "DELETE FROM last WHERE object_id=%ld ", tr->dummy_id[j]);
113 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
114 }
115
116 /* Rollback last and history tables */
117 if(ACT_UPDATE(tr->action)) { /* so we are updating an object */
118 g_string_sprintf(query, "DELETE FROM history WHERE object_id=%ld AND sequence_id=%ld", tr->object_id, tr->sequence_id-1);
119 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
120 /* we do not need to delete a row in the last for updates */
121 }
122 else { /* we failed to create an object */
123 sequence_id=1; /* sequence start == 1 */
124 g_string_sprintf(query, "DELETE FROM last WHERE object_id=%ld AND sequence_id=%ld", tr->object_id, sequence_id);
125 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
126 }
127
128
129 /* Unlock all tables */
130 g_string_sprintf(query, "UNLOCK TABLES ");
131 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
132
133
134 g_string_free(query, TRUE);
135 return(0);
136 } /* rollback() */
137
138
139 /************************************************************
140 * int commit() *
141 * *
142 * Commits the transaction *
143 * *
144 * It locks all relevant tables and processes the rollback *
145 * General approach is to clean up all new and updated *
146 * records related to the transaction *
147 * (thread_id==thread_ins) and (thread_id==thread_upd), *
148 * and delete untouched ones (thread_id==0) *
149 * *
150 ************************************************************/
151
152 int commit(Transaction_t *tr) {
/* [<][>][^][v][top][bottom][index][help] */
153 GString *query;
154 int err=0;
155 int i,j;
156 A_Type_t attr_type;
157 int sql_err;
158
159 if(ACT_DELETE(tr->action)) return(0);
160
161 if ((query = g_string_sized_new(STR_XXL)) == NULL){
162 fprintf(stderr, "E: cannot allocate gstring\n");
163 tr->succeeded=0;
164 tr->error|=ERROR_U_MEM;
165 die;
166 }
167
168 /* Lock all relevant tables */
169 g_string_sprintf(query, "LOCK TABLES %s WRITE,", DF_get_class_sql_table(tr->class_type));
170
171 for (i=0; tables[tr->class_type][i] != NULL; i++)
172 g_string_sprintfa(query, " %s WRITE,", tables[tr->class_type][i]);
173
174 for (i=TAB_START; tables[tr->class_type][i] != NULL; i++)
175 g_string_sprintfa(query, " %s WRITE,", tables[tr->class_type][i]);
176
177 g_string_sprintfa(query, " last WRITE, history WRITE ");
178
179 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
180
181 /* fprintf(stderr,"%s\n", query->str); */
182
183 /* Commit the transaction for AUX and LEAF tables that may be affected (taken from object template) */
184 for (i=TAB_START; tables[tr->class_type][i] != NULL; i++) {
185 /* Delete old records from the tables */
186 g_string_sprintf(query, "DELETE FROM %s WHERE object_id=%ld AND thread_id=0 ", tables[tr->class_type][i], tr->object_id);
187 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
188 /* fprintf(stderr, "D: query (del old): %s\n", query->str); */
189
190 /* Set thread_id to 0 to commit the transaction */
191 g_string_sprintf(query, "UPDATE %s SET thread_id=0 WHERE object_id=%ld", tables[tr->class_type][i], tr->object_id);
192 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
193 /* fprintf(stderr, "D: query (com new): %s\n", query->str); */
194 }
195
196 /* Commit the transaction for the MAIN tables */
197
198 /* Commit the transaction for person_role, mntner, as_set, route_set tables */
199 /* They require different handling because of dummies */
200 /* The rule is: Update: dummy->0, Insert: preserve dummy value */
201 /* These tables do not require deletions since we cannot have such condition (object_id==0 AND thread_id==0) */
202 if((tr->class_type==C_PN) || (tr->class_type==C_RO) ||
203 (tr->class_type==C_AS) || (tr->class_type==C_RS) ||
204 (tr->class_type==C_MT)){
205
206 /* Process the rows updated/touched */
207 g_string_sprintf(query, "UPDATE %s SET thread_id=0, dummy=0 WHERE object_id=%ld AND thread_id=%d ", DF_get_class_sql_table(tr->class_type), tr->object_id, tr->thread_upd);
208 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
209 }
210
211 switch (tr->class_type) {
212 case C_IR:
213 case C_IN:
214 case C_I6:
215 case C_FS:
216 if((tr->save)){ /* Some special processing for tables with the second attribute */
217 /* Update the second field of the table with query like one below */
218 /* UPDATE %s SET thread_id=%d, local_as='%s' WHERE object_id=%ld */
219
220 switch(tr->class_type) {
221 /* Local-as for inet-rtr */
222 case C_IR: attr_type=A_LA;
223 break;
224 /* netname for inetnum and inet6num */
225 case C_IN:
226 case C_I6: attr_type=A_NA;
227 break;
228 /* filter for filter-set */
229 case C_FS: attr_type=A_FI;
230 break;
231 default:
232 die;
233 break;
234 }
235 g_string_sprintf(query, DF_get_update_query(attr_type), DF_get_class_sql_table(tr->class_type), 0, (char *)tr->save, tr->object_id);
236 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
237 }
238 else die;
239 break;
240
241 default:
242 /* Process all other MAIN tables for updates/inserts and person_role, mntner, as_set, route_set tables for rows inserts */
243 g_string_sprintf(query, "UPDATE %s SET thread_id=0 WHERE object_id=%ld AND thread_id>0", DF_get_class_sql_table(tr->class_type), tr->object_id);
244 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
245 break;
246 }
247
248
249 /* for tables that might be affected by dummies */
250 for(j=0; j < tr->ndummy; j++)/* if dummies have been created */
251 for (i=0; tables[tr->class_type][i] != NULL; i++) {
252 g_string_sprintf(query, "UPDATE %s SET thread_id=0 WHERE object_id=%ld ", tables[tr->class_type][i], tr->dummy_id[j]);
253 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
254 }
255
256
257 for(j=0; j < tr->ndummy; j++){/* if dummies have been created*/
258 g_string_sprintf(query, "UPDATE last SET thread_id=0 WHERE object_id=%ld ", tr->dummy_id[j]);
259 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
260 }
261
262 /* Unlock all tables */
263 g_string_sprintf(query, "UNLOCK TABLES ");
264 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
265
266 /* Update radix tree for route, inetnum and inaddr-arpa domain*/
267 if(tr->standalone==0) { /* only if server*/
268
269 /* Create a radix node for the object */
270 if( ( (tr->class_type==C_RT)
271 || (tr->class_type==C_IN)
272 || (tr->class_type==C_I6)
273 || (tr->class_type==C_DN))
274 && (ACT_UPD_RX(tr->action))) {
275 rp_upd_pack_t *packptr = tr->packptr;
276
277 packptr->key = tr->object_id;
278
279 if( RP_pack_node(RX_OPER_CRE, packptr, tr->source_hdl) == RX_OK ) {
280 err = 0;
281 } else {
282 err = (-1) ;
283 }
284 }
285 /* XXX Check for errors */
286 }
287
288 g_string_free(query, TRUE);
289 return(err);
290 } /* commit() */
291
292
293 /************************************************************
294 * int delete() *
295 * *
296 * Deletes the object *
297 * *
298 * It checks for referential integrity and then deletes the *
299 * object from all relevant tables. Then it updates the *
300 * radix tree for routes, inetnums and rev.domains *
301 * *
302 ************************************************************/
303 int delete(Transaction_t *tr)
/* [<][>][^][v][top][bottom][index][help] */
304 {
305 GString *query;
306 int err=0;
307 int i;
308 int num;
309 long ref_id;
310 long num_rec;
311 long timestamp;
312
313 char sobject_id[STR_M];
314 char *sql_str;
315 int sql_err;
316
317
318 /* Try to allocate g_string. Return on error */
319 if ((query = g_string_sized_new(STR_XXL)) == NULL){
320 fprintf(stderr, "E: cannot allocate gstring\n");
321 tr->succeeded=0;
322 tr->error|=ERROR_U_MEM;
323 die;
324 }
325
326
327 /* Check for referential integrity of deletion */
328
329 sprintf(sobject_id, "%ld", tr->object_id);
330
331 switch(tr->class_type){
332 case C_PN:
333 case C_RO:
334
335 /* Check that this person/role object is not referenced */
336
337 for (i=0; t_ipn[i] != NULL; i++) {
338 /* Calculate number of references */
339 sql_str= get_field_str(tr->sql_connection, "COUNT(*)", t_ipn[i], "pe_ro_id", sobject_id, NULL);
340 if(sql_str) {
341 num_rec = atol(sql_str); free(sql_str);
342 ref_id=tr->object_id;
343 /* Check if it is a self reference (for role objects) */
344 if(num_rec==1) {
345 sql_str= get_field_str(tr->sql_connection, "object_id", t_ipn[i], "pe_ro_id", sobject_id, NULL);
346 if(sql_str) {
347 ref_id = atol(sql_str); free(sql_str);
348 } else {
349 tr->succeeded=0; tr->error |= ERROR_U_DBS; break;
350 }
351 }
352 /* If there are references (and not the only self reference) we cannot delete */
353 if((num_rec>1) || (ref_id!=tr->object_id)) {
354 g_string_sprintfa(tr->error_script,"E[%d][%ld]:ref integrity: %s\n" ,ERROR_U_OBJ, num_rec, t_ipn[i]);
355 tr->succeeded=0; tr->error |= ERROR_U_OBJ;
356 }
357 } else {
358 /* SQL error occured */
359 tr->succeeded=0; tr->error |= ERROR_U_DBS;
360 g_string_sprintfa(tr->error_script,"E[%d][%s]:%s\n", ERROR_U_DBS, t_ipn[i], SQ_error(tr->sql_connection));
361 }
362 }
363
364 /* Check that this person/role object is not referenced by name (legacy stuff) */
365 /* But allow overriding this check in NRTM mode and with override_integrity */
366 if(tr->dummy==1)break;
367
368 for (i=0; t_ipn[i] != NULL; i++) {
369 /* Calculate number of references */
370
371 g_string_sprintf(query, "SELECT COUNT(*) FROM %s, person_role "
372 "WHERE person_role.object_id=%s.pe_ro_id "
373 "AND person_role.nic_hdl='%s' ", t_ipn[i], t_ipn[i], tr->save);
374
375 sql_str= get_qresult_str(tr->sql_connection, query->str);
376 if(sql_str) {
377 num_rec = atol(sql_str); free(sql_str);
378 /* If there are references (no self reference is possible in this case) we cannot delete */
379 if(num_rec>0) {
380 g_string_sprintfa(tr->error_script,"E[%d][%ld]:ref integrity: %s\n" ,ERROR_U_OBJ, num_rec, t_ipn[i]);
381 tr->succeeded=0; tr->error |= ERROR_U_OBJ;
382 }
383 } else {
384 /* SQL error occured */
385 tr->succeeded=0; tr->error |= ERROR_U_DBS;
386 g_string_sprintfa(tr->error_script,"E[%d][%s]:%s\n", ERROR_U_DBS, t_ipn[i], SQ_error(tr->sql_connection));
387 }
388 }
389
390 break;
391
392 case C_MT:
393
394 /* Check that this mntner object is not referenced */
395
396 for (i=0; t_imt[i] != NULL; i++) {
397 /* Calculate number of references */
398 sql_str= get_field_str(tr->sql_connection, "COUNT(*)", t_imt[i], "mnt_id", sobject_id, NULL);
399 if(sql_str) {
400 num_rec = atol(sql_str); free(sql_str);
401 ref_id=tr->object_id;
402 /* Check if it is a self reference */
403 if(num_rec==1) {
404 sql_str= get_field_str(tr->sql_connection, "object_id", t_imt[i], "mnt_id", sobject_id, NULL);
405 if(sql_str) {
406 ref_id = atol(sql_str); free(sql_str);
407 } else {
408 tr->succeeded=0; tr->error |= ERROR_U_DBS; break;
409 }
410 }
411 /* If there are references (and not the only self reference) we cannot delete */
412 if((num_rec>1) || (ref_id!=tr->object_id)) {
413 g_string_sprintfa(tr->error_script,"E[%d][%ld]:ref integrity: %s\n" ,ERROR_U_OBJ, num_rec, t_imt[i]);
414 tr->succeeded=0; tr->error |= ERROR_U_OBJ;
415 }
416 } else {
417 tr->succeeded=0; tr->error |= ERROR_U_DBS;
418 }
419 }
420 break;
421
422 case C_RS:
423 case C_AS:
424 /* Check that this set object is not referenced */
425 /* Calculate number of references */
426 sql_str= get_field_str(tr->sql_connection, "COUNT(*)", "member_of", "set_id", sobject_id, NULL);
427 if(sql_str) {
428 num_rec = atol(sql_str); free(sql_str);
429 /* XXX though set may contain other sets as memebers, */
430 /* there is no member-of attribute in these objects. */
431 /* So no self-reference is possible */
432 if(num_rec!=0) {
433 g_string_sprintfa(tr->error_script,"E[%d][%ld]:ref integrity: %s\n" ,ERROR_U_OBJ, num_rec, "member_of");
434 /*tr->succeeded=0; tr->error |= ERROR_U_OBJ;*/
435 /* XXX Do not refuse the transaction but change the object to dummy */
436 /* Update the history table */
437 g_string_sprintf(query, "INSERT history "
438 "SELECT 0, object_id, sequence_id, timestamp, object_type, object "
439 "FROM last "
440 "WHERE object_id=%ld ", tr->object_id);
441
442
443 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
444 if (sql_err) {
445 fprintf(stderr, "E ERROR!<perform_update>: INSERT history failed:[%d][%s]\n", num, query->str);
446 tr->succeeded=0;
447 tr->error |=ERROR_U_DBS;
448 }
449
450 /* get sequence number */
451 tr->sequence_id = get_sequence_id(tr);
452 tr->sequence_id++;
453
454 /* insert new version into the last */
455 timestamp=time(NULL);
456
457 /* update the main table */
458 g_string_sprintf(query, "UPDATE %s SET dummy=1 WHERE object_id=%ld ", DF_get_class_sql_table(tr->class_type), tr->object_id);
459
460 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
461 if (sql_err) {
462 fprintf(stderr, "E ERROR!<perform_update>: UPDATE last failed: [%d][%s]\n", num, query->str);
463 tr->succeeded=0;
464 tr->error |= ERROR_U_DBS;
465 }
466
467 /* empty the contents, but leave in the table to prevent re-use of object_id */
468 g_string_sprintf(query, "UPDATE last SET object='DUMMY SET', object_type=%d, sequence_id=%ld, timestamp=%ld WHERE object_id=%ld ", DUMMY_TYPE, tr->sequence_id, timestamp, tr->object_id);
469
470 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
471 if (sql_err) {
472 fprintf(stderr, "E ERROR!<perform_update>: UPDATE last failed: [%d][%s]\n", num, query->str);
473 tr->succeeded=0;
474 tr->error |= ERROR_U_DBS;
475 }
476 return(0);
477
478 }
479 } else {
480 tr->succeeded=0; tr->error |= ERROR_U_DBS;
481 }
482 break;
483
484 default:
485 break;
486 }
487
488 /* Check if we have passed referential integrity check */
489 if(tr->succeeded==0){
490 return(-1);
491 }
492
493
494 /* Lock all relevant tables */
495 g_string_sprintf(query, "LOCK TABLES %s WRITE,", DF_get_class_sql_table(tr->class_type));
496
497 for (i=0; tables[tr->class_type][i] != NULL; i++)
498 g_string_sprintfa(query, " %s WRITE,", tables[tr->class_type][i]);
499
500 for (i=TAB_START; tables[tr->class_type][i] != NULL; i++)
501 g_string_sprintfa(query, " %s WRITE,", tables[tr->class_type][i]);
502
503 g_string_sprintfa(query, " last WRITE, history WRITE ");
504
505 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
506 if (sql_err) {
507 fprintf(stderr, "E ERROR!<perform_update>: locking failed:[%d][%s]\n", num, query->str);
508 tr->succeeded=0;
509 tr->error |=ERROR_U_DBS;
510 die;
511 }
512 /* Update the history table */
513 g_string_sprintf(query, "INSERT history "
514 "SELECT 0, object_id, sequence_id, timestamp, object_type, object "
515 "FROM last "
516 "WHERE object_id=%ld ", tr->object_id);
517 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
518 if (sql_err) {
519 fprintf(stderr, "E ERROR!<perform_update>: INSERT history failed:[%d][%s]\n", num, query->str);
520 tr->succeeded=0;
521 tr->error |=ERROR_U_DBS;
522 die;
523 }
524
525 /* Delete records from the leaf and aux tables */
526 for (i=TAB_START; tables[tr->class_type][i] != NULL; i++) {
527 g_string_sprintf(query, "DELETE FROM %s WHERE object_id=%ld ", tables[tr->class_type][i], tr->object_id);
528 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
529 /* fprintf(stderr, "D: query (delete): %s\n", query->str);*/
530 if (sql_err) {
531 fprintf(stderr, "E ERROR!<perform_update>: DELETE form leaf/aux failed:[%d][%s]\n", num, query->str);
532 tr->succeeded=0;
533 tr->error |=ERROR_U_DBS;
534 die;
535 }
536 }
537
538
539
540 /* Process the MAIN table */
541 g_string_sprintf(query, "DELETE FROM %s WHERE object_id=%ld ", DF_get_class_sql_table(tr->class_type), tr->object_id);
542
543
544 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
545 if (sql_err) {
546 fprintf(stderr, "E ERROR!<perform_update>: DELETE form main failed:[%d][%s]\n", num, query->str);
547 tr->succeeded=0;
548 tr->error |=ERROR_U_DBS;
549 die;
550 }
551
552 /* get sequence number */
553 tr->sequence_id = get_sequence_id(tr);
554 tr->sequence_id++;
555
556 /* insert new version into the last */
557 timestamp=time(NULL);
558
559 /* empty the contents, but leave in the table to restrict re-use of object_id */
560 g_string_sprintf(query, "UPDATE last SET object='', timestamp=%ld WHERE object_id=%ld ", timestamp, tr->object_id);
561
562 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
563 if (sql_err) {
564 fprintf(stderr, "E ERROR!<perform_update>: UPDATE last failed: [%d][%s]\n", num, query->str);
565 tr->succeeded=0;
566 tr->error |= ERROR_U_DBS;
567 die;
568 }
569
570
571 /* Do more in the forest
572 * Update radix tree for route and inetnum
573 */
574 if(tr->standalone==0) { /* only if server */
575
576
577 /* Only for these types of objects and only if we have collected data (tr->save != NULL) */
578 if( ( (tr->class_type==C_RT)
579 || (tr->class_type==C_IN)
580 || (tr->class_type==C_I6)
581 || (tr->class_type==C_DN))) {
582 /* Collect some data for radix tree and NH repository update */
583 g_slist_foreach((tr->object)->attributes, get_rx_data, tr);
584
585 /* Except for regular domains we need to update radix tree */
586 if(ACT_UPD_RX(tr->action)){
587 rp_upd_pack_t *packptr = tr->packptr;
588 packptr->key = tr->object_id;
589 if( RP_pack_node(RX_OPER_DEL, packptr, tr->source_hdl) == RX_OK ) {
590 err = 0;
591 } else {
592 err = (-1);
593 die;
594 }
595 } /* update radix tree */
596 }
597 }
598
599 /* Unlock all tables */
600 g_string_sprintf(query, "UNLOCK TABLES ");
601 sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
602 if (sql_err) {
603 fprintf(stderr, "E ERROR!<perform_update>: UNLOCK failed: [%d][%s]\n", num, query->str);
604 tr->succeeded=0;
605 tr->error |= ERROR_U_DBS;
606 die;
607 }
608
609
610 g_string_free(query, TRUE);
611
612 return(err);
613
614 } /* delete() */