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. SV_sleep
  7. SV_signal_thread
  8. SV_do_child
  9. main_loop
  10. SV_concurrent_server
  11. SV_start
  12. SV_shutdown

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

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