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