modules/ud/ud_main.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- get_NRTM_fd
- UD_do_nrtm
- UD_do_updates
1 /***************************************
2 $Revision: 1.19 $
3
4 Wrapper for NRTM client
5
6 Status: NOT REVUED, NOT TESTED
7
8 Author(s): Andrei Robachevsky
9
10 ******************/ /******************
11 Modification History:
12 andrei (17/01/2000) Created.
13 ******************/ /******************
14 Copyright (c) 2000 RIPE NCC
15
16 All Rights Reserved
17
18 Permission to use, copy, modify, and distribute this software and its
19 documentation for any purpose and without fee is hereby granted,
20 provided that the above copyright notice appear in all copies and that
21 both that copyright notice and this permission notice appear in
22 supporting documentation, and that the name of the author not be
23 used in advertising or publicity pertaining to distribution of the
24 software without specific, written prior permission.
25
26 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
28 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
29 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
30 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
31 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 ***************************************/
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <fcntl.h>
38 #include <signal.h>
39 #include "ud.h"
40 #include "ud_int.h"
41 #include "constants.h"
42
43 #include "server.h"
44 #include "protocol_mirror.h"
45 #include "ta.h"
46
47 /* here we store sockets for update threads */
48 /* they are from SV module */
49 extern int SV_update_sock[];
50
51 /* Response time to swtching updates on and off */
52 #define TIMEOUT 60
53 /* Maximum number of objects(serials) we can consume at a time */
54 #define SBUNCH 1000
55
56 /************************************************************
57 * int get_NRTM_fd() *
58 * *
59 * Gets the NRTM stream *
60 * *
61 * First tries to request the serials from the NRTM server *
62 * If the name of the server appears to be not a network name*
63 * it tries to open the file with this name *
64 * *
65 * nrtm - pointer to _nrtm structure *
66 * upto_last - if==1 then requests to download serials using *
67 * LAST keyword *
68 * *
69 * Returns: *
70 * A file descriptor for a data stream *
71 * -1 - error *
72 * *
73 ************************************************************/
74 int get_NRTM_fd(struct _nrtm *nrtm, int upto_last, char *source)
/* [<][>][^][v][top][bottom][index][help] */
75 {
76 int sockfd;
77 struct hostent *hptr;
78 struct sockaddr_in serv_addr;
79 struct in_addr *paddr;
80 char line_buff[STR_XXL];
81 int fd;
82 int nwrite;
83 struct hostent result;
84 int error;
85 int network;
86
87
88 fprintf(stderr, "Making connection to NRTM server ...\n");
89 if ((sockfd=socket(AF_INET, SOCK_STREAM, 0))==-1){
90 perror("socket");
91 return(-1);
92 }
93 /* hptr=gethostbyname(nrtm->server);*/
94 hptr=gethostbyname_r(nrtm->server, &result, line_buff, sizeof(line_buff), &error);
95
96 /* Check if it is a network stream or a file */
97 if (hptr) { /* this is a network stream*/
98 paddr=(struct in_addr *)hptr->h_addr;
99 bzero(&serv_addr, sizeof(serv_addr));
100 serv_addr.sin_family=AF_INET;
101 serv_addr.sin_port=nrtm->port;
102 memcpy(&serv_addr.sin_addr, paddr, sizeof(struct in_addr));
103 fprintf(stderr,"Trying %s port %d\n", inet_ntoa(serv_addr.sin_addr), nrtm->port);
104 if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))==-1) {
105 perror("connect");
106 return(-1);
107 }
108 fprintf(stderr, "Sending Invitation\n");
109
110 /* Request all available serials (upto LAST), or SBUNCH of them */
111 if(upto_last)
112 sprintf(line_buff, "-g %s:%d:%ld-LAST\n", source, nrtm->version, nrtm->current_serial+1);
113 else
114 sprintf(line_buff, "-g %s:%d:%ld-%ld\n", source, nrtm->version, nrtm->current_serial+1, nrtm->current_serial+SBUNCH);
115 nwrite=SK_write(sockfd, line_buff, strlen(line_buff) );
116 if(nwrite != strlen(line_buff)) { perror("write"); return(-1); }
117 fd=sockfd;
118 network=1;
119 fprintf(stderr, "Returning stream pointer\n");
120 }
121 else { /* this is a file stream*/
122 network=0;
123 close(sockfd);
124 fprintf(stderr, "Trying file ...\n");
125 if((fd=open(nrtm->server, O_RDONLY, 0666))==-1) {
126 perror("open");
127 return(-1);
128 }
129 }
130 return(fd);
131 }
132
133 /************************************************************
134 * void UD_do_nrtm() *
135 * *
136 * Processes NRTM stream *
137 * *
138 * It cycles requesting objects from the NRTM server, *
139 * processing them and then sleeping a specified amount of *
140 * time. *
141 * *
142 * It starts by requesting SBUNCH number of serials and does *
143 * so untill no serials are received (actually a warning *
144 * is received saying that the requested range is invalid) *
145 * This approach avoids excessive load on the NRTM server *
146 * *
147 * After that it requests serials using LAST keyward keeping *
148 * almost in sync with the server *
149 * *
150 ************************************************************/
151
152 void UD_do_nrtm(void *arg)
/* [<][>][^][v][top][bottom][index][help] */
153 {
154 int source = (int)arg;
155 UD_stream_t ud_stream;
156 struct _nrtm *nrtm;
157 int delay;
158 int do_update=1;
159 int do_server;
160 char *logfilename;
161 FILE *file;
162 int nrtm_fd;
163 int num_ok;
164 int upto_last;
165 char ta_activity[STR_M];
166 ca_dbSource_t *source_hdl = ca_get_SourceHandleByPosition(source);
167 char *db_host, *db_name, *db_user, *db_passwd;
168 int db_port;
169 char *source_name;
170
171
172
173 nrtm=calloc(1, sizeof(struct _nrtm));
174 if(nrtm==NULL) {
175 printf("Cannot allocate memory\n");
176 die;
177 }
178 /* get mode of operation: protected/unprotected (dummy) */
179 ud_stream.source_hdl=source_hdl;
180 ud_stream.ud_mode=ca_get_srcmode(source_hdl);
181
182 fprintf(stderr, "Mode of operation:\n");
183 if(IS_DUMMY_ALLOWED(ud_stream.ud_mode))fprintf(stderr, "* dummy allowed\n");
184 else fprintf(stderr, "* dummy not allowed\n");
185 if(IS_UPDATE(ud_stream.ud_mode))fprintf(stderr, "* DBupdate\n");
186 else fprintf(stderr, "* NRTM\n");
187 if(IS_STANDALONE(ud_stream.ud_mode))fprintf(stderr, "* running standalone\n");
188 else fprintf(stderr, "* running as a server\n");
189
190 /* get mirror server */
191 nrtm->server=ca_get_srcnrtmhost(source_hdl);
192
193
194 /* get mirror port */
195 nrtm->port = htons(ca_get_srcnrtmport(source_hdl));
196 printf("XXX nrtm_port=%d\n", ntohs(nrtm->port));
197
198 /*
199 if(nrtm->port == -1) {
200 printf("Invalid service/port: %d\n", nrtm->port);
201 return;
202 }
203 */
204
205 /* get mirror version */
206 nrtm->version=ca_get_srcnrtmprotocolvers(source_hdl);
207
208 /* get source we are going to mirror */
209 source_name = ca_get_srcname(source_hdl);
210
211
212 /* get error log facility */
213 logfilename=ca_get_srcnrtmlog(source_hdl);
214
215 db_host = ca_get_srcdbmachine(source_hdl);
216 db_port = ca_get_srcdbport(source_hdl);
217 db_name = ca_get_srcdbname(source_hdl);
218 db_user = ca_get_srcdbuser(source_hdl);
219 db_passwd = ca_get_srcdbpassword(source_hdl);
220
221 /* Connect to the database */
222 fprintf(stderr, "D: Making SQL connection to %s@%s ...", db_name, db_host);
223 ud_stream.db_connection=SQ_get_connection(db_host, db_port, db_name, db_user, db_passwd);
224
225
226 if(! ud_stream.db_connection) {
227 fprintf(stderr, "D: ERROR: no SQL connection\n");
228 die;
229 }
230
231 fprintf(stderr, "OK\n");
232
233 ud_stream.num_skip=0;
234 ud_stream.load_pass=0;
235 ud_stream.nrtm=nrtm;
236 ud_stream.log.logfile = fopen(logfilename, "a+");
237 if(!ud_stream.log.logfile){
238 fprintf(stderr, "D: ERROR: cannot open log file %s\n", logfilename);
239 die;
240 }
241
242 free(logfilename);
243
244
245 upto_last=0; /* let's start gradually if the backlog is > SBUNCH (1000) serials*/
246
247 /*+++ main cycle +++*/
248
249 do {
250 do_update=CO_get_do_update();
251 if(do_update) {
252
253 /* Check connection to the database and try to reconnect */
254 if(mysql_ping(ud_stream.db_connection)) {
255 fprintf(stderr, "D: ERROR: SQL connection time out - reestablishing\n");
256 }
257
258 /* get current serial */
259 nrtm->current_serial=PM_get_current_serial(ud_stream.db_connection);
260
261 if(nrtm->current_serial == -1) {
262 fprintf(stderr, "D: ERROR: Error obtaining current serial: %ld\n", nrtm->current_serial);
263 die;
264 }
265
266 fprintf(stderr, "current_serial:\t%ld\n", nrtm->current_serial);
267 fprintf(stderr, "conecting to server...\n");
268
269 /* Get file descriptor of the data stream (RPSL format, use mirror reflector to convert if needed)*/
270 nrtm_fd=get_NRTM_fd(nrtm, upto_last, source_name);
271
272 /* make a record for thread accounting */
273 TA_add(nrtm_fd, "nrtm_clnt");
274 sprintf(ta_activity,"[%s]%ld->", source_name, nrtm->current_serial);
275 TA_setactivity(ta_activity);
276 file=fdopen(nrtm_fd, "r+");
277
278
279 fprintf(stderr, "OK\n");
280 printf("OK\n");
281
282
283 if (file==NULL) {
284 fprintf(stderr, "Cannot open data stream. Trying...\n");
285 sleep(100);
286 continue;
287 }
288
289
290 ud_stream.stream=file;
291 ud_stream.log.num_ok=0;
292 ud_stream.log.num_failed=0;
293
294
295 fprintf(stderr, "starting processing stream\n");
296
297 num_ok=UD_process_stream(&ud_stream);
298
299
300 /*Check for errors */
301 if(num_ok<0) {
302 fprintf(stderr, "processing stream failed\n");
303 do_server=0;
304 break;
305 }
306 else fprintf(stderr, "processing stream finished\n");
307
308 /* Now we can process serials in normal way (upto LAST)*/
309 if(num_ok==0) upto_last=1;
310
311 fprintf(ud_stream.log.logfile, "forwarded to serial:\t%ld\n", (nrtm->current_serial+num_ok));
312 fflush(ud_stream.log.logfile);
313 fprintf(stderr, "forwarded to serial:\t%ld\n", (nrtm->current_serial+num_ok));
314 printf("Objects received: %d\n-----------\n", num_ok);
315
316 /* set activity for thread record */
317 sprintf(ta_activity,"[%s]->%ld", source_name, (nrtm->current_serial+num_ok));
318 TA_setactivity(ta_activity);
319
320
321 /* get delay */
322 delay=ca_get_srcnrtmdelay(source_hdl);
323 SV_sleep(LOCK_SHTDOWN, delay);
324 } /* if do_updates */
325 else SV_sleep(LOCK_SHTDOWN, TIMEOUT);
326
327 do_server=CO_get_do_server();
328 TA_delete();
329
330 } while(do_server); /* main cycle */
331
332 fclose(ud_stream.log.logfile);
333 free(source_name);
334 /* free data associated with nrtm structure */
335 if(nrtm) {
336 free(nrtm->server);
337 free(nrtm);
338 }
339
340 /* That's all. Close connection to the DB */
341 SQ_close_connection(ud_stream.db_connection);
342 free(db_host);
343 free(db_name);
344 free(db_user);
345 free(db_passwd);
346
347 fprintf(stderr, "NRTM stopped\n");
348
349 } /* UD_do_nrtm() */
350
351 /************************************************************
352 * void UD_do_updates() *
353 * *
354 * Processes updates *
355 * *
356 * It cycles accepting connections and processing them *
357 * (interactive server). This assures that there is only *
358 * one write thread per database/source. *
359 * *
360 ************************************************************/
361
362 void UD_do_updates(void *arg)
/* [<][>][^][v][top][bottom][index][help] */
363 {
364 int source = (int)arg;
365 int listening_socket = SV_update_sock[source];
366 int connected_socket;
367 UD_stream_t ud_stream;
368 int do_update=1;
369 int do_server;
370 char *logfilename;
371 FILE *file, *file_ack;
372 int num_ok;
373 ca_dbSource_t *source_hdl = ca_get_SourceHandleByPosition(source);
374 char *db_host, *db_name, *db_user, *db_passwd;
375 int db_port;
376
377
378
379 /* get mode of operation: protected/unprotected (dummy) */
380 /* ud_stream.ud_mode=CO_get_update_mode(); */
381 ud_stream.source_hdl=source_hdl;
382 ud_stream.ud_mode=ca_get_srcmode(source_hdl);
383
384 fprintf(stderr, "Mode of operation:\n");
385 if(IS_DUMMY_ALLOWED(ud_stream.ud_mode))fprintf(stderr, "* dummy allowed\n");
386 else fprintf(stderr, "* dummy not allowed\n");
387 if(IS_UPDATE(ud_stream.ud_mode))fprintf(stderr, "* DBupdate\n");
388 else fprintf(stderr, "* NRTM\n");
389 if(IS_STANDALONE(ud_stream.ud_mode))fprintf(stderr, "* running standalone\n");
390 else fprintf(stderr, "* running as a server\n");
391
392
393 /* get error log facility */
394 logfilename=ca_get_srcnrtmlog(source_hdl);
395 db_host = ca_get_srcdbmachine(source_hdl);
396 db_port = ca_get_srcdbport(source_hdl);
397 db_name = ca_get_srcdbname(source_hdl);
398 db_user = ca_get_srcdbuser(source_hdl);
399 db_passwd = ca_get_srcdbpassword(source_hdl);
400
401 /* Connect to the database */
402 fprintf(stderr, "D: Making SQL connection to %s@%s ...", db_name, db_host);
403
404 /* ud_stream.db_connection=SQ_get_connection2(); */
405 ud_stream.db_connection=SQ_get_connection(db_host, db_port, db_name, db_user, db_passwd);
406
407 if(! ud_stream.db_connection) {
408 fprintf(stderr, "D: ERROR: no SQL connection\n");
409 die;
410 }
411
412 fprintf(stderr, "OK\n");
413
414 ud_stream.num_skip=0;
415 ud_stream.load_pass=0;
416 ud_stream.nrtm=NULL;
417 ud_stream.log.logfile = fopen(logfilename, "a+");
418 if(!ud_stream.log.logfile){
419 fprintf(stderr, "D: ERROR: cannot open log file %s\n", logfilename);
420 die;
421 }
422
423 free(logfilename);
424
425
426 /*+++ main cycle +++*/
427
428 do { /* be alive while do_server is 1. do_server is turned off by SIGINT */
429
430 /* make a record for thread accounting */
431 TA_add(listening_socket, "update");
432 TA_setactivity("waiting");
433
434
435 /* accept connection */
436 connected_socket = SK_accept_connection(listening_socket);
437 if(connected_socket==-1) break;
438
439
440 /* make a record for thread accounting */
441 TA_delete(); /* Delete 'waiting' record */
442 TA_add(connected_socket, "update");
443
444 file=fdopen(connected_socket, "r");
445 file_ack=fdopen(connected_socket, "w");
446
447 do_update=CO_get_do_update();
448 if(do_update) {
449
450 TA_setactivity("suspended");
451
452 fprintf(stderr, "Connection accepted...\n");
453
454 if ((file==NULL) || (file_ack==NULL)) {
455 fprintf(stderr, "Cannot open data stream. Closing connction\n");
456 return;
457 }
458 fprintf(stderr, "Connection accepted...\n");
459
460 ud_stream.stream=file;
461 ud_stream.log.num_ok=0;
462 ud_stream.log.num_failed=0;
463
464 /* Check connection to the database and try to reconnect*/
465 if(mysql_ping(ud_stream.db_connection)) {
466 fprintf(stderr, "D: ERROR: SQL connection time out - reestablishing\n");
467 }
468
469 fprintf(stderr, "starting processing object\n");
470
471 num_ok=UD_process_stream(&ud_stream);
472
473 fprintf(stderr, "processing object finished\n");
474
475 if(num_ok==1) {
476 fprintf(file_ack, "%%ERROR 0\n");
477 fprintf(stderr, "%%ERROR 0\n");
478 }
479 else {
480 num_ok=(-1)*num_ok;
481 fprintf(file_ack, "%%ERROR %d\n",num_ok);
482 fprintf(stderr, "%%ERROR %d\n",num_ok);
483 fprintf(file_ack, "Transaction had the following problems:\n");
484 if(num_ok & ERROR_U_MEM) fprintf(file_ack, "Memory allocation error\n");
485 /* if(num_ok & ERROR_U_DBS) fprintf(file_ack, "Database (SQL) error\n");*/
486 /* if(num_ok & ERROR_U_OBJ) fprintf(file_ack, "Object (RF) error\n");*/
487 /* if(num_ok & ERROR_U_AUT) fprintf(file_ack, "Object authentication error\n");*/
488 if(num_ok & ERROR_U_BADOP) fprintf(file_ack, "Bad operation\n");
489 if(num_ok & ERROR_U_COP) fprintf(file_ack, "Conflicting operation\n");
490 if(num_ok & ERROR_U_NSUP) fprintf(file_ack, "Object of this type is not supported\n");
491 if(num_ok & ERROR_U_BUG) fprintf(file_ack, "Software bug - report to <ripe-dbm@ripe.net>\n");
492 }
493 if(ud_stream.error_script)fprintf(file_ack, "%s\n", ud_stream.error_script);
494
495 if(ud_stream.error_script) free(ud_stream.error_script);
496
497 fflush(file_ack); fclose(file_ack);
498 fclose(file);
499 } /* if do_update*/
500 else { /* Otherwise print a message*/
501 /* To display with 'show threads' */
502 TA_setactivity("suspended");
503
504 fprintf(file_ack, "%%ERROR 1000\n%%Updates are suspended\n");
505 fflush(file_ack); fclose(file_ack);
506 fclose(file);
507 }
508 /* make a record for thread accounting */
509 TA_delete();
510
511 do_server=CO_get_do_server();
512
513 } while (do_server); /* main cycle */
514
515 fclose(ud_stream.log.logfile);
516 /* That's all. Close connection to the DB */
517 SQ_close_connection(ud_stream.db_connection);
518 free(db_host);
519 free(db_name);
520 free(db_user);
521 free(db_passwd);
522
523
524 fprintf(stderr, "server stopped\n");
525
526 } /* UD_do_update() */
527
528
529
530