## 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.17 $
       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    return(ERROR_U_MEM); }
      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 /* Rollback last and history tables */
     111     if(ACT_UPDATE(tr->action)) { /* so we are updating an object */
     112    g_string_sprintf(query, "DELETE FROM history WHERE object_id=%ld AND sequence_id=%ld", tr->object_id, tr->sequence_id-1);
     113    sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     114    /* we do not need to delete a row in the last for updates    */
     115   }
     116     else { /* we failed to create an object */
     117       sequence_id=1; /* sequence start == 1 */
     118    g_string_sprintf(query, "DELETE FROM last WHERE object_id=%ld AND sequence_id=%ld", tr->object_id, sequence_id);
     119    sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     120   }
     121
     122
     123     for(j=0; j < tr->ndummy; j++){/* if dummies have been created */
     124          g_string_sprintf(query, "DELETE FROM last WHERE object_id=%ld ", tr->dummy_id[j]);
     125          sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     126   }
     127
     128   /* Unlock all tables */
     129   g_string_sprintf(query, "UNLOCK TABLES ");
     130   sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     131
     132
     133   g_string_free(query, TRUE);
     134   return(0);
     135 } /* rollback() */
     136
     137
     138 /************************************************************
     139 * int commit()                                              *
     140 *                                                           *
     141 * Commits the transaction                                   *
     142 *                                                           *
     143 * It locks all relevant tables and processes the rollback   *
     144 * General approach is to clean up all new and updated       *
     145 * records related to the transaction                        *
     146 * (thread_id==thread_ins) and (thread_id==thread_upd),      *
     147 * and delete untouched ones (thread_id==0)                  *
     148 *                                                           *
     149 ************************************************************/
     150
     151 int commit(Transaction_t *tr) {
         /* [<][>][^][v][top][bottom][index][help] */
     152 GString *query;
     153 int err=0;
     154 int i,j;
     155 A_Type_t attr_type;
     156 int sql_err;
     157
     158 if(ACT_DELETE(tr->action)) return(0);
     159
     160  if ((query = g_string_sized_new(STR_XXL)) == NULL){
     161    fprintf(stderr, "E: cannot allocate gstring\n");
     162    tr->succeeded=0;
     163    tr->error|=ERROR_U_MEM;
     164    return(ERROR_U_MEM);
     165  }
     166
     167 /* Lock all relevant tables */
     168     g_string_sprintf(query, "LOCK TABLES %s WRITE,", DF_get_class_sql_table(tr->class_type));
     169
     170     for (i=0; tables[tr->class_type][i] != NULL; i++)
     171       g_string_sprintfa(query, " %s WRITE,", tables[tr->class_type][i]);
     172
     173     for (i=TAB_START; tables[tr->class_type][i] != NULL; i++)
     174       g_string_sprintfa(query, " %s WRITE,", tables[tr->class_type][i]);
     175
     176     g_string_sprintfa(query, " last WRITE, history WRITE ");
     177
     178     sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     179
     180 /* fprintf(stderr,"%s\n", query->str); */
     181
     182 /* Commit the transaction for AUX and LEAF tables that may be affected (taken from object template) */
     183   for (i=TAB_START; tables[tr->class_type][i] != NULL; i++) {
     184  /* Delete old records from the tables */
     185     g_string_sprintf(query, "DELETE FROM %s WHERE object_id=%ld AND thread_id=0 ", tables[tr->class_type][i], tr->object_id);
     186     sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     187     /*    fprintf(stderr, "D: query (del old): %s\n", query->str);  */
     188
     189  /* Set thread_id to 0 to commit the transaction */
     190     g_string_sprintf(query, "UPDATE %s SET thread_id=0 WHERE object_id=%ld", tables[tr->class_type][i], tr->object_id);
     191     sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     192     /*    fprintf(stderr, "D: query (com new): %s\n", query->str); */
     193   }
     194
     195 /* Commit the transaction for the MAIN tables */
     196
     197 /* Commit the transaction for person_role, mntner, as_set, route_set tables */
     198 /* They require different handling because of dummies */
     199 /* The rule is: Update: dummy->0, Insert: preserve dummy value */
     200 /* These tables do not require deletions since we cannot have such condition (object_id==0 AND thread_id==0) */
     201  if((tr->class_type==C_PN) || (tr->class_type==C_RO) ||
     202    (tr->class_type==C_AS) || (tr->class_type==C_RS) ||
     203    (tr->class_type==C_MT)){
     204
     205  /* Process the rows updated/touched */
     206     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);
     207     sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     208  }
     209
     210  switch (tr->class_type) {
     211    case C_IR:
     212    case C_IN:
     213    case C_I6:
     214    case C_FS:
     215     if((tr->save)){ /* Some special processing for tables with the second attribute */
     216      /* Update the second field of the table with query like one below */
     217      /* UPDATE %s SET thread_id=%d, local_as='%s' WHERE object_id=%ld */
     218
     219      switch(tr->class_type) {
     220       /* Local-as for inet-rtr */
     221       case C_IR: attr_type=A_LA;
     222                  break;
     223       /* netname for inetnum and inet6num */
     224       case C_IN:
     225       case C_I6: attr_type=A_NA;
     226                  break;
     227       /* filter for filter-set */
     228       case C_FS: attr_type=A_FI;
     229                  break;
     230       default:
     231                  die;
     232                  break;
     233      }
     234      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);
     235      sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     236     }
     237     else die;
     238     break;
     239
     240    default:
     241  /* Process all other MAIN tables for updates/inserts and person_role, mntner, as_set, route_set tables for rows inserts */
     242     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);
     243     sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     244     break;
     245  }
     246
     247
     248 /* for tables that might be affected by dummies */
     249  for(j=0; j < tr->ndummy; j++)/* if dummies have been created */
     250    for (i=0; tables[tr->class_type][i] != NULL; i++) {
     251     g_string_sprintf(query, "UPDATE %s SET thread_id=0 WHERE object_id=%ld ", tables[tr->class_type][i], tr->dummy_id[j]);
     252     sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     253  }
     254
     255
     256    for(j=0; j < tr->ndummy; j++){/* if dummies have been created*/
     257          g_string_sprintf(query, "UPDATE last SET thread_id=0 WHERE object_id=%ld ", tr->dummy_id[j]);
     258          sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     259   }
     260
     261  /* Unlock all tables */
     262  g_string_sprintf(query, "UNLOCK TABLES ");
     263  sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     264
     265  /* Update radix tree for route, inetnum and inaddr-arpa domain*/
     266  if(tr->standalone==0) { /* only if server*/
     267
     268  /* Create a radix node for the object */
     269    if( (   (tr->class_type==C_RT)
     270         || (tr->class_type==C_IN)
     271         || (tr->class_type==C_I6)
     272         || (tr->class_type==C_DN))
     273        && (ACT_UPD_RX(tr->action))) {
     274      rp_upd_pack_t *packptr = tr->packptr;
     275
     276      packptr->key = tr->object_id;
     277
     278      if( RP_pack_node(RX_OPER_CRE, packptr, tr->source_hdl) == RX_OK ) {
     279        err = 0;
     280      } else {
     281        err = (-1) ;
     282      }
     283    }
     284    /* XXX Check for errors */
     285  }
     286
     287   g_string_free(query, TRUE);
     288   return(err);
     289 } /* commit() */
     290
     291
     292 /************************************************************
     293 * int delete()                                              *
     294 *                                                           *
     295 * Deletes the object                                        *
     296 *                                                           *
     297 * It checks for referential integrity and then deletes the  *
     298 * object from all relevant tables. Then it updates the      *
     299 * radix tree for routes, inetnums and rev.domains           *
     300 *                                                           *
     301 ************************************************************/
     302 int delete(Transaction_t *tr)
         /* [<][>][^][v][top][bottom][index][help] */
     303 {
     304 GString *query;
     305 int err=0;
     306 int i;
     307 int num;
     308 long ref_id;
     309 long num_rec;
     310 long timestamp;
     311
     312 char sobject_id[STR_M];
     313 char *sql_str;
     314 int sql_err;
     315
     316
     317  /* Try to allocate g_string. Return on error */
     318  if ((query = g_string_sized_new(STR_XXL)) == NULL){
     319    fprintf(stderr, "E: cannot allocate gstring\n");
     320    tr->succeeded=0;
     321    tr->error|=ERROR_U_MEM;
     322    return(ERROR_U_MEM);
     323  }
     324
     325
     326 /* Check for referential integrity of deletion */
     327
     328    sprintf(sobject_id, "%ld", tr->object_id);
     329
     330    switch(tr->class_type){
     331     case C_PN:
     332     case C_RO:
     333
     334        /* Check that this person/role object is not referenced */
     335
     336        for (i=0; t_ipn[i] != NULL; i++) {
     337         /* Calculate number of references */
     338         sql_str= get_field_str(tr->sql_connection, "COUNT(*)", t_ipn[i], "pe_ro_id", sobject_id, NULL);
     339         if(sql_str) {
     340          num_rec = atol(sql_str);  free(sql_str);
     341          ref_id=tr->object_id;
     342          /* Check if it is a self reference (for role objects) */
     343          if(num_rec==1) {
     344           sql_str= get_field_str(tr->sql_connection, "object_id", t_ipn[i], "pe_ro_id", sobject_id, NULL);
     345           if(sql_str) {
     346            ref_id = atol(sql_str);  free(sql_str);
     347           } else {
     348            tr->succeeded=0; tr->error |= ERROR_U_DBS; break;
     349           }
     350          }
     351          /* If there are references (and not the only self reference) we cannot delete */
     352          if((num_rec>1) || (ref_id!=tr->object_id)) {
     353            g_string_sprintfa(tr->error_script,"E[%d][%ld]:ref integrity: %s\n" ,ERROR_U_OBJ, num_rec, t_ipn[i]);
     354            tr->succeeded=0; tr->error |= ERROR_U_OBJ;
     355          }
     356         } else {
     357         /* SQL error occured */
     358          tr->succeeded=0; tr->error |= ERROR_U_DBS;
     359          g_string_sprintfa(tr->error_script,"E[%d][%s]:%s\n", ERROR_U_DBS, t_ipn[i], SQ_error(tr->sql_connection));
     360         }
     361        }
     362
     363        /* Check that this person/role object is not referenced by name (legacy stuff) */
     364        /* But allow overriding this check in NRTM mode and with override_integrity    */
     365        if(tr->dummy==1)break;
     366
     367        for (i=0; t_ipn[i] != NULL; i++) {
     368         /* Calculate number of references */
     369
     370         g_string_sprintf(query, "SELECT COUNT(*) FROM %s, person_role "
     371                                 "WHERE person_role.object_id=%s.pe_ro_id "
     372                                 "AND person_role.nic_hdl='%s' ", t_ipn[i], t_ipn[i], tr->save);
     373
     374         sql_str= get_qresult_str(tr->sql_connection, query->str);
     375         if(sql_str) {
     376          num_rec = atol(sql_str);  free(sql_str);
     377          /* If there are references (no self reference is possible in this case) we cannot delete */
     378          if(num_rec>0) {
     379            g_string_sprintfa(tr->error_script,"E[%d][%ld]:ref integrity: %s\n" ,ERROR_U_OBJ, num_rec, t_ipn[i]);
     380            tr->succeeded=0; tr->error |= ERROR_U_OBJ;
     381          }
     382         } else {
     383         /* SQL error occured */
     384          tr->succeeded=0; tr->error |= ERROR_U_DBS;
     385          g_string_sprintfa(tr->error_script,"E[%d][%s]:%s\n", ERROR_U_DBS, t_ipn[i], SQ_error(tr->sql_connection));
     386         }
     387        }
     388
     389        break;
     390
     391     case C_MT:
     392
     393         /* Check that this mntner object is not referenced */
     394
     395        for (i=0; t_imt[i] != NULL; i++) {
     396        /* Calculate number of references */
     397         sql_str= get_field_str(tr->sql_connection, "COUNT(*)", t_imt[i], "mnt_id", sobject_id, NULL);
     398         if(sql_str) {
     399          num_rec = atol(sql_str);  free(sql_str);
     400          ref_id=tr->object_id;
     401          /* Check if it is a self reference  */
     402          if(num_rec==1) {
     403             sql_str= get_field_str(tr->sql_connection, "object_id", t_imt[i], "mnt_id", sobject_id, NULL);
     404             if(sql_str) {
     405               ref_id = atol(sql_str);  free(sql_str);
     406             } else {
     407               tr->succeeded=0; tr->error |= ERROR_U_DBS; break;
     408             }
     409          }
     410          /* If there are references (and not the only self reference) we cannot delete */
     411          if((num_rec>1) || (ref_id!=tr->object_id)) {
     412            g_string_sprintfa(tr->error_script,"E[%d][%ld]:ref integrity: %s\n" ,ERROR_U_OBJ, num_rec, t_imt[i]);
     413            tr->succeeded=0; tr->error |= ERROR_U_OBJ;
     414          }
     415         } else {
     416          tr->succeeded=0; tr->error |= ERROR_U_DBS;
     417         }
     418        }
     419        break;
     420
     421     case C_RS:
     422     case C_AS:
     423         /* Check that this set object is not referenced */
     424         /* Calculate number of references */
     425         sql_str= get_field_str(tr->sql_connection, "COUNT(*)", "member_of", "set_id", sobject_id, NULL);
     426         if(sql_str) {
     427          num_rec = atol(sql_str);  free(sql_str);
     428          /* XXX though set may contain other sets as memebers, */
     429          /* there is no member-of attribute in these objects. */
     430          /* So no self-reference is possible */
     431          if(num_rec!=0) {
     432            g_string_sprintfa(tr->error_script,"E[%d][%ld]:ref integrity: %s\n" ,ERROR_U_OBJ, num_rec, "member_of");
     433            /*tr->succeeded=0; tr->error |= ERROR_U_OBJ;*/
     434           /* XXX Do not refuse the transaction but change the object to dummy */
     435           /* Update the history table */
     436                g_string_sprintf(query,  "INSERT history "
     437                                         "SELECT 0, object_id, sequence_id, timestamp, object_type, object "
     438                                         "FROM last "
     439                                         "WHERE object_id=%ld ", tr->object_id);
     440
     441
     442                sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     443                if (sql_err) {
     444                 fprintf(stderr, "E ERROR!<perform_update>: INSERT history failed:[%d][%s]\n", num, query->str);
     445                 tr->succeeded=0;
     446                 tr->error |=ERROR_U_DBS;
     447                }
     448
     449                /* get sequence number */
     450                tr->sequence_id = get_sequence_id(tr);
     451                tr->sequence_id++;
     452
     453                /* insert new version into the last */
     454                timestamp=time(NULL);
     455
     456               /* update the main table */
     457               g_string_sprintf(query, "UPDATE %s SET dummy=1 WHERE object_id=%ld ", DF_get_class_sql_table(tr->class_type), tr->object_id);
     458
     459               sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     460               if (sql_err) {
     461                fprintf(stderr, "E ERROR!<perform_update>: UPDATE last failed: [%d][%s]\n", num, query->str);
     462                tr->succeeded=0;
     463                tr->error |= ERROR_U_DBS;
     464               }
     465
     466               /* empty the contents, but leave in the table to restrict re-use of object_id */
     467               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);
     468
     469               sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     470               if (sql_err) {
     471                fprintf(stderr, "E ERROR!<perform_update>: UPDATE last failed: [%d][%s]\n", num, query->str);
     472                tr->succeeded=0;
     473                tr->error |= ERROR_U_DBS;
     474               }
     475               return(0);
     476
     477          }
     478         } else {
     479          tr->succeeded=0; tr->error |= ERROR_U_DBS;
     480         }
     481         break;
     482
     483     default:
     484         break;
     485    }
     486
     487  /* Check if we have passed referential integrity check */
     488  if(tr->succeeded==0){
     489        return(-1);
     490  }
     491
     492
     493 /* Lock all relevant tables */
     494     g_string_sprintf(query, "LOCK TABLES %s WRITE,", DF_get_class_sql_table(tr->class_type));
     495
     496     for (i=0; tables[tr->class_type][i] != NULL; i++)
     497       g_string_sprintfa(query, " %s WRITE,", tables[tr->class_type][i]);
     498
     499     for (i=TAB_START; tables[tr->class_type][i] != NULL; i++)
     500       g_string_sprintfa(query, " %s WRITE,", tables[tr->class_type][i]);
     501
     502     g_string_sprintfa(query, " last WRITE, history WRITE ");
     503
     504     sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     505
     506     for (i=TAB_START; tables[tr->class_type][i] != NULL; i++) {
     507     g_string_sprintf(query, "DELETE FROM %s WHERE object_id=%ld ", tables[tr->class_type][i], tr->object_id);
     508     sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     509     /*    fprintf(stderr, "D: query (delete): %s\n", query->str);*/
     510   }
     511
     512 /* Process the MAIN table  */
     513     g_string_sprintf(query, "DELETE FROM %s WHERE object_id=%ld ", DF_get_class_sql_table(tr->class_type), tr->object_id);
     514     sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     515
     516 /* Update the history table */
     517     g_string_sprintf(query,     "INSERT history "
     518                                 "SELECT 0, object_id, sequence_id, timestamp, object_type, object "
     519                                 "FROM last "
     520                                 "WHERE object_id=%ld ", tr->object_id);
     521
     522
     523   sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     524   if (sql_err) {
     525          fprintf(stderr, "E ERROR!<perform_update>: INSERT history failed:[%d][%s]\n", num, query->str);
     526          tr->succeeded=0;
     527          tr->error |=ERROR_U_DBS;
     528   }
     529
     530   /* get sequence number */
     531   tr->sequence_id = get_sequence_id(tr);
     532   tr->sequence_id++;
     533
     534   /* insert new version into the last */
     535   timestamp=time(NULL);
     536
     537  /* empty the contents, but leave in the table to restrict re-use of object_id */
     538   g_string_sprintf(query, "UPDATE last SET object='', timestamp=%ld  WHERE object_id=%ld ", timestamp, tr->object_id);
     539
     540   sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     541   if (sql_err) {
     542         fprintf(stderr, "E ERROR!<perform_update>: UPDATE last failed: [%d][%s]\n", num, query->str);
     543          tr->succeeded=0;
     544          tr->error |= ERROR_U_DBS;
     545   }
     546
     547
     548   /* Do more in the forest
     549    * Update radix tree for route and inetnum
     550    */
     551   if(tr->standalone==0) { /* only if server */
     552   /* Collect some data for radix tree and NH repository update */
     553     g_slist_foreach((tr->object)->attributes, get_rx_data, tr);
     554
     555     /* Only for these types of objects and only if we have collected data (tr->save != NULL) */
     556     if( (   (tr->class_type==C_RT)
     557          || (tr->class_type==C_IN)
     558          || (tr->class_type==C_I6)
     559          || (tr->class_type==C_DN))
     560         && (ACT_UPD_RX(tr->action))) {
     561       rp_upd_pack_t *packptr = tr->packptr;
     562
     563       packptr->key = tr->object_id;
     564       if( RP_pack_node(RX_OPER_DEL, packptr, tr->source_hdl) == RX_OK ) {
     565         err = 0;
     566       } else {
     567         err = (-1) ;
     568       }
     569     }
     570   }
     571
     572  /* Unlock all tables */
     573   g_string_sprintf(query, "UNLOCK TABLES ");
     574   sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
     575
     576   g_string_free(query, TRUE);
     577
     578   return(err);
     579
     580 } /* delete() */

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