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

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