modules/ud/ud_core.c

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

FUNCTIONS

This source file includes following functions.
  1. convert_if
  2. convert_rf
  3. convert_as
  4. convert_as_range
  5. convert_time
  6. get_set_name
  7. get_object_id
  8. get_minmax_id
  9. get_qresult_str
  10. get_field_str
  11. get_sequence_id
  12. get_ref_id
  13. isdummy
  14. isnichandle
  15. process_reverse_domain
  16. insert_reverse_domain
  17. update_reverse_domain
  18. auth_member_of
  19. create_dummy
  20. update_attr
  21. each_attribute_process
  22. each_primary_key_select
  23. perform_create
  24. perform_update
  25. object_process

   1 /***************************************
   2   
   3   $Revision: 1.33 $
   4 
   5   Core functions for update lower layer 
   6 
   7   Status: NOT REVUED, NOT TESTED
   8 
   9  Author(s):       Chris Ottrey, Andrei Robachevsky
  10 
  11   ******************/ /******************
  12   Modification History:
  13         andrei (17/01/2000) Created.
  14   ******************/ /******************
  15   Copyright (c) 2000                              RIPE NCC
  16  
  17   All Rights Reserved
  18   
  19   Permission to use, copy, modify, and distribute this software and its
  20   documentation for any purpose and without fee is hereby granted,
  21   provided that the above copyright notice appear in all copies and that
  22   both that copyright notice and this permission notice appear in
  23   supporting documentation, and that the name of the author not be
  24   used in advertising or publicity pertaining to distribution of the
  25   software without specific, written prior permission.
  26   
  27   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  28   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  29   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  30   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  31   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  32   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  33  ***************************************/
  34 #include "ud.h"
  35 #include "ud_int.h"
  36 #include "ud_tr.h"
  37 
  38 #include <sys/types.h>
  39 #include <signal.h>
  40 #include <time.h>
  41 
  42 static int perform_update(Transaction_t *tr);
  43 
  44 static int perform_create(Transaction_t *tr);
  45 
  46 static void each_primary_key_select(void *element_data, void *result_ptr);
  47 
  48 static void each_attribute_process(void *element_data, void *tr_ptr);
  49 
  50 static void update_attr(Attribute_t *attr, Transaction_t *tr);
  51 
  52 static int create_dummy(Attribute_t *attr, Transaction_t *tr);
  53 
  54 static int auth_member_of(Attribute_t *attr, Transaction_t *tr);
  55 
  56 /***************************************************
  57 * char *s_split(char *line)                        *
  58 *                                                  *
  59 * Consequently returns words of the 'line'         * 
  60 * When there are no words it returns NULL          *
  61 * You need to retreive all words !                 *
  62 *                                                  *
  63 * NB This function damages 'line' replacing        *
  64 * whitespace with '\0'                             *
  65 * *************************************************/
  66 #define ATTR_DELIMITERS " ,"
  67 
  68 
  69 /**********************************************************
  70 * Attribute expansion/conversion functions                *
  71 ***********************************************************/
  72 /* Convert ifaddr attribute into numbers */
  73 er_ret_t convert_if(char *avalue, unsigned int *pif_address)
     /* [<][>][^][v][top][bottom][index][help] */
  74 {
  75 char *delim;
  76 ip_addr_t ip_addr;
  77 er_ret_t ret;
  78 
  79   if ((delim=index(avalue, ' '))!=NULL) *delim='\0';
  80   ret=IP_addr_a2v4(avalue, &ip_addr,  pif_address );
  81   return(ret);
  82 }
  83 
  84 
  85 /* Convert refer attribute. Free host after use ! */
  86 char *convert_rf(char *avalue, int *type, int *port)
     /* [<][>][^][v][top][bottom][index][help] */
  87 {
  88 char *delim, *token;
  89 char buff[STR_M];
  90 char *host;
  91 
  92   host=NULL;
  93   strcpy(buff, avalue);
  94   g_strchug(buff);
  95   delim=index(buff, ' ');
  96   *delim='\0';
  97   delim++; 
  98 
  99 /* convert the type      */
 100   if(strcmp(buff, S_RIPE)==0)*type=RF_RIPE;
 101    else if(strcmp(buff, S_INTERNIC)==0)*type=RF_INTERNIC;
 102     else if(strcmp(buff, S_SIMPLE)==0)*type=RF_SIMPLE;
 103      else if(strcmp(buff, S_CLIENTADDERSS)==0)*type=RF_CLIENTADDRESS;
 104 
 105   token=delim;
 106   g_strchug(token);
 107   delim=index(token, ' ');
 108   if(delim){
 109    *delim='\0';
 110    delim++; 
 111   }           
 112 /* convert the hostname      */
 113   host = g_strdup(token);
 114       
 115 /* convert port number      */
 116   if(delim){
 117     token=delim;        
 118     *port = atoi(token);
 119     if (*port==0) *port=RF_DEF_PORT; /* default port number*/
 120   } else *port=RF_DEF_PORT;
 121   return(host);
 122 }
 123 
 124 
 125 /* Convert AS# into integer */
 126 static int convert_as(char *as)
     /* [<][>][^][v][top][bottom][index][help] */
 127 {
 128 char *ptr;
 129  ptr=as; ptr++; ptr++; 
 130  return(atoi(ptr));   
 131 }
 132 
 133 /* Convert AS range (AS4321 - AS5672) into numbers */
 134 int convert_as_range(const char *as_range, int *begin, int *end)
     /* [<][>][^][v][top][bottom][index][help] */
 135 {
 136 char *range;
 137 char *token;
 138   
 139   range=g_strdup(as_range);
 140   token=range;
 141   *begin=convert_as(strsep(&token, " -"));
 142   *end=convert_as(strsep(&token, " -"));
 143   free(range);
 144   return(0);
 145 }
 146 
 147 /* Convert time in ASCII format (19991224) into time_t unix time */
 148 time_t convert_time(char *asc_time)
     /* [<][>][^][v][top][bottom][index][help] */
 149 {
 150 struct tm tm;
 151 char buf[STR_S];
 152 char *ptr;
 153 
 154   
 155   bzero(&tm, sizeof(tm));
 156   
 157   strncpy(buf, asc_time, 4); ptr=buf+4; *ptr='\0';
 158   tm.tm_year = atoi(buf) - 1900;
 159   
 160   strncpy(buf, (asc_time+4), 2); ptr=buf+2; *ptr='\0';
 161   tm.tm_mon = atoi(buf) - 1;
 162   
 163   strncpy(buf, (asc_time+6), 2); ptr=buf+2; *ptr='\0';
 164   tm.tm_mday = atoi(buf);
 165   
 166   return(mktime(&tm));
 167 
 168 }     
 169 
 170 
 171 /************************************************************
 172 *  char *get_set_name()                                     *
 173 *                                                           *
 174 * Returns set name for the specified object class           *
 175 *                                                           *
 176 * **********************************************************/
 177 static char *get_set_name(C_Type_t class_type)
     /* [<][>][^][v][top][bottom][index][help] */
 178 {
 179  switch(class_type){
 180   case C_RT:   return("route_set");
 181   case C_AN:   return("as_set");
 182   default:     return(NULL);
 183  }
 184 }
 185 
 186 
 187 /************************************************************
 188 * long get_object_id()                                      *
 189 * Queries the database for an object.                       *
 190 * For constructing a query uses each_primary_key_select()   *
 191 *                                                           *
 192 * Returns:                                                  *
 193 * >0 - object exists, returns object_id                     *
 194 * 0  - object does not exist                                *
 195 * -1 - error (f.e. more than one object with the same PK)   *
 196 * Error code is stored in tr->error                         *
 197 *                                                           *
 198 * **********************************************************/
 199 long get_object_id(Transaction_t *tr)
     /* [<][>][^][v][top][bottom][index][help] */
 200 {
 201 Object_t *obj;
 202 SQ_result_set_t *sql_result;
 203 SQ_row_t *sql_row;
 204 char *sql_str;
 205 long object_id=0;
 206 int sql_err;
 207 
 208  obj=tr->object;
 209 
 210  if ((tr->query = g_string_sized_new(STR_XL)) == NULL){ 
 211   ER_perror(FAC_UD, UD_MEM, "cannot allocate gstring\n");
 212   tr->succeeded=0;
 213   tr->error |= ERROR_U_MEM;
 214   die; 
 215  }
 216  
 217 /* compose query */
 218  g_string_sprintf(tr->query, "SELECT object_id FROM %s WHERE",DF_get_class_sql_table(obj->type));
 219  /* add all primary keys */ 
 220  g_slist_foreach(obj->attributes, each_primary_key_select, tr);
 221  /* truncate the last ' AND '*/
 222  g_string_truncate(tr->query, (tr->query->len) - 4); 
 223         
 224 /* execute query */
 225  ER_dbg_va(FAC_UD, ASP_UD_SQL, "%s [%s]", UD_TAG, tr->query->str);
 226  sql_err=SQ_execute_query(tr->sql_connection, tr->query->str, &sql_result);
 227   
 228 /* in case of an error copy error code and return */ 
 229  if(sql_err) {
 230    ER_perror(FAC_UD, UD_SQL, "%s[%s]\n", SQ_error(tr->sql_connection), tr->query->str);
 231    tr->succeeded=0;
 232    tr->error |= ERROR_U_DBS;
 233    die;
 234  }
 235  g_string_free(tr->query, TRUE);
 236 
 237 /* Fetch the row */ 
 238  if ((sql_row = SQ_row_next(sql_result)) != NULL) {
 239 /* Object exists */
 240 #define OBJECT_ID 0
 241    sql_str = SQ_get_column_string(sql_result, sql_row, OBJECT_ID);
 242    if (sql_str != NULL) {
 243      object_id = atol(sql_str);
 244      free(sql_str);
 245    }
 246 
 247 /* We must process all the rows of the result */
 248 /* otherwise we'll have them as part of the next qry */      
 249    while ( (sql_row = SQ_row_next(sql_result)) != NULL) object_id=-1;
 250  } else 
 251       object_id=0;  /* object does not exist*/
 252    
 253  SQ_free_result(sql_result);
 254  return(object_id);
 255 }
 256 
 257 /************************************************************
 258 * get_minmax_id()                                           *
 259 *                                                           *
 260 * Returns the min or max ID of the table                    *
 261 *                                                           *
 262 * Returns:                                                  *
 263 *  min (max=0) or max (max=1) ID                            *
 264 *  -1 in case of an error                                   *
 265 *                                                           *
 266 *                                                           *
 267 *************************************************************/
 268 long get_minmax_id(SQ_connection_t *sql_connection, char *id_name, char *tbl_name, int max)
     /* [<][>][^][v][top][bottom][index][help] */
 269 {
 270 char query[STR_M];
 271 SQ_result_set_t *sql_result;
 272 SQ_row_t *sql_row;
 273 char *sql_str;
 274 long id;
 275 char *minmax;
 276 int sql_err;
 277 
 278 if(max==1)minmax="max"; else minmax="min";
 279 
 280  sprintf(query, "SELECT %s(%s) FROM %s ", minmax, id_name, tbl_name);
 281 
 282  ER_dbg_va(FAC_UD, ASP_UD_SQL, "%s [%s]", UD_TAG, query);
 283  sql_err = SQ_execute_query(sql_connection, query, &sql_result);
 284  
 285  if(sql_err) {
 286     ER_perror(FAC_UD, UD_SQL, "%s[%s]\n", SQ_error(sql_connection), query);
 287     die;
 288  }
 289         
 290          
 291  if ((sql_row = SQ_row_next(sql_result)) != NULL) {
 292         sql_str = SQ_get_column_string(sql_result, sql_row, 0);
 293 
 294      /* We must process all the rows of the result,*/
 295      /* otherwise we'll have them as part of the next qry */
 296         while ( (sql_row = SQ_row_next(sql_result)) != NULL) {
 297           ER_perror(FAC_UD, UD_SQL, "duplicate PK [%s]\n", query);
 298           if(sql_str)free(sql_str); sql_str=NULL;
 299           die;
 300         }
 301  }
 302  else sql_str=NULL;
 303  
 304  if(sql_result){ SQ_free_result(sql_result); sql_result=NULL; }
 305  
 306  if(sql_str) {
 307   id = atol(sql_str);
 308   free(sql_str);
 309  }
 310  else id=-1;
 311  
 312  return(id);
 313  
 314 }
 315 
 316 
 317 /************************************************************
 318 * get_qresult_str()                                         *
 319 *                                                           *
 320 * Returns string containing query result                    *
 321 *                                                           *
 322 *                                                           *
 323 * Returns:                                                  *
 324 *  String containing the result.Needs to be freed after use *
 325 *  NULL in case of an error                                 *
 326 *  - SQL error                                              *
 327 *  - if query returns more than one string (row)            *
 328 *                                                           *
 329 *************************************************************/
 330 char *get_qresult_str(SQ_connection_t *sql_connection, char *query)
     /* [<][>][^][v][top][bottom][index][help] */
 331 {
 332 SQ_result_set_t *sql_result;
 333 SQ_row_t *sql_row;
 334 char *sql_str;
 335 int sql_err;
 336 
 337 
 338  ER_dbg_va(FAC_UD, ASP_UD_SQL, "%s [%s]", UD_TAG, query);
 339  sql_err=SQ_execute_query(sql_connection, query, &sql_result);
 340  
 341  if(sql_err) {
 342     ER_perror(FAC_UD, UD_SQL, "%s[%s]\n", SQ_error(sql_connection), query);
 343     die;
 344  }
 345         
 346          
 347  if ((sql_row = SQ_row_next(sql_result)) != NULL) {
 348         sql_str = SQ_get_column_string(sql_result, sql_row, 0);
 349 
 350      /* We must process all the rows of the result,*/
 351      /* otherwise we'll have them as part of the next qry */
 352         while ( (sql_row = SQ_row_next(sql_result)) != NULL) {
 353           ER_perror(FAC_UD, UD_SQL, "duplicate PK [%s]\n", query); 
 354           if(sql_str)free(sql_str); sql_str=NULL;
 355         }
 356  }
 357  else sql_str=NULL;
 358  
 359  SQ_free_result(sql_result);
 360  return(sql_str);
 361 }
 362 
 363 
 364 
 365 /************************************************************
 366 * get_field_str()                                           *
 367 *                                                           *
 368 * Returns string containing the field.                      *
 369 *  field - field name to be retrieved                       *
 370 *  ref_tbl_name - name of the table containing the field    *
 371 *  ref_name - reference name                                *
 372 *  attr_value - reference value                             *
 373 *  condition - additional condition ( f.e. 'AND dummy=0'    *
 374 *                                                           *
 375 * Returns:                                                  *
 376 *  String containing the field. Needs to be freed after use *
 377 *  NULL in case of an error                                 *
 378 *                                                           *
 379 *************************************************************/
 380 char *get_field_str(SQ_connection_t *sql_connection, char *field, 
     /* [<][>][^][v][top][bottom][index][help] */
 381                            char *ref_tbl_name, char *ref_name, 
 382                            char * attr_value, char *condition)
 383 {
 384 char query[STR_L];
 385 
 386  sprintf(query, "SELECT %s FROM %s "
 387                 "WHERE %s='%s' ",
 388                 field, ref_tbl_name, ref_name, attr_value);
 389  if (condition)strcat(query, condition);
 390 
 391  return( get_qresult_str(sql_connection, query));
 392 
 393 } 
 394 
 395 /************************************************************
 396 * long get_sequence_id(Transaction_t *tr)
 397 * >0 - success
 398 * -1 - sql error
 399 *
 400 * **********************************************************/
 401 
 402 long get_sequence_id(Transaction_t *tr)
     /* [<][>][^][v][top][bottom][index][help] */
 403 {
 404 char *sql_str;
 405 char str_id[STR_M];
 406 long sequence_id=-1;
 407 
 408 
 409   sprintf(str_id, "%ld", tr->object_id);
 410   sql_str= get_field_str(tr->sql_connection, "sequence_id", "last", "object_id", str_id, NULL);
 411   if(sql_str) {
 412           sequence_id = atol(sql_str);
 413           free(sql_str);
 414   }
 415   
 416   return(sequence_id);
 417 
 418 }
 419 
 420 
 421 /************************************************************
 422 * long get_ref_id(char *ref_tbl_name, char *ref_name, char * attr_value)
 423 * >0 - success
 424 * -1 - sql error
 425 *
 426 * **********************************************************/
 427 
 428 static long get_ref_id(Transaction_t *tr, char *ref_tbl_name, char *ref_name, char * attr_value, char *condition)
     /* [<][>][^][v][top][bottom][index][help] */
 429 {
 430 char *sql_str;
 431 long ref_id=-1;
 432 
 433         sql_str= get_field_str(tr->sql_connection, "object_id", ref_tbl_name, ref_name, attr_value, condition);
 434         if(sql_str) {
 435                  ref_id = atol(sql_str);
 436                  free(sql_str);
 437         }
 438         return(ref_id); 
 439 }
 440 
 441 
 442 /************************************************************
 443 * int isdummy()
 444 *
 445 * Returns 1 if the object in question is a dummy, 
 446 * otherwise returns 0.
 447 * 
 448 * In case of error:
 449 * -1 - sql error or object does not exist
 450 *
 451 ***********************************************************/
 452 
 453 int isdummy(Transaction_t *tr)
     /* [<][>][^][v][top][bottom][index][help] */
 454 {
 455 char *sql_str;
 456 char str_id[STR_M];
 457 int object_type=-1;
 458 
 459   sprintf(str_id, "%ld", tr->object_id);
 460   sql_str= get_field_str(tr->sql_connection, "object_type", "last", "object_id", str_id, NULL);
 461   if(sql_str) {
 462           object_type = atoi(sql_str);
 463           free(sql_str);
 464   }
 465   
 466   if (object_type==-1) {
 467    ER_perror(FAC_UD, UD_SQL, "cannot get object type\n");
 468    die;
 469   } 
 470   if (object_type==DUMMY_TYPE) return(1);
 471   else return(0);
 472 
 473 }
 474 
 475 /* it may be either a legacy name reference, or a nic-handle  */
 476 /* we rely on other parsers/syntax checkers, so no surprises  */
 477 /* thus, the check is simple - if there is a space - not a nh */
 478 static int isnichandle(char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 479 {
 480  if(index(name, ' ')) return(0);
 481  else return(1);        
 482 }
 483 
 484 
 485 /************************************************************
 486 * process_reverse_domain()                                  *
 487 *                                                           *
 488 * Tries to insert additional data for reverse domains       *
 489 * This data includes prefix and perfix length for reverse   *
 490 * delegation block. It is stored in inaddr_arpa table for   *
 491 * IPv4 and ip6int table for IPv6 address spaces             *
 492 *                                                           *
 493 * Returns:                                                  *
 494 * 0  success                                                *
 495 * -1 sql error                                              *
 496 *                                                           *
 497 *************************************************************/
 498 
 499 static int process_reverse_domain(Transaction_t *tr, 
     /* [<][>][^][v][top][bottom][index][help] */
 500                                   ip_prefix_t *prefptr,
 501                                   int op)
 502 {
 503   unsigned prefix, prefix_length; /* ipv4 */
 504   ip_v6word_t msb, lsb;          /* ipv6 */
 505   char query[STR_L];
 506   int num;
 507   int sql_err;
 508 
 509                                   
 510   if( IP_pref_b2_space(prefptr) == IP_V4 ) {  /* ipv4 */
 511     if(op==0) { /* insert record */
 512       IP_revd_b2v4(prefptr, &prefix, &prefix_length);
 513       sprintf(query, "INSERT INTO inaddr_arpa SET thread_id=%d, object_id=%ld, prefix=%u, prefix_length=%d ", 
 514               tr->thread_ins, tr->object_id, prefix, prefix_length);
 515     }
 516     else {
 517       /* update record */
 518       sprintf(query, "UPDATE inaddr_arpa SET thread_id=%d WHERE object_id=%ld ", 
 519               tr->thread_upd, tr->object_id);
 520     }
 521   }
 522   else { /* ipv6 */
 523     if(op==0) { /* insert record */   
 524       IP_revd_b2v6(prefptr, &msb, &lsb, &prefix_length);
 525       sprintf(query, "INSERT INTO ip6int SET thread_id=%d, object_id=%ld, msb='%llu', lsb='%llu', prefix_length=%d ", 
 526               tr->thread_ins, tr->object_id, msb, lsb, prefix_length);
 527     }
 528     else {
 529       /* update record */
 530       sprintf(query, "UPDATE ip6int SET thread_id=%d WHERE object_id=%ld ", 
 531               tr->thread_upd, tr->object_id);
 532     }
 533   }
 534 
 535   ER_dbg_va(FAC_UD, ASP_UD_SQL, "%s [%s]", UD_TAG, query);
 536   sql_err = SQ_execute_query(tr->sql_connection, query, (SQ_result_set_t **)NULL);
 537   num = mysql_affected_rows(tr->sql_connection); 
 538   
 539   /* Check for errors */
 540   if (sql_err) {
 541    ER_perror(FAC_UD, UD_SQL, "%s[%s]\n", SQ_error(tr->sql_connection), query);
 542    die;
 543   }
 544   /* If nothing was affected then WHERE clause returned nothing - DB error */
 545   if(num == 0) {
 546    ER_perror(FAC_UD, UD_SQL, "insert inaddr had no effect [%s]\n", query);
 547    die;
 548   }       
 549   return(0);
 550 }
 551 
 552 #define insert_reverse_domain(tr, pr) process_reverse_domain(tr, pr, 0)
     /* [<][>][^][v][top][bottom][index][help] */
 553 #define update_reverse_domain(tr, pr) process_reverse_domain(tr, pr, 1)
     /* [<][>][^][v][top][bottom][index][help] */
 554 
 555 
 556 /************************************************************
 557 * auth_member_of()                                          *
 558 *                                                           *
 559 * Function that checks the authorization for membership     *
 560 * (i.e. if the object is authorized to be a memeber by      *
 561 * mbrs-by-ref attribute of the set is refers by member-of   *
 562 * attribute).                                               *
 563 * First checks if 'mbrs-by-ref: ANY'                        *
 564 * If not then checks that maintner referenced by            *
 565 * mbrs-by-ref attribute of the set is the one in mnt-by.    *
 566 *                                                           *
 567 * Returns:                                                  *
 568 * 0  success                                                *
 569 * 1  not allowed                                            *
 570 * -1 SQL error                                              *  
 571 *                                                           *
 572 *************************************************************/
 573 static int auth_member_of(Attribute_t *attr, Transaction_t *tr)
     /* [<][>][^][v][top][bottom][index][help] */
 574 {
 575 GString *query;
 576 char *set_name;
 577 char *qresult;
 578 
 579 /* Check if set has mbrs_by_ref==ANY 
 580    In such case mbrs_by_ref.mnt_id==0 
 581 */
 582 
 583  if ((query = g_string_sized_new(STR_XL)) == NULL){
 584   tr->succeeded=0;
 585   tr->error |= ERROR_U_MEM; 
 586   ER_perror(FAC_UD, UD_MEM, "cannot allocate gstring\n"); 
 587   die; 
 588  }
 589  
 590  set_name = get_set_name(tr->class_type);
 591 /* ER_dbg_va(FAC_UD, ASP_UD_OBJ, "%s set name retrieved: %s\n", UD_TAG, set_name);      */
 592 
 593 /* Check if the set protects itself with mbrs-by-ref attribute */
 594    g_string_sprintf(query,"SELECT COUNT(*) FROM mbrs_by_ref, %s "
 595                           "WHERE mbrs_by_ref.object_id=%s.object_id "
 596                           "AND %s.%s='%s' ",
 597                           set_name, set_name, set_name, set_name, attr->value);
 598 
 599    qresult = get_qresult_str(tr->sql_connection, query->str);
 600    /* should be '0' if there is no mbrs-by-ref attribute */
 601    if (strcmp(qresult, "0")==0){
 602            /* there is no mbrs-by-ref attribute - so we cannot go ahead */
 603            ER_dbg_va(FAC_UD, ASP_UD_OBJ, "[%ld] membership by reference is not allowed (no mbrs-by-ref) [%d:%s]", tr->transaction_id, attr->type, attr->value);
 604            g_string_free(query, TRUE);
 605            return(1);
 606    }
 607    else free(qresult);
 608 
 609 /* Check if membership is protected by the keyword "ANY" */
 610 /* There is a dummy mntmer object in the database corresponding to "ANY" */
 611 /* Its object_id==0 */
 612 /* EXAMPLE:
 613 
 614    SELECT route_set.object_id 
 615    FROM   mbrs_by_ref, route_set
 616    WHERE  mbrs_by_ref.object_id=route_set.object_id
 617    AND    route_set.route_set=<setname>
 618    AND    mbrs_by_ref.mnt_id=0
 619 */   
 620     g_string_sprintf(query,"SELECT %s.object_id FROM mbrs_by_ref, %s "
 621                            "WHERE mbrs_by_ref.object_id=%s.object_id "
 622                            "AND %s.%s='%s' AND mbrs_by_ref.mnt_id=0 ", 
 623                            set_name, set_name, set_name, set_name, set_name, attr->value);
 624   
 625     qresult = get_qresult_str(tr->sql_connection, query->str);
 626   /* if such record exists - go ahead */
 627     if(qresult) {
 628         free(qresult);  
 629         g_string_free(query, TRUE);
 630         return(0);  
 631     }
 632 
 633 /* Now check if our mnt_by belongs to mbrs_by_ref list of the set */
 634 /* we search only mnt_by.thread_id!=0 to check against new/updated mnt-by attribute */
 635     g_string_sprintf(query, "SELECT mbrs_by_ref.object_id FROM route_set, mbrs_by_ref, mnt_by "
 636                             "WHERE mbrs_by_ref.mnt_id=mnt_by.mnt_id "
 637                             "AND mnt_by.object_id=%ld "
 638                             "AND %s.object_id=mbrs_by_ref.object_id "
 639                             "AND %s.%s='%s' "
 640                             "AND mnt_by.thread_id!=0 ",
 641                             tr->object_id, set_name, set_name, set_name, attr->value);
 642 
 643     qresult = get_qresult_str(tr->sql_connection, query->str);
 644     /* If our mntner is listed (non-empty result)  membership is authorized */
 645     if (qresult) {
 646          free(qresult);g_string_free(query, TRUE);
 647          return(0);
 648     } else {
 649          ER_dbg_va(FAC_UD, ASP_UD_OBJ, "[%ld] membership by reference is not autorized [%d:%s]", tr->transaction_id, attr->type, attr->value);
 650          g_string_free(query, TRUE);
 651          return(1);
 652     }
 653  }/* auth_member_of()  */
 654         
 655 
 656 /************************************************************
 657 * create_dummy()                                            *
 658 *                                                           *
 659 * Function that creates a dummy object (that is one that    *
 660 * is referenced from an object but does not                 *
 661 * exist in the database).                                   *
 662 * Dummy object exists only in relevant main and 'last'      *
 663 * tables. Its creation is controlled by tr->dummy_allowed.  *
 664 * Queries for the dummies are defined in Dummy[] array.     *
 665 *                                                           *
 666 * Returns:                                                  *
 667 * 0  success                                                *
 668 * 1  no rf integrity and dummy not allowed                  *
 669 * -1 SQL error                                              *
 670 *                                                           *
 671 *************************************************************/
 672 static int create_dummy(Attribute_t *attr, Transaction_t *tr) 
     /* [<][>][^][v][top][bottom][index][help] */
 673 {
 674 const char *query_fmt;
 675 long dummy_id;
 676 char query[STR_L];
 677 int result=0;
 678 char *set_name;
 679 char *p_name;
 680 int query_type;
 681 long timestamp;
 682 char str_id[STR_M];
 683 gchar *attr_value=NULL;
 684 int sql_err;
 685 char *token=NULL;
 686 
 687   query_fmt = DF_get_dummy_query(attr->type);
 688   if (strcmp(query_fmt, "") == 0) { 
 689      ER_perror(FAC_UD, UD_BUG, "empty query string\n");
 690      die;
 691   }
 692   
 693   /* We allow creating dummy sets in any mode */
 694   /* For others attributes return if we are in protected mode */
 695   if ((attr->type!=A_MO) &&  (!IS_DUMMY_ALLOWED(tr->mode))) return(1);
 696 
 697   /* Insert dummy in the last table */
 698   /* Calculate the object_id - should be max+1 */
 699   dummy_id = get_minmax_id(tr->sql_connection, "object_id", "last", 1) +1;
 700  /* Record dummy's object_id, it'll be needed in commit/rollback */
 701   tr->dummy_id[tr->ndummy]=dummy_id; tr->ndummy++;
 702 
 703   /* Update the TR for crash recovery */
 704   /* If we crash before actually creating an entry in last */
 705   /* there should be no harm - later in rollback we will just try to delete nonexistent object */
 706   TR_update_dummy(tr);
 707 
 708   sprintf(str_id, "%ld", tr->object_id);
 709   timestamp=time(NULL);
 710   sprintf(query, "INSERT INTO last SET thread_id=%d, timestamp=%ld, object_type=%d, object='DUMMY for %s'", 
 711                   tr->thread_ins, timestamp, DUMMY_TYPE, str_id);
 712   
 713   ER_dbg_va(FAC_UD, ASP_UD_SQL, "%s [%s]", UD_TAG, query);
 714   sql_err = SQ_execute_query(tr->sql_connection, query, (SQ_result_set_t **)NULL);
 715   
 716   /* Check for errors */
 717   if (sql_err) {
 718    ER_perror(FAC_UD, UD_SQL, "%s[%s]\n", SQ_error(tr->sql_connection), query);    
 719    die;
 720   }     
 721         
 722   /* check that the dummy_id is correct */
 723   if(dummy_id != mysql_insert_id(tr->sql_connection)) die; /* probably implementation of autoincrement changed */
 724 
 725    
 726   /* compose the query */
 727   query_type=DF_get_dummy_query_type(attr->type);
 728   switch (query_type) { 
 729          
 730          /* person_role */
 731          case UD_AX_PR:
 732               sprintf(query, query_fmt, tr->thread_ins, dummy_id, attr->value, DUMMY_TYPE);
 733               break;
 734          
 735          /* maintner */
 736          case UD_AX_MT: 
 737               sprintf(query, query_fmt, tr->thread_ins, dummy_id, attr->value, DUMMY_TYPE);
 738               break;
 739          
 740          /* as_set, route_set */
 741          case UD_AX_MO: 
 742               set_name = get_set_name(tr->class_type);
 743               sprintf(query, query_fmt, set_name, tr->thread_ins, dummy_id, set_name, attr->value);       
 744               break;
 745               
 746          default:
 747               ER_perror(FAC_UD, UD_BUG, "query not defined for this type of attribute[%d]\n", attr->type);
 748               die;
 749               break;
 750   }
 751         
 752   ER_dbg_va(FAC_UD, ASP_UD_SQL, "%s [%s]", UD_TAG, query);
 753   sql_err = SQ_execute_query(tr->sql_connection, query, (SQ_result_set_t **)NULL);
 754   if (sql_err) {
 755    ER_perror(FAC_UD, UD_SQL, "%s[%s]\n", SQ_error(tr->sql_connection), query);
 756    die;
 757   }
 758   
 759   /* for legacy person/role reference (without nic-handle) create records in names table */
 760   if( (query_type == UD_AX_PR) && (!isnichandle (attr->value)) ){
 761    /* parse the names */
 762     /*ER_dbg_va(FAC_UD, ASP_UD_OBJ, "%s adding names for dummy\n", UD_TAG);*/
 763     query_fmt = DF_get_insert_query(A_PN);
 764     attr_value = g_strdup(attr->value); 
 765     token = attr_value;
 766     while((p_name=strsep(&token, " "))){
 767                 sprintf(query, query_fmt, tr->thread_ins, dummy_id, DUMMY_TYPE, p_name);
 768                 ER_dbg_va(FAC_UD, ASP_UD_SQL, "%s [%s]", UD_TAG, query);
 769                 sql_err = SQ_execute_query(tr->sql_connection, query, (SQ_result_set_t **)NULL);
 770                 if (sql_err)
 771                  if(SQ_errno(tr->sql_connection) != ER_DUP_ENTRY) {
 772                   ER_perror(FAC_UD, UD_SQL, "insert dummy names:%s[%s]\n", SQ_error(tr->sql_connection), query);
 773                   result=-1;
 774                  }
 775     }
 776     free(attr_value);
 777   }
 778  return(result);
 779 }
 780 
 781 /************************************************************
 782 * update_attr()                                             *
 783 *                                                           *
 784 * Function that updates an attribute if it already exists.  *
 785 * Called from each_attribute_proces() function if it        *
 786 * cannot insert the row.                                    *
 787 * Queries for the attributes are defined in Update[] array. *
 788 *                                                           *
 789 * Returns: Nothing. Error code is stored in tr->error.      *
 790 *                                                           *
 791 *************************************************************/
 792 static void update_attr(Attribute_t *attr, Transaction_t *tr)
     /* [<][>][^][v][top][bottom][index][help] */
 793 {
 794 int num;
 795 const char *query_fmt;
 796 char *set_name;
 797 unsigned int if_address;
 798 char * rf_host;
 799 int rf_port, rf_type;
 800 char *a_value;
 801 int sq_info[3];
 802 char * condition;
 803 char *sq_error;
 804 char query[STR_XL];
 805 ip_prefix_t dn_pref;
 806 int sql_err;
 807 char *token;
 808 char *mu_mntner;
 809 
 810 
 811 /* It may be needed to update second attribute stored in the main table, like inetnum, filter-set, etc. */
 812  if((tr->load_pass!=0)&&(DF_get_update_query_type(attr->type)!=UD_MA_U2)) return;
 813 
 814 /*      ER_dbg_va(FAC_UD, ASP_UD_OBJ, "%s updating attribute...\n", UD_TAG);*/
 815 
 816    /* Do some additional processing for reverse domains */
 817    /* XXX Later we will implement this under UD_MA_DN case */
 818    if ((attr->type == A_DN) && (IP_revd_a2b(&dn_pref, attr->value)==IP_OK)) {
 819      if(update_reverse_domain(tr, &dn_pref) !=0 ){
 820        tr->error|=ERROR_U_DBS;
 821        tr->succeeded=0;
 822        g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:%s\n" ,
 823                          ERROR_U_DBS, attr->type, attr->value, SQ_error(tr->sql_connection));   
 824      }
 825    }
 826    
 827    /* get query format string */
 828    query_fmt =  DF_get_update_query(attr->type);
 829 
 830    if (strcmp(query_fmt, "") == 0) return;
 831 
 832    switch (DF_get_update_query_type(attr->type)) {
 833          case UD_MAIN_: sprintf(query, query_fmt, tr->thread_upd, tr->object_id);
 834                         break;
 835          case UD_MA_PR: 
 836                         sprintf(query, query_fmt, tr->thread_upd, tr->class_type, tr->object_id);
 837                         break;  
 838          case UD_MA_U2: /* save the new value of the attribute for commit*/
 839                   /* this is necessary for filter(filter-set), netname (inet?num), */
 840                   /* local-as(inet-rtr) attributes, as they are another field in the record */
 841                         if((tr->load_pass != 0)){
 842                       /* for fast loader we need to update the field as we have no commit */
 843                           sprintf(query, query_fmt, DF_get_class_sql_table(tr->class_type), 0, attr->value, tr->object_id);
 844                         }
 845                         else {
 846                          tr->save=g_strdup(attr->value);
 847 /*                       ER_dbg_va(FAC_UD, ASP_UD_OBJ, "%s u2 saved [%s]\n", UD_TAG, tr->save); */
 848                          /* update TR for crash recovery */
 849                          TR_update_save(tr);
 850                          return;
 851                         }        
 852                         break;                  
 853          case UD_AX_PR:
 854                         /* This is for non-conformant admin-c, etc.*/
 855                         a_value=attr->value;
 856                         if(strlen(attr->value)>MAX_NIC_HDL)*(attr->value + MAX_NIC_HDL)='\0';
 857                         
 858                         if (!IS_DUMMY_ALLOWED(tr->mode))condition="AND dummy=0 "; else condition=NULL;
 859                         sprintf(query, query_fmt, tr->thread_upd, tr->object_id, 
 860                                 get_ref_id(tr, "person_role", "nic_hdl", attr->value, condition));
 861                         break;
 862          case UD_AX_MT: 
 863                         if (!IS_DUMMY_ALLOWED(tr->mode))condition="AND dummy=0 "; else condition=NULL;
 864                         sprintf(query, query_fmt, tr->thread_upd, tr->object_id, 
 865                                 get_ref_id(tr, "mntner", "mntner", attr->value, condition));
 866                         break;
 867          case UD_AX_MU: /* for mnt_routes table*/
 868                         a_value=g_strdup(attr->value); 
 869                         token = a_value;
 870                         mu_mntner=strsep(&token, " ");
 871                         if (!IS_DUMMY_ALLOWED(tr->mode))condition="AND dummy=0 "; else condition=NULL;
 872                         sprintf(query, query_fmt, tr->thread_upd, tr->object_id, 
 873                                 get_ref_id(tr, "mntner", "mntner", mu_mntner, condition));
 874                         free(a_value);
 875                         break;
 876          case UD_AX_MO: 
 877                         set_name = get_set_name(tr->class_type);
 878 /*                    ER_dbg_va(FAC_UD, ASP_UD_OBJ, "%s retrieved set name: %s\n", UD_TAG, set_name);*/
 879                         if (!IS_DUMMY_ALLOWED(tr->mode))condition="AND dummy=0 "; else condition=NULL;
 880                         sprintf(query, query_fmt, tr->thread_upd, tr->object_id, 
 881                                         get_ref_id(tr, set_name, set_name, attr->value, condition));
 882                         break;                          
 883          case UD_AX_MR:
 884                         if ((strcmp(attr->value, "ANY")==0) || (strcmp(attr->value, "any")==0) || (strcmp(attr->value, "Any")==0))
 885                         sprintf(query, query_fmt, tr->thread_upd, tr->object_id, 
 886                                 get_ref_id(tr, "mntner", "mntner", "ANY",NULL));
 887                         else {  
 888                          if (!IS_DUMMY_ALLOWED(tr->mode))condition="AND dummy=0 "; else condition=NULL;
 889                          sprintf(query, query_fmt, tr->thread_upd, tr->object_id, 
 890                                 get_ref_id(tr, "mntner", "mntner", attr->value, condition));
 891                         }
 892                         break;
 893          case UD_LEAF_: 
 894                         sprintf(query, query_fmt, tr->thread_upd, tr->object_id, attr->value);
 895                         break;
 896          case UD_LF_IF:
 897                 /* Convert ascii ip -> numeric one */
 898                         convert_if(attr->value, &if_address);
 899                         sprintf(query, query_fmt, tr->thread_upd, tr->object_id, if_address);
 900                         break;
 901          case UD_LF_RF:
 902                         rf_host=convert_rf(attr->value, &rf_type, &rf_port);
 903                         sprintf(query, query_fmt, tr->thread_upd, tr->object_id, rf_type, rf_host, rf_port);
 904                         if(rf_host)free(rf_host);
 905                         break;                  
 906          case UD_LF_AY:
 907                         sprintf(query, query_fmt, tr->thread_upd, tr->object_id, convert_time(attr->value));
 908                         break;          
 909            default:
 910                         tr->error|=ERROR_U_BUG;
 911                         tr->succeeded=0;
 912                         g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:no update qry\n" ,ERROR_U_BUG, attr->type, attr->value);
 913                         ER_perror(FAC_UD, UD_BUG, "query not defined for this type of attribute:[%d:%s]\n", attr->type, attr->value);
 914                         die;
 915                         break;
 916         }
 917    /* Execute the query */
 918     ER_dbg_va(FAC_UD, ASP_UD_SQL, "%s [%s]", UD_TAG, query);
 919     sql_err = SQ_execute_query(tr->sql_connection, query, (SQ_result_set_t **)NULL);
 920     if(sql_err) { /* an error occured*/
 921      /* Error - copy the error condition and return */
 922         sq_error=SQ_error(tr->sql_connection);
 923         ER_perror(FAC_UD, UD_SQL, "%s[%s]\n", sq_error, query);
 924         tr->error|=ERROR_U_DBS;
 925         tr->succeeded=0;
 926         g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:%s\n" ,ERROR_U_DBS, attr->type, attr->value, sq_error);
 927         ER_perror(FAC_UD, UD_SQL, "%s[%s]\n", SQ_error(tr->sql_connection), query);
 928         die;
 929     }
 930     else {
 931      /* Query OK */
 932       num = mysql_affected_rows(tr->sql_connection);
 933       if(num == 0) { /* check for duplicates*/
 934         SQ_get_info(tr->sql_connection, sq_info); /* UPDATE ... SET*/
 935         if ((sq_info[SQL_DUPLICATES]==0) && (sq_info[SQL_MATCHES]==0)) { 
 936         /* Condition with zero duplicates and matches may occur when the object is a dummy */
 937         /* and we are running in protected mode ( dummies are not allowed, tr->dummy==0). */
 938         /* In such case we will append "AND dummy=0" to the query, which won't */
 939         /* return a match if the object in question is a dummy */
 940           ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "[%ld] dummy prevents update: [%s]", tr->transaction_id, query);
 941           tr->error|=ERROR_U_OBJ;
 942           tr->succeeded=0;
 943           g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:dummy update\n" ,ERROR_U_OBJ, attr->type, attr->value);
 944         } /* else duplicate entry - silently drop it  */
 945       } 
 946       /* For member_of attribute we need to check membership claim in protected mode */
 947       if ((attr->type == A_MO) && (!IS_DUMMY_ALLOWED(tr->mode))){
 948           if(auth_member_of(attr, tr)!=0){
 949           tr->error|=ERROR_U_AUT;
 950           tr->succeeded=0;
 951           ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "[%ld] membership by reference is not allowed [%d:%s]", tr->transaction_id, attr->type, attr->value);
 952           g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:membership not allowed\n" ,ERROR_U_AUT, attr->type, attr->value);    
 953         }
 954       }
 955     }  
 956 return;
 957 }/*  update_attr()  */
 958 
 959 
 960 /************************************************************
 961 * each_attribute_proces()                                   *
 962 *                                                           *
 963 * Main function that processes object attributes one by one.*
 964 * Called from g_slist_foreach() function.                   * 
 965 * First it tries to insert an attribute.                    *
 966 * If an error it assumes that attribute is already in       *
 967 * a table and calls update_attr() to update it.             *
 968 * Queries for the attributes are defined in Insert[] array. * 
 969 *                                                           *
 970 * Returns: Nothing. Error code is stored in tr->error.      *
 971 *                                                           *
 972 *************************************************************/
 973 static void each_attribute_process(void *element_data, void *tr_ptr) 
     /* [<][>][^][v][top][bottom][index][help] */
 974 {
 975 int num;
 976 const char *query_fmt;
 977 int query_type;
 978 int do_query;
 979 Attribute_t *attr = element_data;
 980 Transaction_t *tr = (Transaction_t *)tr_ptr;
 981 unsigned int prefix, prefix_length, if_address;
 982 unsigned int begin_in, end_in;
 983 ip_v6word_t  high, low;
 984 
 985 int begin_as, end_as;
 986 char query[STR_XL];
 987 char * set_name;
 988 char * rf_host; /* needs to be freed after use*/
 989 int rf_type, rf_port;
 990 char *a_value;
 991 int sq_info[3];
 992 char *mu_mntner, *mu_prefix;
 993 int dummy_err;
 994 char *sq_error;
 995 ip_prefix_t dn_pref;
 996 int sql_err;
 997 int res;
 998 char *token;
 999 
1000 /* we still want to continue to collect all possible errors*/
1001 /*  if(tr->succeeded == 0) return; */
1002  
1003  /* To switch off querying for some types of attributes */
1004   do_query=1;
1005   
1006  /* Determine the query type */ 
1007   query_type=DF_get_insert_query_type(attr->type);
1008 
1009 /* For loadind pass #1 we need to process only main tables */
1010   if(tr->load_pass==1){ 
1011         switch(query_type) {
1012          case UD_MAIN_:
1013          case UD_MA_U2:
1014          case UD_MA_PR:
1015          case UD_MA_RT:
1016          case UD_MA_IN:
1017          case UD_MA_I6:
1018          case UD_MA_OR:
1019          case UD_MA_AK:
1020                         break;
1021          default:       return; /* return for other than MAIN tables*/
1022         }
1023   }
1024   
1025     query_fmt = DF_get_insert_query(attr->type);
1026 
1027 /* return if no query is defined for this attribute */
1028   if (strcmp(query_fmt, "") == 0) return;
1029 
1030  /* compose the query depending on the attribute */
1031   switch (query_type) {
1032    case UD_MAIN_: /* for MAIN tables */
1033                 if (ACT_UPDATE(tr->action)) do_query=0;
1034                 else
1035                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, attr->value);
1036                 break;
1037    case UD_MA_OR: /* for the origin attribute */
1038                 if (ACT_UPDATE(tr->action)) do_query=0;
1039                 else {
1040                   sprintf(query, query_fmt, tr->thread_ins, attr->value, tr->object_id);
1041                   tr->action |= TA_UPD_RX;
1042                   RP_pack_set_orig(attr->type, tr->packptr, attr->value);
1043                 }
1044                 break;
1045    case UD_MA_PR: /* for person_role table*/
1046                 if (ACT_UPDATE(tr->action)) do_query=0;
1047                 else
1048                  sprintf(query, query_fmt, tr->thread_ins, tr->class_type, tr->object_id,  attr->value);
1049                 
1050                 /* check if we need to update NHR */
1051                 if (ACT_UPD_NHR(tr->action)) {
1052                  /* Check if we can allocate it */       
1053                   res = NH_check(tr->nh, tr->sql_connection);
1054                   if(res == -1) { /* we cannot allocate this NIC handle (DB error) */
1055                      tr->succeeded=0;
1056                      tr->error |= ERROR_U_DBS;
1057                      g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:cannot allocate nic-handle\n", ERROR_U_DBS, attr->type, attr->value);
1058                      ER_perror(FAC_UD, UD_SQL, "cannot allocate nic hdl[%s]\n", attr->value);
1059                      die; 
1060                   }
1061                   else 
1062                   if(res == 0) { /* we cannot allocate this NIC handle (full space or ID in use) */
1063                     tr->succeeded=0; 
1064                     tr->error |= ERROR_U_OBJ;
1065                     g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:nic-handle already in use\n", ERROR_U_OBJ, attr->type, attr->value); 
1066                     return;
1067                   }
1068                 }
1069                 break;  
1070    case UD_MA_RT: /* for route table*/
1071                 if (ACT_UPDATE(tr->action)) do_query=0;
1072                 else {
1073                   tr->action |= TA_UPD_RX;
1074                   RP_pack_set_pref4(attr->type, attr->value, tr->packptr, &prefix, &prefix_length);
1075                   /*ER_dbg_va(FAC_UD, ASP_UD_OBJ, "%s route: %u/%u\n", UD_TAG, prefix, prefix_length);                  */
1076                   sprintf(query, query_fmt, tr->thread_ins,  
1077                           tr->object_id, prefix, prefix_length);
1078                 }
1079                 break;
1080    case UD_MA_IN: /* for inetnum table*/
1081                 if (ACT_UPDATE(tr->action)) do_query=0;
1082                 else {
1083                   tr->action |= TA_UPD_RX;
1084                   RP_pack_set_rang(attr->type, attr->value, tr->packptr, &begin_in, &end_in);
1085                   /* XXX error handling ? */
1086                   sprintf(query, query_fmt, tr->thread_ins, tr->object_id, begin_in, end_in);
1087                 }       
1088                 break;
1089    case UD_MA_I6: /* for inet6num table*/
1090                 if (ACT_UPDATE(tr->action)) do_query=0;
1091                 else {
1092                   tr->action |= TA_UPD_RX;
1093                   RP_pack_set_pref6(attr->type, attr->value, tr->packptr, &high, &low, &prefix_length);
1094                   /* XXX error handling ? */
1095                   sprintf(query, query_fmt, tr->thread_ins, tr->object_id, high, low, prefix_length);
1096                 }       
1097                 break;  
1098    case UD_MA_U2: /* This is actually an update - go to update_attr - this is more natural */
1099                  do_query=0;
1100                 break;
1101    case UD_MA_AK: /* for as_block table*/
1102                 if (ACT_UPDATE(tr->action)) do_query=0;
1103                 else {
1104                   convert_as_range(attr->value, &begin_as, &end_as);
1105                   sprintf(query, query_fmt, tr->thread_ins, tr->object_id, begin_as, end_as);
1106                 }
1107                 break;                          
1108    case UD_AUX__: /* for AUX tables*/
1109                 if((attr->type==A_AC) || (attr->type==A_TC) || (attr->type==A_ZC))
1110                  if(strlen(attr->value)>MAX_NIC_HDL)*(attr->value + MAX_NIC_HDL)='\0';
1111 
1112                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, tr->class_type, attr->value);
1113                 if(!IS_DUMMY_ALLOWED(tr->mode))strcat(query, " AND dummy=0 ");
1114                 break;
1115    case UD_AX_MO: /* for member_of table*/
1116                 set_name = get_set_name(tr->class_type);
1117 /*              ER_dbg_va(FAC_UD, ASP_UD_OBJ, "%s retrieved set name: %s\n", UD_TAG, set_name);*/
1118                 sprintf(query, query_fmt, tr->thread_ins,  
1119                  tr->object_id, set_name, tr->class_type, set_name, set_name, set_name, attr->value);
1120                 break;  
1121    case UD_AX_MR: /* for mbrs_by_ref table*/
1122                 if ((strcmp(attr->value, "ANY")==0) || (strcmp(attr->value, "any")==0) || (strcmp(attr->value, "Any")==0))
1123                  sprintf(query, query_fmt, tr->thread_ins, tr->object_id, tr->class_type, "ANY");
1124                 else  
1125                  sprintf(query, query_fmt, tr->thread_ins, tr->object_id, tr->class_type, attr->value);
1126                 break;  
1127    case UD_AX_MU: /* for mnt_routes table*/
1128                 a_value=g_strdup(attr->value); 
1129                 token = a_value;
1130                 mu_mntner=strsep(&token, " ");
1131                 mu_prefix=token;
1132                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, tr->class_type, mu_mntner);
1133                 free(a_value);
1134                 if (!IS_DUMMY_ALLOWED(tr->mode))strcat(query, " AND dummy=0 ");
1135                 break;
1136    case UD_LEAF_: /* for LEAF tables*/
1137                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, attr->value);
1138                 break;
1139    case UD_LF_OT: /* for LEAF tables containing object_type field*/
1140                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, tr->class_type, attr->value);
1141                 break;                          
1142    case UD_LF_AT: /* check PGPKEY. If yes - check the existence of key-cert.*/
1143                 if(!IS_DUMMY_ALLOWED(tr->mode)){
1144                  if(strncmp("PGPKEY", attr->value, 6)==0) {
1145                    if(get_ref_id(tr, "key_cert", "key_cert", attr->value, NULL)<=0) { 
1146                     ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "[%ld] no key-cert object[%s]", tr->transaction_id, attr->value);
1147                     tr->error|=ERROR_U_OBJ;
1148                     tr->succeeded=0;
1149                     g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:no key-cert object\n" ,ERROR_U_OBJ, attr->type, attr->value);
1150                     return;
1151                    }
1152                  }
1153                 } 
1154                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, tr->class_type, attr->value);
1155                 break;      
1156    case UD_LF_IF: /* for ifaddr tables*/
1157                 /* Convert ascii ip -> numeric one*/
1158                 convert_if(attr->value, &if_address);
1159                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, if_address);
1160                 break;
1161    case UD_LF_RF: /* for refer table*/
1162                 rf_host=convert_rf(attr->value, &rf_type, &rf_port);
1163                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, rf_type, rf_host, rf_port);
1164                 if(rf_host)free(rf_host);
1165                 break;  
1166    case UD_LF_AY: /* for auth_override table*/
1167                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, convert_time(attr->value));
1168                 break;
1169         default:
1170                 tr->succeeded=0;
1171                 tr->error |= ERROR_U_BUG;
1172                 g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:query not defined for the attribute\n" ,ERROR_U_BUG, attr->type, attr->value);
1173                 ER_perror(FAC_UD, UD_BUG, "query not defined for this type of attribute:[%d:%s]\n", attr->type, attr->value);
1174                 die;
1175                 break;
1176   }
1177   
1178  /* Make the query. For primary keys go straight to updates if we are updating the object */
1179   if(do_query){
1180    ER_dbg_va(FAC_UD, ASP_UD_SQL, "%s [%s]", UD_TAG, query);
1181    sql_err = SQ_execute_query(tr->sql_connection, query, (SQ_result_set_t **)NULL);
1182   } 
1183   else {
1184    update_attr(attr, tr);
1185    return;
1186   }
1187   
1188   if (sql_err)  {
1189   /* we received an error */
1190    if(SQ_errno(tr->sql_connection) == ER_DUP_ENTRY){ /* Only error "Duplicate entry" may be considered*/
1191         if (ACT_UPDATE(tr->action)) { /* In update mode this is common (so actually not an error)*/
1192                 update_attr(attr, tr);
1193                 return;
1194         }       
1195      /* Otherwise this is a duplicate attribute, just ignore it */
1196      /* In the future if we are more stringent, checks may be added here */     
1197    }
1198    else { /* Other errors reveal a database/server problem*/
1199         sq_error=SQ_error(tr->sql_connection);
1200         tr->error|=ERROR_U_DBS;
1201         tr->succeeded=0;
1202         ER_perror(FAC_UD, UD_BUG, "%s[%s]\n", sq_error, query);
1203         g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:%s\n" ,ERROR_U_DBS, attr->type, attr->value, sq_error);
1204         die;
1205    }
1206   } /* if error occured */
1207   else { 
1208  /* If the query was successful */
1209    num = mysql_affected_rows(tr->sql_connection);
1210    if(num>0){ /* this is OK*/
1211  /* Do some additional processing for member_of attribute  */
1212         if ((attr->type == A_MO) && (!IS_DUMMY_ALLOWED(tr->mode))){
1213 /*              ER_dbg_va(FAC_UD, ASP_UD_OBJ, "%s need to auth membership\n", UD_TAG);*/
1214                 if(auth_member_of(attr, tr)!=0){
1215                  tr->error|=ERROR_U_AUT;
1216                  tr->succeeded=0;
1217                  ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "[%ld] membership not allowed [%d:%s]", tr->transaction_id, attr->type, attr->value);
1218                  g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:membership not allowed\n" ,ERROR_U_AUT, attr->type, attr->value);     
1219                 }
1220         }
1221         else
1222           /* Do some additional processing for reverse zones domains */
1223           if ((attr->type == A_DN) 
1224               && IP_revd_a2b(&dn_pref, attr->value)==IP_OK ) {
1225             
1226             if(insert_reverse_domain(tr, &dn_pref) != 0 ) {
1227                 tr->error|=ERROR_U_DBS;
1228                 tr->succeeded=0;
1229                 ER_perror(FAC_UD, UD_SQL, "cannot insert inverse domain:[%d:%s]\n", attr->type, attr->value);
1230                 die;    
1231             }
1232             else {
1233               /* save data for the radix tree update */
1234               tr->action |= TA_UPD_RX;
1235               RP_pack_set_revd(attr->type, attr->value, tr->packptr);
1236             }
1237           }
1238         return;
1239    }
1240    if(num == 0) {
1241 /* this could be an empty update or a null select */        
1242         SQ_get_info(tr->sql_connection, sq_info); 
1243         if (sq_info[SQL_DUPLICATES]>0) {
1244         /* INSERT ... SELECT ... affected 0 rows, but there is 1 duplicate */
1245         /* which means that we already have such record in the table */ 
1246         /* this indicates that this is actually an update - update this attribute */     
1247                 if (sq_info[SQL_DUPLICATES]>1) { 
1248                         tr->error|=ERROR_U_DBS;
1249                         tr->succeeded=0;
1250                         ER_perror(FAC_UD, UD_SQL, "too many duplicates:[%d:%s]\n", attr->type, attr->value);
1251                         die;
1252                 }
1253                 update_attr(attr, tr);
1254         }
1255         else { 
1256         /* this is an emty SELECT because there is no referred object */        
1257         /* try to create dummy and repeat the original query*/
1258                 
1259 /*              ER_dbg_va(FAC_UD, ASP_UD_OBJ, "%s no ref. integrity. Trying to create dummy\n", UD_TAG);*/
1260 
1261                 dummy_err = create_dummy(attr, tr);
1262                 if (dummy_err == 0) {
1263                 /* Dummy was created */ 
1264                         g_string_sprintfa(tr->error_script,"W[%d][%d:%s]:dummy created\n" ,0, attr->type, attr->value);
1265                         ER_dbg_va(FAC_UD, ASP_UD_SQL, "%s [%s]", UD_TAG, query);
1266                         sql_err = SQ_execute_query(tr->sql_connection, query, (SQ_result_set_t **)NULL);
1267                         num = mysql_affected_rows(tr->sql_connection);
1268                         if (sql_err) {
1269                           sq_error=SQ_error(tr->sql_connection);
1270                           ER_perror(FAC_UD, UD_SQL, "%s[%s]\n", sq_error, query);
1271                           tr->error|=ERROR_U_DBS;
1272                           tr->succeeded=0;
1273                           g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:%s\n" ,
1274                                             ERROR_U_DBS, attr->type, attr->value, sq_error);
1275                           die;
1276                         }                    
1277                         if (num==0) {
1278                           ER_perror(FAC_UD, UD_SQL, "0 rows affected [%s]\n", query);
1279                           tr->error|=ERROR_U_DBS;
1280                           tr->succeeded=0;
1281                           g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:re-insert qry\n" ,
1282                                             ERROR_U_DBS, attr->type, attr->value);
1283                           die;
1284                         }
1285                 }
1286                 else 
1287                  if(dummy_err == 1) {
1288                  /* dummy not allowed */         
1289                    tr->error |= ERROR_U_OBJ;
1290                    tr->succeeded=0;
1291                    g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:dummy not allowed\n" ,ERROR_U_OBJ, attr->type, attr->value);
1292                    ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "[%ld] dummy not allowed [%d:%s]", tr->transaction_id, attr->type, attr->value);
1293                  }
1294                  else {
1295                  /* SQL problem */       
1296                    tr->error|=ERROR_U_DBS;
1297                    tr->succeeded=0;
1298                    ER_perror(FAC_UD, UD_SQL, "dummy cannot be created [%d:%s]", attr->type, attr->value);
1299                    g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:dummy cannot be created\n" ,ERROR_U_DBS, attr->type, attr->value);
1300                    die;
1301                 }       
1302         }  /* RI*/
1303    }/* if num == 0*/
1304   } /* if the query was successful */
1305   
1306   return;
1307 } /* each_attribute_process() */
1308 
1309 
1310 
1311 /************************************************************
1312 * each_primary_key_select()                                 *
1313 *                                                           *
1314 * Function that forms a query for an object (w prinary keys)*
1315 * Called from g_slist_foreach() function.                   *
1316 * Primary keys are defined in Select[] array.               *
1317 *                                                           *
1318 * Returns: Nothing.                                         *
1319 *                                                           *
1320 *************************************************************/ 
1321 static void each_primary_key_select(void *element_data, void *result_ptr) 
     /* [<][>][^][v][top][bottom][index][help] */
1322 {
1323 Attribute_t *attr = element_data;
1324 Transaction_t *tr = (Transaction_t *)result_ptr;
1325 const char *query_fmt;
1326 unsigned int prefix, prefix_length;
1327 unsigned int begin_in, end_in;
1328 int begin_as, end_as;
1329 ip_prefix_t prefstr;
1330 ip_range_t  rangstr;
1331 ip_v6word_t i6_msb, i6_lsb;
1332 
1333    query_fmt = DF_get_select_query(attr->type);
1334 
1335   if (strcmp(query_fmt, "") != 0) {
1336     switch (DF_get_select_query_type(attr->type)) {
1337      case UD_MAIN_: 
1338                 g_string_sprintfa(tr->query, query_fmt, attr->value);
1339                 g_string_sprintfa(tr->K, attr->value);
1340                 break;
1341      case UD_MA_RT:
1342                 IP_pref_a2v4(attr->value, &prefstr, &prefix, &prefix_length);
1343                 g_string_sprintfa(tr->query, query_fmt, prefix, prefix_length);
1344                 g_string_sprintfa(tr->K, attr->value);
1345                 break;
1346      case UD_MA_IN:
1347                 IP_rang_a2v4(attr->value, &rangstr, &begin_in, &end_in);
1348                 g_string_sprintfa(tr->query, query_fmt, begin_in, end_in);
1349                 g_string_sprintfa(tr->K, attr->value);
1350                 break;
1351      case UD_MA_I6:
1352                 IP_pref_a2v6(attr->value, &prefstr, &i6_msb, &i6_lsb, &prefix_length);
1353                 g_string_sprintfa(tr->query, query_fmt, i6_msb, i6_lsb, prefix_length);
1354                 g_string_sprintfa(tr->K, attr->value);
1355                 break;                                          
1356      case UD_MA_AK:
1357                 convert_as_range(attr->value, &begin_as, &end_as);
1358                 g_string_sprintfa(tr->query, query_fmt, begin_as, end_as);
1359                 g_string_sprintfa(tr->K, attr->value);
1360                 break;
1361      default:
1362                 ER_perror(FAC_UD, UD_BUG, "query not defined for this type of attribute:[%d:%s]\n", attr->type, attr->value);
1363                 die;
1364 
1365         break;
1366     } 
1367   }
1368 } 
1369 
1370 /************************************************************
1371 * perform_create(const Object_t *obj, Transaction_t *tr)    * 
1372 *                                                           *
1373 * Procedure for creating a new object.                      *
1374 * First inserts object into 'last' table and gets object_id.*
1375 * Then processes all attributes.                            *
1376 *                                                           *
1377 * Returns: tr->succeeded: >0 success, 0 - error             *
1378 * Error code is stored in tr->error.                        *
1379 *                                                           *
1380 *************************************************************/ 
1381 static int perform_create(Transaction_t *tr) 
     /* [<][>][^][v][top][bottom][index][help] */
1382 {
1383  Object_t *obj;
1384  char *str;
1385  GString *query;
1386  long timestamp;
1387  int sql_err;
1388  long object_id;
1389   
1390   
1391  if ((query = g_string_sized_new(STR_XL)) == NULL){
1392   tr->succeeded=0;
1393   tr->error |= ERROR_U_MEM; 
1394   ER_perror(FAC_UD, UD_MEM, "cannot allocate gstring\n");
1395   die; 
1396  }
1397  
1398  
1399  obj=tr->object;
1400   
1401       str = (obj->object)->str;
1402       timestamp=time(NULL);
1403       tr->sequence_id=1; /* we start with 1*/
1404       /* Calculate the object_id - should be max+1 */
1405       tr->object_id = get_minmax_id(tr->sql_connection, "object_id", "last", 1);
1406       /* if last is empty, start with 1, otherwise the assign the next id */
1407       if(tr->object_id==-1)tr->object_id=1; else tr->object_id++;
1408       TR_update_id(tr);
1409 
1410       g_string_sprintf(query, "INSERT INTO last SET thread_id=%d, timestamp=%ld, sequence_id=1, object_type=%d, object='%s', pkey='%s' ",
1411                       tr->thread_ins, timestamp, tr->class_type, str, tr->K->str);
1412 
1413       ER_dbg_va(FAC_UD, ASP_UD_SQL, "%s [%s]", UD_TAG, query->str);
1414       sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
1415 
1416      /* Check for affected rows. One row should be affected . */ 
1417       if (sql_err) {
1418         tr->error|=ERROR_U_DBS;
1419         tr->succeeded=0; 
1420         ER_perror(FAC_UD, UD_SQL, "%s[%s]\n", SQ_error(tr->sql_connection), query->str);
1421         die;
1422       }
1423       else {
1424       /* Get generated (autoincrement) object_id */
1425         object_id=mysql_insert_id(tr->sql_connection);
1426         /* compare it with the calculated one */
1427         if(tr->object_id != object_id) die; /* probably implementation of autoincrement changed */
1428         g_slist_foreach(obj->attributes, each_attribute_process, tr);
1429       }
1430     g_string_free(query, TRUE);
1431     return(tr->succeeded);  
1432 } /* perform_create() */
1433 
1434 /************************************************************
1435 * perform_update(Transaction_t *tr)                         * 
1436 *                                                           *
1437 * Procedure for updating (existing) object.                 *
1438 * First processes all attributes.                           *
1439 * Then saves previous object in 'history' and updates       *
1440 * 'last' table.                                             *
1441 *                                                           *
1442 * Returns: tr->succeeded: >0 success, 0 - error             *
1443 * Error code is stored in tr->error.                        *
1444 *                                                           *
1445 *************************************************************/ 
1446 static int perform_update(Transaction_t *tr) 
     /* [<][>][^][v][top][bottom][index][help] */
1447 {
1448 Object_t *obj;
1449 char *str;
1450 GString *query;
1451 int num;
1452 long sequence_id;
1453 long timestamp;
1454 char *sq_error;
1455 int sql_err;
1456  
1457 
1458    obj=tr->object;
1459    /* get sequence number */
1460     
1461    sequence_id = get_sequence_id(tr);
1462    if(sequence_id==-1) {
1463       tr->error|=ERROR_U_DBS;
1464       tr->succeeded=0;
1465       ER_perror(FAC_UD, UD_SQL, "cannot get sequence_id");
1466       die;
1467    } 
1468    else tr->sequence_id=sequence_id; /* save it for rollback*/
1469    /* Update TR record */     
1470    TR_update_id(tr);
1471 
1472   /* process each attribute one by one */
1473   g_slist_foreach(obj->attributes, each_attribute_process, tr);
1474 
1475   /* If we've already failed or this is fast load - just return */
1476   if((tr->succeeded == 0) || (tr->load_pass != 0)) return(tr->succeeded);
1477   
1478     /* No return: thread_id=0 */
1479     /* Do it only if previous transactions finished well */
1480   if ((query = g_string_sized_new(STR_XL)) == NULL){
1481    tr->succeeded=0;
1482    tr->error |= ERROR_U_MEM; 
1483    ER_perror(FAC_UD, UD_MEM, "cannot allocate gstring");
1484    die; 
1485   }     
1486     /* copy object to the history table */
1487     g_string_sprintf(query,"INSERT history "
1488                   "SELECT %d, object_id, sequence_id, timestamp, object_type, object, pkey, serial, prev_serial "
1489                   "FROM last "
1490                   "WHERE object_id=%ld ", tr->thread_ins, tr->object_id);
1491 
1492     ER_dbg_va(FAC_UD, ASP_UD_SQL, "%s [%s]", UD_TAG, query->str);
1493     sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
1494     
1495    /* Check for affected rows. One row should be affected . */
1496     num = mysql_affected_rows(tr->sql_connection);
1497     if (num < 1) {
1498          tr->error|=ERROR_U_DBS;
1499          tr->succeeded=0;
1500          if (sql_err) {
1501           sq_error=SQ_error(tr->sql_connection);
1502           ER_perror(FAC_UD, UD_SQL, "%s[%s]\n", SQ_error(tr->sql_connection), query->str);
1503           die;
1504          }
1505          else {
1506           ER_perror(FAC_UD, UD_SQL, "0 rows affected [%s]\n", query->str);
1507         /* This is to check that this is really could happen */  
1508           die;
1509          } 
1510          g_string_free(query, TRUE);
1511          return(tr->succeeded);
1512     }
1513 
1514     /* Insert new version into the last */
1515     
1516     /* Put a timestamp */
1517     str = (obj->object)->str;
1518     timestamp=time(NULL);
1519 
1520 /* update last for commit/rollback */
1521                    
1522     g_string_sprintf(query, "INSERT last "
1523                    "SET thread_id=%d, object_id=%ld, sequence_id=%ld, timestamp=%ld, object_type=%d, object='%s', pkey='%s' ",
1524                    tr->thread_ins, tr->object_id, tr->sequence_id+1, timestamp, tr->class_type, str, tr->K->str);
1525 
1526 
1527     ER_dbg_va(FAC_UD, ASP_UD_SQL, "%s [%s]", UD_TAG, query->str);
1528     sql_err = SQ_execute_query(tr->sql_connection, query->str, (SQ_result_set_t **)NULL);
1529     
1530     /* Check for affected rows. One row should be affected */
1531     num = mysql_affected_rows(tr->sql_connection);
1532     if (num < 1) {
1533          tr->error|=ERROR_U_DBS;
1534          tr->succeeded=0;
1535          if(sql_err) {
1536           g_string_sprintfa(tr->error_script,"E[%d][:]:UPDATE last failed:%s\n" ,ERROR_U_DBS,SQ_error(tr->sql_connection));
1537           ER_perror(FAC_UD, UD_SQL, "%s[%s]\n", SQ_error(tr->sql_connection), query->str);
1538           die;
1539          }
1540          else {
1541           ER_perror(FAC_UD, UD_SQL, "0 rows affected [%s]\n", query->str);
1542           /* This is to check that this is really could happen */  
1543           die;
1544          } 
1545          g_string_free(query, TRUE);
1546          return(tr->succeeded);
1547     }
1548  g_string_free(query, TRUE);
1549  return(tr->succeeded);   
1550 } /* perform_update() */
1551 
1552 
1553 
1554 
1555 /************************************************************
1556 * int object_process(Transaction_t *tr)                     *
1557 *                                                           *
1558 * This is the interface between core and upper layer        *
1559 * All it gets is Transaction *tr, which contains all        *
1560 * necessary information, including the object in its        *
1561 * internal representation.                                  *
1562 *                                                           *
1563 * Returns: tr->succeeded: >0 success, 0 - error             *
1564 * Error code is stored in tr->error.                        *
1565 *                                                           *
1566 *************************************************************/ 
1567 int object_process(Transaction_t *tr) 
     /* [<][>][^][v][top][bottom][index][help] */
1568 {
1569 int res;
1570 char nic[MAX_NH_LENGTH];
1571 int commit_now;
1572 
1573    /* for fast loader we do not perform commits/rollbacks */
1574    if(tr->load_pass == 0) commit_now = 0; else commit_now = 1;
1575    
1576    /* create and initialize TR record for crash recovery */
1577    TR_create_record(tr);
1578   
1579    if(ACT_DELETE(tr->action)){
1580                 ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s object: delete", UD_TAG);
1581                 /* check referential integrity of deletion */
1582                 UD_check_ref(tr);
1583                 /* for person & role - free the nic-handle in the NHR */
1584                 if(tr->succeeded && ((tr->class_type==C_PN) || (tr->class_type==C_RO)) && tr->nh ){
1585                  res = NH_free(tr->nh, tr->sql_connection, commit_now);
1586 
1587                  if(res == -1) { 
1588                    tr->succeeded=0; 
1589                    tr->error |= ERROR_U_DBS;
1590                    ER_perror(FAC_UD, UD_SQL, "cannot delete nic handle");
1591                    die;
1592                  }
1593                  else if(res == 0) { 
1594                    tr->succeeded=0; 
1595                    tr->error |= ERROR_U_OBJ;
1596                    ER_perror(FAC_UD, UD_SQL, "nic handle not found");
1597                    die;
1598                  }
1599                 }
1600                 /* if everything is Ok we are ready to commit */
1601                 if (tr->succeeded){
1602                  /* update object_id and sequence_id fields */
1603                  tr->sequence_id = get_sequence_id(tr);
1604                  TR_update_id(tr);
1605 
1606                  /* checkpoint the TR  - we are going to commit*/
1607                  CP_COMMIT(tr->action); TR_update_escript(tr); TR_update_status(tr);    
1608 
1609                  /* send an ack */      
1610                  UD_ack(tr);
1611 
1612                  /* delete the object and checkpoint it*/
1613                  UD_delete(tr);
1614                  UD_update_rx(tr, RX_OPER_DEL);
1615 
1616                  /* we need to update sequence_id because it was changed during update */
1617                  CP_DELETE_PASSED(tr->action); TR_update_id(tr); TR_update_status(tr);
1618 
1619                  /* Commit nic-handle deletion to the repository */
1620                  NH_commit(tr->sql_connection);
1621 
1622                  CP_COMMIT_NH_PASSED(tr->action); TR_update_status(tr);
1623 
1624                 }
1625                 else { /* just send an ack */
1626                  UD_ack(tr);
1627                 }
1628                 return(tr->succeeded); /*commit is not needed*/
1629     }
1630     else if(ACT_UPDATE(tr->action)){            
1631                 ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s object: update\n", UD_TAG);
1632                 perform_update(tr);
1633 
1634                 /* Commit nic-handle allocation (if any) to the repository if we are replacing dummy*/
1635                 if(ACT_UPD_NHR(tr->action) && tr->succeeded && ((tr->class_type==C_PN) || (tr->class_type==C_RO)) && tr->nh ){
1636                  /* convert nh to DB nIC handle before registration */
1637                  /* because there nh will bee freed */
1638                  NH_convert(nic, tr->nh);
1639 
1640                  res = NH_register(tr->nh, tr->sql_connection, commit_now);
1641 
1642                  if(res == -1) { 
1643                   tr->succeeded=0; 
1644                   tr->error |= ERROR_U_DBS;
1645                   ER_perror(FAC_UD, UD_SQL, "cannot allocate nic handle\n");
1646                   die;
1647                  }
1648                  else if(res == 0) { 
1649                   tr->succeeded=0; 
1650                   tr->error |= ERROR_U_OBJ;
1651                   ER_perror(FAC_UD, UD_SQL, "nic handle already in use\n");
1652                   die;
1653                  }
1654                  else { /* copy the NH to the report to return to DBupdate */
1655                  /* Convert nh to the database format */     
1656                   g_string_sprintfa(tr->error_script,"I[%d][%s]\n", A_NH, nic);
1657                  }               
1658                 }
1659     }
1660     else if(ACT_CREATE(tr->action)){
1661                 ER_dbg_va(FAC_UD, ASP_UD_OBJ, "%s object: create", UD_TAG);
1662                 perform_create(tr);
1663 
1664                 /* Commit nic-handle allocation (if any) to the repository */
1665                 if(tr->succeeded && ((tr->class_type==C_PN) || (tr->class_type==C_RO)) && tr->nh ){
1666                  /* convert nh to DB nIC handle before registration */
1667                  NH_convert(nic, tr->nh);
1668 
1669                  res = NH_register(tr->nh, tr->sql_connection, commit_now);
1670 
1671                  if(res == -1) { 
1672                   tr->succeeded=0; 
1673                   tr->error |= ERROR_U_DBS;
1674                   ER_perror(FAC_UD, UD_SQL, "cannot allocate nic handle");
1675                   die;
1676                  }
1677                  else if(res == 0) { 
1678                   tr->succeeded=0; 
1679                   tr->error |= ERROR_U_OBJ;
1680                   ER_perror(FAC_UD, UD_SQL, "nic handle already in use");
1681                   die;
1682                  }
1683                  else { /* copy the NH to the report to return to DBupdate */
1684                   g_string_sprintfa(tr->error_script,"I[%d][%s]\n", A_NH, nic);
1685                  }
1686                 }
1687         
1688      }
1689      else {
1690                 ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "[%ld] object: unknown action", tr->transaction_id, UD_TAG);
1691                 tr->succeeded=0;
1692                 tr->error|=ERROR_U_BADOP;
1693                 return(tr->succeeded);
1694      }          
1695 
1696    if(tr->load_pass == 0) { /* not for fast loader*/
1697       /* update object_id and sequence_id fields */
1698       TR_update_id(tr);
1699 
1700       if (tr->succeeded) {
1701 /*ER_dbg_va(FAC_UD, ASP_UD_OBJ, "%s Commit transaction\n", UD_TAG);      */
1702         /* checkpoint the TR  - we are going to commit*/
1703         CP_COMMIT(tr->action); TR_update_escript(tr); TR_update_status(tr);
1704 
1705         /* send an ack */       
1706         UD_ack(tr);
1707         /* commit the transaction and checkpoint it */
1708 
1709         UD_commit(tr);
1710         /* Commit nic-handle modifications to the repository */
1711 
1712         NH_commit(tr->sql_connection);
1713 
1714         CP_COMMIT_NH_PASSED(tr->action); TR_update_status(tr);
1715         /* TR will be marked as clean in UD_create_serial() */
1716       }
1717       else {
1718 /*ER_dbg_va(FAC_UD, ASP_UD_OBJ, "%s roll back transaction\n", UD_TAG);      */
1719         /* send an ack */       
1720         UD_ack(tr);
1721         UD_rollback(tr);
1722 
1723         CP_ROLLBACK_PASSED(tr->action); TR_update_status(tr);
1724         
1725         /* rollback nic-handle modifications to the repository */
1726         NH_rollback(tr->sql_connection);
1727 
1728         
1729         CP_ROLLBACK_NH_PASSED(tr->action); TR_update_status(tr);
1730         /* Delete TR record if in update mode. Next time (if any) DBupdate tries to submit, we'll start from scratch */
1731         /* In NRTM mode we create serial anyway, so the record will be deleted  */
1732         /* after serial is created TR record will be deleted in */
1733 
1734       }
1735     }  
1736  return(tr->succeeded);   
1737 } /* object_process() */
1738 

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