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.25 $
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 <stream.h>*/
40
41
42 #include "ud.h"
43 #include "ud_int.h"
44
45 #include "constants.h"
46
47 #include "er_macro.h"
48 #include "er_paths.h"
49
50 #include "server.h"
51 #include "protocol_mirror.h"
52 #include "ta.h"
53
54 /* here we store sockets for update threads */
55 /* they are from SV module */
56 extern int SV_update_sock[];
57
58 /* Response time to swtching updates on and off */
59 #define TIMEOUT 60
60
61 /* timeout between successive attempts to establish connection with server */
62 #define PM_CONNECTION_TIMEOUT 10
63
64 /* Maximum number of objects(serials) we can consume at a time */
65 #define SBUNCH 1000
66
67 /* Timeout in seconds when reading from DBupdate */
68 #define STREAM_TIMEOUT 120
69
70 /************************************************************
71 * int get_NRTM_fd() *
72 * *
73 * Gets the NRTM stream *
74 * *
75 * First tries to request the serials from the NRTM server *
76 * If the name of the server appears to be not a network name*
77 * it tries to open the file with this name *
78 * *
79 * nrtm - pointer to _nrtm structure *
80 * upto_last - if==1 then requests to download serials using *
81 * LAST keyword *
82 * *
83 * Returns: *
84 * A file descriptor for a data stream *
85 * -1 - error *
86 * *
87 ************************************************************/
88 int get_NRTM_fd(struct _nrtm *nrtm, int upto_last, char *source)
/* [<][>][^][v][top][bottom][index][help] */
89 {
90 int sockfd;
91 struct hostent *hptr;
92 struct sockaddr_in serv_addr;
93 struct in_addr *paddr;
94 char line_buff[STR_XXL];
95 int fd;
96 int nwrite;
97 struct hostent result;
98 int error;
99 int network;
100
101
102 /* fprintf(stderr, "Making connection to NRTM server ...\n");*/
103 if ((sockfd=socket(AF_INET, SOCK_STREAM, 0))==-1){
104 ER_perror(FAC_UD, UD_FS, "cannot create socket");
105 return(-1);
106 }
107 #ifdef __linux__
108 if(gethostbyname_r(nrtm->server, &result, line_buff, sizeof(line_buff), &hptr, &error)<0) hptr=NULL;
109 #else/* default is Solaris implementation */
110 hptr=gethostbyname_r(nrtm->server, &result, line_buff, sizeof(line_buff), &error);
111 #endif
112
113 /* Check if it is a network stream or a file */
114 if (hptr) { /* this is a network stream*/
115 paddr=(struct in_addr *)hptr->h_addr;
116 bzero(&serv_addr, sizeof(serv_addr));
117 serv_addr.sin_family=AF_INET;
118 serv_addr.sin_port=nrtm->port;
119 memcpy(&serv_addr.sin_addr, paddr, sizeof(struct in_addr));
120 /* fprintf(stderr,"Trying %s port %d\n", inet_ntoa(serv_addr.sin_addr), nrtm->port);*/
121 if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))==-1) {
122 ER_perror(FAC_UD, UD_FS, "cannot cannect");
123 return(-1);
124 }
125 /* fprintf(stderr, "Sending Invitation\n"); */
126
127 /* Request all available serials (upto LAST), or SBUNCH of them */
128 if(upto_last==1)
129 sprintf(line_buff, "-g %s:%d:%ld-LAST\n", source, nrtm->version, nrtm->current_serial+1);
130 else if(upto_last==-1) /* persistent mirroring */
131 sprintf(line_buff, "-k -g %s:%d:%ld-LAST\n", source, nrtm->version, nrtm->current_serial+1);
132 else
133 sprintf(line_buff, "-g %s:%d:%ld-%ld\n", source, nrtm->version, nrtm->current_serial+1, nrtm->current_serial+SBUNCH);
134 nwrite=SK_write(sockfd, line_buff, strlen(line_buff) );
135 if(nwrite != strlen(line_buff)) {
136 ER_perror(FAC_UD, UD_FS, "cannot write");
137 return(-1);
138 }
139 fd=sockfd;
140 network=1;
141 /* fprintf(stderr, "Returning stream pointer\n"); */
142 }
143 else { /* this is a file stream*/
144 network=0;
145 close(sockfd);
146 /* fprintf(stderr, "Trying file ...\n");*/
147 if((fd=open(nrtm->server, O_RDONLY, 0666))==-1) {
148 ER_perror(FAC_UD, UD_FS, "cannot open");
149 return(-1);
150 }
151 }
152 return(fd);
153 }
154
155
156
157 /************************************************************
158 * void UD_do_nrtm() *
159 * *
160 * Processes NRTM stream *
161 * *
162 * It cycles requesting objects from the NRTM server, *
163 * processing them and then sleeping a specified amount of *
164 * time. *
165 * *
166 * It starts by requesting SBUNCH number of serials and does *
167 * so untill no serials are received (actually a warning *
168 * is received saying that the requested range is invalid) *
169 * This approach avoids excessive load on the NRTM server *
170 * *
171 * After that it requests serials using LAST keyward keeping *
172 * almost in sync with the server *
173 * *
174 ************************************************************/
175
176 void UD_do_nrtm(void *arg)
/* [<][>][^][v][top][bottom][index][help] */
177 {
178 int source = (int)arg;
179 UD_stream_t ud_stream;
180 struct _nrtm *nrtm;
181 int nrtm_delay;
182 int do_update=1;
183 int do_server;
184 int nrtm_fd;
185 int num_ok;
186 int upto_last;
187 char ta_activity[STR_M];
188 ca_dbSource_t *source_hdl = ca_get_SourceHandleByPosition(source);
189 char *db_host, *db_name, *db_user, *db_passwd;
190 int db_port;
191 /* get source we are going to mirror */
192 char *source_name = ca_get_srcname(source_hdl);
193
194 { /* set up the lohgging path */
195 int res;
196 char *er_ud_def = ca_get_er_ud_def; /* something like 'RIPUPDLOG basename' */
197 char er_def[256];
198 char *erret = NULL;
199
200 sprintf(er_def, "%s %s", er_ud_def, source_name);
201 fprintf(stderr, "[%s]\n", er_def);
202 if( (res = ER_macro_spec(er_def, &erret)) != 0 ) {
203 fputs(erret, stderr);
204 die;
205 /* or some other error handling */
206 }
207 free(erret); /* the response is allocated and must be freed */
208 free(er_ud_def);
209 }
210
211 nrtm=calloc(1, sizeof(struct _nrtm));
212 if(nrtm==NULL) {
213 ER_perror(FAC_UD, UD_MEM, "cannot allocate memory");
214 die;
215 }
216 /* get mode of operation: protected/unprotected (dummy) */
217 memset(&ud_stream, 0, sizeof(ud_stream));
218 ud_stream.source_hdl=source_hdl;
219 ud_stream.ud_mode=ca_get_srcmode(source_hdl);
220 nrtm_delay=ca_get_srcnrtmdelay(source_hdl);
221 /* Zero delay means persistent connection */
222 if (nrtm_delay==0) ud_stream.ud_mode |= B_PERSIST_MIRR;
223
224 fprintf(stderr, "Mode of operation:\n");
225 if(IS_DUMMY_ALLOWED(ud_stream.ud_mode))fprintf(stderr, "* dummy allowed\n");
226 else fprintf(stderr, "* dummy not allowed\n");
227
228 if(IS_UPDATE(ud_stream.ud_mode))fprintf(stderr, "* DBupdate\n");
229 else if(IS_NRTM_CLNT(ud_stream.ud_mode)) {
230
231 if(IS_PERSIST_MIRR(ud_stream.ud_mode))fprintf(stderr, "* NRTM: persistent conection\n");
232 else fprintf(stderr, "* NRTM\n");
233 }
234 else fprintf(stderr, "* STATIC\n");
235
236 if(IS_STANDALONE(ud_stream.ud_mode))fprintf(stderr, "* running standalone\n");
237 else fprintf(stderr, "* running as a server\n");
238
239 /* get mirror server */
240 nrtm->server=ca_get_srcnrtmhost(source_hdl);
241
242
243 /* get mirror port */
244 nrtm->port = htons(ca_get_srcnrtmport(source_hdl));
245 printf("XXX nrtm_port=%d\n", ntohs(nrtm->port));
246
247 /* get mirror version */
248 nrtm->version=ca_get_srcnrtmprotocolvers(source_hdl);
249
250
251 /* get error log facility */
252 /* logfilename=ca_get_srcnrtmlog(source_hdl); */
253
254 db_host = ca_get_srcdbmachine(source_hdl);
255 db_port = ca_get_srcdbport(source_hdl);
256 db_name = ca_get_srcdbname(source_hdl);
257 db_user = ca_get_srcdbuser(source_hdl);
258 db_passwd = ca_get_srcdbpassword(source_hdl);
259
260 /* Connect to the database */
261 ER_dbg_va(FAC_UD, ASP_UD_SQL, "%s making SQL connection to %s@%s ...", UD_TAG, db_name, db_host);
262 ud_stream.db_connection=SQ_get_connection(db_host, db_port, db_name, db_user, db_passwd);
263
264
265 if(! ud_stream.db_connection) {
266 ER_perror(FAC_UD, UD_SQL, "no connection to SQL server");
267 die;
268 }
269
270 ud_stream.num_skip=0;
271 ud_stream.load_pass=0;
272 ud_stream.nrtm=nrtm;
273
274 if(IS_PERSIST_MIRR(ud_stream.ud_mode))upto_last=-1; /* the faster the better */
275 else upto_last=0; /* let's start gradually if the backlog is > SBUNCH (1000) serials*/
276
277 /*+++ main cycle +++*/
278
279 do {
280 do_update=CO_get_do_update();
281 if(do_update) {
282
283 /* Check connection to the database and try to reconnect */
284 if(mysql_ping(ud_stream.db_connection)) {
285 ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "%s connection to SQL server timed out - reistablishing", UD_TAG);
286 }
287
288 /* get current serial */
289 nrtm->current_serial=PM_get_current_serial(ud_stream.db_connection);
290
291 if(nrtm->current_serial == -1) {
292 ER_perror(FAC_UD, UD_SQL, "cannot obtain current serial: %ld", nrtm->current_serial);
293 die;
294 }
295
296 ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "%s connecting to NRTM server (current serial=%ld)", UD_TAG, nrtm->current_serial);
297
298 /* Get file descriptor of the data stream (RPSL format, use mirror reflector to convert if needed)*/
299 nrtm_fd=get_NRTM_fd(nrtm, upto_last, source_name);
300 if (nrtm_fd==-1) {
301 ER_inf_va(FAC_UD, ASP_UD_OBJ, "%s Cannot open data stream. Trying...", UD_TAG);
302 SV_sleep(PM_CONNECTION_TIMEOUT);
303 continue;
304 }
305
306
307 /* make a record for thread accounting */
308 TA_add(nrtm_fd, "nrtm_clnt");
309 sprintf(ta_activity,"[%s]%ld->", source_name, nrtm->current_serial);
310 TA_setactivity(ta_activity);
311
312
313 ud_stream.condat.sock = nrtm_fd;
314 ud_stream.log.num_ok=0;
315 ud_stream.log.num_failed=0;
316
317
318 ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s starting processing stream", UD_TAG);
319
320 /***************** process stream ****************/
321
322 num_ok=UD_process_stream(&ud_stream);
323
324 /***************** process stream ****************/
325
326 ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s processing stream finished", UD_TAG);
327
328 /* close the socket of the NRTM stream */
329 close(ud_stream.condat.sock);
330
331
332
333 ER_inf_va(FAC_UD, ASP_UD_OBJ, "%s forwarded to serial:%ld", UD_TAG, (nrtm->current_serial+num_ok));
334
335 /* set activity for thread record */
336 sprintf(ta_activity,"[%s]->%ld", source_name, (nrtm->current_serial+num_ok));
337 TA_setactivity(ta_activity);
338
339 /* if we are NOT in persistent mode */
340 if(!IS_PERSIST_MIRR(ud_stream.ud_mode)) {
341 /* Now we can process serials in normal way (upto LAST)*/
342 if(num_ok==0) upto_last=1;
343 /* get delay */
344 nrtm_delay=ca_get_srcnrtmdelay(source_hdl);
345 /* sleep the delay seconds or untill the shutdown requested */
346 SV_sleep(nrtm_delay);
347 } /* otherwise - no delay at all */
348
349 } /* if do_updates */
350 else SV_sleep(TIMEOUT);
351
352
353 TA_delete();
354
355 } while((do_server=CO_get_do_server())); /* main cycle */
356
357 /* fclose(ud_stream.log.logfile);*/
358 free(source_name);
359 /* free data associated with nrtm structure */
360 if(nrtm) {
361 free(nrtm->server);
362 free(nrtm);
363 }
364
365 /* That's all. Close connection to the DB */
366 SQ_close_connection(ud_stream.db_connection);
367 free(db_host);
368 free(db_name);
369 free(db_user);
370 free(db_passwd);
371
372 ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s NRTM client stopped", UD_TAG);
373 } /* UD_do_nrtm() */
374
375 /************************************************************
376 * void UD_do_updates() *
377 * *
378 * Processes updates *
379 * *
380 * It cycles accepting connections and processing them *
381 * (interactive server). This assures that there is only *
382 * one write thread per database/source. *
383 * *
384 ************************************************************/
385
386 void UD_do_updates(void *arg)
/* [<][>][^][v][top][bottom][index][help] */
387 {
388 int source = (int)arg;
389 int listening_socket = SV_update_sock[source];
390 int connected_socket;
391 UD_stream_t ud_stream;
392 int do_update=1;
393 int do_server;
394 int num_ok;
395 ca_dbSource_t *source_hdl = ca_get_SourceHandleByPosition(source);
396 char *db_host, *db_name, *db_user, *db_passwd;
397 int db_port;
398
399 { /* set up the lohgging path */
400 /* get source we are going to update */
401 char *source_name = ca_get_srcname(source_hdl);
402 int res;
403 char *er_ud_def = ca_get_er_ud_def; /* something like 'RIPUPDLOG basename' */
404 char er_def[256];
405 char *erret = NULL;
406
407 sprintf(er_def, "%s %s", er_ud_def, source_name);
408 if( (res = ER_macro_spec(er_def, &erret)) != 0 ) {
409 fputs(erret, stderr);
410 die;
411 /* or some other error handling */
412 }
413 free(erret); /* the response is allocated and must be freed */
414 free(er_ud_def);
415 free(source_name);
416 }
417
418 /* get mode of operation: protected/unprotected (dummy) */
419 memset(&ud_stream, 0, sizeof(ud_stream));
420 ud_stream.source_hdl=source_hdl;
421 ud_stream.ud_mode=ca_get_srcmode(source_hdl);
422
423 fprintf(stderr, "Mode of operation:\n");
424 if(IS_DUMMY_ALLOWED(ud_stream.ud_mode))fprintf(stderr, "* dummy allowed\n");
425 else fprintf(stderr, "* dummy not allowed\n");
426 if(IS_UPDATE(ud_stream.ud_mode))fprintf(stderr, "* DBupdate\n");
427 else fprintf(stderr, "* NRTM\n");
428 if(IS_STANDALONE(ud_stream.ud_mode))fprintf(stderr, "* running standalone\n");
429 else fprintf(stderr, "* running as a server\n");
430
431
432 /* get error log facility */
433 db_host = ca_get_srcdbmachine(source_hdl);
434 db_port = ca_get_srcdbport(source_hdl);
435 db_name = ca_get_srcdbname(source_hdl);
436 db_user = ca_get_srcdbuser(source_hdl);
437 db_passwd = ca_get_srcdbpassword(source_hdl);
438
439 /* Connect to the database */
440 ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s making SQL connection to %s@%s ...", UD_TAG, db_name, db_host);
441 ud_stream.db_connection=SQ_get_connection(db_host, db_port, db_name, db_user, db_passwd);
442
443 if(! ud_stream.db_connection) {
444 ER_perror(FAC_UD, UD_SQL, "no connection to SQL server\n");
445 die;
446 }
447
448
449 ud_stream.condat.rd_timeout.tv_sec=STREAM_TIMEOUT;
450 ud_stream.num_skip=0;
451 ud_stream.load_pass=0;
452 ud_stream.nrtm=NULL;
453
454 /*+++ main cycle +++*/
455
456 do { /* be alive while do_server is 1. do_server is turned off by SIGINT */
457
458 /* make a record for thread accounting */
459 TA_add(listening_socket, "update");
460 TA_setactivity("waiting");
461
462
463 /* accept connection */
464 connected_socket = SK_accept_connection(listening_socket);
465 if(connected_socket==-1) break;
466
467
468 /* make a record for thread accounting */
469 TA_delete(); /* Delete 'waiting' record */
470 TA_add(connected_socket, "update");
471
472
473 ud_stream.condat.sock = connected_socket;
474 ud_stream.condat.rtc = 0;
475
476 do_update=CO_get_do_update();
477 if(do_update) {
478
479 TA_setactivity("suspended");
480
481 ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s Connection accepted...", UD_TAG);
482
483 ud_stream.log.num_ok=0;
484 ud_stream.log.num_failed=0;
485
486 /* Check connection to the database and try to reconnect*/
487 if(mysql_ping(ud_stream.db_connection)) {
488 ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "%s connection to SQL server timed out - reistablishing", UD_TAG);
489 }
490
491 ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s starting processing object", UD_TAG);
492
493 /***************** process stream ****************/
494
495 num_ok=UD_process_stream(&ud_stream);
496
497 /***************** process stream ****************/
498
499 ER_dbg_va(FAC_UD, ASP_UD_OBJ, "%s processing object finished", UD_TAG);
500
501 /* close the socket of the NRTM stream */
502 close(ud_stream.condat.sock);
503
504 } /* if do_update*/
505 else { /* Otherwise print a message*/
506 /* To display with 'show threads' */
507 TA_setactivity("suspended");
508
509 }
510 /* make a record for thread accounting */
511 TA_delete();
512
513 do_server=CO_get_do_server();
514
515 } while (do_server); /* main cycle */
516
517 /* fclose(ud_stream.log.logfile); */
518 /* That's all. Close connection to the DB */
519 SQ_close_connection(ud_stream.db_connection);
520 free(db_host);
521 free(db_name);
522 free(db_user);
523 free(db_passwd);
524
525
526 ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "%s update server stopped", UD_TAG);
527 } /* UD_do_update() */
528
529
530
531