modules/sv/server.c

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

FUNCTIONS

This source file includes following functions.
  1. log_print
  2. counter_add
  3. counter_state
  4. counter_wait
  5. radix_init
  6. radix_load
  7. SV_sleep
  8. SV_signal_thread
  9. SV_do_child
  10. main_loop
  11. SV_concurrent_server
  12. SV_start
  13. SV_shutdown

   1 /***************************************
   2   $Revision: 1.62 $
   3 
   4   Example code: A server for a client to connect to.
   5 
   6   Status: NOT REVUED, NOT TESTED
   7 
   8   Authors:       Chris Ottrey, Joao Damas,
   9                  heavy rewrite by Andrei Robachevsky, Marek Bukowy 
  10 
  11   +html+ <DL COMPACT>
  12   +html+ <DT>Online References:
  13   +html+ <DD><UL>
  14   +html+   <LI>Based on <A HREF="http://iii.ripe.net/dbase/coding/new.code/progress/ottrey/code/java/src/DBServer.java">DBServer.java</A>
  15   +html+ </UL>
  16   +html+ </DL>
  17  
  18   ******************/ /******************
  19   Modification History:
  20         ottrey (02/03/1999) Created.
  21         ottrey (08/03/1999) Modified.
  22         joao   (22/06/1999) Modified.
  23   ******************/ /******************
  24   Copyright (c) 1999,2000,2001,2002                  RIPE NCC
  25  
  26   All Rights Reserved
  27   
  28   Permission to use, copy, modify, and distribute this software and its
  29   documentation for any purpose and without fee is hereby granted,
  30   provided that the above copyright notice appear in all copies and that
  31   both that copyright notice and this permission notice appear in
  32   supporting documentation, and that the name of the author not be
  33   used in advertising or publicity pertaining to distribution of the
  34   software without specific, written prior permission.
  35   
  36   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  37   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  38   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  39   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  40   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  41   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  42  ***************************************/
  43 
  44 #include "rip.h"
  45 
  46 #include <ctype.h>
  47 
  48 #include <sys/types.h>
  49 #include <sys/stat.h>
  50 #include <sys/wait.h>
  51 #include <sys/socket.h>
  52 #include <netinet/in.h>
  53 #include <errno.h>
  54 #include <unistd.h>
  55 #include <string.h>
  56 #include <sys/poll.h>
  57 
  58 /* Listening sockets */
  59 int SV_whois_sock;
  60 int SV_config_sock;
  61 int SV_mirror_sock;
  62 
  63 /* each updatable source has its own update thread and its own socket */
  64 #define MAX_SOURCES 100
  65 int SV_update_sock[MAX_SOURCES];
  66 
  67 /* when the process shuts down, it writes to this file descriptor */
  68 int SV_shutdown_send_fd = -1;
  69 
  70 /* server threads should check this file descriptor, and terminate 
  71    as soon as possible if data becomes available on it */
  72 int SV_shutdown_recv_fd = -1;
  73 
  74 /*+ Server starting time +*/
  75 time_t SV_starttime;
  76 /* the filename where we store the PID of the server */
  77 char *SV_pidfile;
  78 
  79 /* Logging results */
  80 static void log_print(const char *arg) {
     /* [<][>][^][v][top][bottom][index][help] */
  81 
  82   printf(arg);
  83 
  84 } /* log_print() */
  85 
  86 
  87 /* counters - by marek */
  88 typedef struct {
  89   int count;
  90   pthread_mutex_t lock; /*+ Mutex lock.Used for synchronizing changes.+*/
  91   pthread_cond_t  cond; /*+ condition variable +*/
  92 } svr_counter_t;
  93 
  94 
  95 /* structure passed to every running server */
  96 typedef struct {
  97   void (*function)(int);    
  98   int conn_sock;
  99   int accept_sock;
 100   int limit;         /* limit for the number of concurrent connections */
 101   svr_counter_t *counter; /* number of active clients */
 102   char *name;
 103 } svr_args;
 104          
 105 
 106 /*++++++++++++++++++++++++++++++++++++++
 107   function to operate on the counter structures -  
 108   takes the increment (can be negative), changes the value
 109   using the locks and everything,  
 110 
 111   int
 112   counter_add            returns the new value.
 113 
 114   svr_counter_t *cst     counter structure
 115   
 116   int incval             increment value (can be negative)
 117 
 118   Author:
 119     marek
 120   ++++++++++++++++++++++++++++++++++++++*/
 121 static
 122 int
 123 counter_add( svr_counter_t *cst, int incval )
     /* [<][>][^][v][top][bottom][index][help] */
 124 {
 125     int newval;
 126     
 127     /* add under mutex */
 128     pthread_mutex_lock( &(cst->lock) );
 129     cst->count += incval;
 130     newval = cst->count;
 131     pthread_mutex_unlock(&(cst->lock) );
 132     
 133     /* now - signal the change of value to the waiting thread */
 134     pthread_cond_signal( &(cst->cond) );
 135 
 136     return newval;
 137 }
 138 
 139 
 140 /*++++++++++++++++++++++++++++++++++++++
 141  
 142   int 
 143   counter_state         returns the current value of a counter
 144   
 145   svr_counter_t *cst    counter
 146 
 147   Author:
 148     marek
 149 
 150   ++++++++++++++++++++++++++++++++++++++*/
 151 static 
 152 int 
 153 counter_state( svr_counter_t *cst ) 
     /* [<][>][^][v][top][bottom][index][help] */
 154 {
 155   return counter_add( cst, 0 );
 156 }
 157 
 158 
 159 /*++++++++++++++++++++++++++++++++++++++
 160   waits until the counter is in the range [0-limit].
 161   unless the limit is 0, in which case the check is disabled.
 162 
 163   int counter_wait      returns the new value of the counter after wait
 164 
 165   svr_counter_t *cst    counter
 166 
 167   int limit             limit / range, or 0 to disable the check
 168 
 169   Author:
 170     marek
 171   ++++++++++++++++++++++++++++++++++++++*/
 172 static
 173 int counter_wait(svr_counter_t *cst, int limit )
     /* [<][>][^][v][top][bottom][index][help] */
 174 { 
 175   int newval;
 176   
 177   pthread_mutex_lock( &(cst->lock) );
 178   
 179   if( limit != 0 ) {
 180     while( cst->count >= limit ) {
 181       pthread_cond_wait( &(cst->cond), &(cst->lock));
 182     }
 183   }
 184   
 185   newval = cst->count;
 186   pthread_mutex_unlock(&(cst->lock) );
 187   
 188   return newval;
 189 }
 190 
 191 /*++++++++++++++++++++++++++++++++++++++
 192 
 193   Initialize the radix tree - all trees are added to the forest in
 194   a locked state.  As each tree finishes loading (from radix_load()),
 195   it is unlocked.
 196 
 197   ++++++++++++++++++++++++++++++++++++++*/
 198 static void 
 199 radix_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 200 {
 201     int i;
 202     ca_dbSource_t *source_hdl;
 203 
 204     TH_init_read_write_lockw(&rx_forest_rwlock);
 205     for(i=0; (source_hdl = ca_get_SourceHandleByPosition(i))!=NULL ; i++){   
 206         dieif( RP_init_trees( source_hdl ) != RP_OK );
 207     }
 208 }
 209 
 210 /*++++++++++++++++++++++++++++++++++++++
 211 
 212   Load the radix tree - all trees are initialized from the appropriate
 213   SQL tables.  As each tree finishes loading (from radix_load()), it is
 214   unlocked.  They must be created by the radix_init() function.
 215 
 216   ++++++++++++++++++++++++++++++++++++++*/
 217 static void
 218 radix_load(void)
     /* [<][>][^][v][top][bottom][index][help] */
 219 {
 220     int i;
 221     ca_dbSource_t *source_hdl;
 222 
 223     for(i=0; (source_hdl = ca_get_SourceHandleByPosition(i))!=NULL ; i++){   
 224         dieif( RP_sql_load_reg( source_hdl ) != RP_OK ); 
 225     }
 226 }
 227 
 228 
 229 /************************************************************
 230 *  int SV_sleep()                                           *
 231 *                                                           *
 232 * sleeps till shutdown request comes                        * 
 233 * but at most <delay> seconds                               *
 234 *                                                           *
 235 * Returns:                                                  *
 236 * 0 - timeout                                               *
 237 * 1 - shutdown                                              *
 238 *                                                           *
 239 ************************************************************/
 240 
 241 int SV_sleep(int delay)
     /* [<][>][^][v][top][bottom][index][help] */
 242 {
 243  int do_server;
 244  int elapsed_time=0;
 245 
 246  while((do_server=CO_get_do_server()) && (elapsed_time<delay))
 247  {
 248   sleep(TIME_SLICE);
 249   elapsed_time+=TIME_SLICE;
 250  }
 251  if(do_server)return(0); else return(1);        
 252 }
 253 
 254 /*++++++++++++++++++++++++++++++++++++++
 255 
 256   Handle signals.
 257   
 258   Changes the flags:
 259         do_nrtm
 260         do_update
 261         do_whoisd
 262 
 263   More:
 264   +html+ <PRE>
 265   Author:
 266         andrei
 267   +html+ </PRE>
 268   ++++++++++++++++++++++++++++++++++++++*/
 269 void *SV_signal_thread() {
     /* [<][>][^][v][top][bottom][index][help] */
 270 char print_buf[STR_M];
 271 sigset_t sset;
 272 int sigReceived;
 273 int do_update;
 274 
 275         sigemptyset(&sset);
 276         /* SIGTERM and SIGINT are used to shutdown the server */
 277         /* SIGUSR1 is used to pause/resume updates - rarely used as we have PC command */
 278         sigaddset(&sset, SIGTERM);
 279         sigaddset(&sset, SIGINT);
 280         sigaddset(&sset, SIGUSR1);
 281         /* This is a bit confusing, but is needed */
 282         /* For more information on signal handling in */
 283         /* threads see for example "Multithreading Programming */
 284         /* Techniques" by Shashi Prasad, ISBN 0-07-912250-7, pp. 94-101 */
 285         
 286         /* XXX If one needs to handle more signals, don't forget to */
 287         /* block them in other threads in install_signal_handler() in whois_rip.c */
 288         pthread_sigmask(SIG_BLOCK, &sset, NULL);
 289 
 290         for(;;)
 291         {
 292 #ifdef HAVE_THR_SIGWAIT
 293          _thr_sigwait(&sset, &sigReceived);
 294 #else
 295          sigwait(&sset, &sigReceived);
 296 #endif
 297          sprintf(print_buf, "Signal received [%d]\n", sigReceived);
 298          log_print(print_buf); strcpy(print_buf, "");
 299          /*      fprintf(stderr, "Signal received [%d]\n", sigReceived); */
 300          switch (sigReceived)
 301          {
 302            case SIGINT:
 303            case SIGTERM:
 304            /* SIGINT and SIGTERM stop all servers */
 305                 SV_shutdown();
 306                 pthread_exit((void *)0);
 307                 break;
 308                 
 309            case SIGUSR1:
 310            /* SIGUSR1 will switch the updates on and off */
 311                 do_update=CO_get_do_update();
 312                 if(do_update)do_update=0; else do_update=1;     
 313                 sprintf(print_buf, "%d", do_update);
 314                 CO_set_const("UD.do_update", print_buf); 
 315                 if(do_update)
 316                   sprintf(print_buf, "Starting updates\n");
 317                 else   
 318                   sprintf(print_buf, "Stopping updates\n");
 319                 log_print(print_buf); strcpy(print_buf, ""); 
 320                 /*              fprintf(stderr, "Stopping updates (SIGTERM received)\n"); */
 321                 break; 
 322          }       
 323         }
 324 } /* SV_signal_thread() */
 325 
 326 
 327 /* SV_do_child() */
 328 /*++++++++++++++++++++++++++++++++++++++
 329   
 330   Handle whois/config/mirror connections. Takes a pointer to the
 331   service description structure, containing a connected socket, limit
 332   of active threads, pointer to the counter of them. Does not stop to
 333   obey the limits, assumes this to be checked and assumes that it is
 334   already counted.  Decrements the counter on exit.
 335 
 336   Precondition: the counter must be incremented before this function is called.
 337 
 338   void *SV_do_child     Actually, does not return anything useful. Just NULL.
 339 
 340   void *varg            service description structure.
 341 
 342   Author:
 343     marek
 344   ++++++++++++++++++++++++++++++++++++++*/
 345 void *SV_do_child(void *varg)
     /* [<][>][^][v][top][bottom][index][help] */
 346 {
 347   svr_args *args = (svr_args *) varg;
 348   int sock = args->conn_sock;
 349   int curclients;
 350 
 351   ER_dbg_va(FAC_TH, ASP_TH_NEW,
 352             ": Child thread [%d]: Socket number = %d", 
 353             args->name, pthread_self(), sock);
 354 
 355   curclients = counter_state( args->counter ); /* already added */
 356   ER_dbg_va(FAC_TH, ASP_TH_NEW, 
 357             "%s threads++ = %d", args->name, curclients); 
 358 
 359   TA_add(sock, args->name);
 360 
 361   args->function(sock);
 362 
 363   /* TA_delete must come first - otherwise the server would crash
 364      when trying to report address of a closed socket */
 365   TA_delete();
 366   close(sock);
 367 
 368   /* update the global thread counter. */
 369   curclients = counter_add( args->counter, -1);
 370   ER_dbg_va(FAC_TH, ASP_TH_NEW, 
 371             "%s threads-- = %d", args->name, curclients); 
 372 
 373   UT_free(args);
 374 
 375   return NULL; /* exit the thread */
 376 } /* SV_do_child */
 377 
 378 
 379 /* main_loop() */
 380 /*++++++++++++++++++++++++++++++++++++++
 381 
 382   Waits for an incoming connection on the and spawns a new thread to
 383   handle it.  Takes a pointer to the service description structure
 384   containing the number of the listening socket, limit of active
 385   threads, pointer to the counter of them, and the function to call
 386   with a connected socket.  Increments the counter before starting 
 387   a client thread to run SV_do_child(). 
 388 
 389   void *arg      pointer to the service description structure.
 390 
 391   More:
 392   +html+ <PRE>
 393   Author:
 394         ottrey
 395         joao
 396         andrei (do_server)
 397         marek (rewritten/simplified/added limits)
 398   +html+ </PRE>
 399   ++++++++++++++++++++++++++++++++++++++*/
 400 static void  *main_loop(void *arg) {
     /* [<][>][^][v][top][bottom][index][help] */
 401   svr_args *argset = (svr_args *)arg;
 402   svr_args *argcopy;
 403   char loopname[32];
 404   int children;
 405   char chnum[16];
 406   struct pollfd pfd[2];
 407 
 408   snprintf(loopname, 32, "s-%s", argset->name);
 409 
 410   TA_add(0, loopname);
 411 
 412   pfd[0].fd = argset->accept_sock;
 413   pfd[0].events = POLLIN;
 414   pfd[1].fd = SV_shutdown_recv_fd;
 415   pfd[1].events = POLLIN;
 416   
 417   while( CO_get_do_server() != 0 ) {
 418     /* check the number of clients, do not proceed until it's below limit */
 419     children = counter_wait( argset->counter, argset->limit );
 420     snprintf(chnum, 16, "%d", children);
 421     TA_setactivity(chnum); /* display the current number of children */
 422 
 423     /* check for input */
 424     if (poll(pfd, 2, -1) == -1) {
 425         ER_perror(FAC_SV, 1, "%s got error %d on poll; %s", argset->name,
 426                   errno, strerror(errno));
 427         continue;
 428     }
 429 
 430     /* see if we're shutting down */
 431     if (pfd[1].revents != 0) break;
 432     
 433     /* wait for new connections */
 434     argset->conn_sock = SK_accept_connection(argset->accept_sock);
 435     if(argset->conn_sock == -1) {
 436       break;
 437     }
 438     
 439     ER_dbg_va(FAC_TH, ASP_TH_NEW, "%s: starting a new child thread", 
 440               loopname);
 441     TA_increment();
 442     /* incrementing argset->counter here - to avoid race condition and 
 443        ensure a _more_correct_ value of current clients also for unlimited 
 444        or infrequent connections. Does not really matter otherwise.
 445 
 446        NOTE: this architecture implies that higher values can be 
 447        displayed for infrequent threads, because there's no way 
 448        to change it when threads are exiting while this thread is 
 449        blocked in call to accept(). If this call was in the child thread,
 450        the number would be an underestimation instead. I prefer over-e.
 451     */
 452     counter_add( argset->counter, 1);
 453 
 454     /* Start a new thread. will decrement counter when exiting */
 455 
 456     /* now. There's a race condition - argset must be copied in SV_do_child
 457        and can be reused here only afterwards. To avoid it, we make a copy 
 458        and expect SV_do_child to free it after use. 
 459        Caveat: the counter remains where it was, we just copy the pointer.
 460     */
 461     argcopy = UT_malloc( sizeof(svr_args) );
 462     memcpy( argcopy, argset, sizeof(svr_args) );
 463     TH_create( SV_do_child, (void *)argcopy );
 464   } 
 465 
 466   TA_delete();
 467   ER_dbg_va(FAC_TH, ASP_TH_NEW, "Exiting from the main loop");
 468 
 469   return NULL;
 470 } /* main_loop() */
 471 
 472 /* SV_concurrent_server() */
 473 /*++++++++++++++++++++++++++++++++++++++
 474 
 475   This is the routine that creates the main threads. 
 476 
 477   int     sock        The socket to connect to.
 478 
 479   int     limit       Limit of active clients (0 == no limit)
 480 
 481   void *  do_function The function to call for each type of service
 482 
 483   More:
 484   +html+ <PRE>
 485   Author:
 486         ottrey
 487         joao
 488         marek
 489   +html+ </PRE>
 490   ++++++++++++++++++++++++++++++++++++++*/
 491 static
 492 void SV_concurrent_server(int sock, int limit,  char *name,
     /* [<][>][^][v][top][bottom][index][help] */
 493                           void do_function(int)) 
 494 {
 495   svr_args *args;
 496   
 497   args = (svr_args *)UT_calloc(1, sizeof(svr_args));
 498 
 499   args->accept_sock=sock;
 500   args->limit=limit;
 501   args->name=name;
 502   args->function=do_function;
 503   args->counter = (svr_counter_t *)UT_calloc(1, sizeof(svr_counter_t));
 504 
 505   pthread_mutex_init( &(args->counter->lock), NULL );
 506   pthread_cond_init(  &(args->counter->cond), NULL );
 507   args->counter->count = 0;
 508 
 509 
 510   /* Start a new thread. */
 511 
 512   TH_create(main_loop, (void *)args);
 513 
 514 } /* SV_concurrent_server() */
 515 
 516 /* SV_start() */
 517 /*++++++++++++++++++++++++++++++++++++++
 518 
 519   Start the server.
 520 
 521   More:
 522   +html+ <PRE>
 523   Authors:
 524         ottrey
 525         joao
 526   +html+ </PRE>
 527   +html+ Starts up the server.
 528   +html+ <OL>
 529   +html+   <LI> Create sockets on the necessary ports (whois, config and mirror)
 530   +html+   <LI> Start new threads for each service.
 531   +html+ </OL>
 532   +html+ <A HREF=".DBrc">.properties</A>
 533 
 534   ++++++++++++++++++++++++++++++++++++++*/
 535 int SV_start(char *pidfile) {
     /* [<][>][^][v][top][bottom][index][help] */
 536   int whois_port = -1;
 537   int config_port = -1;
 538   int mirror_port = -1; 
 539   int update_port = -1;
 540   int update_mode = 0;
 541   int pid_fd;
 542   int nwrite;
 543   struct timeval tval;
 544   char starttime[128];
 545   char server_pid[16];
 546   ca_dbSource_t *source_hdl;
 547   char *source_name;
 548   int source;
 549   char *db_host, *db_name, *db_user, *db_passwd;
 550   int db_port;
 551   SQ_connection_t *db_connection;
 552   int shutdown_pipe[2];
 553 
 554   /* Store the starting time */
 555   gettimeofday(&tval, NULL);
 556   SV_starttime = tval.tv_sec;/* seconds since Jan. 1, 1970 */
 557 
 558   /* Log the starting time */
 559   ctime_r(&SV_starttime, starttime);
 560   ER_inf_va(FAC_SV, 0xFFFFFF, "Server is started %s", starttime);
 561 
 562   /* Create our shutdown pipe */
 563   if (pipe(shutdown_pipe) != 0) {
 564       ER_perror(FAC_SV, 1, 
 565                 "error %d creating shutdown pipe; %s", errno, strerror(errno));
 566       return(-1); 
 567   }
 568   SV_shutdown_send_fd = shutdown_pipe[1];
 569   SV_shutdown_recv_fd = shutdown_pipe[0];
 570 
 571   /* Store the PID of the process */
 572   SV_pidfile = pidfile;
 573   /* create the file read-writable by the process owner */
 574   if((pid_fd=open(SV_pidfile,  O_CREAT | O_TRUNC | O_WRONLY, 0600))==-1) {
 575       ER_perror(FAC_SV, 1, "cannot open pid file %s", SV_pidfile);     
 576       return(-1);
 577   }
 578   sprintf(server_pid, "%d", (int)getpid()); 
 579   nwrite=write(pid_fd, server_pid, strlen(server_pid) );
 580   close(pid_fd);
 581   if(nwrite != strlen(server_pid)) { 
 582       ER_perror(FAC_SV, 1, "cannot write to pid file %s", SV_pidfile);
 583       return(-1); 
 584   }
 585   
 586   
 587   /* Initialise modules */
 588   SK_init();
 589   PW_init();
 590    
 591   /* Initialise the access control list. */
 592   AC_build();
 593   AC_acc_load();
 594   /* explicitly start the decay thread */
 595   TH_create((void *(*)(void *))AC_decay, NULL);
 596 
 597 
 598   
 599   /* Get port information for each service */
 600   whois_port  = ca_get_svwhois_port;
 601   ER_inf_va(FAC_SV, ASP_SV_PORT, "whois port is %d", whois_port);
 602 /*  ER_dbg_va(FAC_SV, ASP_SV_PORT, "whois port is %d", whois_port); */
 603 
 604   config_port = ca_get_svconfig_port;
 605   ER_inf_va(FAC_SV, ASP_SV_PORT, "config port is %d", config_port);
 606 /*  ER_dbg_va(FAC_SV, ASP_SV_PORT, "config port is %d", config_port); */
 607   
 608 
 609   mirror_port = ca_get_svmirror_port;
 610   ER_inf_va(FAC_SV, ASP_SV_PORT, "mirror port is %d", mirror_port);
 611 /*  ER_dbg_va(FAC_SV, ASP_SV_PORT, "mirror port is %d", mirror_port);*/
 612 
 613 
 614   /* 6. Create a socket on the necessary ports/addresses and bind to them. */
 615   /* whois socket */
 616   SV_whois_sock = SK_getsock(SOCK_STREAM, whois_port, 128, INADDR_ANY);
 617 /* Currently binds to INADDR_ANY. Will need to get specific address */
 618 /*  SV_whois_sock = SK_getsock(SOCK_STREAM,whois_port,whois_addr); */
 619   /* config interface socket */
 620   SV_config_sock = SK_getsock(SOCK_STREAM, config_port, 5, INADDR_ANY);
 621   /* nrt socket */
 622   SV_mirror_sock = SK_getsock(SOCK_STREAM,mirror_port, 128, INADDR_ANY);
 623   
 624   /* Check every Database and create sockets */
 625   /* we need first to create and bind all of them */
 626   /* so that in case of failure we do not start any */
 627   /* update thread */
 628   fprintf(stderr, "Check the DB\n");
 629   for(source=0; (source_hdl = ca_get_SourceHandleByPosition(source))!=NULL ; source++){
 630      /* check for crash and recover if needed */
 631      /* make a connection to a database */
 632      db_host = ca_get_srcdbmachine(source_hdl);
 633      db_port = ca_get_srcdbport(source_hdl);
 634      db_name = ca_get_srcdbname(source_hdl);
 635      db_user = ca_get_srcdbuser(source_hdl);
 636      db_passwd = ca_get_srcdbpassword(source_hdl);
 637      db_connection=SQ_get_connection(db_host, db_port, db_name, db_user, db_passwd);
 638      /* now check TR record */
 639      TR_recover(db_connection);
 640      /* free resources */
 641      SQ_close_connection(db_connection);
 642      UT_free(db_host);
 643      UT_free(db_name);
 644      UT_free(db_user);
 645      UT_free(db_passwd);
 646      
 647      update_mode = ca_get_srcmode(source_hdl);
 648      if(IS_UPDATE(update_mode)) {
 649        /* update_port = SK_atoport(CO_get_update_port(), "tcp"); */
 650        update_port = ca_get_srcupdateport(source_hdl); 
 651        printf("XXX htons(update_port)=%d\n", update_port);
 652        /* XXX ask AMRM to change the name of the function */
 653  
 654        SV_update_sock[source] = SK_getsock(SOCK_STREAM, update_port, 128, INADDR_ANY);
 655      }
 656      else SV_update_sock[source] = 0;
 657   }   
 658   SV_update_sock[source+1]=-1; /* end of socket array */
 659    
 660   /* Initialise the radix trees
 661      already can allow socket connections, because the trees will 
 662      be created locked, and will be unlocked when loaded */
 663   radix_init();
 664  
 665   /* Now.... accept() calls block until they get a connection
 666      so to listen on more than one port we need more
 667      than one thread */
 668 
 669   /* Create master thread for whois threads */
 670   SV_concurrent_server(SV_whois_sock, 64, "whois", PW_interact);
 671   /* Create master thread for config threads */
 672   SV_concurrent_server(SV_config_sock, 0, "config", PC_interact);
 673   /* Create master thread for mirror threads */
 674   SV_concurrent_server(SV_mirror_sock, 0, "mirror", PM_interact);
 675 
 676   /* Load the radix trees - this must be done before the 
 677      updates are allowed to proceed */
 678   radix_load();
 679   
 680   /* Walk through the sources and */
 681   /* run update thread for every source with CANUPD == 'y' */
 682    
 683    for(source=0; (source_hdl = ca_get_SourceHandleByPosition(source))!=NULL ; source++){
 684      update_mode = ca_get_srcmode(source_hdl);
 685      source_name= ca_get_srcname(source_hdl);
 686 
 687      if(IS_UPDATE(update_mode)) { 
 688      /* run RIPupdate thread */
 689        fprintf(stderr,"Source [%s] Mode UPDATE [port=%d]\n", source_name, ca_get_srcupdateport(source_hdl));
 690        ER_inf_va(FAC_SV, 0xFFFFFF, "Source [%s] Mode UPDATE [port=%d]", source_name, ca_get_srcupdateport(source_hdl));
 691        TH_create((void *(*)(void *))UD_do_updates, (void *)source); 
 692      }
 693      else if(IS_NRTM_CLNT(update_mode)){
 694        /* start NRTM client */
 695        fprintf(stderr,"Source [%s] Mode NRTM\n", source_name);    
 696        ER_inf_va(FAC_SV, 0xFFFFFF, "Source [%s] Mode NRTM", source_name);
 697        TH_create((void *(*)(void *))UD_do_nrtm, (void *)source);
 698      }
 699      else {
 700              fprintf(stderr,"Source [%s] Mode STATIC\n", source_name);
 701              ER_inf_va(FAC_SV, 0xFFFFFF, "Source [%s] Mode STATIC", source_name);
 702      }
 703      UT_free(source_name); /* because ca_* functions return copies */   
 704    }    
 705   /* terminate the thread */
 706   /* XXX not return becase then we terminate the whole process */
 707   pthread_exit(NULL);
 708   return(1); /* we will never reach this point */
 709 } /* SV_start() */
 710 
 711 /* SV_shutdown() */
 712 /*++++++++++++++++++++++++++++++++++++++
 713 
 714   Shutdown the server.
 715 
 716   More:
 717   +html+ <PRE>
 718   Authors:
 719         andrei
 720   +html+ </PRE>
 721   +html+ Stops the server.
 722   +html+ <OL>
 723   +html+   <LI> Close listening sockets (whois, config, mirror and updates)
 724   +html+   <LI> Stop all threads by triggering do_server variable.
 725   +html+ </OL>
 726   +html+ <A HREF=".DBrc">.properties</A>
 727 
 728   ++++++++++++++++++++++++++++++++++++++*/
 729 void SV_shutdown() {
     /* [<][>][^][v][top][bottom][index][help] */
 730 char print_buf[STR_M];
 731 int source;
 732 time_t shutdowntime;
 733 struct timeval tval;
 734 char shuttime[100];
 735  
 736  sprintf(print_buf, "%d", 0);
 737  /* Stop updates */
 738  CO_set_const("UD.do_update", print_buf);
 739  /* Stop all servers */
 740  CO_set_const("SV.do_server", print_buf);
 741  sprintf(print_buf, "Stopping all servers\n");
 742  fprintf(stderr, print_buf);
 743  /*log_print(print_buf); */
 744  strcpy(print_buf, "");
 745  
 746  /* wait for all updates to complete */
 747  /* XXX may be changed with blocking interface for stop updates */
 748  sleep(5);
 749  
 750  /* Store the shutdown time */
 751   gettimeofday(&tval, NULL);
 752   shutdowntime = tval.tv_sec;/* seconds since Jan. 1, 1970 */
 753 
 754   /* Log the sshutdown time */
 755   ctime_r(&shutdowntime, shuttime);
 756   ER_inf_va(FAC_SV, 0xFFFFFF, "Server shutdown %s", shuttime);
 757 
 758   
 759     
 760  /* Wake up all sleeping threads */
 761  fprintf(stderr, "Going to wake sleeping threads up\n");
 762 
 763  /* Delete the pid file to indicate normal shutdown */
 764  if(unlink(SV_pidfile)==-1) {
 765       ER_perror(FAC_SV, 1, "cannot delete pid file %s:", SV_pidfile);     
 766  }
 767 
 768  /* write to shutdown pipe */
 769  if (write(SV_shutdown_send_fd, "", 1) != 1) {
 770       ER_perror(FAC_SV, 1, "error %d writing to shutdown pipe; %s", 
 771                 errno, strerror(errno));
 772  }
 773 
 774  
 775 /* don't do this, it's not polite  ;) */
 776 #if 0
 777  /* CLose all listening sockets, so accept call exits */
 778  close(SV_whois_sock);
 779  close(SV_config_sock);
 780  close(SV_mirror_sock);
 781  for (source=0; SV_update_sock[source]!=-1; source++)
 782          if(SV_update_sock[source]!=0)close(SV_update_sock[source]);
 783 #endif /* 0 */ 
 784  
 785 } /* SV_shutdown() */

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