## modules/ud/ud_comrol.c

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

## FUNCTIONS

This source file includes following functions.

1. rollback
2. commit
3. 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() */

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