modules/ud/ud_process_stream.c

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

FUNCTIONS

This source file includes following functions.
  1. ud_parse_init
  2. ud_parse_free
  3. split_attribute
  4. reorder_attributes
  5. each_attribute_print
  6. print_object
  7. escape_apostrophes
  8. line_type
  9. UD_parse_object
  10. report_transaction
  11. process_nrtm
  12. process_updates
  13. process_transaction
  14. UD_process_stream

   1 /***************************************
   2   $Revision: 1.35 $
   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                              RIPE NCC
  15  
  16   All Rights Reserved
  17   
  18   Permission to use, copy, modify, and distribute this software and its
  19   documentation for any purpose and without fee is hereby granted,
  20   provided that the above copyright notice appear in all copies and that
  21   both that copyright notice and this permission notice appear in
  22   supporting documentation, and that the name of the author not be
  23   used in advertising or publicity pertaining to distribution of the
  24   software without specific, written prior permission.
  25   
  26   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  27   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  28   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  29   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  30   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  31   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  32  ***************************************/
  33 #include <sys/types.h>
  34 #include <sys/socket.h>
  35 #include <netdb.h>
  36 #include <arpa/inet.h>
  37 #include <unistd.h>
  38 #include <sys/stat.h>
  39 #include <fcntl.h>
  40 #include <string.h>
  41 #include "constants.h"
  42 #include "query_command.h"
  43 #include "ud.h"
  44 #include "ud_int.h"
  45 
  46 typedef enum _Line_Type_t {
  47  LINE_ATTRIBUTE,
  48  LINE_COMMENT,
  49  LINE_EMPTY,
  50  LINE_EOF,
  51  LINE_ADD,
  52  LINE_UPD,
  53  LINE_DEL,
  54  LINE_OVERRIDE_ADD,
  55  LINE_OVERRIDE_UPD,
  56  LINE_OVERRIDE_DEL,
  57  LINE_PLUS
  58 } Line_Type_t;
  59 
  60 /* Maximum number of objects(serials) we can consume at a time */
  61 #define SBUNCH 1000
  62 
  63 static int report_transaction(Transaction_t *tr, Log_t *log, char *obj_name, char *reason);
  64 static int process_nrtm(UD_stream_t *ud_stream, Transaction_t *tr, char *object_name, int operation);
  65 static int process_updates(UD_stream_t *ud_stream, Transaction_t *tr, char *object_name, int operation);
  66 static int process_transaction(UD_stream_t *ud_stream,Object_t *obj,char *object_name,nic_handle_t *nh, int operation);
  67                                                                                                 
  68 /* Delimiters that separate list members, both RPS(,) and legacy( ) */
  69 #define ATTR_DELIMITERS " ,"
  70 
  71 
  72 void ud_parse_init(Obj_parse_t *parse){
     /* [<][>][^][v][top][bottom][index][help] */
  73      bzero(parse, sizeof(Obj_parse_t));
  74      parse->start_object=1;     
  75 }
  76 
  77 void ud_parse_free(Obj_parse_t *parse){
     /* [<][>][^][v][top][bottom][index][help] */
  78      free(parse->object_name);
  79 }
  80 
  81 
  82 
  83 static GSList *split_attribute(GSList *attr_list, A_Type_t attr_type, char *attr_value){
     /* [<][>][^][v][top][bottom][index][help] */
  84 char *token;
  85 char *split;
  86 char *value, *n;
  87 Attribute_t *attr_split;
  88 GSList *the_list = attr_list;
  89 
  90   /* check for line continuation (+) */
  91   if (strncmp(attr_value, "+", 1) == 0) attr_value++;
  92   /* check for end-of-line comments */
  93   n = index(attr_value, '#');
  94       /* if there is no comment check for trailing \n */
  95   if(n == NULL) n = index(attr_value, '\n');
  96   /* now copy the clean value into the attribute */
  97   if(n == NULL) value = g_strdup(attr_value); 
  98   else  value = g_strndup(attr_value, (n - attr_value));
  99      
 100   token=value;
 101   while((split=strsep(&token, ATTR_DELIMITERS))){
 102      attr_split = attribute_new1(attr_type, split);
 103      if (attr_split) the_list = g_slist_append(the_list, attr_split);
 104   }
 105   free(value);
 106  return(the_list);
 107 }
 108 
 109 /************************************************************
 110 *                                                           *
 111 * The function to reorder attributes in the List            *
 112 * nic-hdl and mnt-by should come first                      *
 113 *                                                           *
 114 * should return 0 if they are equal, a negative value if    * 
 115 * the first element comes before the second, or a positive  *
 116 * value if the first element comes after the second         *
 117 *                                                           *
 118 ************************************************************/
 119 static gint reorder_attributes(const void *element1, const void *element2)
     /* [<][>][^][v][top][bottom][index][help] */
 120 {
 121 Attribute_t *attr1 = (Attribute_t *)element1;
 122 Attribute_t *attr2 = (Attribute_t *)element2;
 123 gint order = -1;
 124   
 125   if(attr2->type == A_MB) order= 1;
 126   if(attr1->type == A_MB) order= -1;
 127   if(attr2->type == A_NH) order= 1;
 128   if(attr1->type == A_NH) order= -1;
 129 
 130   return(order);
 131 
 132 }
 133 
 134 /* XXX */
 135 static void each_attribute_print(void *element_data, void *tr_ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 136 {
 137 
 138 Attribute_t *attr = (Attribute_t *)element_data;
 139 
 140  fprintf(stderr, "[%d|%s]\n", attr->type, attr->value);
 141 
 142 }
 143 
 144 /* XXX */
 145 static void print_object(Object_t *obj)
     /* [<][>][^][v][top][bottom][index][help] */
 146 {
 147   g_slist_foreach(obj->attributes, each_attribute_print, NULL); 
 148   fprintf(stderr, ">>>>>\n%s\n", obj->object->str);
 149 }
 150 
 151 
 152 /******************************************************************
 153 * GString *escape_apostrophes()                                   *
 154 * Escapes apostrophes in the text so they do not confuse printf   *
 155 * functions and don't corrupt SQL queries                         *
 156 *                                                                 *
 157 * *****************************************************************/
 158 GString *escape_apostrophes(GString *text) {
     /* [<][>][^][v][top][bottom][index][help] */
 159   int i;
 160   for (i=0; i < text->len; i++) {
 161     if ((text->str[i] == '\'') || (text->str[i] == '\\')) {
 162       text = g_string_insert_c(text, i, '\\');
 163       i++;
 164     }
 165   }
 166  return(text); 
 167 } /* escape_apostrophes() */
 168 
 169 
 170 /******************************************************************
 171 * Line_Type_t line_type(e)                                        *
 172 * Determines the line type analysing the first letters            *
 173 *                                                                 *
 174 * ****************************************************************/
 175 static Line_Type_t line_type(const char *line) {
     /* [<][>][^][v][top][bottom][index][help] */
 176   Line_Type_t result = -1;
 177 
 178   if (strncmp(line, "# EOF", 4) == 0) {
 179     result = LINE_EOF;
 180   }
 181   else if (strncmp(line, "#", 1) == 0) {
 182     result = LINE_COMMENT;
 183   }
 184   else if (strcmp(line, "\n") == 0) {
 185     result = LINE_EMPTY;
 186   }
 187   else if (strcmp(line, "ADD\n") == 0) {
 188     result = LINE_ADD;
 189   }
 190   else if (strcmp(line, "UPD\n") == 0) {
 191     result = LINE_UPD;
 192   }
 193   else if (strcmp(line, "DEL\n") == 0) {
 194     result = LINE_DEL;
 195   }
 196   else if (strcmp(line, "ADD_OVERRIDE\n") == 0) {
 197     result = LINE_OVERRIDE_ADD;
 198   }
 199   else if (strcmp(line, "UPD_OVERRIDE\n") == 0) {
 200     result = LINE_OVERRIDE_UPD;
 201   }
 202   else if (strcmp(line, "DEL_OVERRIDE\n") == 0) {
 203     result = LINE_OVERRIDE_DEL;
 204   }
 205   else if (strncmp(line, "+", 1) == 0) {
 206     result = LINE_PLUS;
 207   }  
 208   else {
 209     result = LINE_ATTRIBUTE;
 210   }
 211 
 212   return result;
 213 } /* line_type() */
 214 
 215 /******************************************************************
 216 * Object_t *UD_parse_object()                                     *
 217 *                                                                 *
 218 * Parses the object accepting line by line                        *
 219 *                                                                 *
 220 * ****************************************************************/
 221 Object_t *UD_parse_object(SQ_connection_t *sql_connection, Obj_parse_t *parse, char *line_buff)
     /* [<][>][^][v][top][bottom][index][help] */
 222 {
 223 GString *g_line_buff;
 224 Attribute_t *class_attr, *attr;
 225 char *a_value, *ptr;
 226 char nic[MAX_NH_LENGTH];
 227  
 228  
 229   if (parse->start_object == 1) {
 230    parse->obj = object_new(line_buff);
 231   }
 232   if (parse->obj) {
 233 
 234     if ((g_line_buff = g_string_sized_new(STR_XXL)) == NULL){ 
 235       fprintf(stderr, "E: cannot allocate gstring\n"); 
 236       die; 
 237     }
 238   
 239    g_string_sprintf(g_line_buff, "%s", line_buff);
 240    /* escape apostrophes in the input line */
 241    g_line_buff=escape_apostrophes(g_line_buff);
 242    
 243    if(parse->start_object == 1){
 244    /* If this is the first attribute(==object name/type) */   
 245     parse->start_object=0;
 246     parse->object_name = g_strndup(g_line_buff->str, g_line_buff->len);
 247      *(parse->object_name+g_line_buff->len-1)='\0';
 248     fprintf(stderr, "D: object: [%s] ", parse->object_name);
 249   /* Create an attribute - the first one determines a class */
 250     parse->class_attr_list=NULL; /* Initialize the list that will hold splitted class attribute */
 251     class_attr = attribute_new(g_line_buff->str);
 252     if (class_attr == NULL) die; /* Should not happen */
 253     if((class_attr->type==A_PN)||(class_attr->type==A_RO)){
 254    /* split names */  
 255       parse->class_attr_list = split_attribute(parse->class_attr_list, class_attr->type, class_attr->value);  
 256       attribute_free(class_attr, NULL);
 257     } else {
 258       parse->class_attr_list = g_slist_append(parse->class_attr_list, class_attr); 
 259     }
 260   /* do nothing more with this attribute - we will prepend it at the end */
 261    }
 262    else {
 263      attr = attribute_new(g_line_buff->str);
 264         
 265      if (attr) {
 266        parse->a_type=attr->type;   
 267        a_value=attr->value;
 268        if(parse->a_type==A_NH) {
 269           /*  Parse the string into nh structure */
 270           /*  In case of an AUTO NIC handle check the ID in the database */
 271           /* Possible errors leave to core processing */
 272           if(NH_parse(attr->value, &parse->nh_ptr) == 0) { 
 273 /*         fprintf(stderr, "D:parsing NIC: [%s]\n", attr->value); */
 274            /* Check if we can allocate it */  
 275             if(NH_check(parse->nh_ptr, sql_connection)>0){
 276             /* Convert nh to the database format */  
 277               NH_convert(nic, parse->nh_ptr);
 278 /*      fprintf(stderr, "D:NIC:[%s]\n", nic); */
 279               /* Replace NIC handle in the string which is copied to the text object */
 280               sprintf(line_buff, g_line_buff->str);
 281               ptr = strstr(line_buff, attr->value);
 282               /* parse new attribute string */
 283               strcpy(ptr, nic);
 284               g_string_sprintf(g_line_buff, line_buff);
 285               g_string_sprintfa(g_line_buff, "\n");
 286               /* Update the attribute */
 287               attribute_upd(attr, attr->type, nic); 
 288 /*      fprintf(stderr, "D:attribute updated\n"); */
 289             }
 290           }
 291        } /* NHR stuff */
 292      }
 293      else 
 294        a_value=g_line_buff->str;
 295 
 296      if (parse->a_type>=0) { /* This indicates that the input line contains the value of the attribute */
 297          switch (parse->a_type) {
 298             /*these attributes may appear several on the line - split them*/   
 299             case A_PN: /* person */
 300             case A_RO: /* role */
 301             case A_MR: /* mbrs-by-ref */
 302             case A_MB: /* mnt-by */
 303             case A_MO: /* member-of */
 304             case A_SD: /* sub-dom */
 305             case A_RZ: /* rev-srv */
 306             case A_NS: /* nserver */
 307                 parse->obj->attributes = split_attribute(parse->obj->attributes, parse->a_type, a_value);
 308                 if (attr) attribute_free(attr, NULL);
 309              attr=NULL;
 310              break; 
 311             default: break;  
 312          }
 313 /*       g_string_sprintfa(obj->object, "%s", g_line_buff->str); */
 314          if(attr)parse->obj->attributes = g_slist_append(parse->obj->attributes, attr);  
 315      }
 316    } /* if not start_object (not the first/class attribute) */
 317    /* copy the line into object no matter whether it is an attribute or not (continualtion, etc.) */
 318    g_string_sprintfa(parse->obj->object, "%s", g_line_buff->str);
 319    g_string_free(g_line_buff, TRUE);
 320   }/* if (obj) */
 321     return(parse->obj);
 322 }
 323 
 324 /******************************************************************
 325 * report_transaction()                                            *
 326 *                                                                 * 
 327 * Prints error report to the log                                  *
 328 *                                                                 *
 329 * reason - additional message that will be included               *
 330 *                                                                 *
 331 * *****************************************************************/
 332 static int report_transaction(Transaction_t *tr, Log_t *log, char *obj_name, char *reason)
     /* [<][>][^][v][top][bottom][index][help] */
 333 {
 334 int result=0;
 335 
 336  if(tr->succeeded==0) {
 337   result=tr->error;
 338   log->num_failed++;
 339   fprintf(stderr, "FAILED[%s][%s(%d)](%d/%d)\n ", obj_name, reason, result, log->num_failed, (log->num_failed)+(log->num_ok)); 
 340   fprintf(log->logfile, "*FAILED[%s][%s](%d/%d)\n ", obj_name, reason, log->num_failed, (log->num_failed)+(log->num_ok));
 341   if(result & ERROR_U_MEM) fprintf(log->logfile, "\t*Memory allocation error\n");
 342   if(result & ERROR_U_DBS) fprintf(log->logfile, "\t*Database (SQL) error\n");
 343   if(result & ERROR_U_OBJ) fprintf(log->logfile, "\t*Object (RF) error\n");
 344   if(result & ERROR_U_AUT) fprintf(log->logfile, "\t*Object authentication error\n");
 345   if(result & ERROR_U_BADOP) fprintf(log->logfile, "\t*Bad operation\n");
 346   if(result & ERROR_U_COP) fprintf(log->logfile, "\t*Conflicting operation\n");
 347   if(result & ERROR_U_NSUP) fprintf(log->logfile, "\t*Object of this type is not supported\n");
 348   if(result & ERROR_U_BUG) fprintf(log->logfile, "\t*Software bug - report to <ripe-dbm@ripe.net>\n");
 349   fprintf(log->logfile, "%s", (tr->error_script)->str);
 350   result=(-1)*result;                                                
 351   fflush(log->logfile);
 352  }
 353  else {
 354   result=1;
 355   log->num_ok++;
 356   fprintf(stderr, "OK(%d/%d)\n", log->num_ok, (log->num_failed)+(log->num_ok));
 357  }
 358                                                                                                                                                 
 359  return(result);
 360 }/* report_transaction() */
 361 
 362 
 363 
 364 /************************************************************
 365 * process_nrtm()                                            *
 366 *                                                           *
 367 * Process object in NRTM client mode                        *
 368 *                                                           *
 369 * nrtm - pointer to _nrtm structure                         *
 370 * log - pointer to Log_t structure                          *
 371 * object_name - name of the object                          * 
 372 * operation - operation code (OP_ADD/OP_DEL)                *
 373 *                                                           *
 374 * Returns:                                                  *
 375 * 1  - okay                                                 *
 376 * <0 - error                                                *
 377 *                                                           *
 378 ************************************************************/
 379 
 380 static int process_nrtm(UD_stream_t *ud_stream, Transaction_t *tr, char *object_name, int operation)
     /* [<][>][^][v][top][bottom][index][help] */
 381 {
 382 int result=0;
 383 int dummy=0;
 384 struct _nrtm *nrtm = ud_stream->nrtm;
 385 Log_t *log_ptr= &(ud_stream->log);
 386 
 387   /* We allow NRTM updates for some inconsistent objects                  */
 388   /* One of the examples is reference by name which looks like nic-handle */
 389   /* For this purpose we allow dummy creation when updating an object     */
 390   /* We also check for dummy allowance when deleting an object            */
 391   /* this is done to allow deletion of person objects referenced by name  */
 392 
 393   tr->dummy=1;
 394   
 395   switch (operation) {
 396   
 397   case OP_ADD:
 398     if(nrtm->tr){ /* DEL ADD => saved*/
 399       if(tr->object_id==0) { 
 400         /* object does not exist in the DB */      
 401         object_process(nrtm->tr); /* delete the previous(saved) object*/
 402         result=report_transaction(nrtm->tr, log_ptr, nrtm->object_name, "NRTM:DEL:While deleting previous(saved)");
 403         /* create DEL serial */
 404         create_serial(nrtm->tr);
 405         object_free(nrtm->tr->object);
 406         transaction_free(nrtm->tr); nrtm->tr=NULL;
 407         /* Create an object and update NHR */
 408         tr->action=(TA_CREATE | TA_UPD_NHR);
 409 /*      fprintf(stderr,"CREATE next\n"); */
 410         object_process(tr); /* create a new one*/
 411         result=report_transaction(tr, log_ptr, object_name, "NRTM:ADD:While creating new");
 412         /* create ADD serial */
 413         create_serial(tr);
 414       }
 415       else { 
 416       /* object already exists in the DB - update or dummy replacement*/
 417         if(tr->object_id==nrtm->tr->object_id) {/*compare the two, may be we may collapse operations*/
 418           object_free(nrtm->tr->object);
 419           transaction_free(nrtm->tr); nrtm->tr=NULL;
 420 /*        fprintf(stderr,"DEL-ADD ->> UPDATE\n");*/
 421           tr->action=TA_UPDATE;
 422           object_process(tr);
 423           report_transaction(tr, log_ptr, object_name,"NRTM:upd");
 424           result=report_transaction(tr, log_ptr, object_name,"NRTM:upd");
 425           /* create DEL+ADD serial records */
 426           tr->action=TA_DELETE; create_serial(tr);
 427           tr->action=TA_CREATE; create_serial(tr);
 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 /*        fprintf(stderr,"DEL previous\n");*/
 432           object_process(nrtm->tr); /* delete the previous(saved) object*/
 433           result=report_transaction(nrtm->tr, log_ptr, nrtm->object_name, "NRTM:DEL:While deleting previous(saved)");
 434           /* create a DEL serial record */
 435           create_serial(nrtm->tr);
 436           object_free(nrtm->tr->object);
 437           transaction_free(nrtm->tr); nrtm->tr=NULL;
 438           tr->action=TA_UPDATE;
 439           dummy=isdummy(tr);
 440           /* If we are replacing dummy with a real object update NHR */
 441           if(dummy==1) tr->action |= TA_UPD_NHR;
 442 /*        fprintf(stderr,"UPDATE next(dummy)\n"); */
 443           object_process(tr); /* create a new one*/
 444           result=report_transaction(tr, log_ptr, object_name, "NRTM:ADD:While creating new");
 445           /* For serials this is CREATE operation */
 446           if(dummy==1) tr->action=TA_CREATE;
 447           /* create ADD serial record */
 448           create_serial(tr);
 449         }
 450       }
 451     }
 452     else { /* ADD ADD =>brand new object*/
 453       if(tr->object_id==0) {
 454 /*      fprintf(stderr,"CREATE new\n");*/
 455         /* Create an object and update NHR */
 456         tr->action=(TA_CREATE | TA_UPD_NHR);
 457         object_process(tr);
 458         result=report_transaction(tr, log_ptr, object_name,"NRTM:ADD:While creating new");
 459         /* create ADD serial */
 460         create_serial(tr);
 461       }
 462       else { /* object already exists in the database */
 463         /* this may happen because of dummies*/
 464         /* or with some implementations of mirroring protocol that have atomic update */
 465         /* instead of add + del */
 466 /*      fprintf(stderr,"CREATE new\n");*/
 467         tr->action=TA_UPDATE;
 468         dummy=isdummy(tr);
 469  /* If we are replacing dummy with a real object update NHR */
 470         if(dummy==1) tr->action |= TA_UPD_NHR;
 471         object_process(tr);
 472         result=report_transaction(tr, log_ptr, object_name,"NRTM:ADD:While creating new");
 473         if(dummy==1) tr->action=TA_CREATE; /* we don't want to generate DEL serial for dummy replacement*/
 474         /* create ADD serial record */
 475         create_serial(tr);
 476       } 
 477     }
 478     break;
 479     
 480   case OP_DEL:
 481     if(nrtm->tr){ /*DEL DEL =>saved */
 482 /*    fprintf(stderr,"DEL previous\n");*/
 483       object_process(nrtm->tr); /* delete the previous(saved) object*/
 484       result=report_transaction(nrtm->tr, log_ptr, nrtm->object_name, "NRTM:DEL:While deleting previous(saved) object");
 485       /* create DEL serial record */
 486       create_serial(nrtm->tr);
 487       object_free(nrtm->tr->object);
 488       transaction_free(nrtm->tr); nrtm->tr=NULL;
 489     }
 490     if(tr->object_id>0){ /* save the object*/
 491       fprintf(stderr,"SAVED\n");
 492       tr->action=TA_DELETE;
 493       nrtm->tr=tr;
 494       strcpy(nrtm->object_name, object_name);
 495       return(1);
 496     }
 497     else { /* this is an error - Trying to DEL non-existing object*/
 498       tr->succeeded=0; tr->error|=ERROR_U_COP;
 499       result=report_transaction(tr, log_ptr, object_name, "NRTM:OOS:Trying to DEL non-existing object");
 500       /* create DEL serial record anyway */
 501       tr->action=TA_DELETE;
 502       create_serial(tr);
 503     }
 504     break;
 505   
 506   default:
 507     tr->succeeded=0; tr->error |=ERROR_U_BADOP;
 508     break;  
 509   }
 510 
 511  /* Free resources */  
 512   object_free(tr->object);
 513   transaction_free(tr);
 514   
 515   return(result);
 516 } /* process_nrtm() */
 517 
 518 
 519 
 520 /************************************************************
 521 * process_updates()                                         *
 522 *                                                           *
 523 * Process object in update mode                             *
 524 *                                                           *
 525 * ud_stream - pointer to UD_stream structure                *
 526 * object_name - name of the object                          *
 527 * operation - operation code (OP_ADD/OP_DEL)                *
 528 *                                                           *
 529 * Note:                                                     *
 530 * Frees tr and tr->obj on exit                              *
 531 *                                                           *
 532 * Returns:                                                  *
 533 * 1  - okay                                                 *
 534 * <0 - error                                                *
 535 *                                                           * 
 536 ************************************************************/
 537 
 538 static int process_updates(UD_stream_t *ud_stream, Transaction_t *tr, char *object_name, int operation)
     /* [<][>][^][v][top][bottom][index][help] */
 539 {
 540 int result=0;
 541 Log_t *log_ptr= &(ud_stream->log);
 542 int dummy=0;
 543 
 544     switch(operation) {
 545     /* Compare operations and report an error if they do not match */    
 546     case OP_ADD:
 547              if(tr->object_id!=0) { /* trying to create, but object exists */
 548         tr->succeeded=0; tr->error|=ERROR_U_COP;
 549       } else {
 550        /* Action: create the object and update NHR */
 551         tr->action=(TA_CREATE | TA_UPD_NHR);
 552         object_process(tr);
 553       }
 554       break;
 555     case OP_UPD:
 556       if(tr->object_id==0) { /* trying to update non-existing object*/
 557         tr->succeeded=0; tr->error|=ERROR_U_COP;
 558       } else {
 559         tr->action=TA_UPDATE;
 560         dummy=isdummy(tr);
 561         /* If we are replacing dummy with a real object update NHR */
 562         if(dummy==1) tr->action |= TA_UPD_NHR;
 563         object_process(tr);
 564       }
 565       break;
 566 
 567     case OP_DEL:        
 568       if(tr->object_id==0) { /* trying t delete non-existing object*/
 569         tr->succeeded=0; tr->error|=ERROR_U_COP;
 570       } else {
 571         tr->action=TA_DELETE;
 572         object_process(tr);
 573       }
 574       break;
 575                 
 576     default:                
 577       /* bad operation for this mode if not standalone */
 578       if(tr->standalone) {
 579         if(tr->object_id==0)tr->action=TA_CREATE; else tr->action=TA_UPDATE;
 580         object_process(tr);
 581       }
 582       else {
 583         tr->succeeded=0; 
 584         tr->error|=ERROR_U_BADOP; 
 585       }
 586       break;
 587     }
 588    /* Make a report */
 589     result=report_transaction(tr, log_ptr, object_name, "RIPupd:");
 590 
 591    /* If not in standalone mode create serial and copy error transcript */ 
 592     if(!tr->standalone) {
 593       if(result==1)create_serial(tr);
 594       ud_stream->error_script=g_strdup((tr->error_script)->str);
 595     }  
 596 
 597    /* Free resources */   
 598     object_free(tr->object);
 599     transaction_free(tr);
 600     
 601     return(result);
 602         
 603 } /* process_updates() */
 604 
 605 
 606 /************************************************************
 607 *                                                           *
 608 * int process_transaction()                                 *
 609 *                                                           *
 610 * Processes the transaction                                 *
 611 *                                                           *
 612 * ud_stream - pointer to UD_stream_t structure              *
 613 *                                                           *
 614 * Returns:                                                  *
 615 * 1 - no error                                              *
 616 * <0- errors                                                *
 617 *                                                           *
 618 ************************************************************/
 619 
 620 /* It frees the obj */
 621 
 622 static int process_transaction(UD_stream_t *ud_stream, 
     /* [<][>][^][v][top][bottom][index][help] */
 623                         Object_t *obj, 
 624                         char *object_name, 
 625                         nic_handle_t *nh,
 626                         int operation)
 627 {
 628 Transaction_t *tr = NULL;
 629 Log_t *log_ptr = &(ud_stream->log);
 630 Attribute_t *attr=NULL;
 631 int result;
 632 
 633 /* start new transaction now */ 
 634  tr = transaction_new(ud_stream->db_connection, obj->type);
 635 
 636 /* Return with error if transaction cannot be created */ 
 637  if (tr == NULL) die;
 638  
 639  tr->standalone=IS_STANDALONE(ud_stream->ud_mode);
 640  tr->dummy=IS_DUMMY_ALLOWED(ud_stream->ud_mode);
 641  tr->load_pass=ud_stream->load_pass;
 642  tr->object=obj;
 643  tr->nh=nh;
 644  tr->source_hdl=ud_stream->source_hdl;
 645  
 646 /* We perform no commit/rollback in the loader mode, so thread_id should be set to 0 */
 647  if(ud_stream->load_pass!=0) { tr->thread_ins=0; tr->thread_upd=0; }
 648     
 649 /* For the first load pass we only create objects */ 
 650  if(ud_stream->load_pass==1) tr->object_id=0;
 651   else tr->object_id=get_object_id(tr);
 652  
 653 /* Object cannot be retrieved */
 654  if(tr->object_id==-1) { /* DB error*/
 655     tr->succeeded=0;
 656     tr->error |= ERROR_U_DBS;
 657     report_transaction(tr, log_ptr, object_name, "Object cannot be retrieved");
 658     transaction_free(tr);
 659     object_free(obj);
 660     die;
 661  }
 662 /* save the name of person/role as we need it for referential */
 663 /* integrity check when deleting the object against names. */
 664 /* This is needed to support legacy references by name rather */
 665 /* then by nic_hdl */
 666   if((tr->class_type==C_PN) || (tr->class_type==C_RO)){
 667      attr = attribute_new(object_name);
 668       
 669      if (attr==NULL) {
 670        tr->succeeded=0;
 671        tr->error |= ERROR_U_MEM;
 672        report_transaction(tr, log_ptr, object_name, "Cannot allocate memory");
 673        transaction_free(tr);
 674        object_free(obj);
 675        die;
 676     }
 677     
 678     /* Save the value */
 679     tr->save=g_strdup(attr->value);
 680 /*    fprintf(stderr, "Allocated [%s]\n", tr->save); */
 681     attribute_free(attr, NULL);
 682   }
 683                                                
 684 /* Process transaction. tr and obj are freed inside the process_* functions */
 685 
 686  if(IS_UPDATE(ud_stream->ud_mode))
 687  /* We are in update mode */
 688     result=process_updates(ud_stream, tr, object_name, operation);
 689  else
 690  /* We are in NRTM mode */   
 691     result=process_nrtm(ud_stream, tr, object_name, operation);
 692 
 693  return(result);
 694 
 695 }          
 696           
 697 
 698 /************************************************************
 699 *                                                           *
 700 * int UD_process_stream(UD_stream_t *ud_stream)             *
 701 *                                                           *
 702 * Processes the stream                                      *
 703 *                                                           *
 704 * ud_stream - pointer to UD_stream_t structure              *
 705 *                                                           *
 706 * Returns:                                                  *
 707 * in update mode (!standalone)(1 object processed):         *
 708 * 1 - no error                                              *
 709 * <0- errors                                                *
 710 *                                                           *
 711 * in NRTM & standalone modes                                *
 712 * total number of object processed                          *
 713 *                                                           *
 714 ************************************************************/
 715 
 716 int UD_process_stream(UD_stream_t *ud_stream)
     /* [<][>][^][v][top][bottom][index][help] */
 717 {
 718   char line_buff[STR_XXL];
 719 /*  GString *g_line_buff; */
 720   GSList *class_attr_list = NULL;
 721   Attribute_t *class_attr;
 722   Attribute_t *attr;
 723   nic_handle_t *nh_ptr = NULL; /* To save  NIC handle structure */
 724   Object_t *obj = NULL;
 725   SQ_connection_t *sql_connection;
 726   int start_object;
 727   int a_type;
 728   char *a_value;
 729   char *ptr;
 730   /* here we will store the parsed nic-hdl in required format */
 731   char nic[MAX_NH_LENGTH];
 732   struct _nrtm *nrtm;
 733   Log_t *log_ptr= &(ud_stream->log);
 734   time_t stime, ftime;
 735   double obj_second1, obj_second10;
 736   int result;
 737   int operation=0;
 738   int interrupt=0;
 739   int do_update;
 740   int default_ud_mode = ud_stream->ud_mode;
 741   Line_Type_t linetype;
 742 
 743   Obj_parse_t obj_parse; /* the structure used to parse a text object */
 744   ud_parse_init(&obj_parse);
 745   
 746   nrtm=ud_stream->nrtm;
 747   start_object = 1;
 748   a_type=-1; 
 749 
 750 
 751   /* Allocate line bufer */
 752 /*  if ((g_line_buff = g_string_sized_new(STR_XXL)) == NULL){ 
 753     fprintf(stderr, "E: cannot allocate gstring\n"); 
 754     die; 
 755   }
 756 */
 757   /* Check connection to the database */
 758   if(mysql_ping(ud_stream->db_connection)) {
 759    fprintf(stderr, "D: ERROR: no SQL connection\n");
 760 /*   g_string_free(g_line_buff, TRUE);*/
 761    return(-1);
 762   }
 763    
 764   fprintf(stderr, "OK\n");
 765   sql_connection=ud_stream->db_connection;
 766 
 767 /* This is useful for loading DB from huge disk file. */
 768 /* We may start from <num_skip>th object */
 769 /*  num_skip=ud_stream->num_skip; */
 770 /*  if(num_skip>0) fprintf(stderr, "skipping %lu records\n", num_skip); */
 771 
 772   /* Start timer for statistics */
 773   stime=time(NULL);
 774 
 775  /* Main loop. Reading input stream line by line */
 776  /* Empty line signals to start processing an object, if we have it */ 
 777   while (fgets(line_buff, STR_XXL, ud_stream->stream) != NULL) {
 778 
 779     switch (linetype=line_type(line_buff)) {
 780       case LINE_PLUS:
 781       case LINE_ATTRIBUTE:
 782        
 783        obj = UD_parse_object(ud_stream->db_connection, &obj_parse, line_buff);
 784 
 785       break;
 786 
 787       case LINE_COMMENT:
 788       break;
 789 
 790       case LINE_EOF:
 791       break;
 792       
 793       case LINE_ADD:
 794       /* restore the default operation mode */
 795        operation=OP_ADD;
 796        ud_stream->ud_mode=default_ud_mode;
 797       break;
 798       
 799       case LINE_OVERRIDE_ADD:
 800       /* for override - switch the dummy bit on */
 801        operation=OP_ADD;
 802        ud_stream->ud_mode=default_ud_mode|B_DUMMY;
 803       break;
 804       
 805       case LINE_UPD:
 806       /* restore the default operation mode */
 807        operation=OP_UPD;
 808        ud_stream->ud_mode=default_ud_mode;
 809       break;  
 810 
 811       case LINE_OVERRIDE_UPD:
 812       /* for override - switch the dummy bit on */
 813        operation=OP_UPD;
 814        ud_stream->ud_mode=default_ud_mode|B_DUMMY;
 815       break;
 816       
 817       case LINE_DEL:
 818       /* restore the default operation mode */
 819        operation=OP_DEL;
 820        ud_stream->ud_mode=default_ud_mode;
 821       break; 
 822 
 823       case LINE_OVERRIDE_DEL:
 824       /* for override - switch the dummy bit on */
 825        operation=OP_DEL;
 826        ud_stream->ud_mode=default_ud_mode|B_DUMMY;
 827       break;
 828  
 829       case LINE_EMPTY:
 830        /* start processing the object */
 831         if ((obj=obj_parse.obj)) { /* if not just garbage*/
 832          /* reorder some attributes */
 833          obj->attributes = g_slist_sort(obj->attributes, reorder_attributes);
 834          /* prepend the class attribute */
 835          obj->attributes = g_slist_concat(obj_parse.class_attr_list, obj->attributes);
 836          /* XXX */
 837          /* print_object(obj); */
 838 
 839          /* start new transaction now */ 
 840          result=process_transaction(ud_stream, obj, obj_parse.object_name, obj_parse.nh_ptr, operation);
 841           
 842          /* process_transaction() frees tr and obj structures, */
 843          /* so make sure we'll not reference these objects in the future */
 844          operation=OP_NOOP;
 845          ud_stream->ud_mode=default_ud_mode;
 846          ud_parse_free(&obj_parse);
 847           
 848          /* this is a good place for quick interrupt */
 849          do_update=CO_get_do_update();
 850          if (do_update) interrupt=0; else interrupt=1;
 851          /* we still need to exit in update server mode (only 1 object at a time */ 
 852          if (IS_UPDATE(ud_stream->ud_mode) && (!IS_STANDALONE(ud_stream->ud_mode))) interrupt=1;
 853         } /* if this is a real object */
 854         /* initialize the parsing structure */
 855         ud_parse_init(&obj_parse);
 856 
 857       break;
 858 
 859       default:
 860         fprintf(stderr, "ERROR: Bad line type\n");
 861     } /* switch */
 862     
 863     /* Finish processing if interrupt has been set */
 864     if (interrupt) break;
 865   } /* while */
 866  
 867  /* Some postprocessing */
 868   if(!IS_UPDATE(ud_stream->ud_mode)){
 869   /* We are in NRTM mode */
 870   /* Clean up */
 871    fclose(ud_stream->stream);
 872   /* In NRTM mode there may be a saved object that is unprocessed */   
 873    if(nrtm->tr){ /*saved backlog?*/
 874     object_process(nrtm->tr); /* delete the previous(saved) object*/
 875     result=report_transaction(nrtm->tr, &(ud_stream->log), nrtm->object_name, 
 876                               "NRTM:DEL:While deleting previous(saved) object");
 877     /* create DEL serial record no matter what the result is */
 878     create_serial(nrtm->tr);
 879     object_free(nrtm->tr->object);
 880     transaction_free(nrtm->tr); nrtm->tr=NULL;
 881    } 
 882   }
 883 
 884  /* That's all. Free GString */
 885 /*  g_string_free(g_line_buff, TRUE);*/
 886 
 887                                                                                                        
 888  /* Calculate some statistics */
 889   ftime=time(NULL);
 890   obj_second1 = (float)(log_ptr->num_ok)/(ftime-stime);
 891   obj_second10 = (float)(log_ptr->num_ok+log_ptr->num_failed)/(ftime-stime);
 892   
 893   /* Print the report */
 894   if(IS_STANDALONE(ud_stream->ud_mode) || (!IS_UPDATE(ud_stream->ud_mode))) {
 895 /*   printf("\n\n******** report **********\n%d objects OK\n%d objects failed\n", 
 896             log_ptr->num_ok, log_ptr->num_failed); */
 897    fprintf(log_ptr->logfile,"\n******** report **********\n");
 898    fprintf(log_ptr->logfile," %d objects OK (%5.2f obj/s)\n", log_ptr->num_ok, obj_second1);
 899    fprintf(log_ptr->logfile," %d objects failed\n", log_ptr->num_failed);
 900    fprintf(log_ptr->logfile," average processing time %5.2f obj/s (%5.2f obj/min)\n", 
 901                           obj_second10, obj_second10*60);
 902    result=log_ptr->num_ok+log_ptr->num_failed;
 903   }
 904   return(result);
 905 
 906 } /* UD_process_stream */
 907 

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