bin/create/create.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- escape_apostrophes
- each_attribute_to_string
- object_to_string
- attribute_new
- object_free
- object_new
- line_type
- rollback
- commit
- each_attribute_update
- transaction_free
- transaction_new
- perform_updates
- object_process
- object_discard
- 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() */