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

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