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

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