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] */