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.17 $
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 return;
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 return;
240 }
241
242 free(db_host);
243 free(db_name);
244 free(db_user);
245 free(db_passwd);
246 free(logfilename);
247
248
249 upto_last=0; /* let's start gradually if the backlog is > SBUNCH (1000) serials*/
250
251 /*+++ main cycle +++*/
252
253 do {
254 do_update=CO_get_do_update();
255 if(do_update) {
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 return;
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 fprintf(stderr, "NRTM stopped\n");
343
344 } /* UD_do_nrtm() */
345
346 /************************************************************
347 * void UD_do_updates() *
348 * *
349 * Processes updates *
350 * *
351 * It cycles accepting connections and processing them *
352 * (interactive server). This assures that there is only *
353 * one write thread per database/source. *
354 * *
355 ************************************************************/
356
357 void UD_do_updates(void *arg)
/* [<][>][^][v][top][bottom][index][help] */
358 {
359 int source = (int)arg;
360 int listening_socket = SV_update_sock[source];
361 int connected_socket;
362 UD_stream_t ud_stream;
363 int do_update=1;
364 int do_server;
365 char *logfilename;
366 FILE *file, *file_ack;
367 int num_ok;
368 ca_dbSource_t *source_hdl = ca_get_SourceHandleByPosition(source);
369 char *db_host, *db_name, *db_user, *db_passwd;
370 int db_port;
371
372
373
374 /* get mode of operation: protected/unprotected (dummy) */
375 /* ud_stream.ud_mode=CO_get_update_mode(); */
376 ud_stream.source_hdl=source_hdl;
377 ud_stream.ud_mode=ca_get_srcmode(source_hdl);
378
379 fprintf(stderr, "Mode of operation:\n");
380 if(IS_DUMMY_ALLOWED(ud_stream.ud_mode))fprintf(stderr, "* dummy allowed\n");
381 else fprintf(stderr, "* dummy not allowed\n");
382 if(IS_UPDATE(ud_stream.ud_mode))fprintf(stderr, "* DBupdate\n");
383 else fprintf(stderr, "* NRTM\n");
384 if(IS_STANDALONE(ud_stream.ud_mode))fprintf(stderr, "* running standalone\n");
385 else fprintf(stderr, "* running as a server\n");
386
387
388 /* get error log facility */
389 logfilename=ca_get_srcnrtmlog(source_hdl);
390 db_host = ca_get_srcdbmachine(source_hdl);
391 db_port = ca_get_srcdbport(source_hdl);
392 db_name = ca_get_srcdbname(source_hdl);
393 db_user = ca_get_srcdbuser(source_hdl);
394 db_passwd = ca_get_srcdbpassword(source_hdl);
395
396 /* Connect to the database */
397 fprintf(stderr, "D: Making SQL connection to %s@%s ...", db_name, db_host);
398
399 /* ud_stream.db_connection=SQ_get_connection2(); */
400 ud_stream.db_connection=SQ_get_connection(db_host, db_port, db_name, db_user, db_passwd);
401
402 if(! ud_stream.db_connection) {
403 fprintf(stderr, "D: ERROR: no SQL connection\n");
404 return;
405 }
406
407 fprintf(stderr, "OK\n");
408
409 ud_stream.num_skip=0;
410 ud_stream.load_pass=0;
411 ud_stream.nrtm=NULL;
412 ud_stream.log.logfile = fopen(logfilename, "a+");
413 if(!ud_stream.log.logfile){
414 fprintf(stderr, "D: ERROR: cannot open log file %s\n", logfilename);
415 return;
416 }
417
418 free(db_host);
419 free(db_name);
420 free(db_user);
421 free(db_passwd);
422 free(logfilename);
423
424
425 /*+++ main cycle +++*/
426
427 do { /* be alive while do_server is 1. do_server is turned off by SIGINT */
428
429 /* make a record for thread accounting */
430 TA_add(listening_socket, "update");
431 TA_setactivity("waiting");
432
433
434 /* accept connection */
435 connected_socket = SK_accept_connection(listening_socket);
436 if(connected_socket==-1) break;
437
438
439 /* make a record for thread accounting */
440 TA_delete(); /* Delete 'waiting' record */
441 TA_add(connected_socket, "update");
442
443 file=fdopen(connected_socket, "r");
444 file_ack=fdopen(connected_socket, "w");
445
446 do_update=CO_get_do_update();
447 if(do_update) {
448
449 TA_setactivity("suspended");
450
451 fprintf(stderr, "Connection accepted...\n");
452
453 if ((file==NULL) || (file_ack==NULL)) {
454 fprintf(stderr, "Cannot open data stream. Closing connction\n");
455 return;
456 }
457 fprintf(stderr, "Connection accepted...\n");
458
459 ud_stream.stream=file;
460 ud_stream.log.num_ok=0;
461 ud_stream.log.num_failed=0;
462
463
464 fprintf(stderr, "starting processing object\n");
465
466 num_ok=UD_process_stream(&ud_stream);
467
468 fprintf(stderr, "processing object finished\n");
469
470 if(num_ok==1) {
471 fprintf(file_ack, "%%ERROR 0\n");
472 fprintf(stderr, "%%ERROR 0\n");
473 }
474 else {
475 num_ok=(-1)*num_ok;
476 fprintf(file_ack, "%%ERROR %d\n",num_ok);
477 fprintf(stderr, "%%ERROR %d\n",num_ok);
478 fprintf(file_ack, "Transaction had the following problems:\n");
479 if(num_ok & ERROR_U_MEM) fprintf(file_ack, "Memory allocation error\n");
480 /* if(num_ok & ERROR_U_DBS) fprintf(file_ack, "Database (SQL) error\n");*/
481 /* if(num_ok & ERROR_U_OBJ) fprintf(file_ack, "Object (RF) error\n");*/
482 /* if(num_ok & ERROR_U_AUT) fprintf(file_ack, "Object authentication error\n");*/
483 if(num_ok & ERROR_U_BADOP) fprintf(file_ack, "Bad operation\n");
484 if(num_ok & ERROR_U_COP) fprintf(file_ack, "Conflicting operation\n");
485 if(num_ok & ERROR_U_NSUP) fprintf(file_ack, "Object of this type is not supported\n");
486 if(num_ok & ERROR_U_BUG) fprintf(file_ack, "Software bug - report to <ripe-dbm@ripe.net>\n");
487 }
488 if(ud_stream.error_script)fprintf(file_ack, "%s\n", ud_stream.error_script);
489
490 if(ud_stream.error_script) free(ud_stream.error_script);
491
492 fflush(file_ack); fclose(file_ack);
493 fclose(file);
494 } /* if do_update*/
495 else { /* Otherwise print a message*/
496 /* To display with 'show threads' */
497 TA_setactivity("suspended");
498
499 fprintf(file_ack, "%%ERROR 1000\n%%Updates are suspended\n");
500 fflush(file_ack); fclose(file_ack);
501 fclose(file);
502 }
503 /* make a record for thread accounting */
504 TA_delete();
505
506 do_server=CO_get_do_server();
507
508 } while (do_server); /* main cycle */
509
510 fclose(ud_stream.log.logfile);
511 /* That's all. Close connection to the DB */
512 SQ_close_connection(ud_stream.db_connection);
513
514
515 fprintf(stderr, "server stopped\n");
516
517 } /* UD_do_update() */
518
519
520
521