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