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. ud_each_primary_key_select
  23. perform_create
  24. perform_update
  25. object_process

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

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