## 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.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

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