modules/ud/ud_process_stream.c

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

DEFINITIONS

This source file includes following functions.
  1. LINE_ATTRIBUTE
  2. LINE_COMMENT
  3. LINE_EMPTY
  4. LINE_EOF
  5. LINE_ADD
  6. LINE_UPD
  7. LINE_DEL
  8. LINE_OVERRIDE_ADD
  9. LINE_OVERRIDE_UPD
  10. LINE_OVERRIDE_DEL
  11. LINE_ACK
  12. Line_Type_t
  13. ud_replace_autonic
  14. reorder_attr
  15. ud_reorder_attributes
  16. ud_split_names
  17. escape_apostrophes
  18. line_type
  19. report_transaction
  20. process_nrtm
  21. process_updates
  22. process_transaction
  23. UD_process_stream

   1 /***************************************
   2   $Revision: 1.62 $
   3 
   4   Functions to process data stream( file, network socket, etc.)
   5 
   6   Status: NOT REVUED, NOT TESTED
   7 
   8  Author(s):       Chris Ottrey, Andrei Robachevsky
   9 
  10   ******************/ /******************
  11   Modification History:
  12         andrei (17/01/2000) Created.
  13   ******************/ /******************
  14   Copyright (c) 2000,2001,2002                    RIPE NCC
  15  
  16   All Rights Reserved
  17   
  18   Permission to use, copy, modify, and distribute this software and its
  19   documentation for any purpose and without fee is hereby granted,
  20   provided that the above copyright notice appear in all copies and that
  21   both that copyright notice and this permission notice appear in
  22   supporting documentation, and that the name of the author not be
  23   used in advertising or publicity pertaining to distribution of the
  24   software without specific, written prior permission.
  25   
  26   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  27   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  28   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  29   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  30   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  31   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  32  ***************************************/
  33 
  34 #include "rip.h"
  35 #include "syntax_api.h"
  36 
  37 
  38 #include <sys/types.h>
  39 #include <sys/socket.h>
  40 #include <netdb.h>
  41 #include <arpa/inet.h>
  42 #include <unistd.h>
  43 #include <sys/stat.h>
  44 #include <fcntl.h>
  45 #include <string.h>
  46 
  47  
  48 typedef enum _Line_Type_t {
  49  LINE_ATTRIBUTE,
     /* [<][>][^][v][top][bottom][index][help] */
  50  LINE_COMMENT,
     /* [<][>][^][v][top][bottom][index][help] */
  51  LINE_EMPTY,
     /* [<][>][^][v][top][bottom][index][help] */
  52  LINE_EOF,
     /* [<][>][^][v][top][bottom][index][help] */
  53  LINE_ADD,
     /* [<][>][^][v][top][bottom][index][help] */
  54  LINE_UPD,
     /* [<][>][^][v][top][bottom][index][help] */
  55  LINE_DEL,
     /* [<][>][^][v][top][bottom][index][help] */
  56  LINE_OVERRIDE_ADD,
     /* [<][>][^][v][top][bottom][index][help] */
  57  LINE_OVERRIDE_UPD,
     /* [<][>][^][v][top][bottom][index][help] */
  58  LINE_OVERRIDE_DEL,
     /* [<][>][^][v][top][bottom][index][help] */
  59  LINE_ACK
     /* [<][>][^][v][top][bottom][index][help] */
  60 } Line_Type_t;
     /* [<][>][^][v][top][bottom][index][help] */
  61 
  62 /* Maximum number of objects(serials) we can consume at a time */
  63 #define SBUNCH 1000
  64 
  65 static int report_transaction(Transaction_t *tr, long transaction_id, Log_t *log, ut_timer_t *psotime, char *reason);
  66 static int process_nrtm(UD_stream_t *ud_stream, Transaction_t *tr, int operation);
  67 static int process_updates(UD_stream_t *ud_stream, Transaction_t *tr, int operation);
  68 static int process_transaction(UD_stream_t *ud_stream, GString *obj_buff, int operation, long transaction_id);
  69 
  70 static GString *escape_apostrophes(GString *text);
  71 static nic_handle_t *ud_replace_autonic(Transaction_t *tr, rpsl_object_t *object);
  72 static void reorder_attr(void *element_data, void *ptr);
  73 static void ud_reorder_attributes(rpsl_object_t *object);
  74 
  75 
  76 /******************************************************************
  77 * ud_replace_autonic()                                            *
  78 *                                                                 *
  79 * Checks if nic handle is an AUTO one (XX*-SRS)                   *
  80 * So it tries to assign a nic handle and if successfull           *
  81 * substitutes the attribute value                                 * 
  82 *                                                                 *
  83 ******************************************************************/
  84 static nic_handle_t *ud_replace_autonic(Transaction_t *tr, rpsl_object_t *object)
     /* [<][>][^][v][top][bottom][index][help] */
  85 {
  86 nic_handle_t *nh_ptr=NULL;
  87 rpsl_attr_t *nic_hdl, *nic_hdl_old;
  88 GList *nic_hdl_list, *nic_hdl_first;
  89 gint ofs;
  90 char *nic_submitted, *nic_db;
  91 
  92  nic_hdl_list = rpsl_object_get_attr(object, "nic-hdl");
  93  nic_hdl_first =g_list_first(nic_hdl_list);
  94  nic_submitted = rpsl_attr_get_clean_value((rpsl_attr_t *)nic_hdl_first->data);
  95 
  96  /* check if it is an auto NIC handle and replace it with a real one */ 
  97  if(NH_parse(nic_submitted, &nh_ptr) == 0) {
  98   /* this is an AUTO nic handle */
  99   /* Try to allocate it */
 100   if(NH_check(nh_ptr, tr->sql_connection)>0){
 101     /* Convert nh to the database format */
 102     nic_db = NH_convert(nh_ptr);
 103     /* we need to make a copy as we free the whole list later */
 104     nic_hdl = rpsl_attr_copy((rpsl_attr_t *)nic_hdl_first->data);
 105     rpsl_attr_replace_value(nic_hdl, nic_db); 
 106     UT_free(nic_db);
 107   }
 108   /* replace this attribute in the object */
 109   ofs = rpsl_attr_get_ofs(nic_hdl);
 110   /* remove attribute from object and free it */
 111   nic_hdl_old = rpsl_object_remove_attr(object, ofs, NULL);
 112   if(nic_hdl_old) rpsl_attr_delete(nic_hdl_old); 
 113   else die; 
 114   rpsl_object_add_attr(object, nic_hdl, ofs, NULL);
 115  }/* if this was an AUTO nic handle */
 116 
 117  
 118  UT_free(nic_submitted);
 119 
 120  rpsl_attr_delete_list(nic_hdl_list);
 121  return(nh_ptr);
 122 }
 123 
 124 static void reorder_attr(void *element_data, void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 125 {
 126 rpsl_attr_t *attr = (rpsl_attr_t *)element_data;
 127 rpsl_object_t *object = (rpsl_object_t *)ptr;
 128 int ofs;
 129 
 130   /* move the attribute to the beginning 
 131      so that all mnt-by are at the beginning of the object */
 132   ofs = rpsl_attr_get_ofs(attr);
 133   attr = rpsl_object_remove_attr(object, ofs, NULL);
 134   if (attr) rpsl_object_add_attr(object, attr, 1, NULL);
 135   else die;
 136 }
 137 
 138 /******************************************************************
 139 * reorder attributes                                              *
 140 *  . mnt-by should go before member-of to allow correct           * 
 141 *      membership autorization (still done in RIPupd)             *
 142 *  . nic-hdl should go before any admin-c, tech-c to prevent      * 
 143 *       errrors in self referencing role objects                  *
 144 ******************************************************************/
 145 static void ud_reorder_attributes(rpsl_object_t *object)
     /* [<][>][^][v][top][bottom][index][help] */
 146 {
 147 GList *mnt_by_list, *nic_hdl_list;
 148  /* get the list of mnt-by attributes */
 149  mnt_by_list = rpsl_object_get_attr(object, "mnt-by");
 150  /* reorder so that all mnt-by are at the beginning of the object */
 151  if(mnt_by_list != NULL) {
 152   g_list_foreach(mnt_by_list, reorder_attr, object);
 153 
 154   /* free GList only, not members as they are stored in the object */
 155   rpsl_attr_delete_list(mnt_by_list);
 156  } 
 157 
 158  /* move nic-hdl to the beginning */ 
 159  nic_hdl_list = rpsl_object_get_attr(object, "nic-hdl");
 160  if(nic_hdl_list != NULL) {
 161   g_list_foreach(nic_hdl_list, reorder_attr, object);
 162 
 163   /* free GList only, not members as they are stored in the object */
 164   rpsl_attr_delete_list(nic_hdl_list);
 165  } 
 166   
 167   
 168 } 
 169 
 170 /******************************************************************
 171 * split the role or person attribute value into multiple names    *
 172 *                                                                 *
 173 * destroys the original object and builds a new one (only for     *
 174 * C_RO or C_PN                                                    *
 175 ******************************************************************/
 176 
 177 static rpsl_object_t *ud_split_names(rpsl_object_t *object)
     /* [<][>][^][v][top][bottom][index][help] */
 178 {
 179 const rpsl_attr_t *attr;
 180 gchar **names;
 181 const GList *old_attrs;
 182 GList *p;
 183 GString *new_obj;
 184 rpsl_object_t *ret_val;
 185 C_Type_t class_type;
 186 int i;
 187 
 188   class_type = rpsl_get_class_id(rpsl_object_get_class(object));
 189   if ((class_type != C_PN) && (class_type != C_RO)) return object;
 190   
 191   /* get the list of person or role attribute */
 192   attr = rpsl_object_get_attr_by_ofs(object, 0);
 193 
 194   /* split the names into words */
 195   names = g_strsplit(rpsl_attr_get_value(attr), " ", 0);
 196   new_obj =  g_string_new("");
 197 
 198   /* replace the value of the first attribute */
 199   for (i=0; names[i] != NULL; i++) {
 200       g_string_sprintfa(new_obj, "%s:%s\n", rpsl_attr_get_name(attr), names[i]);
 201   }
 202 
 203   g_strfreev(names);
 204 
 205   /* copy all other attributes */
 206   old_attrs = rpsl_object_get_all_attr(object);
 207   for (p=g_list_next(old_attrs); p != NULL; p = g_list_next(p)) {
 208       g_string_sprintfa(new_obj, "%s:%s\n", rpsl_attr_get_name(p->data), rpsl_attr_get_value(p->data));
 209   }
 210 
 211   ret_val = rpsl_object_init(new_obj->str);
 212   g_string_free(new_obj, TRUE);
 213   rpsl_object_delete(object);
 214   return ret_val;
 215   
 216   
 217 }
 218 
 219 
 220 /******************************************************************
 221 * GString *escape_apostrophes()                                   *
 222 * Escapes apostrophes in the text so they do not confuse printf   *
 223 * functions and don't corrupt SQL queries                         *
 224 *                                                                 *
 225 * *****************************************************************/
 226 static GString *escape_apostrophes(GString *text) {
     /* [<][>][^][v][top][bottom][index][help] */
 227   int i;
 228   for (i=0; i < text->len; i++) {
 229     if ((text->str[i] == '\'') || (text->str[i] == '\\')) {
 230       text = g_string_insert_c(text, i, '\\');
 231       i++;
 232     }
 233   }
 234  return(text); 
 235 } /* escape_apostrophes() */
 236 
 237 
 238 /******************************************************************
 239 * Line_Type_t line_type(e)                                        *
 240 * Determines the line type analysing the first letters            *
 241 *                                                                 *
 242 * ****************************************************************/
 243 static Line_Type_t line_type(const char *line, long *transaction_id) {
     /* [<][>][^][v][top][bottom][index][help] */
 244 
 245   if (strncmp(line, "# EOF", 4) == 0) return(LINE_EOF);
 246   if (strncmp(line, "#", 1) == 0)     return(LINE_COMMENT);
 247   if (strcmp(line, "\n") == 0)        return(LINE_EMPTY);
 248  
 249   if (strncmp(line, "ACK", 3) == 0) {
 250     *transaction_id = atol(line+3);       
 251     return(LINE_ACK);
 252   }
 253   if (strncmp(line, "ADD_OVERRIDE", 12) == 0) {
 254     *transaction_id = atol(line+12);      
 255     return(LINE_OVERRIDE_ADD);
 256   }
 257   if (strncmp(line, "UPD_OVERRIDE", 12) == 0) {
 258     *transaction_id = atol(line+12);      
 259     return(LINE_OVERRIDE_UPD);
 260   }
 261   if (strncmp(line, "DEL_OVERRIDE", 12) == 0) {
 262     *transaction_id = atol(line+12);      
 263     return(LINE_OVERRIDE_DEL);
 264   }
 265  
 266   if (strncmp(line, "ADD", 3) == 0) {
 267     *transaction_id = atol(line+3);
 268     return(LINE_ADD);
 269   }
 270   if (strncmp(line, "UPD", 3) == 0) {
 271     *transaction_id = atol(line+3);
 272     return(LINE_UPD);
 273   }
 274   if (strncmp(line, "DEL", 3) == 0) {
 275     *transaction_id = atol(line+3); 
 276     return(LINE_DEL);
 277   }
 278  
 279 /* Otherwise this is an attribute */  
 280     return(LINE_ATTRIBUTE);
 281 
 282 } /* line_type() */
 283 
 284 
 285 /******************************************************************
 286 * report_transaction()                                            *
 287 *                                                                 * 
 288 * Prints error report to the log                                  *
 289 *                                                                 *
 290 * reason - additional message that will be included               *
 291 *                                                                 *
 292 * *****************************************************************/
 293 static int report_transaction(Transaction_t *tr, long transaction_id,  Log_t *log, ut_timer_t *psotime, char *reason)
     /* [<][>][^][v][top][bottom][index][help] */
 294 {
 295 int result=0;
 296 ut_timer_t fotime;
 297 float timediff;
 298 const char *class_name = DF_class_type2name(tr->class_type);
 299 char *primary_key = tr->K->str;
 300 
 301 
 302  /* calculate statistics */
 303   UT_timeget(&fotime);
 304   timediff = UT_timediff(psotime, &fotime);
 305  
 306  if(tr->succeeded==0) {
 307   result=tr->error;
 308   log->num_failed++;
 309   ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "[%ld] %.2fs FAILED [%s:%s][%s]", transaction_id, timediff, class_name, primary_key, reason);
 310   if(result & ERROR_U_OBJ) ER_dbg_va(FAC_UD, ASP_UD_OBJ,"[%ld] object: referential integrity error", transaction_id);
 311   if(result & ERROR_U_AUT) ER_dbg_va(FAC_UD, ASP_UD_OBJ,"[%ld] object: authentication error", transaction_id);
 312   if(result & ERROR_U_BADOP) ER_dbg_va(FAC_UD, ASP_UD_OBJ,"[%ld] object: unsupported operation", transaction_id);
 313   if(result & ERROR_U_COP) ER_dbg_va(FAC_UD, ASP_UD_OBJ,"[%ld] object: conflicting operation", transaction_id);
 314   if(result & ERROR_U_NSUP) ER_dbg_va(FAC_UD, ASP_UD_OBJ,"[%ld] object: this type is not supported", transaction_id);
 315   ER_dbg_va(FAC_UD, ASP_UD_OBJ, "[%ld] object: details [%s]", transaction_id, (tr->error_script)->str);
 316   result=1; /* # of failures */
 317  }
 318  else {
 319   result=0;
 320   log->num_ok++;
 321   ER_inf_va(FAC_UD, ASP_UD_OBJ, "[%ld] %.2fs OK     [%s:%s][%s]", transaction_id, timediff, class_name, primary_key, reason);
 322   ER_dbg_va(FAC_UD, ASP_UD_OBJ, "[%ld] object: details [%s]", transaction_id, (tr->error_script)->str);
 323  }
 324                                                                                                                                                
 325  return(result);
 326 }/* report_transaction() */
 327 
 328 
 329 
 330 /************************************************************
 331 * process_nrtm()                                            *
 332 *                                                           *
 333 * Process object in NRTM client mode                        *
 334 *                                                           *
 335 * nrtm - pointer to _nrtm structure                         *
 336 * log - pointer to Log_t structure                          *
 337 * object_name - name of the object                          * 
 338 * operation - operation code (OP_ADD/OP_DEL)                *
 339 *                                                           *
 340 * Returns:                                                  *
 341 * 1  - okay                                                 *
 342 * <0 - error                                                *
 343 *                                                           *
 344 ************************************************************/
 345 
 346 static int process_nrtm(UD_stream_t *ud_stream, Transaction_t *tr, int operation)
     /* [<][>][^][v][top][bottom][index][help] */
 347 {
 348 int result=0;
 349 int dummy=0;
 350 struct _nrtm *nrtm = ud_stream->nrtm;
 351 long serial_id;
 352 Log_t *log_ptr= &(ud_stream->log);
 353 ut_timer_t sotime;
 354 int ta_upd_nhr;
 355 
 356     /* Start timer for statistics */
 357     UT_timeget(&sotime);
 358 
 359   /* We allow NRTM updates for some inconsistent objects                  */
 360   /* One of the examples is reference by name which looks like nic-handle */
 361   /* For this purpose we allow dummy creation when updating an object     */
 362   /* We also check for dummy allowance when deleting an object            */
 363   /* this is done to allow deletion of person objects referenced by name  */
 364 
 365   tr->mode|=B_DUMMY;
 366   if(IS_NO_NHR(tr->mode))ta_upd_nhr=0; else ta_upd_nhr = TA_UPD_NHR;
 367   
 368   switch (operation) {
 369   
 370   case OP_ADD:
 371     if(nrtm->tr){ /* DEL ADD => saved*/
 372       if(tr->object_id==0) { 
 373         /* object does not exist in the DB */      
 374         /* delete the previous(saved) object*/
 375         object_process(nrtm->tr); 
 376         /* create DEL serial */
 377         UD_lock_serial(nrtm->tr);
 378         serial_id = UD_create_serial(nrtm->tr);
 379         CP_CREATE_S_PASSED(nrtm->tr->action); TR_update_status(nrtm->tr); 
 380         UD_commit_serial(nrtm->tr);
 381         UD_unlock_serial(nrtm->tr);
 382         /* Mark TR as clean */
 383         TR_mark_clean(nrtm->tr);
 384         /* log the transaction */
 385         result=report_transaction(nrtm->tr, serial_id, log_ptr, &sotime, "M:DEL");
 386         
 387         transaction_free(nrtm->tr); nrtm->tr=NULL;
 388         
 389         /* Create an object and update NHR */
 390         tr->action=(TA_CREATE | ta_upd_nhr);
 391         /* restart the timer for statistics */
 392         UT_timeget(&sotime);
 393         object_process(tr); /* create a new one*/
 394         /* create ADD serial */
 395         UD_lock_serial(tr);
 396         serial_id = UD_create_serial(tr); 
 397         CP_CREATE_S_PASSED(tr->action); TR_update_status(tr);
 398         UD_commit_serial(tr);
 399         UD_unlock_serial(tr);
 400         /* Mark TR as clean */
 401         TR_mark_clean(tr);
 402         /* log the transaction */
 403         result=report_transaction(tr, serial_id, log_ptr, &sotime, "M:ADD");
 404       }
 405       else { 
 406       /* object already exists in the DB - update or dummy replacement*/
 407         /*compare the two, may be we may collapse operations*/
 408         if(tr->object_id==nrtm->tr->object_id) {
 409           /* DEL-ADD ->> UPDATE */ 
 410           transaction_free(nrtm->tr); nrtm->tr=NULL;
 411           tr->action=TA_UPD_CLLPS;
 412           object_process(tr);
 413           /* create DEL+ADD serial records */
 414           UD_lock_serial(tr);
 415           tr->action=TA_DELETE; serial_id = UD_create_serial(tr);
 416           result=report_transaction(tr, serial_id, log_ptr, &sotime, "M:DEL(UPD)");
 417 
 418           /* restart the timer for statistics */
 419           UT_timeget(&sotime);
 420           tr->sequence_id++;
 421           tr->action=TA_CREATE; serial_id = UD_create_serial(tr);
 422           CP_CREATE_S_PASSED(tr->action); TR_update_status(tr);
 423           UD_commit_serial(tr);
 424           UD_unlock_serial(tr);
 425           /* Mark TR as clean */
 426           TR_mark_clean(tr);
 427           result=report_transaction(tr, serial_id, log_ptr, &sotime, "M:ADD(UPD)");
 428         }
 429         else { /* this should be a dummy object in the database(that we are going to replace with the real one */
 430         /* or an interleaved operation*/
 431           object_process(nrtm->tr); /* delete the previous(saved) object*/
 432           /* create a DEL serial record */
 433           UD_lock_serial(nrtm->tr);
 434           serial_id = UD_create_serial(nrtm->tr); 
 435           CP_CREATE_S_PASSED(nrtm->tr->action); TR_update_status(nrtm->tr);
 436           UD_commit_serial(nrtm->tr);
 437           UD_unlock_serial(nrtm->tr);
 438           /* Mark TR as clean */
 439           TR_mark_clean(nrtm->tr);
 440           /* log the transaction */
 441           result=report_transaction(nrtm->tr, serial_id, log_ptr, &sotime, "M:DEL");
 442 
 443 
 444           transaction_free(nrtm->tr); nrtm->tr=NULL;
 445 
 446           /* restart the timer for statistics */
 447           UT_timeget(&sotime);
 448           
 449           tr->action=TA_UPDATE;
 450           /* check if we are replacing a dummy object */
 451           dummy=isdummy(tr);
 452           if(dummy==1) tr->action = TA_UPD_DUMMY;
 453           object_process(tr); /* create a new one*/
 454           /* For serials this is CREATE operation. Increase sequence to have it correct in serals */
 455           if(dummy==1) { tr->action=TA_CREATE; tr->sequence_id++; } 
 456           /* create ADD serial record */
 457           UD_lock_serial(tr);
 458           serial_id = UD_create_serial(tr); 
 459           CP_CREATE_S_PASSED(tr->action); TR_update_status(tr);
 460           UD_commit_serial(tr);
 461           UD_unlock_serial(tr);
 462           /* Mark TR as clean */
 463           TR_mark_clean(tr);
 464           /* log the transaction */
 465           result=report_transaction(tr, serial_id, log_ptr, &sotime, "M:ADD");
 466 
 467         }
 468       }
 469     }
 470     else { /* ADD ADD =>brand new object*/
 471       if(tr->object_id==0) {
 472 /*      fprintf(stderr,"CREATE new\n");*/
 473         /* Create an object and update NHR */
 474         tr->action=(TA_CREATE | ta_upd_nhr);
 475         object_process(tr);
 476         /* create ADD serial */
 477         UD_lock_serial(tr);
 478         serial_id = UD_create_serial(tr); 
 479         CP_CREATE_S_PASSED(tr->action); TR_update_status(tr);
 480         UD_commit_serial(tr);
 481         UD_unlock_serial(tr);
 482 
 483         /* Mark TR as clean */
 484         TR_mark_clean(tr);
 485         /* log the transaction */
 486         result=report_transaction(tr, serial_id, log_ptr, &sotime, "M:ADD");
 487       }
 488       else { /* object already exists in the database */
 489         /* this may happen because of dummies*/
 490         /* or with some implementations of mirroring protocol that have atomic update */
 491         /* instead of add + del */
 492         tr->action=TA_UPDATE;
 493         dummy=isdummy(tr);
 494         if(dummy==1) tr->action = TA_UPD_DUMMY;
 495         object_process(tr);
 496         /* For serials this is CREATE operation. Increase sequence to have it correct in serals */
 497         if(dummy==1) { tr->action=TA_CREATE; tr->sequence_id++; }
 498         /* create ADD serial record */
 499         UD_lock_serial(tr);
 500         serial_id = UD_create_serial(tr); 
 501         CP_CREATE_S_PASSED(tr->action); TR_update_status(tr);
 502         UD_commit_serial(tr);
 503         UD_unlock_serial(tr);
 504         /* Mark TR as clean */
 505         TR_mark_clean(tr);
 506         /* log the transaction */
 507         result=report_transaction(tr, serial_id, log_ptr, &sotime, "M:ADD");
 508         
 509       } 
 510     }
 511     break;
 512     
 513   case OP_DEL:
 514     if(nrtm->tr){ /*DEL DEL =>saved */
 515       /* check this is not a deletion of the same object twice */
 516       /* this should not happen but we cannot trust foreign sources */
 517       /* in such case process saved transaction but fail the current one */
 518       if(nrtm->tr->object_id == tr->object_id) tr->object_id=0;
 519             
 520       object_process(nrtm->tr); /* delete the previous(saved) object*/
 521       /* create DEL serial record */
 522       UD_lock_serial(nrtm->tr);
 523       serial_id = UD_create_serial(nrtm->tr);  
 524       CP_CREATE_S_PASSED(nrtm->tr->action); TR_update_status(nrtm->tr);
 525       UD_commit_serial(nrtm->tr);
 526       UD_unlock_serial(nrtm->tr);
 527       /* Mark TR as clean */
 528       TR_mark_clean(nrtm->tr);
 529       /* log the transaction */
 530       result=report_transaction(nrtm->tr, serial_id, log_ptr, &sotime, "M:DEL");
 531       
 532       transaction_free(nrtm->tr); nrtm->tr=NULL;
 533     }
 534     /* save the real object (not a dummy one ) */
 535     if(tr->object_id>0 && !isdummy(tr)){ 
 536       /* save the object*/
 537       tr->action=(TA_DELETE | ta_upd_nhr);
 538       nrtm->tr=tr;
 539       return(0);
 540     }
 541     else { /* this is an error - Trying to DEL non-existing object*/
 542       tr->succeeded=0; tr->error|=ERROR_U_COP;
 543       tr->action=(TA_DELETE | ta_upd_nhr);
 544       /* create and initialize TR record for crash recovery */
 545       TR_create_record(tr);
 546       /* create DEL serial record anyway */
 547       UD_lock_serial(tr);
 548       serial_id = UD_create_serial(tr); 
 549       CP_CREATE_S_PASSED(tr->action); TR_update_status(tr);
 550       UD_commit_serial(tr);
 551       UD_unlock_serial(tr);
 552       /* Mark TR as clean */
 553       TR_mark_clean(tr);
 554       /* log the transaction */
 555       result=report_transaction(tr, serial_id, log_ptr, &sotime, "M:DEL: non-existing object");
 556       
 557     }
 558     break;
 559   
 560   default:
 561     tr->succeeded=0; tr->error |=ERROR_U_BADOP;
 562     break;  
 563   }
 564 
 565  /* Free resources */  
 566   transaction_free(tr);
 567   
 568   return(result);
 569 } /* process_nrtm() */
 570 
 571 
 572 
 573 /************************************************************
 574 * process_updates()                                         *
 575 *                                                           *
 576 * Process object in update mode                             *
 577 *                                                           *
 578 * ud_stream - pointer to UD_stream structure                *
 579 * object_name - name of the object                          *
 580 * operation - operation code (OP_ADD/OP_DEL)                *
 581 *                                                           *
 582 * Note:                                                     *
 583 * Frees tr and tr->obj on exit                              *
 584 *                                                           *
 585 * Returns:                                                  *
 586 * 0  - okay                                                 *
 587 * <0- number of failed objects                              *
 588 *                                                           * 
 589 ************************************************************/
 590 
 591 static int process_updates(UD_stream_t *ud_stream, Transaction_t *tr, int operation)
     /* [<][>][^][v][top][bottom][index][help] */
 592 {
 593 int result=0;
 594 Log_t *log_ptr= &(ud_stream->log);
 595 int dummy=0;
 596 ut_timer_t sotime;
 597 int ta_upd_nhr;
 598 char *reason;
 599 
 600     /* Start timer for statistics */
 601     UT_timeget(&sotime);
 602     if(IS_NO_NHR(tr->mode))ta_upd_nhr=0; else ta_upd_nhr = TA_UPD_NHR;
 603 
 604     switch(operation) {
 605     /* Compare operations and report an error if they do not match */    
 606     case OP_ADD:
 607       if(tr->object_id!=0) { /* trying to create, but object exists */
 608         tr->succeeded=0; tr->error|=ERROR_U_COP;
 609         reason="U:ADD:object already exists";
 610         g_string_sprintfa(tr->error_script,"E[%d]:NEW requested but object already exists\n" ,ERROR_U_COP);
 611         UD_ack(tr); /* Send a NACK */
 612       } else {
 613        /* Action: create the object and update NHR */
 614         tr->action=(TA_CREATE | ta_upd_nhr);
 615         reason="U:ADD";
 616         object_process(tr);
 617       }
 618       break;
 619     case OP_UPD:
 620       if(tr->object_id==0) { /* trying to update non-existing object*/
 621         tr->succeeded=0; tr->error|=ERROR_U_COP;
 622         reason="U:UPD:non-existing object";
 623         g_string_sprintfa(tr->error_script,"E[%d]:UPD requested but no existing object found\n" ,ERROR_U_COP);
 624         UD_ack(tr); /* Send a NACK */
 625       } else {
 626         tr->action=TA_UPDATE;
 627         reason="U:UPD";
 628         dummy=isdummy(tr);
 629         if(dummy==1) tr->action = TA_UPD_DUMMY;
 630         object_process(tr);
 631       }
 632       break;
 633 
 634     case OP_DEL:        
 635       if(tr->object_id==0) { /* trying t delete non-existing object*/
 636         tr->succeeded=0; tr->error|=ERROR_U_COP;
 637         reason="U:DEL:non-existing object";
 638         g_string_sprintfa(tr->error_script,"E[%d]:DEL requested but no existing object found\n" ,ERROR_U_COP);
 639         UD_ack(tr);
 640       } else {
 641         tr->action=(TA_DELETE | ta_upd_nhr);
 642         reason="U:DEL";
 643         object_process(tr);
 644       }
 645       break;
 646                 
 647     default:                
 648       /* bad operation for this mode if not standalone */
 649       if(IS_STANDALONE(tr->mode)) {
 650         if(tr->object_id==0){
 651           tr->action=(TA_CREATE | ta_upd_nhr); 
 652           reason="U:ADD";
 653         }
 654         else {
 655           tr->action=TA_UPDATE;
 656           reason="U:UPD";
 657         }
 658         object_process(tr);
 659       }
 660       else {
 661         tr->succeeded=0; 
 662         tr->error|=ERROR_U_BADOP;
 663         g_string_sprintfa(tr->error_script,"E[%d]:Unknown operation requested\n" ,ERROR_U_BADOP);
 664         reason="U:bad operation";
 665         UD_ack(tr); /* Send a NACK */ 
 666       }
 667       break;
 668     }
 669    /* If not in standalone mode create serial and copy error transcript */ 
 670     if(!IS_STANDALONE(tr->mode)) {
 671       if(tr->succeeded){
 672               /* we don't want to generate DEL serial for dummy replacement*/
 673               if(dummy==1) { tr->action=TA_CREATE; tr->sequence_id++; }
 674               UD_lock_serial(tr);
 675               UD_create_serial(tr); 
 676               CP_CREATE_S_PASSED(tr->action); TR_update_status(tr);
 677               UD_commit_serial(tr);
 678               UD_unlock_serial(tr);
 679               /* Mark the TR as clean */
 680               TR_mark_clean(tr);
 681       }
 682     }  
 683    
 684    /* Make a report. U stands for update stream. No reason */
 685     result=report_transaction(tr, tr->transaction_id, log_ptr, &sotime, reason);
 686 
 687    /* Free resources */   
 688 /*    rpsl_object_delete(tr->object); */
 689     transaction_free(tr);
 690     
 691     return(result);
 692         
 693 } /* process_updates() */
 694 
 695 
 696 /************************************************************
 697 *                                                           *
 698 * int process_transaction()                                 *
 699 *                                                           *
 700 * Processes the transaction                                 *
 701 *                                                           *
 702 * ud_stream - pointer to UD_stream_t structure              *
 703 *                                                           *
 704 * Returns:                                                  *
 705 * 0 - no error                                              *
 706 * <0- number of failed objects                              *
 707 *                                                           *
 708 ************************************************************/
 709 
 710 /* It frees the obj */
 711 
 712 static int process_transaction(UD_stream_t *ud_stream, 
     /* [<][>][^][v][top][bottom][index][help] */
 713                          GString *g_obj_buff,
 714                          int operation,
 715                         long transaction_id)
 716 {
 717 Transaction_t *tr = NULL;
 718 int result;
 719 nic_handle_t *nh_ptr=NULL;
 720 rpsl_object_t *submitted_object=NULL, *sql_object=NULL;
 721 const GList *rpsl_err_list;
 722 gchar *object_txt, *flat_object_txt;
 723 ut_timer_t sotime;
 724 long serial_id;
 725 
 726 
 727  /* check if the requested transaction has already been processed */
 728  /* this may happen in case of crash. If so, just send an ack and return */
 729  if(TR_check(ud_stream->db_connection, transaction_id, (ud_stream->condat).sock))return(1);
 730 
 731  /* escape apostrophes, otherwise sql will be confused */
 732  g_obj_buff=escape_apostrophes(g_obj_buff);
 733 
 734  /* check if it is an object and init it */
 735  if ((submitted_object=rpsl_object_init(g_obj_buff->str))==NULL) return(-1);
 736 
 737 /* start new transaction now */
 738  tr = transaction_new(ud_stream->db_connection, rpsl_get_class_id(rpsl_object_get_class(submitted_object)));
 739  if (tr == NULL) die;
 740  
 741  tr->mode = ud_stream->ud_mode;
 742  tr->load_pass = ud_stream->load_pass;
 743  tr->source_hdl = ud_stream->source_hdl;
 744  tr->socket = (ud_stream->condat).sock;
 745  tr->transaction_id = transaction_id;
 746  tr->object = submitted_object;
 747 
 748  UT_timeget(&sotime);
 749  
 750 
 751  /* check for syntax errors (with whois_rip syntax set) */
 752  if((rpsl_err_list = rpsl_object_errors(submitted_object)) != NULL) {
 753  int num_err = 0;
 754  gboolean is_garbage = FALSE;
 755  gboolean is_only_comments = FALSE;
 756 
 757 
 758  /* check the severity of the errors */
 759  /* we need to catch: */
 760  /* template errors - missing primary keys _only_ */
 761  /* attribute syntax errors - just to abort without processing */
 762   do {
 763      const rpsl_attr_t *attr;
 764      const rpsl_error_t *err = rpsl_err_list->data;
 765      gboolean is_important_error = FALSE;
 766 
 767      switch (err->code) {
 768       /* totally bogus object, or missing primary keys */
 769       case RPSL_ERR_ONLYCOMMENTS:
 770            is_only_comments = TRUE;
 771       case RPSL_ERR_MISSINGKEY:
 772       case RPSL_ERR_BADCLASS:
 773       case RPSL_ERR_UNKNOWNCLASS:
 774            is_garbage = TRUE;
 775            is_important_error = TRUE;
 776            break;
 777       /* inappropriate, duplicate attributes */
 778       case RPSL_ERR_ATTRNOTALLOWED:
 779            attr = rpsl_object_get_attr_by_ofs(submitted_object, err->attr_num);
 780            if (rpsl_attr_is_key(submitted_object, rpsl_attr_get_name(attr))) {
 781               is_important_error = TRUE;
 782            }
 783            break;
 784       /* bad and single attribuets that have multiple appearance in the object are dangerous */     
 785       case RPSL_ERR_BADATTR:
 786       case RPSL_ERR_ATTRSINGLE:
 787            is_important_error = TRUE;
 788            break;
 789            
 790      }
 791      /* report error */
 792      /* no need to have an extended report */
 793      /* basically for debuggung purposes   */
 794      /* it will never be passed to the user */
 795      if (is_important_error) {
 796         g_string_sprintfa(tr->error_script,"E[%d]:%s\n", ERROR_U_OBJ, err->descr);
 797         num_err++;
 798      }
 799      rpsl_err_list = g_list_next(rpsl_err_list);
 800   } while (rpsl_err_list != NULL);
 801 
 802   if (num_err > 0) {
 803      tr->succeeded = 0;
 804      tr->error |= ERROR_U_OBJ;
 805     /* garbage just ignore */
 806     if (is_garbage){
 807       if(!is_only_comments)
 808         ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "garbage in NRTM stream [%s]", g_obj_buff->str);
 809     } else {
 810       ER_dbg_va(FAC_UD, ASP_UD_UPDLOG,"Malformed object:[%s]\n%s\n",tr->error_script->str, g_obj_buff->str);
 811       /* we cannot process this object and store it in the database */
 812       /* but in case of NRTM this indicates a malformed stream */
 813       /* we try our best to be in sync with the master, so we need to store */
 814       /* this block (maybe object) in failed_transaction */
 815       if(IS_NRTM_CLNT(ud_stream->ud_mode)){
 816         object_txt = rpsl_object_get_text(submitted_object, RPSL_STD_COLUMN);
 817         tr->object_txt = object_txt;
 818         if(operation==OP_DEL) tr->action=TA_DELETE; else tr->action=TA_CREATE;
 819         UD_lock_serial(tr);
 820         serial_id = UD_create_serial(tr); 
 821         CP_CREATE_S_PASSED(tr->action); TR_update_status(tr);
 822         UD_commit_serial(tr);
 823         UD_unlock_serial(tr);
 824         /* Mark TR as clean */
 825         TR_mark_clean(tr);
 826         /* log the transaction */
 827         result=report_transaction(tr, serial_id, &ud_stream->log, &sotime, "M:---");
 828       }
 829     }
 830     UD_ack(tr);
 831     transaction_free(tr);
 832     return(-1);
 833   }
 834  }/* checked for syntax errors */
 835 
 836 
 837  /* If we maintain NHR, for person and role objects */
 838  /* check and replace the AUTO nic handle */
 839  if(!IS_NO_NHR(ud_stream->ud_mode)){
 840     if((tr->class_type == C_PN) || (tr->class_type == C_RO)) {
 841       nh_ptr = ud_replace_autonic(tr, submitted_object);
 842       /* NULL nh_ptr indicates a problem with a NIC handle */
 843       if(nh_ptr == NULL) {
 844         tr->succeeded = 0;
 845         tr->error |= ERROR_U_OBJ;
 846         g_string_sprintfa(tr->error_script,"E[%d]:Wrong NIC handle format\n", ERROR_U_OBJ);
 847         ER_inf_va(FAC_UD, ASP_UD_UPDLOG,"Malformed object:[Wrong NIC handle]\n%s\n", g_obj_buff->str);
 848         /* we cannot process this object and store it in the database */
 849         /* but in case of NRTM this indicates a malformed stream */
 850         /* we try our best to be in sync with the master, so we need to store */
 851         /* this block (maybe object) in failed_transaction */
 852         if(IS_NRTM_CLNT(ud_stream->ud_mode)){
 853           object_txt = rpsl_object_get_text(submitted_object, RPSL_STD_COLUMN);
 854           tr->object_txt = object_txt;
 855           if(operation==OP_DEL) tr->action=TA_DELETE; else tr->action=TA_CREATE;
 856           UD_lock_serial(tr);
 857           serial_id = UD_create_serial(tr); 
 858           CP_CREATE_S_PASSED(tr->action); TR_update_status(tr);
 859           UD_commit_serial(tr);
 860           UD_unlock_serial(tr);
 861           /* Mark TR as clean */
 862           TR_mark_clean(tr);
 863           /* log the transaction */
 864           result=report_transaction(tr, serial_id, &ud_stream->log, &sotime, "M:---");
 865         }
 866         UD_ack(tr);
 867         transaction_free(tr);
 868         return(-1);
 869       }  
 870     }
 871  }
 872  
 873    /* normalize the object (reorder and split attributes */
 874  sql_object = rpsl_object_copy_flattened(submitted_object);
 875 
 876  /* put nic-hdl and mnt-by at the top of the list */
 877  ud_reorder_attributes(sql_object);
 878 
 879  /* split the names */
 880   sql_object = ud_split_names(sql_object); 
 881          
 882  /* save the original text of submitted object */
 883  object_txt = rpsl_object_get_text(submitted_object, RPSL_STD_COLUMN);
 884          
 885  tr->object = sql_object;
 886  tr->object_txt = object_txt; /* needs to be freed */
 887  tr->nh = nh_ptr;
 888  
 889 /* We perform no commit/rollback in the loader mode, so thread_id should be set to 0 */
 890  if(IS_STANDALONE(tr->mode)){ tr->thread_ins=0; tr->thread_upd=0; }
 891 
 892 /* For the first load pass we only create objects */ 
 893 
 894  if(tr->load_pass==1) {
 895          /* still we need to fill tr->K (last.pkey) field */ 
 896          /* tr->load_pass ==1 will trigger this behaviour in ud_each_primary_key_select */
 897          g_list_foreach((GList *)rpsl_object_get_all_attr(tr->object), ud_each_primary_key_select, tr);
 898          tr->object_id=0;
 899  }
 900  else tr->object_id=get_object_id(tr);
 901 
 902  /* check if error has been detected */
 903  /*XXX replace error codes with symbolic consts */
 904  if(tr->object_id==-2) { /* Object erorr - wrong syntax in one of the PK */
 905     ER_inf_va(FAC_UD, ASP_UD_UPDLOG,"Malformed object:[%s]\n%s\n",tr->error_script->str, g_obj_buff->str);   
 906     UD_ack(tr);
 907     /* this object is not deleted by transaction_delete() */
 908     rpsl_object_delete(submitted_object);
 909     transaction_free(tr);
 910     return(-1);
 911  }   
 912  
 913 /* Object cannot be retrieved */
 914  if(tr->object_id==-1) { /* DB error*/
 915     tr->succeeded=0;
 916     tr->error |= ERROR_U_DBS;
 917     ER_perror(FAC_UD, UD_SQL, "Object cannot be retrieved:[%s]", tr->object_txt);
 918     die;
 919  }
 920 
 921 /* Process transaction. tr and obj are freed inside the process_* functions */
 922 /* tr is freed there because in NRTM we need to save a transaction for later processing */
 923  if(IS_UPDATE(ud_stream->ud_mode))
 924  /* We are in update mode */
 925     result=process_updates(ud_stream, tr, operation);
 926  else
 927  /* We are in NRTM mode */   
 928     result=process_nrtm(ud_stream, tr, operation);
 929  
 930  
 931  /* free the original submitted object */
 932  rpsl_object_delete(submitted_object);
 933  return(result);
 934 
 935 }          
 936           
 937 
 938 /************************************************************
 939 *                                                           *
 940 * int UD_process_stream(UD_stream_t *ud_stream)             *
 941 *                                                           *
 942 * Processes the stream                                      *
 943 *                                                           *
 944 * ud_stream - pointer to UD_stream_t structure              *
 945 *                                                           *
 946 * Returns:                                                  *
 947 * in update mode (!standalone)(1 object processed):         *
 948 * 1 - no error                                              *
 949 * <0- errors                                                *
 950 *                                                           *
 951 * in NRTM & standalone modes                                *
 952 * total number of object processed                          *
 953 *                                                           *
 954 ************************************************************/
 955 
 956 int UD_process_stream(UD_stream_t *ud_stream)
     /* [<][>][^][v][top][bottom][index][help] */
 957 {
 958   char line_buff[STR_XXL];
 959   SQ_connection_t *sql_connection;
 960   struct _nrtm *nrtm;
 961   Log_t *log_ptr= &(ud_stream->log);
 962   ut_timer_t stime, ftime, sotime;
 963   float obj_second1, obj_second10, timediff;
 964   int result=0;
 965   int operation=0;
 966   int interrupt=0;
 967   int do_update;
 968   int default_ud_mode = ud_stream->ud_mode;
 969   Line_Type_t linetype;
 970   Transaction_t *tr;
 971   long transaction_id=0; /* transaction_id (to be supplied by DBupdate and stored in Database) */
 972   long serial_id;
 973   GString *g_obj_buff;
 974   
 975   nrtm=ud_stream->nrtm;
 976 
 977   if ((g_obj_buff = g_string_sized_new(STR_XXL)) == NULL){
 978         ER_perror(FAC_UD, UD_MEM, "cannot allocate gstring");
 979      die;
 980   }
 981 
 982   /* Check connection to the database */
 983   if(SQ_ping(ud_stream->db_connection)) {
 984    ER_perror(FAC_UD, UD_SQL, "%s", SQ_error(ud_stream->db_connection));
 985    die;
 986   }
 987   sql_connection=ud_stream->db_connection;
 988   
 989   UT_timeget(&stime);
 990 
 991  /* Main loop. Reading input stream line by line */
 992  /* Empty line signals to start processing an object, if we have it */ 
 993   while (SK_cd_gets(&ud_stream->condat, line_buff, sizeof(line_buff))>0) {
 994 
 995 
 996     switch (linetype=line_type(line_buff, &transaction_id)) {
 997 
 998       case LINE_COMMENT:
 999       case LINE_EOF:
1000       break;
1001 
1002       case LINE_ACK:
1003        tr = transaction_new(ud_stream->db_connection, 0);
1004        tr->transaction_id=transaction_id;
1005        TR_delete_record(tr);
1006        transaction_free(tr);
1007       break;
1008       
1009       
1010       case LINE_ADD:
1011       /* restore the default operation mode */
1012        operation=OP_ADD;
1013        ud_stream->ud_mode=default_ud_mode;
1014       break;
1015       
1016       case LINE_OVERRIDE_ADD:
1017       /* for override - switch the dummy bit on */
1018        operation=OP_ADD;
1019        ud_stream->ud_mode=default_ud_mode|B_DUMMY;
1020       break;
1021       
1022       case LINE_UPD:
1023       /* restore the default operation mode */
1024        operation=OP_UPD;
1025        ud_stream->ud_mode=default_ud_mode;
1026       break;  
1027 
1028       case LINE_OVERRIDE_UPD:
1029       /* for override - switch the dummy bit on */
1030        operation=OP_UPD;
1031        ud_stream->ud_mode=default_ud_mode|B_DUMMY;
1032       break;
1033       
1034       case LINE_DEL:
1035       /* restore the default operation mode */
1036        operation=OP_DEL;
1037        ud_stream->ud_mode=default_ud_mode;
1038       break; 
1039 
1040       case LINE_OVERRIDE_DEL:
1041       /* for override - switch the dummy bit on */
1042        operation=OP_DEL;
1043        ud_stream->ud_mode=default_ud_mode|B_DUMMY;
1044       break;
1045  
1046       case LINE_EMPTY:
1047        /* start processing the object */
1048         /* escape apostrophes, otherwise sql will be confused */
1049          /* XXX */
1050 /*       print_object(obj); */
1051          /* check if we have collected something */
1052          if(g_obj_buff->len >0){
1053 #if 0         
1054            /* no operation suggest a garbage in the stream - just ignore it */
1055            if(IS_NRTM_CLNT(ud_stream->ud_mode) && (operation==OP_NOOP)) { 
1056                ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "garbage in NRTM stream");
1057            } else 
1058 #endif           
1059            {    
1060              /* start new transaction now */
1061              result=process_transaction(ud_stream, g_obj_buff, operation, transaction_id);
1062              /* process_transaction() frees tr and obj structures, */
1063              /* so make sure we'll not reference these objects in the future */
1064              operation=OP_NOOP;
1065              transaction_id=0;
1066            }  
1067            ud_stream->ud_mode=default_ud_mode;
1068            if ((g_obj_buff = g_string_truncate(g_obj_buff,0)) == NULL){
1069                  ER_perror(FAC_UD, UD_MEM, "cannot allocate gstring");
1070                  die;
1071            }
1072          } 
1073          /* this is a good place for quick interrupt */
1074          do_update=CO_get_do_update();
1075          if (do_update) interrupt=0; else interrupt=1;
1076 
1077       break;
1078 
1079       default:
1080        /* this may be an object - fill the buffer */
1081         g_string_sprintfa(g_obj_buff, "%s", line_buff);
1082         break;
1083     } /* switch */
1084     
1085     /* Finish processing if interrupt has been set */
1086     if (interrupt) break;
1087   } /* Main loop of data stream processing : while */
1088  
1089 
1090  /* Some postprocessing */
1091   if(IS_NRTM_CLNT(ud_stream->ud_mode)){
1092   /* We are in NRTM mode */
1093   /* Clean up */
1094   /* In NRTM mode there may be a saved object that is unprocessed */   
1095    if(nrtm->tr){ /*saved backlog?*/
1096 /*XXX Do nothing with this backlog; next time we connect we will process it */   
1097 #if 0   
1098     /* restart the timer for statistics */
1099     UT_timeget(&sotime);
1100     object_process(nrtm->tr); /* delete the previous(saved) object*/
1101 /*    result=report_transaction(nrtm->tr, &(ud_stream->log), nrtm->object_name, 
1102                               "NRTM:DEL:While deleting previous(saved) object"); */
1103     /* create DEL serial record no matter what the result is */
1104     UD_lock_serial(nrtm->tr);
1105     serial_id = UD_create_serial(nrtm->tr); 
1106     CP_CREATE_S_PASSED(nrtm->tr->action); TR_update_status(nrtm->tr);
1107     UD_commit_serial(nrtm->tr);
1108     UD_unlock_serial(nrtm->tr);
1109     /* Mark TR as clean */
1110     TR_mark_clean(nrtm->tr);
1111     /* log the transaction */
1112     result=report_transaction(nrtm->tr, serial_id, log_ptr, &sotime, "M:DEL");
1113 #endif
1114     transaction_free(nrtm->tr); nrtm->tr=NULL;
1115    } 
1116   }
1117 
1118  /* That's all. Free GString */
1119   g_string_free(g_obj_buff, TRUE);
1120 
1121                                                                                                        
1122  /* Calculate some statistics */
1123   UT_timeget(&ftime);
1124   timediff = UT_timediff(&stime, &ftime);
1125   obj_second1 = (float)(log_ptr->num_ok)/timediff;
1126   obj_second10 = (float)(log_ptr->num_ok+log_ptr->num_failed)/timediff;
1127   
1128   /* Print the report */
1129   if(IS_STANDALONE(ud_stream->ud_mode) || (!IS_UPDATE(ud_stream->ud_mode))) {
1130 
1131    ER_inf_va(FAC_UD, ASP_UD_UPDLOG,"%s ******** report **********", UD_TAG);
1132    ER_inf_va(FAC_UD, ASP_UD_UPDLOG,"%s %d objects OK (%7.4f obj/s)", UD_TAG, log_ptr->num_ok, obj_second1);
1133    ER_inf_va(FAC_UD, ASP_UD_UPDLOG,"%s %d objects failed", UD_TAG, log_ptr->num_failed);
1134    ER_inf_va(FAC_UD, ASP_UD_UPDLOG,"%s average processing time %7.4f obj/s (%6.2f obj/min)", UD_TAG, 
1135                           obj_second10, obj_second10*60);
1136    result=log_ptr->num_ok+log_ptr->num_failed;
1137   }
1138   return(result);
1139 
1140 } /* UD_process_stream */
1141 

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