bin/create/create.c

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

FUNCTIONS

This source file includes following functions.
  1. escape_apostrophes
  2. each_attribute_to_string
  3. object_to_string
  4. attribute_new
  5. object_free
  6. object_new
  7. line_type
  8. rollback
  9. commit
  10. each_attribute_update
  11. transaction_free
  12. transaction_new
  13. perform_updates
  14. object_process
  15. object_discard
  16. main

   1 /***************************************
   2   $Revision: 1.4 $
   3 
   4   Example code: Create
   5 
   6   Status: NOT REVUED, NOT TESTED
   7 
   8   Author:       Chris Ottrey
   9 
  10   +html+ <DL COMPACT>
  11   +html+ <DT>Online References:
  12   +html+ <DD><UL>
  13   +html+ </UL>
  14   +html+ </DL>
  15  
  16   ******************/ /******************
  17   Modification History:
  18         ottrey (01/11/1999) Created.
  19   ******************/ /******************
  20   Copyright (c) 1999                              RIPE NCC
  21  
  22   All Rights Reserved
  23   
  24   Permission to use, copy, modify, and distribute this software and its
  25   documentation for any purpose and without fee is hereby granted,
  26   provided that the above copyright notice appear in all copies and that
  27   both that copyright notice and this permission notice appear in
  28   supporting documentation, and that the name of the author not be
  29   used in advertising or publicity pertaining to distribution of the
  30   software without specific, written prior permission.
  31   
  32   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  33   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  34   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  35   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  36   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  37   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  38   ***************************************/
  39 #include <stdio.h>
  40 #include <strings.h>
  41 #include <glib.h>
  42 #include "defs.h"
  43 #include "mysql_driver.h"
  44 
  45 #define DEFAULT_PROP_FILE_NAME ".properties"
  46 #define SLEEP_TIME 10
  47 
  48 /*+ String sizes +*/
  49 #define STR_S   63
  50 #define STR_M   255
  51 #define STR_L   1023
  52 #define STR_XL  4095
  53 #define STR_XXL 16383
  54 
  55 typedef enum _Line_Type_t {
  56   LINE_ADD,
  57   LINE_DEL,
  58   LINE_ATTRIBUTE,
  59   LINE_COMMENT,
  60   LINE_EMPTY,
  61   LINE_EOF
  62 } Line_Type_t;
  63 
  64 typedef struct _Attribute_t { 
  65   A_Type_t type;
  66   char *value;
  67 } Attribute_t;
  68 
  69 typedef struct _Object_t {
  70   C_Type_t type;
  71   GSList *attributes;
  72 } Object_t;
  73 
  74 typedef struct _Transaction {
  75   SQ_connection_t *sql_connection;
  76   int thread_id;
  77   C_Type_t class_type;
  78   int succeeded;
  79 } Transaction_t;
  80 
  81 char * const Tables[] = {
  82   "ac",
  83   "an",
  84   "dn",
  85   "tc",
  86   "zc",
  87   "nh",
  88   "object",
  89   NULL
  90 }; /* Tables */
  91 
  92 #include "UD_inserts.def"
  93 
  94 FILE *Scum_file;
  95 
  96 static void escape_apostrophes(GString *text) {
     /* [<][>][^][v][top][bottom][index][help] */
  97   int i;
  98   for (i=0; i < text->len; i++) {
  99     if (text->str[i] == '\'') {
 100       g_string_insert_c(text, i, '\\');
 101       i++;
 102     }
 103   }
 104 } /* escape_apostrophes() */
 105 
 106 static void each_attribute_to_string(void *element_data, void *result_ptr) {
     /* [<][>][^][v][top][bottom][index][help] */
 107   Attribute_t *attr = element_data;
 108   GString *result = (GString *)result_ptr;
 109   GString *value = g_string_new(attr->value);
 110 
 111   escape_apostrophes(value);
 112 
 113   g_string_sprintfa(result, "%s:   \t%s\n", DF_get_attribute_name(attr->type), value->str);
 114 
 115 } /* each_attribute_to_string() */
 116 
 117 static char *object_to_string(const Object_t *obj) {
     /* [<][>][^][v][top][bottom][index][help] */
 118   GString *result = g_string_sized_new(STR_XL);
 119 
 120   g_slist_foreach(obj->attributes, each_attribute_to_string, result);
 121 
 122   return result->str;
 123 } /* object_to_string() */
 124 
 125 static Attribute_t *attribute_new(const char *line) {
     /* [<][>][^][v][top][bottom][index][help] */
 126   Attribute_t *attr = NULL;
 127   int type;
 128   char *colon;
 129   gchar *token;
 130 
 131   colon = index(line, ':'); 
 132   if (colon != NULL) {
 133     if (line[0] =='*') {
 134       token = g_strndup(line+1, 2);
 135       type = DF_attribute_code2type(token);
 136     }
 137     else {
 138       token = g_strndup(line, (colon - line));
 139       type = DF_attribute_name2type(token);
 140     }
 141 
 142     if (type >= 0) {
 143       char *n;
 144       attr = (Attribute_t *)calloc(1, sizeof(Attribute_t)+1);
 145       attr->type = type;
 146       attr->value = g_strdup((colon+2));
 147       /* Remove the tailing \n */
 148       n = index(attr->value, '\n');
 149       if (n != NULL) {
 150         *n = '\0';
 151       }
 152       /* Strip the whitespace */
 153       g_strstrip(attr->value);
 154     }
 155     else {
 156       fprintf(stderr, "ERROR: Bad attribute: %s\n", token);
 157     }
 158   }
 159   else {
 160     fprintf(stderr, "ERROR: Not an attribute: %s\n", line);
 161   }
 162 
 163   return attr;
 164 } /* attribute_new() */
 165 
 166 static object_free(Object_t *obj) {
     /* [<][>][^][v][top][bottom][index][help] */
 167   g_slist_free(obj->attributes);
 168   free(obj);
 169 } /* object_free() */
 170 
 171 static Object_t *object_new(const char *line) {
     /* [<][>][^][v][top][bottom][index][help] */
 172   Object_t *obj = NULL;
 173 
 174   int type;
 175   char *colon;
 176   gchar *token;
 177 
 178   colon = index(line, ':'); 
 179   if (colon != NULL) {
 180     if (line[0] =='*') {
 181       token = g_strndup(line+1, 2);
 182       type = DF_class_code2type(token);
 183     }
 184     else {
 185       token = g_strndup(line, (colon - line));
 186       type = DF_class_name2type(token);
 187     }
 188 
 189     if (type >= 0) {
 190       obj = (Object_t *)calloc(1, sizeof(Object_t)+1);
 191       obj->attributes = NULL;
 192       obj->type = type;
 193     }
 194     else {
 195       fprintf(stderr, "ERROR: Object has an invalid class: %s\n", token);
 196     }
 197   }
 198   else {
 199     fprintf(stderr, "ERROR: No colon found in line: %s\n", line);
 200   }
 201 
 202   return obj;
 203 } /* object_new() */
 204 
 205 static Line_Type_t line_type(const char *line) {
     /* [<][>][^][v][top][bottom][index][help] */
 206   Line_Type_t result = -1;
 207 
 208   int i;
 209   char * const *attr_aliases = DF_get_attribute_aliases();
 210   char attr_code[2];
 211 
 212   if (strncmp(line, "# EOF", 4) == 0) {
 213     result = LINE_EOF;
 214   }
 215   else if (strncmp(line, "ADD", 3) == 0) {
 216     result = LINE_ADD;
 217   }
 218   else if (strncmp(line, "DEL", 3) == 0) {
 219     result = LINE_DEL;
 220   }
 221   else if (strncmp(line, "#", 1) == 0) {
 222     result = LINE_COMMENT;
 223   }
 224   else if (strcmp(line, "\n") == 0) {
 225     result = LINE_EMPTY;
 226   }
 227   else {
 228     result = LINE_ATTRIBUTE;
 229   }
 230 
 231   return result;
 232 } /* line_type() */
 233 
 234 static rollback(Transaction_t *tr) {
     /* [<][>][^][v][top][bottom][index][help] */
 235   GString *query = g_string_sized_new(STR_XL);
 236 
 237   int i;
 238   for (i=0; Tables[i] != NULL; i++) {
 239     g_string_sprintf(query, "DELETE FROM %s WHERE thread_id=%d", Tables[i], tr->thread_id);
 240     SQ_execute_query(tr->sql_connection, query->str);
 241   }
 242 
 243   g_string_free(query, TRUE);
 244 } /* rollback() */
 245 
 246 static commit(Transaction_t *tr) {
     /* [<][>][^][v][top][bottom][index][help] */
 247   GString *query = g_string_sized_new(STR_XL);
 248 
 249   int i;
 250   for (i=0; Tables[i] != NULL; i++) {
 251     g_string_sprintf(query, "UPDATE %s SET thread_id=0 WHERE thread_id=%d", Tables[i], tr->thread_id);
 252     SQ_execute_query(tr->sql_connection, query->str);
 253     printf("%s\n", query->str);
 254   }
 255 
 256   g_string_free(query, TRUE);
 257 } /* commit() */
 258 
 259 static void each_attribute_update(void *element_data, void *tr_ptr) {
     /* [<][>][^][v][top][bottom][index][help] */
 260   my_ulonglong num;
 261   char *query_fmt;
 262   Attribute_t *attr = element_data;
 263   Transaction_t *tr = (Transaction_t *)tr_ptr;
 264 
 265   query_fmt = Insert[attr->type];
 266 
 267   if (strcmp(query_fmt, "") != 0) {
 268     GString *query = g_string_sized_new(STR_XL);
 269 
 270 //    g_string_sprintf(query, "INSERT %s SELECT nh.id, max(object.id), object_type.id, %d FROM nh, object, object_type WHERE nh.value='%s' AND object_type.code='%s' GROUP BY object_type.code", DF_get_attribute_code(attr->type), tr->thread_id, attr->value, DF_get_class_code(tr->class_type));
 271     g_string_sprintf(query, query_fmt, tr->thread_id, attr->value, DF_get_class_code(tr->class_type));
 272     printf("%s\n", query->str);
 273 
 274     SQ_execute_query(tr->sql_connection, query->str);
 275     num = mysql_affected_rows(tr->sql_connection);
 276     if ((num == -1) || (num == 0)) {
 277       printf("A ERROR!: %lld\n", num);
 278       tr->succeeded=0;
 279     }
 280 
 281     g_string_free(query, TRUE);
 282   }
 283 } /* each_attribute_update() */
 284 
 285 static void transaction_free(Transaction_t *tr) {
     /* [<][>][^][v][top][bottom][index][help] */
 286   free(tr);
 287 } /* transaction_free() */
 288 
 289 static Transaction_t *transaction_new(SQ_connection_t *sql_connection, C_Type_t class_type) {
     /* [<][>][^][v][top][bottom][index][help] */
 290   Transaction_t *tr = (Transaction_t *)calloc(1, sizeof(Transaction_t));
 291 
 292   if (tr != NULL) {
 293     tr->sql_connection = sql_connection;
 294     tr->class_type = class_type;
 295     tr->thread_id = mysql_thread_id(sql_connection);
 296     tr->succeeded = 1;
 297   }
 298 
 299   return tr;
 300 } /* transaction_new() */
 301 
 302 static void perform_updates(const Object_t *obj, Transaction_t *tr) {
     /* [<][>][^][v][top][bottom][index][help] */
 303   char *str;
 304   GString *query = g_string_sized_new(STR_XL);
 305   my_ulonglong num;
 306 
 307   if (tr != NULL) { 
 308   if (tr->sql_connection != NULL) { 
 309       str = object_to_string(obj);
 310       g_string_sprintf(query, "INSERT INTO object SET value='%s', thread_id=%d", str, tr->thread_id);
 311       printf("%s\n", query->str);
 312 
 313       SQ_execute_query(tr->sql_connection, query->str);
 314       num = mysql_affected_rows(tr->sql_connection);
 315       if ((num == -1) || (num == 0)) {
 316         printf("B ERROR!: %lld\n", num);
 317         tr->succeeded=0;
 318       }
 319 
 320       g_slist_foreach(obj->attributes, each_attribute_update, tr);
 321 
 322       free(str);
 323     }
 324   }
 325 
 326   g_string_free(query, TRUE);
 327 } /* perform_updates() */
 328 
 329 static object_process(const Object_t *obj) {
     /* [<][>][^][v][top][bottom][index][help] */
 330   SQ_connection_t *sql_connection;
 331   int thread_id;
 332   Transaction_t *tr = NULL;
 333   char *str;
 334   
 335   //sql_connection = SQ_get_connection("rowan.ripe.net", 3306, "test", "user", "password");
 336   sql_connection = SQ_get_connection2();
 337 
 338   if (sql_connection) {
 339 
 340     tr = transaction_new(sql_connection, obj->type);
 341 
 342     if (tr != NULL) {
 343       perform_updates(obj, tr);
 344       if (tr->succeeded == 1) {
 345         commit(tr);
 346       }
 347       else {
 348         rollback(tr);
 349         str = object_to_string(obj);
 350         fprintf(Scum_file, "Couldn't add;\n%s\n", str);
 351         free(str);
 352       }
 353       transaction_free(tr);
 354     }
 355 
 356     SQ_close_connection(sql_connection);
 357   }
 358 
 359 } /* object_process() */
 360 
 361 static object_discard(Object_t *obj) {
     /* [<][>][^][v][top][bottom][index][help] */
 362   char *str;
 363 
 364   fprintf(stderr, "ERROR: Bad attribute in object => discard\n");
 365 
 366   str = object_to_string(obj);
 367   fprintf(stderr, "%s", str);
 368   free(str);
 369 
 370   object_free(obj);
 371 } /* object_discard() */
 372 
 373 
 374 int main(int argc, char** argv) {
     /* [<][>][^][v][top][bottom][index][help] */
 375   char *prop_file_name;
 376   FILE *f1, *f2;
 377   GString *current_serial;
 378   int serial_curr=0;
 379   int serial_prev=0;
 380   int i, j;
 381   char line_buff[STR_XXL];
 382 
 383   Attribute_t *attr;
 384   Object_t *obj;
 385   int start_object = 1;
 386 
 387   /* 1. Get the properties file name from argv[1] (Defaults to ".properties" if none specified) */
 388   if (argc == 2) {
 389     prop_file_name = (char *)calloc(1, strlen(argv[1])+1 );
 390     strcpy(prop_file_name,argv[1]);
 391   } else { 
 392     prop_file_name = (char *)calloc(1, strlen(DEFAULT_PROP_FILE_NAME)+1 );
 393     strcpy(prop_file_name, DEFAULT_PROP_FILE_NAME);
 394   }
 395   printf("Loading properties from prop_file_name=%s\n", prop_file_name);
 396 
 397   /* 2. Load properties object from prop_file. */
 398   PR_load(prop_file_name); printf("%s\n", PR_to_string() );
 399 
 400   /* 3. Set the constants. */
 401   CO_set(); printf("%s\n", CO_to_string() );
 402 
 403   current_serial = g_string_sized_new(STR_L);
 404 
 405   Scum_file = fopen("scum", "w");
 406 
 407   while (1) {
 408     sleep(SLEEP_TIME);
 409 
 410     serial_prev = serial_curr;
 411 
 412     f1 = fopen("/ncc/db2/serials/current/RIPE.CURRENTSERIAL", "r");
 413     fscanf(f1, "%d", &serial_curr);
 414     fclose(f1);
 415 
 416     f1 = fopen("/ncc/db2/serials/current/RIPE.OLDESTSERIAL", "r");
 417     fscanf(f1, "%d", &serial_prev);
 418     fclose(f1);
 419 
 420     if (serial_prev != 0) {
 421       for (j=serial_prev; j < serial_curr; j++) { 
 422         g_string_sprintf(current_serial, "/ncc/db2/serials/current/RIPE.%d", j);
 423         f2 = fopen((char *)current_serial->str, "r");
 424         while (fgets(line_buff, STR_XL, f2) != NULL) {
 425           switch (line_type(line_buff)) {
 426             case LINE_ATTRIBUTE:
 427               if (start_object == 1) {
 428                 start_object = 0;
 429                 obj = object_new(line_buff);
 430               }
 431               if (obj != NULL) {
 432                 attr = attribute_new(line_buff);
 433                 if (attr != NULL) {
 434                   obj->attributes = g_slist_append(obj->attributes, attr);
 435                 }
 436                 else {
 437                   object_discard(obj);
 438                   obj = NULL;
 439                 }
 440               }
 441             break;
 442 
 443             case LINE_ADD:
 444             break;
 445 
 446             case LINE_DEL:
 447               goto there;
 448             break;
 449 
 450             case LINE_COMMENT:
 451             break;
 452 
 453             case LINE_EOF:
 454             break;
 455 
 456             case LINE_EMPTY:
 457               if (obj != NULL) {
 458                 object_process(obj);
 459                 object_free(obj);
 460                 obj = NULL;
 461               }
 462               start_object=1;
 463             break;
 464 
 465             default:
 466               fprintf(stderr, "ERROR: Bad line type\n");
 467           } /* switch */
 468         }
 469 there:
 470         fclose(f2);
 471 
 472         if (obj != NULL) {
 473           object_process(obj);
 474           object_free(obj);
 475           obj = NULL;
 476         }
 477         start_object=1;
 478       }
 479     }
 480   }
 481   
 482   fclose(Scum_file);
 483 
 484   g_string_free(current_serial, TRUE);
 485 
 486   return(0);
 487 
 488 } /* main() */

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