1 | /***************************************
2 | $Revision: 1.5 $
3 |
4 | Core functions for update lower layer
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 "ud.h"
34 | #include "ud_int.h"
35 | #include "UD_queries.def"
36 |
37 | char * const Type2main[] = {
38 | "as_block",
39 | "as_set",
40 | "aut_num",
41 | "domain",
42 | "inet_rtr",
43 | "inet6num",
44 | "inetnum",
45 | "key_cert",
46 | "limerick",
47 | "mntner",
48 | "person_role", //pn
49 | "person_role", //ro
50 | "route",
51 | "route_set",
52 | NULL
53 | }; /* Main tables names for object types */
54 |
55 |
56 | static int perform_update(Transaction_t *tr);
57 |
58 | static int perform_create(Transaction_t *tr);
59 |
60 | static void each_primary_key_select(void *element_data, void *result_ptr);
61 |
62 | static void each_attribute_process(void *element_data, void *tr_ptr);
63 |
64 | static int update_attr(Attribute_t *attr, Transaction_t *tr);
65 |
66 | static int create_dummy(Attribute_t *attr, Transaction_t *tr);
67 |
68 | static int auth_member_of(Attribute_t *attr, Transaction_t *tr);
69 |
70 |
71 |
72 |
73 |
74 | /***************************************************
75 | * char *s_split(char *line) *
76 | * *
77 | * Consequently returns words of the 'line' *
78 | * When there are no words it returns NULL *
79 | * You need to retreive all words ! *
80 | * *
81 | * NB This function damages 'line' replacing *
82 | * whitespace with '\0' *
83 | * *************************************************/
84 | static char *s_split(char *line)
85 | {
86 | static char *delim;
87 | static char *token=NULL;
88 |
89 | if(token==NULL)token=line;
90 | else token=delim;
91 |
92 | if(token==NULL)return(token);
93 | while(isspace((int)*token))token++;
94 | delim=token;
95 |
96 | while(!isspace((int)*delim)) {
97 | if((*delim)=='\0'){
98 | if(delim==token)token=NULL;
99 | delim=NULL; return(token);
100 | }
101 | delim++;
102 | }
103 | *delim='\0'; delim++;
104 | return(token);
105 |
106 | }
107 |
108 | /* The same as s_split() but returns nwords words */
109 | /* and the rest of the line */
110 | static char *s_splitn(char *line, int nwords)
111 | {
112 | static char *delim;
113 | static char *token=NULL;
114 | static int w=0;
115 |
116 |
117 | if(token==NULL)token=line;
118 | else token=delim;
119 |
120 | w++; if(w>nwords){ w=0; delim=token; token=NULL; return(delim); }
121 |
122 | if(token==NULL)return(token);
123 | while(isspace((int)*token))token++;
124 | delim=token;
125 |
126 | while(!isspace((int)*delim)) {
127 | if((*delim)=='\0'){
128 | if(delim==token)token=NULL;
129 | delim=NULL; return(token);
130 | }
131 | delim++;
132 | }
133 | *delim='\0'; delim++;
134 | return(token);
135 |
136 |
137 | }
138 |
139 | /**********************************************************
140 | * Attribute expansion/conversion functions *
141 | ***********************************************************/
142 |
143 | /* Convert route attribute into numbers */
144 | er_ret_t expand_rt(char *avalue, unsigned int *prefix, unsigned int *prefix_length)
145 | {
146 | ip_prefix_t pref;
147 | er_ret_t ret;
148 |
149 | ret = IP_pref_e2b(&pref, avalue);
150 | *prefix = pref.ip.words[0];
151 | *prefix_length=pref.bits;
152 | return(ret);
153 | }
154 |
155 | /* Convert ifaddr attribute into numbers */
156 | er_ret_t convert_if(char *avalue, unsigned int *address)
157 | {
158 | char *delim;
159 | ip_addr_t ipaddr;
160 | er_ret_t ret;
161 |
162 | if ((delim=index(avalue, ' '))!=NULL) *delim='\0';
163 | ret = IP_addr_e2b(&ipaddr, avalue);
164 | *address = ipaddr.words[0];
165 | return(ret);
166 | }
167 |
168 | /* Convert inetnum attribute into numbers */
169 | er_ret_t convert_in(char *rangstr, unsigned int *begin_in, unsigned int *end_in)
170 | {
171 | ip_range_t myrang;
172 | er_ret_t ret;
173 |
174 | if( IP_rang_e2b(&myrang, rangstr) != IP_OK ) {
175 | // see if's a valid IP, maybe it's an IPv4 classful range
176 | if( IP_addr_e2b( &myrang.begin, rangstr ) == IP_OK )
177 | if ((ret=IP_rang_classful( &myrang , &myrang.begin )) != IP_OK ) return (ret);
178 | }
179 | *begin_in=myrang.begin.words[0];
180 | *end_in=myrang.end.words[0];
181 | return(IP_OK);
182 | }
183 |
184 | /* Convert refer attribute. Free host after use ! */
185 | char *convert_rf(char *avalue, int *type, int *port)
186 | {
187 | char *delim, *token;
188 | char buff[STR_M];
189 | char *host;
190 |
191 | host=NULL;
192 | strcpy(buff, avalue);
193 | g_strchug(buff);
194 | delim=index(buff, ' ');
195 | *delim='\0';
196 | delim++;
197 |
198 | // convert the type
199 | if(strcmp(buff, S_RIPE)==0)*type=RF_RIPE;
200 | else if(strcmp(buff, S_INTERNIC)==0)*type=RF_INTERNIC;
201 | else if(strcmp(buff, S_SIMPLE)==0)*type=RF_SIMPLE;
202 |
203 | token=delim;
204 | g_strchug(token);
205 | delim=index(token, ' ');
206 | if(delim){
207 | *delim='\0';
208 | delim++;
209 | }
210 | // convert the hostname
211 | host = g_strdup(token);
212 |
213 | // convert port number
214 | if(delim){
215 | token=delim;
216 | *port = atoi(token);
217 | if (*port==0) *port=RF_DEF_PORT; // default port number
218 | } else *port=RF_DEF_PORT;
219 | return(host);
220 | }
221 |
222 |
223 | /* Convert AS# into integer */
224 | static int convert_as(char *as)
225 | {
226 | char *ptr;
227 | ptr=as; ptr++; ptr++;
228 | return(atoi(ptr));
229 | }
230 |
231 | /* Convert AS range (AS4321 - AS5672) into numbers */
232 | int convert_as_range(const char *as_range, int *begin, int *end)
233 | {
234 | char buf[STR_M];
235 | strcpy(buf, as_range); //save it
236 | *begin=convert_as(s_split(buf));
237 | s_split(buf); // should be '-'
238 | *end=convert_as(s_split(buf));
239 | while(s_split(buf));
240 | return(0);
241 | }
242 |
243 | /* Convert time in ASCII format (19991224) into time_t unix time */
244 | time_t convert_time(char *asc_time)
245 | {
246 | struct tm tm;
247 | char buf[STR_S];
248 | char *ptr;
249 |
250 |
251 | bzero(&tm, sizeof(tm));
252 |
253 | strncpy(buf, asc_time, 4); ptr=buf+4; *ptr='\0';
254 | tm.tm_year = atoi(buf) - 1900;
255 |
256 | strncpy(buf, (asc_time+4), 2); ptr=buf+2; *ptr='\0';
257 | tm.tm_mon = atoi(buf) - 1;
258 |
259 | strncpy(buf, (asc_time+6), 2); ptr=buf+2; *ptr='\0';
260 | tm.tm_mday = atoi(buf);
261 |
262 | return(mktime(&tm));
263 |
264 | }
265 |
266 | /*********************************
267 | * M I S C ***********************/
268 |
269 | /************************************************************
270 | * long get_object_id() *
271 | * Queries the database for an object. *
272 | * For constructing a query uses each__primary_key_select() *
273 | * *
274 | * Returns: *
275 | * >0 - object exists, returns object_id *
276 | * 0 - object does not exist *
277 | * -1 - DB error (f.e. more than one object with the same PK) *
278 | * *
279 | * **********************************************************/
280 | long get_object_id(Transaction_t *tr)
281 | {
282 | Object_t *obj=tr->object;
283 | SQ_result_set_t *sql_result;
284 | SQ_row_t *sql_row;
285 | char *sql_str;
286 | GString *query;
287 | long object_id=0;
288 |
289 | if ((query = g_string_sized_new(STR_XL)) == NULL){
290 | fprintf(stderr, "E: cannot allocate gstring\n");
291 | tr->succeeded=0;
292 | tr->error |= ERROR_U_MEM;
293 | return(ERROR_U_MEM);
294 | }
295 |
296 | g_string_sprintf(query, "SELECT * FROM %s WHERE",Type2main[obj->type]);
297 | g_slist_foreach(obj->attributes, each_primary_key_select, query);
298 | /* truncate the last ' AND '*/
299 | g_string_truncate(query, (query->len) - 4);
300 |
301 | /* execute query */
302 | sql_result=SQ_execute_query(SQ_STORE, tr->sql_connection, query->str);
303 | g_string_free(query, TRUE);
304 |
305 | if(sql_result == NULL) {
306 | fprintf(stderr,"ERROR: %s\n", SQ_error(tr->sql_connection));
307 | return(-1);
308 | }
309 |
310 | if ((sql_row = SQ_row_next(sql_result)) != NULL) {
311 | /* Object exists */
312 | sql_str = SQ_get_column_string(sql_result, sql_row, OBJECT_ID);
313 | if (sql_str != NULL) {
314 | object_id = atol(sql_str);
315 | free(sql_str);
316 | }
317 |
318 | /* We must process all the rows of the result */
319 | /* otherwise we'll have them as part of the next qry */
320 | while ( (sql_row = SQ_row_next(sql_result)) != NULL) object_id=-1;
321 | } else
322 | object_id=0; // object does not exist
323 |
324 | if(sql_result)SQ_free_result(sql_result);
325 | return(object_id);
326 | }
327 |
328 | /************************************************************
329 | * get_field_str() *
330 | * *
331 | * Returns string containing the field. *
332 | * field - field name to be retrieved *
333 | * ref_tbl_name - name of the table containing the field *
334 | * ref_name - reference name *
335 | * attr_value - reference value *
336 | * condition - additional condition ( f.e. 'AND dummy=0' *
337 | * *
338 | * Returns: *
339 | * String containing the field. Needs to be freed after use *
340 | * NULL in case of an error *
341 | * *
342 | *************************************************************/
343 | char *get_field_str(Transaction_t *tr, char *field,
344 | char *ref_tbl_name, char *ref_name,
345 | char * attr_value, char *condition)
346 | {
347 | static char query[STR_L];
348 | SQ_result_set_t *sql_result;
349 | SQ_row_t *sql_row;
350 | char *sql_str;
351 |
352 | sprintf(query, "SELECT %s FROM %s "
353 | "WHERE %s='%s' ",
354 | field, ref_tbl_name, ref_name, attr_value);
355 | if (condition)strcat(query, condition);
356 |
357 | //fprintf(stderr, "D:<get_field_str>:query: %s\n", query);
358 | sql_result=SQ_execute_query(SQ_STORE, tr->sql_connection, query);
359 |
360 | if(sql_result == NULL) {
361 | fprintf(stderr,"ERROR: %s\n", SQ_error(tr->sql_connection));
362 | return(NULL);
363 | }
364 |
365 |
366 | if ((sql_row = SQ_row_next(sql_result)) != NULL) {
367 | sql_str = SQ_get_column_string(sql_result, sql_row, 0);
368 |
369 | /* We must process all the rows of the result,*/
370 | /* otherwise we'll have them as part of the next qry */
371 | while ( (sql_row = SQ_row_next(sql_result)) != NULL) {
372 | fprintf(stderr, "E:<get_field_str> error : Dupl PK[%s]\n", query);
373 | if(sql_str)free(sql_str); sql_str=NULL;
374 | }
375 | }
376 | else sql_str=NULL;
377 |
378 | if(sql_result){ SQ_free_result(sql_result); sql_result=NULL; }
379 | return(sql_str);
380 | }
381 |
382 | /************************************************************
383 | * long get_sequence_id(Transaction_t *tr)
384 | * >0 - success
385 | * -1 - sql error
386 | *
387 | * **********************************************************/
388 |
389 | long get_sequence_id(Transaction_t *tr)
390 | {
391 | char *sql_str;
392 | char str_id[STR_M];
393 | long sequence_id=-1;
394 |
395 |
396 | sprintf(str_id, "%ld", tr->object_id);
397 | sql_str= get_field_str(tr, "sequence_id", "last", "object_id", str_id, NULL);
398 | if(sql_str) {
399 | sequence_id = atol(sql_str);
400 | // fprintf(stderr, "D: Retrieved set serial id = %ld\n", sequence_id);
401 | free(sql_str);
402 | }
403 |
404 | return(sequence_id);
405 |
406 | }
407 |
408 |
409 | /************************************************************
410 | * long get_ref_id(char *ref_tbl_name, char *ref_name, char * attr_value)
411 | * >0 - success
412 | * -1 - sql error
413 | *
414 | * **********************************************************/
415 |
416 | static long get_ref_id(Transaction_t *tr, char *ref_tbl_name, char *ref_name, char * attr_value, char *condition)
417 | {
418 | char *sql_str;
419 | long ref_id=-1;
420 |
421 | //fprintf(stderr, "D:<get_ref_id>: entering...\n");
422 |
423 | sql_str= get_field_str(tr, "object_id", ref_tbl_name, ref_name, attr_value, condition);
424 | if(sql_str) {
425 | ref_id = atol(sql_str);
426 | // fprintf(stderr, "D: Retrieved set serial id = %ld\n", ref_id);
427 | free(sql_str);
428 | }
429 | return(ref_id);
430 | }
431 |
432 |
433 | static int isnichandle(char *name)
434 | {
435 | return(MA_isset(WK_new(name), WK_NIC_HDL));
436 | }
437 |
438 | static int sql_info(SQ_connection_t *sql_connection, int info[3])
439 | {
440 | int ii;
441 | char *colon, *buf_ptr, buf[20];
442 | char *infoline;
443 |
444 | //fprintf(stderr, "D: Getting additional information about query\n");
445 | infoline=mysql_info(sql_connection);
446 | //fprintf(stderr, "D: %s\n", infoline);
447 | ii=0;
448 | colon = infoline;
449 | while (*colon != '\0') {
450 | colon++;
451 | buf_ptr=buf;
452 | if(isdigit((int)*colon)){
453 | while(isdigit((int)*colon)){
454 | *buf_ptr=*colon; buf_ptr++; colon++;
455 | }
456 | *buf_ptr='\0';
457 | info[ii]=atoi(buf); ii++;
458 | }
459 | }
460 | // free(infoline);
461 | //fprintf(stderr, "D: return %d\n", res[res_type]);
462 | return(0);
463 | }
464 |
465 |
466 | static char *get_set_name(C_Type_t class_type)
467 | {
468 | switch(class_type){
469 | case C_RT: return("route_set");
470 | case C_AN: return("as_set");
471 | default: return(NULL);
472 | }
473 | }
474 |
475 |
476 | /************************************************************
477 | * auth_member_of() *
478 | * *
479 | * Function that checks the authorization for membership *
480 | * (i.e. if the object is authorized to be a memeber by *
481 | * mbrs-by-ref attribute of the set is refers by member-of *
482 | * attribute). *
483 | * First checks if 'mbrs-by-ref: ANY' *
484 | * If not then checks that maintner referenced by *
485 | * mbrs-by-ref attribute of the set is the one in mnt-by. *
486 | * *
487 | * Returns: *
488 | * 0 success *
489 | * 1 not allowed *
490 | * -1 SQL error *
491 | * *
492 | *************************************************************/
493 | static int auth_member_of(Attribute_t *attr, Transaction_t *tr)
494 | {
495 | GString *query;
496 | SQ_result_set_t *sql_result;
497 | SQ_row_t *sql_row;
498 | //char *sql_str;
499 | char *set_name;
500 | //long set_id;
501 | //my_ulonglong num;
502 | int error;
503 |
504 |
505 | error=0;
506 |
507 | /* Check if set has mbrs_by_ref==ANY
508 | In such case mbrs_by_ref.mnt_id==0
509 | */
510 |
511 | if ((query = g_string_sized_new(STR_XL)) == NULL){
512 | tr->succeeded=0;
513 | tr->error |= ERROR_U_MEM;
514 | fprintf(stderr, "E: cannot allocate gstring\n");
515 | return(-1);
516 | }
517 |
518 | set_name= get_set_name(tr->class_type);
519 | // fprintf(stderr, "D:<auth_member_of>: Got set name: %s\n", set_name);
520 | g_string_sprintf(query,"SELECT %s.object_id FROM mbrs_by_ref, %s "
521 | "WHERE mbrs_by_ref.object_id=%s.object_id "
522 | "AND %s.%s='%s' AND mbrs_by_ref.mnt_id=0 ",
523 | set_name, set_name, set_name, set_name, set_name, attr->value);
524 | // fprintf(stderr, "D:<auth_member_of>: query: %s\n", query->str);
525 |
526 | sql_result=SQ_execute_query(SQ_STORE, tr->sql_connection, query->str);
527 | // if (sql_result ==NULL) { // ????????
528 | // fprintf(stderr, "E:<auth_member_of>: NULL SQL result[%s]\n", query->str);
529 | // g_string_free(query, TRUE);
530 | // return(1);
531 | // }
532 |
533 | if ((sql_result==NULL) || ((sql_row = SQ_row_next(sql_result))==NULL)){
534 | if(sql_result){ SQ_free_result(sql_result); sql_result=NULL; }
535 |
536 | /* Check if our mnt_by belongs to mbrs_by_ref list of the set */
537 | g_string_sprintf(query, "SELECT mbrs_by_ref.object_id FROM route_set, mbrs_by_ref, mnt_by "
538 | "WHERE mbrs_by_ref.mnt_id=mnt_by.mnt_id "
539 | "AND mnt_by.object_id=%ld "
540 | "AND %s.object_id=mbrs_by_ref.object_id "
541 | "AND %s.%s='%s' "
542 | "AND mnt_by.thread_id!=0 ",
543 | tr->object_id, set_name, set_name, set_name, attr->value);
544 |
545 | // fprintf(stderr, "D:<auth_member_of>: query: %s\n", query->str);
546 |
547 | sql_result=SQ_execute_query(SQ_STORE, tr->sql_connection, query->str);
548 |
549 | if(sql_result == NULL) {
550 | fprintf(stderr,"ERROR: %s\n", SQ_error(tr->sql_connection));
551 | g_string_free(query, TRUE);
552 | return(-1);
553 | }
554 |
555 | if ((sql_row = SQ_row_next(sql_result)) == NULL) {
556 | /* Membership is not authorized */
557 | fprintf(stderr, "E:<auth_member_of> : Membership is not autorized[%s]\n", query->str);
558 | if(sql_result){ SQ_free_result(sql_result); sql_result=NULL; }
559 | g_string_free(query, TRUE);
560 | return(1);
561 | }
562 | }
563 |
564 | // sql_str = SQ_get_column_string(sql_result, sql_row, 0);
565 | /* We must process all the rows of the result, otherwise we'll have them as part of the next qry */
566 | while ( (sql_row = SQ_row_next(sql_result)) != NULL) {
567 | fprintf(stderr, "E:<auth_member_of> error : More than one object with the same PK\n");
568 | error=-1;
569 | }
570 | if(sql_result){ SQ_free_result(sql_result); sql_result=NULL; }
571 | g_string_free(query, TRUE);
572 | return(0);
573 | }/* auth_member_of() */
574 |
575 |
576 | /************************************************************
577 | * create_dummy() *
578 | * *
579 | * Function that creates a dummy object (that is one that *
580 | * is referenced from an object but does not *
581 | * exist in the database). *
582 | * Dummy object exists only in relevant main and 'last' *
583 | * tables. Its creation is controlled by tr->dummy_allowed. *
584 | * Queries for the dummies are defined in Dummy[] array. *
585 | * *
586 | * Returns: *
587 | * 0 success *
588 | * 1 no rf integrity and dummy not allowed
589 | * -1 SQL error *
590 | * *
591 | *************************************************************/
592 | static int create_dummy(Attribute_t *attr, Transaction_t *tr)
593 | {
594 | SQ_result_set_t *sql_result;
595 | char *query_fmt;
596 | int num;
597 | long dummy_id;
598 | char query[STR_L];
599 | //int result;
600 | char *set_name;
601 | char *p_name;
602 | int query_type;
603 | long timestamp;
604 | char str_id[STR_M];
605 | gchar *chopped_nh=NULL;
606 | gchar *attr_value=NULL;
607 |
608 |
609 | query_fmt = Dummy[attr->type].qry;
610 | if (strcmp(query_fmt, "") == 0) { fprintf(stderr, "E:<create_dummy>: empty query string\n"); return(1); }
611 | if ((attr->type!=A_MO) && (tr->dummy != 1)) return(1);
612 |
613 | /* insert dummy in the last table */
614 | sprintf(str_id, "%ld", tr->object_id);
615 | timestamp=time(NULL);
616 | sprintf(query, "INSERT INTO last SET thread_id=%d, timestamp=%ld, object_type=%d, object='DUMMY for %s'",
617 | tr->thread_ins, timestamp, DUMMY_TYPE, str_id);
618 | // fprintf(stderr, "D: making dummy entry in the last table\n %s\n", query);
619 | sql_result=SQ_execute_query(SQ_STORE, tr->sql_connection, query);
620 | num = mysql_affected_rows(tr->sql_connection);
621 | // fprintf(stderr, "D: query: %d rows affected\n", num);
622 | if (sql_result)SQ_free_result(sql_result);
623 | if ((num == -1) || (num == 0)) {
624 | //fprintf(stderr, "E: dummy->last:[%s]\n", query);
625 | return(-1);
626 | }
627 |
628 | /* insert dummy in the main table */
629 | dummy_id=mysql_insert_id(tr->sql_connection);
630 | tr->dummy_id[tr->ndummy]=dummy_id;
631 | tr->ndummy++; // increase number of attempts to create dummy
632 | // fprintf(stderr, "D:<create_dummy>:dummy_id=%ld\n", dummy_id);
633 | query_type=Dummy[attr->type].qtype;
634 | switch (query_type) {
635 | case UD_AX_PR:
636 | // chop nic-hdl if bigger that MAX_NIC_HDL
637 | if(strlen(attr->value)>MAX_NIC_HDL){
638 | chopped_nh = g_strndup(attr->value, MAX_NIC_HDL);
639 | attr_value=chopped_nh;
640 | } else attr_value = attr->value;
641 | sprintf(query, query_fmt, tr->thread_ins, dummy_id, attr_value, DUMMY_TYPE);
642 | if(chopped_nh){ free(chopped_nh); chopped_nh=NULL;}
643 | break;
644 | case UD_AX_MT:
645 | sprintf(query, query_fmt, tr->thread_ins, dummy_id, attr->value, DUMMY_TYPE);
646 | break;
647 | // as-set, route-set
648 | case UD_AX_MO:
649 | set_name = get_set_name(tr->class_type);
650 | sprintf(query, query_fmt, set_name, tr->thread_ins, dummy_id, set_name, attr->value);
651 | break;
652 | default:
653 | fprintf(stderr, "E: query not defined for this type of attribute[%d]\n", attr->type);
654 | break;
655 | }
656 |
657 | //fprintf(stderr, "D: query: %s\n", query);
658 | sql_result=SQ_execute_query(SQ_STORE, tr->sql_connection, query);
659 | num = mysql_affected_rows(tr->sql_connection);
660 | // fprintf(stderr, "D: query: %d rows affected\n", num);
661 | if (sql_result)SQ_free_result(sql_result);
662 | if ((num == -1) || (num == 0)) {
663 | fprintf(stderr, "E: dummy->main:[num=%d][%s]\n", num, query);
664 | return(-1);
665 | }
666 |
667 | if( query_type == UD_AX_MO ){ // Create row in mbrs_by_ref
668 | sprintf(query, " INSERT mbrs_by_ref SET thread_id=%d, object_id=%ld, mnt_id=0, object_type=%d ",
669 | tr->thread_ins,dummy_id, DUMMY_TYPE);
670 | // fprintf(stderr, "D: query: %s\n", query);
671 | sql_result=SQ_execute_query(SQ_STORE, tr->sql_connection, query);
672 | num = mysql_affected_rows(tr->sql_connection);
673 | // fprintf(stderr, "D: query: %d rows affected\n", num);
674 | if (sql_result)SQ_free_result(sql_result);
675 | if ((num == -1) || (num == 0)) {
676 | fprintf(stderr, "E: dummy->main:[num=%d][%s]\n", num, query);
677 | return(-1);
678 | }
679 | }
680 | else
681 | if( (query_type == UD_AX_PR) && (!isnichandle (attr->value)) ){ // Create rows in names
682 | // parse the names
683 | // fprintf(stderr,"adding names for dummy\n");
684 | query_fmt = Insert[A_PN].qry;
685 | attr_value = g_strdup(attr->value);
686 | while((p_name=s_split(attr_value))){
687 | sprintf(query, query_fmt, tr->thread_ins, dummy_id, DUMMY_TYPE, p_name);
688 | // fprintf(stderr, "D: query: %s\n", query);
689 | sql_result=SQ_execute_query(SQ_STORE, tr->sql_connection, query);
690 | num = mysql_affected_rows(tr->sql_connection);
691 | // fprintf(stderr, "D: query: %d rows affected\n", num);
692 | if (sql_result)SQ_free_result(sql_result);
693 | }
694 | free(attr_value);
695 | }
696 |
697 | return(0);
698 | }
699 |
700 | /************************************************************
701 | * update_attr() *
702 | * *
703 | * Function that updates an attribute if it already exists. *
704 | * Called from each_attribute_proces() function if it *
705 | * cannot insert the row. *
706 | * Queries for the attributes are defined in Update[] array. *
707 | * *
708 | * Returns: Nothing. Error code is stored in tr->succeeded. *
709 | * *
710 | *************************************************************/
711 | static int update_attr(Attribute_t *attr, Transaction_t *tr)
712 | {
713 | SQ_result_set_t * sql_result;
714 | int num;
715 | char *query_fmt;
716 | //GString *query;
717 | char *set_name;
718 | unsigned int if_address;
719 | char * rf_host;
720 | int rf_port, rf_type;
721 | gchar *chopped_nh=NULL;
722 | char *a_value;
723 | //int dupl;
724 | int sq_info[3];
725 | char * condition;
726 | char query[STR_L];
727 |
728 | if(tr->load_pass!=0) return(0);
729 |
730 | // fprintf(stderr, "D: updating attribute...\n");
731 |
732 | query_fmt = Update[attr->type].qry;
733 | if (strcmp(query_fmt, "") == 0) return(0);
734 |
735 | switch (Update[attr->type].qtype) {
736 | case UD_MAIN_: sprintf(query, query_fmt, tr->thread_upd, tr->object_id);
737 | break;
738 | case UD_MA_PR:
739 | sprintf(query, query_fmt, tr->thread_upd, tr->class_type, tr->object_id);
740 | break;
741 | case UD_MA_LA: // save the new value for commit
742 | //g_string_free(query, TRUE);
743 | tr->save=attr->value;
744 | return(0);
745 | break;
746 | case UD_AX_PR:
747 | a_value = attr->value;
748 | if(strlen(attr->value)>MAX_NIC_HDL){ // This is for non-conformant admin-c, etc.
749 | chopped_nh = g_strndup(attr->value, MAX_NIC_HDL);
750 | a_value=chopped_nh;
751 | }
752 | if (tr->dummy!=1)condition="AND dummy=0 "; else condition=NULL;
753 | sprintf(query, query_fmt, tr->thread_upd, tr->object_id,
754 | get_ref_id(tr, "person_role", "nic_hdl", a_value, condition));
755 | if(chopped_nh) free(chopped_nh);
756 | break;
757 | case UD_AX_MT:
758 | if (tr->dummy!=1)condition="AND dummy=0 "; else condition=NULL;
759 | sprintf(query, query_fmt, tr->thread_upd, tr->object_id,
760 | get_ref_id(tr, "mntner", "mntner", attr->value, condition));
761 | break;
762 | case UD_AX_MO:
763 | set_name = get_set_name(tr->class_type);
764 | // fprintf(stderr, "D: retrieved set name: %s\n", set_name);
765 | if (tr->dummy!=1)condition="AND dummy=0 "; else condition=NULL;
766 | sprintf(query, query_fmt, tr->thread_upd, tr->object_id,
767 | get_ref_id(tr, set_name, set_name, attr->value, condition));
768 | break;
769 | case UD_AX_MR:
770 | if ((strcmp(attr->value, "ANY")==0) || (strcmp(attr->value, "any")==0) || (strcmp(attr->value, "Any")==0))
771 | sprintf(query, query_fmt, tr->thread_upd, tr->object_id,
772 | get_ref_id(tr, "mntner", "mntner", "ANY",NULL));
773 | else {
774 | if (tr->dummy!=1)condition="AND dummy=0 "; else condition=NULL;
775 | sprintf(query, query_fmt, tr->thread_upd, tr->object_id,
776 | get_ref_id(tr, "mntner", "mntner", attr->value, condition));
777 | }
778 | break;
779 | case UD_LEAF_:
780 | sprintf(query, query_fmt, tr->thread_upd, tr->object_id, attr->value);
781 | break;
782 | case UD_LF_IF:
783 | // Convert ascii ip -> numeric one. Later to save in tr->save while processing INSERT
784 | convert_if(attr->value, &if_address);
785 | sprintf(query, query_fmt, tr->thread_upd, tr->object_id, if_address);
786 | break;
787 | case UD_LF_RF:
788 | rf_host=convert_rf(attr->value, &rf_type, &rf_port);
789 | sprintf(query, query_fmt, tr->thread_upd, tr->object_id, rf_type, rf_host, rf_port);
790 | if(rf_host)free(rf_host);
791 | break;
792 | case UD_LF_AY:
793 | sprintf(query, query_fmt, tr->thread_upd, tr->object_id, convert_time(attr->value));
794 | break;
795 | default:
796 | fprintf(stderr, "E:<e_a_u> query not defined for this type of attribute:[%d]\n", attr->type);
797 | tr->error|=ERROR_U_BUG;
798 | tr->succeeded=0;
799 | g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:no update qry\n" ,ERROR_U_BUG, attr->type, attr->value);
800 | break;
801 | }
802 | //fprintf(stderr, "D: update: [%s]", query);
803 |
804 | sql_result=SQ_execute_query(SQ_STORE, tr->sql_connection, query);
805 | num = mysql_affected_rows(tr->sql_connection);
806 | // fprintf(stderr, "D: query: %d rows affected\n", num);
807 | if ((num == -1)) {
808 | fprintf(stderr, "E:<each_attribute_create> update query:[%d][%s]\n", num, query);
809 | tr->error|=ERROR_U_DBS;
810 | tr->succeeded=0;
811 | g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:update qry\n" ,ERROR_U_DBS, attr->type, attr->value);
812 | }
813 | else
814 | if(num == 0) { // check for duplicates
815 | sql_info(tr->sql_connection, sq_info); // REPLACE ... SELECT
816 | if ((sq_info[SQL_DUPLICATES]==0) && (sq_info[SQL_MATCHES]==0)) { // this is because of dummies
817 | fprintf(stderr, "E: Update: empty query result: [%s]\n", query);
818 | tr->error|=ERROR_U_DBS;
819 | tr->succeeded=0;
820 | g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:null update qry res\n" ,ERROR_U_DBS, attr->type, attr->value);
821 | } // else duplicate entry - silently drop it
822 | }
823 | if (sql_result){ SQ_free_result(sql_result);sql_result=NULL; }
824 | if (attr->type == A_MO){
825 | // fprintf(stderr, "D:<e_a_p>: need to auth membership\n");
826 | if(auth_member_of(attr, tr)!=0){
827 | tr->error|=ERROR_U_AUT;
828 | tr->succeeded=0;
829 | fprintf(stderr, "E:<each_attribute_create>: membership not allowed\n");
830 | g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:membership not allowed\n" ,ERROR_U_AUT, attr->type, attr->value);
831 | }
832 | }
833 | //fprintf(stderr, "D:<update_attr>: returning \n");
834 | return(0);
835 | }/* update_attr() */
836 |
837 |
838 | /************************************************************
839 | * each_attribute_proces() *
840 | * *
841 | * Main function that processes object attributes one by one.*
842 | * Called from g_slist_foreach() function. *
843 | * First it tries to insert an attribute. *
844 | * If an error it assumes that attribute is already in *
845 | * a table and calls update_attr() to update it. *
846 | * Queries for the attributes are defined in Insert[] array. *
847 | * *
848 | * Returns: Nothing. Error code is stored in tr->succeeded. *
849 | * *
850 | *************************************************************/
851 | static void each_attribute_process(void *element_data, void *tr_ptr)
852 | {
853 | SQ_result_set_t * sql_result;
854 | //my_ulonglong num;
855 | int num;
856 | char *query_fmt;
857 | int query_type;
858 | //int dupl;
859 | int do_query;
860 | Attribute_t *attr = element_data;
861 | Transaction_t *tr = (Transaction_t *)tr_ptr;
862 | unsigned int prefix, prefix_length;
863 | unsigned int begin_in, end_in;
864 | int begin_as, end_as;
865 | //GString *query_u;
866 | char query[STR_L];
867 | char * set_name;
868 | char * rf_host; // needs to be deleted after use
869 | int rf_type, rf_port;
870 | gchar *chopped_nh=NULL;
871 | char *a_value;
872 | int sq_info[3];
873 | char *mu_mntner, *mu_prefix;
874 | int dummy_err;
875 |
876 | static rx_bin_data_t rx_bin_data;
877 | static rx_inum_data_t rx_inum_data;
878 |
879 |
880 | if(tr->succeeded == 0) return; // no sense to continue
881 |
882 | do_query=1;
883 |
884 | query_type=Insert[attr->type].qtype;
885 |
886 | /* For loadind pass #1 we need to process only main tables */
887 | if(tr->load_pass==1){
888 | switch(query_type) {
889 | case UD_MAIN_:
890 | case UD_MA_U2:
891 | case UD_MA_PR:
892 | case UD_MA_RT:
893 | case UD_MA_IN:
894 | case UD_MA_I6:
895 | case UD_MA_LA:
896 | case UD_MA_AK:
897 | break;
898 | default: return; // return for other than MAIN tables
899 | }
900 | }
901 |
902 | query_fmt = Insert[attr->type].qry;
903 |
904 | if (strcmp(query_fmt, "") == 0) return;
905 | // fprintf(stderr,"[%d]:[%s]\n", attr->type, attr->value);
906 | query_type=Insert[attr->type].qtype;
907 | switch (query_type) {
908 | case UD_MAIN_:
909 | if (tr->action==TR_UPDATE) do_query=0;
910 | else
911 | sprintf(query, query_fmt, tr->thread_ins, tr->object_id, attr->value);
912 | break;
913 | case UD_MA_U2:
914 | if (tr->action==TR_UPDATE) do_query=0;
915 | else
916 | sprintf(query, query_fmt, tr->thread_ins, attr->value, tr->object_id);
917 | if(attr->type == A_OR) {
918 | save_rx_orig(&rx_bin_data, attr->value);
919 | tr->save = (void *)&rx_bin_data; // just in case
920 | }
921 | break;
922 | case UD_MA_PR:
923 | if (tr->action==TR_UPDATE) do_query=0;
924 | else
925 | sprintf(query, query_fmt, tr->thread_ins, tr->class_type, tr->object_id, attr->value);
926 | break;
927 | case UD_MA_RT:
928 | if (tr->action==TR_UPDATE) do_query=0;
929 | else {
930 | expand_rt(attr->value, &prefix, &prefix_length);
931 | //fprintf(stderr, "D: route: %u/%u\n", prefix, prefix_length);
932 | sprintf(query, query_fmt, tr->thread_ins,
933 | tr->object_id, prefix, prefix_length);
934 | // save stuff for radix update
935 | save_rx_pref(&rx_bin_data, prefix, prefix_length);
936 | tr->save = (void *)&rx_bin_data;
937 | }
938 | break;
939 | case UD_MA_IN:
940 | if (tr->action==TR_UPDATE) do_query=0;
941 | else {
942 | convert_in(attr->value, &begin_in, &end_in);
943 | sprintf(query, query_fmt, tr->thread_ins, tr->object_id, begin_in, end_in);
944 | save_rx_rang(&rx_inum_data, begin_in, end_in);
945 | tr->save = (void *)&rx_inum_data;
946 | }
947 | break;
948 | case UD_MA_I6:
949 | break;
950 | case UD_MA_LA: // save the new value for commit
951 | tr->save=attr->value;
952 | // fprintf(stderr, "D:<e_a_p> attribute saved: %s\n", tr->save);
953 | return;
954 | break;
955 | case UD_MA_AK:
956 | if (tr->action==TR_UPDATE) do_query=0;
957 | else {
958 | convert_as_range(attr->value, &begin_as, &end_as);
959 | sprintf(query, query_fmt, tr->thread_ins, tr->object_id, begin_as, end_as);
960 | }
961 | break;
962 | case UD_AUX__:
963 | a_value = attr->value;
964 | if((attr->type==A_AC) || (attr->type==A_TC) || (attr->type==A_ZC))
965 | if(strlen(attr->value)>MAX_NIC_HDL){
966 | chopped_nh = g_strndup(attr->value, MAX_NIC_HDL);
967 | a_value=chopped_nh;
968 | }
969 | sprintf(query, query_fmt, tr->thread_ins, tr->object_id, tr->class_type, a_value);
970 | if(tr->dummy!=1)strcat(query, " AND dummy=0 ");
971 | if(chopped_nh){ free(chopped_nh); chopped_nh=NULL;}
972 | break;
973 | case UD_AX_MO:
974 | set_name = get_set_name(tr->class_type);
975 | // fprintf(stderr, "D: retrieved set name: %s\n", set_name);
976 | sprintf(query, query_fmt, tr->thread_ins,
977 | tr->object_id, set_name, tr->class_type, set_name, set_name, set_name, attr->value);
978 | break;
979 | case UD_AX_MR:
980 | if ((strcmp(attr->value, "ANY")==0) || (strcmp(attr->value, "any")==0) || (strcmp(attr->value, "Any")==0))
981 | sprintf(query, query_fmt, tr->thread_ins, tr->object_id, tr->class_type, "ANY");
982 | else
983 | sprintf(query, query_fmt, tr->thread_ins, tr->object_id, tr->class_type, attr->value);
984 | break;
985 | case UD_AX_MU:
986 | a_value=g_strdup(attr->value);
987 | mu_mntner=s_splitn(a_value, 1);
988 | mu_prefix=s_splitn(a_value, 1);
989 | sprintf(query, query_fmt, tr->thread_ins, tr->object_id, mu_prefix, tr->class_type, mu_mntner);
990 | free(a_value);
991 | if(tr->dummy!=1)strcat(query, " AND dummy=0 ");
992 | break;
993 | case UD_LEAF_:
994 | sprintf(query, query_fmt, tr->thread_ins, tr->object_id, attr->value);
995 | break;
996 | case UD_LF_OT:
997 | sprintf(query, query_fmt, tr->thread_ins, tr->object_id, tr->class_type, attr->value);
998 | break;
999 | case UD_LF_AT: // check PGPKEY. If yes - check the existence of key-cert.
1000 | if(tr->dummy!=1){
1001 | if(strncmp("PGPKEY", attr->value, 6)==0) {
1002 | if(get_ref_id(tr, "key_cert", "key_cert", attr->value, NULL)<=0) {
1003 | fprintf(stderr, "E:<e_a_p>: No key-cert object.\n");
1004 | tr->error|=ERROR_U_OBJ;
1005 | tr->succeeded=0;
1006 | g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:no key-cert object\n" ,ERROR_U_OBJ, attr->type, attr->value);
1007 | return;
1008 | }
1009 | }
1010 | }
1011 | sprintf(query, query_fmt, tr->thread_ins, tr->object_id, tr->class_type, attr->value);
1012 | break;
1013 | case UD_LF_IF:
1014 | // Convert ascii ip -> numeric one
1015 | convert_if(attr->value, &prefix);
1016 | sprintf(query, query_fmt, tr->thread_ins, tr->object_id, prefix);
1017 | break;
1018 | case UD_LF_RF:
1019 | rf_host=convert_rf(attr->value, &rf_type, &rf_port);
1020 | sprintf(query, query_fmt, tr->thread_ins, 0 /*tr->object_id*/ , rf_type, rf_host, rf_port);
1021 | if(rf_host)free(rf_host);
1022 | break;
1023 | case UD_LF_AY:
1024 | sprintf(query, query_fmt, tr->thread_ins, tr->object_id, convert_time(attr->value));
1025 | break;
1026 | default:
1027 | fprintf(stderr, "E: query not defined for this type of attribute\n");
1028 | break;
1029 | }
1030 |
1031 | //fprintf(stderr, "D: insert: [%s]", query);
1032 |
1033 | if(do_query){
1034 | sql_result=SQ_execute_query(SQ_STORE, tr->sql_connection, query);
1035 | num = mysql_affected_rows(tr->sql_connection);
1036 | if (sql_result)SQ_free_result(sql_result);sql_result=NULL;
1037 | }
1038 | else {
1039 | update_attr(attr, tr);
1040 | return;
1041 | }
1042 |
1043 | // fprintf(stderr, "D: query: %d rows affected\n", num);
1044 |
1045 | if(num>0){ // this is OK
1046 | // if attr=="member_of" we need additional processing
1047 | if (attr->type == A_MO){
1048 | // fprintf(stderr, "D:<e_a_p>: need to auth membership\n");
1049 | if(auth_member_of(attr, tr)!=0){
1050 | tr->error|=ERROR_U_AUT;
1051 | tr->succeeded=0;
1052 | fprintf(stderr, "E:<each_attribute_create>: membership not allowed\n");
1053 | g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:membership not allowed\n" ,ERROR_U_AUT, attr->type, attr->value);
1054 | }
1055 | }
1056 | return;
1057 | }
1058 |
1059 | if(num == -1){ // if not update that is the error condition. free resources and return (except some attributes)
1060 | if (tr->action==TR_UPDATE) {
1061 | update_attr(attr, tr);
1062 | return;
1063 | }
1064 | else {
1065 | switch(attr->type) {
1066 | case A_EM: break; // duplicate e-mail:
1067 | case A_PN: break; // fe: Antony Antony
1068 | case A_RO: break; // fe: IB og Co Reklame og Marketing
1069 |
1070 | default:
1071 | // !!!!!!!! tr->succeeded=0; fprintf(stderr, "E: query returned an error: [%s]\n", query->str);
1072 | break;
1073 | }
1074 | }
1075 | }
1076 | else
1077 | if(num == 0) {
1078 | sql_info(tr->sql_connection, sq_info);
1079 | if (sq_info[SQL_DUPLICATES]>0) { // update attribute
1080 | if (sq_info[SQL_DUPLICATES]>1) { // this is an error - more that 1 duplicate
1081 | fprintf(stderr, "E: Update: Too many duplicates for query: [%s]\n", query);
1082 | tr->error|=ERROR_U_DBS;
1083 | tr->succeeded=0;
1084 | g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:duplicates\n" ,ERROR_U_DBS, attr->type, attr->value);
1085 | return;
1086 | }
1087 | update_attr(attr, tr);
1088 | }
1089 | else { // try to create dummy and repeat query
1090 |
1091 | // fprintf(stderr, "W: no ref. integrity. Trying to create dummy...");
1092 |
1093 | dummy_err = create_dummy(attr, tr);
1094 | if (dummy_err == 0) {
1095 | // fprintf(stderr, "D: ... dummy OK\n");
1096 | g_string_sprintfa(tr->error_script,"W[%d][%d:%s]:dummy created\n" ,0, attr->type, attr->value);
1097 | // fprintf(stderr, "D: repeating query: %s\n", query);
1098 | sql_result=SQ_execute_query(SQ_STORE, tr->sql_connection, query);
1099 | num = mysql_affected_rows(tr->sql_connection);
1100 | if (sql_result) { SQ_free_result(sql_result); sql_result=NULL;}
1101 | if ((num == -1) || (num==0)) {
1102 | tr->error|=ERROR_U_DBS;
1103 | tr->succeeded=0;
1104 | fprintf(stderr, "E:<each_attribute_create>: insert query: [%s]\n", query);
1105 | g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:insert qry\n" ,ERROR_U_DBS, attr->type, attr->value);
1106 | }
1107 | }
1108 | else
1109 | if(dummy_err == 1) {
1110 | tr->error |= ERROR_U_OBJ;
1111 | tr->succeeded=0;
1112 | g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:rf failure\n" ,ERROR_U_OBJ, attr->type, attr->value);
1113 | }
1114 | else {
1115 | tr->error|=ERROR_U_DBS;
1116 | tr->succeeded=0;
1117 | fprintf(stderr, "E:<each_attribute_create>: dummy not created\n");
1118 | g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:dummy not created\n" ,ERROR_U_DBS, attr->type, attr->value);
1119 | }
1120 | }// RI
1121 | }// if num == 0
1122 | return;
1123 | } /* each_attribute_process() */
1124 |
1125 |
1126 |
1127 | /************************************************************
1128 | * each_primary_key_select() *
1129 | * *
1130 | * Function that forms a query for an object (w prinary keys)*
1131 | * Called from g_slist_foreach() function. *
1132 | * Primary keys are defined in Select[] array. *
1133 | * *
1134 | * Returns: Nothing. Error code is stored in tr->succeeded. *
1135 | * *
1136 | *************************************************************/
1137 | static void each_primary_key_select(void *element_data, void *result_ptr)
1138 | {
1139 | Attribute_t *attr = element_data;
1140 | GString *result = (GString *)result_ptr;
1141 | char *query_fmt;
1142 | unsigned int prefix, prefix_length;
1143 | unsigned int begin_in, end_in;
1144 | int begin_as, end_as;
1145 |
1146 | query_fmt = Select[attr->type].qry;
1147 |
1148 | // fprintf(stderr, "D: qry fmt: %s\n", query_fmt);
1149 |
1150 | if (strcmp(query_fmt, "") != 0) {
1151 | switch (Select[attr->type].qtype) {
1152 | case UD_MAIN_:
1153 | g_string_sprintfa(result, query_fmt, attr->value);
1154 | break;
1155 | case UD_MA_RT:
1156 | expand_rt(attr->value, &prefix, &prefix_length);
1157 | g_string_sprintfa(result, query_fmt, prefix, prefix_length);
1158 | break;
1159 | case UD_MA_IN:
1160 | convert_in(attr->value, &begin_in, &end_in);
1161 | g_string_sprintfa(result, query_fmt, begin_in, end_in);
1162 | break;
1163 | case UD_MA_AK:
1164 | convert_as_range(attr->value, &begin_as, &end_as);
1165 | g_string_sprintfa(result, query_fmt, begin_as, end_as);
1166 | break;
1167 | default:
1168 | fprintf(stderr, "E:<e_p_k_s>: query not defined for this type of attribute:[%d]\n", attr->type);
1169 |
1170 |
1171 | break;
1172 | }
1173 | //fprintf(stderr, "D: each_primary_key_select(): %s\n",result->str);
1174 | }
1175 | }
1176 |
1177 | /************************************************************
1178 | * perform_create(const Object_t *obj, Transaction_t *tr) *
1179 | * *
1180 | * Procedure for creating a new object. *
1181 | * First inserts object into 'last' table and gets object_id.*
1182 | * Then processes all attributes. *
1183 | * *
1184 | * Returns: Nothing. Error code is stored in tr->succeeded. *
1185 | * *
1186 | *************************************************************/
1187 | static int perform_create(Transaction_t *tr)
1188 | {
1189 | Object_t *obj=tr->object;
1190 | SQ_result_set_t *sql_result;
1191 | char *str;
1192 | static char query[STR_XXXL];
1193 | int num;
1194 | long timestamp;
1195 |
1196 | str = (obj->object)->str;
1197 | timestamp=time(NULL);
1198 | sprintf(query, "INSERT INTO last SET thread_id=%d, timestamp=%ld, object_type=%d, object='%s' ",
1199 | tr->thread_ins, timestamp, tr->class_type, str);
1200 |
1201 | sql_result=SQ_execute_query(SQ_STORE, tr->sql_connection, query);
1202 | num = mysql_affected_rows(tr->sql_connection);
1203 | if (sql_result)SQ_free_result(sql_result);
1204 | if ((num == -1) || (num == 0)) {
1205 | fprintf(stderr, "E ERROR!<perform_create>: INSERT last failed:%d\n", num);
1206 | tr->error|=ERROR_U_DBS;
1207 | tr->succeeded=0;
1208 | g_string_sprintfa(tr->error_script,"E[%d][:]:INSERT last failed\n" ,ERROR_U_DBS);
1209 | }
1210 | else {
1211 | tr->object_id=mysql_insert_id(tr->sql_connection);
1212 | g_slist_foreach(obj->attributes, each_attribute_process, tr);
1213 | }
1214 | return(0);
1215 | } /* perform_create() */
1216 |
1217 | /************************************************************
1218 | * perform_update(Transaction_t *tr) *
1219 | * *
1220 | * Procedure for updating (existing) object. *
1221 | * First processes all attributes. *
1222 | * Then saves previous object in 'history' and updates *
1223 | * 'last' table. *
1224 | * *
1225 | * Returns: Nothing. Error code is stored in tr->succeeded. *
1226 | * *
1227 | *************************************************************/
1228 | static int perform_update(Transaction_t *tr)
1229 | {
1230 | Object_t *obj=tr->object;
1231 | SQ_result_set_t * sql_result;
1232 | char *str;
1233 | char str_id[STR_M];
1234 | char *sql_str;
1235 | static char query[STR_XXXL];
1236 | int num;
1237 | long sequence_id;
1238 | long timestamp;
1239 |
1240 | /* process each attribute one by one */
1241 | g_slist_foreach(obj->attributes, each_attribute_process, tr);
1242 |
1243 | /* If we've already failed or this is fast load - just return */
1244 | if((tr->succeeded == 0) || (tr->load_pass != 0)) return(0);
1245 |
1246 | /* No return: thread_id=0 */
1247 | /* Do it only if previous transactions finished well */
1248 |
1249 | /* copy object to the history table */
1250 | fprintf(stderr, "INSERT history\n");
1251 | sprintf(query,"INSERT history "
1252 | "SELECT 0, object_id, sequence_id, timestamp, object_type, object "
1253 | "FROM last "
1254 | "WHERE object_id=%ld ", tr->object_id);
1255 |
1256 | sql_result=SQ_execute_query(SQ_STORE, tr->sql_connection, query);
1257 | num = mysql_affected_rows(tr->sql_connection);
1258 | if (sql_result)SQ_free_result(sql_result);
1259 | if ((num == -1) || (num == 0)) {
1260 | fprintf(stderr, "E ERROR!<perform_update>: INSERT history failed:[%d][%s]\n", num, query);
1261 | tr->error|=ERROR_U_DBS;
1262 | tr->succeeded=0;
1263 | g_string_sprintfa(tr->error_script,"E[%d][:]:INSERT history failed\n" ,ERROR_U_DBS);
1264 | return(-1);
1265 | }
1266 |
1267 | /* get sequence number */
1268 | //fprintf(stderr, "get seq\n");
1269 | sprintf(str_id, "%ld", tr->object_id);
1270 | sql_str= get_field_str(tr, "sequence_id", "last", "object_id", str_id, NULL);
1271 | if(sql_str) {
1272 | sequence_id = atol(sql_str);
1273 | free(sql_str);
1274 | }
1275 | else {
1276 | fprintf(stderr, "E ERROR!<perform_update> cannot get sequence_id: %d\n", num);
1277 | tr->error|=ERROR_U_DBS;
1278 | tr->succeeded=0;
1279 | g_string_sprintfa(tr->error_script,"E[%d][:]:cannot get seq ID\n" ,ERROR_U_DBS);
1280 | return(-1);
1281 | }
1282 |
1283 | tr->sequence_id=sequence_id; // save it for rollback
1284 |
1285 |
1286 | /* insert new version into the last */
1287 | str = (obj->object)->str;
1288 | timestamp=time(NULL);
1289 | sequence_id++;
1290 |
1291 | //fprintf(stderr, "UPDATE last\n");
1292 | /* If we are here - it's almost commit. Otherwise this row will not be updated at all. */
1293 | sprintf(query, "UPDATE last "
1294 | "SET thread_id=0, sequence_id=%ld, timestamp=%ld, object_type=%d, object='%s' "
1295 | "WHERE object_id=%ld ",
1296 | sequence_id, timestamp, tr->class_type, str, tr->object_id);
1297 |
1298 | sql_result=SQ_execute_query(SQ_STORE, tr->sql_connection, query);
1299 | num = mysql_affected_rows(tr->sql_connection);
1300 | if (sql_result)SQ_free_result(sql_result);
1301 | if ((num == -1) || (num == 0)) {
1302 | fprintf(stderr, "E ERROR!<perform_update>: INSERT last failed: [%d][%s]\n", num, query);
1303 | tr->error|=ERROR_U_DBS;
1304 | tr->succeeded=0;
1305 | g_string_sprintfa(tr->error_script,"E[%d][:]:INSERT last failed\n" ,ERROR_U_DBS);
1306 | return(-1);
1307 | }
1308 | return(0);
1309 | } /* perform_update() */
1310 |
1311 |
1312 |
1313 |
1314 | /************************************************************
1315 | * int object_process(Transaction_t *tr) *
1316 | * *
1317 | * This is the interface between core and upper layer *
1318 | * All it gets is Transaction *tr, which contains all *
1319 | * necessary information, including the object in its *
1320 | * internal representation. *
1321 | * *
1322 | * Returns: Nothing. Error code is stored in tr->succeeded. *
1323 | * *
1324 | *************************************************************/
1325 | int object_process(Transaction_t *tr)
1326 | {
1327 |
1328 | /* not supported */
1329 | if(tr->class_type==C_I6) {
1330 | tr->succeeded=0; tr->error |= ERROR_U_NSUP;
1331 | fprintf(stderr, "Object type currently not supported\n");
1332 | return(-1);
1333 | }
1334 |
1335 | switch(tr->action){
1336 | case TR_DELETE:
1337 | fprintf(stderr, "D: Action: Delete...");
1338 | printf("\tD: Action: Delete...");
1339 | delete(tr);
1340 | return(0); //commit is not needed
1341 | break;
1342 |
1343 | case TR_UPDATE:
1344 | fprintf(stderr, "D: Action: Update...");
1345 | printf("\tD: Action: Update...");
1346 | perform_update(tr);
1347 | break;
1348 |
1349 | case TR_CREATE:
1350 | fprintf(stderr, "D: Action: Create...");
1351 | printf("\tD: Action: Create...");
1352 | perform_create(tr);
1353 | break;
1354 |
1355 | default:
1356 | fprintf(stderr, "D: Action: Unknown...");
1357 | tr->succeeded=0;
1358 | tr->error|=ERROR_U_BADOP;
1359 | return(-1);
1360 | break;
1361 | }
1362 | if(tr->load_pass == 0) { // not for fast loader
1363 | if (tr->succeeded == 1) {
1364 | //fprintf(stderr, "D: Commit transaction...\n");
1365 | commit(tr);
1366 | return(0);
1367 | }
1368 | else {
1369 | //fprintf(stderr, "D: Roll back transaction...\n");
1370 | rollback(tr);
1371 | return(0);
1372 | }
1373 | }
1374 | return(0);
1375 | } /* object_process() */
1376 |