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