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