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