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