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

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