## modules/ud/ud_main.c

/* [<][>][^][v][top][bottom][index][help] */

## FUNCTIONS

This source file includes following functions.

1. get_NRTM_fd
2. UD_do_nrtm
3. 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

/* [<][>][^][v][top][bottom][index][help] */