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_qresult_str
  9. get_field_str
  10. get_sequence_id
  11. get_ref_id
  12. isdummy
  13. process_reverse_domain
  14. insert_reverse_domain
  15. update_reverse_domain
  16. auth_member_of
  17. create_dummy
  18. update_attr
  19. each_attribute_process
  20. ud_each_primary_key_select
  21. perform_create
  22. perform_update
  23. object_process

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

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