## 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] */