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

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