modules/sv/server.c

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

FUNCTIONS

This source file includes following functions.
  1. log_print
  2. radix_init
  3. main_loop
  4. SV_start
  5. SV_shutdown
  6. SV_sleep
  7. SV_signal_thread
  8. SV_concurrent_server
  9. SV_do_whois
  10. SV_do_mirror
  11. SV_do_config
  12. SV_watchdog
  13. do_watchdog

   1 /***************************************
   2   $Revision: 1.44 $
   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 
  10   +html+ <DL COMPACT>
  11   +html+ <DT>Online References:
  12   +html+ <DD><UL>
  13   +html+   <LI>Based on <A HREF="http://iii.ripe.net/dbase/coding/new.code/progress/ottrey/code/java/src/DBServer.java">DBServer.java</A>
  14   +html+ </UL>
  15   +html+ </DL>
  16  
  17   ******************/ /******************
  18   Modification History:
  19         ottrey (02/03/1999) Created.
  20         ottrey (08/03/1999) Modified.
  21         joao   (22/06/1999) Modified.
  22   ******************/ /******************
  23   Copyright (c) 1999                              RIPE NCC
  24  
  25   All Rights Reserved
  26   
  27   Permission to use, copy, modify, and distribute this software and its
  28   documentation for any purpose and without fee is hereby granted,
  29   provided that the above copyright notice appear in all copies and that
  30   both that copyright notice and this permission notice appear in
  31   supporting documentation, and that the name of the author not be
  32   used in advertising or publicity pertaining to distribution of the
  33   software without specific, written prior permission.
  34   
  35   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  36   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  37   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  38   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  39   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  40   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  41  ***************************************/
  42 #include <sys/socket.h>
  43 #include <netinet/in.h>
  44 
  45 #include <sys/wait.h>
  46 #include <ctype.h>
  47 
  48 #include <sys/types.h>
  49 #include <sys/stat.h>
  50 
  51 #include "thread.h"
  52 #include "rxroutines.h"
  53 #include "sk.h"
  54 /*
  55 #include "objects.h"
  56 */
  57 #include "constants.h"
  58 
  59 #include "ca_configFns.h"
  60 #include "ca_dictSyms.h"
  61 #include "ca_macros.h"
  62 #include "ca_srcAttribs.h"
  63 
  64 #include "mysql_driver.h"
  65 #include "access_control.h"
  66 #include "ud.h"
  67 #include "server.h"
  68 
  69 #include "rp.h"
  70 #include "memwrap.h"
  71 
  72 #include "ta.h"
  73 
  74 #define RIPE_REG 17
  75 
  76 /*+ String sizes +*/
  77 #define STR_S   63
  78 #define STR_M   255
  79 #define STR_L   1023
  80 #define STR_XL  4095
  81 #define STR_XXL 16383
  82 
  83 
  84 /* Storage for descriptors of the read side of the pipe */
  85 int sv_lockfd[MAX_LOCKS];
  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 /*+ Mutex lock.  Used for synchronizing changes. +*/
  97 pthread_mutex_t   Whois_thread_count_lock;
  98 pthread_mutex_t   Config_thread_count_lock;
  99 pthread_mutex_t   Mirror_thread_count_lock;
 100 
 101 /*+ The number of threads. +*/
 102 int       Whois_thread_count;
 103 int       Config_thread_count;
 104 int       Mirror_thread_count;
 105 
 106 
 107 /*+ Server starting time +*/
 108 time_t SV_starttime;
 109 
 110 /* pthread_mutex_t radix_initializing_lock; */
 111 /* XXX this is a workaround of a problem with mysql - it prevents the
 112 update/nrtm threads from starting before the radix tree is loaded.
 113 
 114 Apparently, even LOCK TABLES doesn't prevent the program from locking up 
 115 */
 116 
 117 static void do_watchdog(void *arg);
 118 
 119 /* Logging results */
 120 static void log_print(const char *arg) {
     /* [<][>][^][v][top][bottom][index][help] */
 121 
 122   printf(arg);
 123 
 124 } /* log_print() */
 125 
 126 
 127 void radix_init(void){
     /* [<][>][^][v][top][bottom][index][help] */
 128   int i;
 129   ca_dbSource_t *source_hdl;
 130 
 131   wr_log_set(0);
 132   /* this needs to be done in two loops, 
 133      because the trees must be created asap (first loop)
 134      and then locked until they are populated in the second loop
 135   */
 136   
 137   for(i=0; (source_hdl = ca_get_SourceHandleByPosition(i))!=NULL ; i++){   
 138     dieif( RP_init_trees( source_hdl ) != RP_OK );
 139   }
 140   
 141   for(i=0; (source_hdl = ca_get_SourceHandleByPosition(i))!=NULL ; i++){   
 142     dieif( RP_sql_load_reg( source_hdl ) != RP_OK ); 
 143   }
 144   
 145   wr_log_set(0); /* switch on/off the memory leak detector */
 146 /*  pthread_mutex_unlock( &radix_initializing_lock );  */
 147   
 148   pthread_exit((void *)0);
 149 }
 150 
 151 /* main_loop() */
 152 /*++++++++++++++++++++++++++++++++++++++
 153 
 154   Waits for an incoming connection on the and spawns a new thread to handle it.
 155 
 156   void *arg Pointer to a struct containing the socket to talk to the client and
 157             the function to call depending on the incoming connection.
 158 
 159   More:
 160   +html+ <PRE>
 161   Author:
 162         ottrey
 163         joao
 164         andrei (do_server)
 165   +html+ </PRE>
 166   ++++++++++++++++++++++++++++++++++++++*/
 167 static void  *main_loop(void *arg) {
     /* [<][>][^][v][top][bottom][index][help] */
 168   th_args *args = (th_args *)arg;
 169   int connected_socket;
 170   int do_server;
 171 
 172   while(do_server=CO_get_do_server()) {
 173 
 174     connected_socket = SK_accept_connection(args->sock);
 175     if(connected_socket==-1) break;
 176 
 177 
 178     ER_dbg_va(FAC_TH, ASP_TH_NEW, "Starting a new thread");
 179 
 180     /* Start a new thread. */
 181 
 182 
 183     TH_create((void *(*)(void *))(args->function), (void *)connected_socket);
 184 //      
 185 //    pthread_attr_init(&attr);    /* initialize attr with default attributes */
 186 //    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 187 //    pthread_create(&tid, &attr, (void *(*)(void *))(args->function), (void *)connected_socket); 
 188   }
 189 
 190    ER_dbg_va(FAC_TH, ASP_TH_NEW, "Exiting from the main loop");
 191 
 192 } /* main_loop() */
 193 
 194 
 195 /* SV_start() */
 196 /*++++++++++++++++++++++++++++++++++++++
 197 
 198   Start the server.
 199 
 200   More:
 201   +html+ <PRE>
 202   Authors:
 203         ottrey
 204         joao
 205   +html+ </PRE>
 206   +html+ Starts up the server.
 207   +html+ <OL>
 208   +html+   <LI> Create sockets on the necessary ports (whois, config and mirror)
 209   +html+   <LI> Start new threads for each service.
 210   +html+ </OL>
 211   +html+ <A HREF=".DBrc">.properties</A>
 212 
 213   ++++++++++++++++++++++++++++++++++++++*/
 214 void SV_start() {
     /* [<][>][^][v][top][bottom][index][help] */
 215   /* Make listening sockets global variables  */
 216   /*  int whois_sock,config_sock,mirror_sock,update_sock; */
 217   /* uint32_t whois_addr,sock_addr,mirror_addr; */
 218   int whois_port = -1;
 219   int config_port = -1;
 220   int mirror_port = -1; 
 221   int update_port = -1;
 222   int update_mode = 0;
 223   sigset_t sset;
 224   int fdes[2];
 225   struct timeval tval;
 226   ca_dbSource_t *source_hdl;
 227   char *source_name;
 228   int source;
 229   char *db_host, *db_name, *db_user, *db_passwd;
 230   int db_port;
 231   SQ_connection_t *db_connection;
 232 
 233   /* Store the starting time */
 234   gettimeofday(&tval, NULL);
 235   SV_starttime = tval.tv_sec;/* seconds since Jan. 1, 1970 */
 236   
 237   /* Create interrupt pipe */
 238   /* Writing to this pipe will cause sleeping threads */
 239   /* to wake up */
 240   fprintf(stderr, "Creating an interrupt pipe\n");
 241   if(pipe(fdes)==-1) {
 242    printf("Cannot open interrupt pipe\n");
 243    exit(-1);
 244   } 
 245   /* Save the pipe descriptors in sv_lock array */
 246   sv_lockfd[WLOCK_SHTDOWN]=fdes[0];
 247   sv_lockfd[LOCK_SHTDOWN]=fdes[1];
 248 
 249   /* Initialise modules */
 250   SK_init();
 251   
 252   /* Initialise the access control list. */
 253   AC_build();
 254   AC_acc_load();
 255   /* explicitly start the decay thread */
 256   TH_create((void *(*)(void *))AC_decay, NULL);
 257 
 258 
 259   
 260   /* Get port information for each service */
 261   whois_port  = htons(ca_get_svwhois_port);
 262   ER_dbg_va(FAC_SV, ASP_SV_PORT, "whois port is %d", ca_get_svwhois_port);
 263 
 264   config_port = htons(ca_get_svconfig_port);
 265   ER_dbg_va(FAC_SV, ASP_SV_PORT, "config port is %d", ca_get_svconfig_port);
 266 
 267   mirror_port = htons(ca_get_svmirror_port);
 268   ER_dbg_va(FAC_SV, ASP_SV_PORT, "mirror port is %d", ca_get_svmirror_port);
 269 
 270 
 271   /* 6. Create a socket on the necessary ports/addresses and bind to them. */
 272   /* whois socket */
 273   SV_whois_sock = SK_getsock(SOCK_STREAM, whois_port, INADDR_ANY);
 274 /* Currently binds to INADDR_ANY. Will need to get specific address */
 275 /*  SV_whois_sock = SK_getsock(SOCK_STREAM,whois_port,whois_addr); */
 276   /* config interface socket */
 277   SV_config_sock = SK_getsock(SOCK_STREAM, config_port, INADDR_ANY);
 278   /* nrt socket */
 279   SV_mirror_sock = SK_getsock(SOCK_STREAM,mirror_port,INADDR_ANY);
 280   
 281   /* Check every Database and create sockets */
 282   /* we need first to create and bind all of them */
 283   /* so that in case of failure we do not start any */
 284   /* update thread */
 285   fprintf(stderr, "Check the DB\n");
 286   for(source=0; (source_hdl = ca_get_SourceHandleByPosition(source))!=NULL ; source++){
 287      /* check for crash and recover if needed */
 288      /* make a connection to a database */
 289      db_host = ca_get_srcdbmachine(source_hdl);
 290      db_port = ca_get_srcdbport(source_hdl);
 291      db_name = ca_get_srcdbname(source_hdl);
 292      db_user = ca_get_srcdbuser(source_hdl);
 293      db_passwd = ca_get_srcdbpassword(source_hdl);
 294      db_connection=SQ_get_connection(db_host, db_port, db_name, db_user, db_passwd);
 295      /* now check TR record */
 296      TR_recover(db_connection);
 297      /* free resources */
 298      SQ_close_connection(db_connection);
 299      free(db_host);
 300      free(db_name);
 301      free(db_user);
 302      free(db_passwd);
 303      
 304      update_mode = ca_get_srcmode(source_hdl);
 305      if(IS_UPDATE(update_mode)) {
 306        /* update_port = SK_atoport(CO_get_update_port(), "tcp"); */
 307        update_port = htons(ca_get_srcupdateport(source_hdl)); 
 308        printf("XXX htons(update_port)=%d\n", htons(update_port));
 309        /* XXX ask AMRM to change the name of the function */
 310  
 311        SV_update_sock[source] = SK_getsock(SOCK_STREAM, update_port, INADDR_ANY);
 312      }
 313      else SV_update_sock[source] = 0;
 314   }   
 315   SV_update_sock[source+1]=-1; /* end of socket array */
 316    
 317    /* Initialise the radix tree (separate thread[s])
 318      already can allow socket connections, because the trees will 
 319      be created locked, and will be unlocked when loaded */
 320 
 321 /*   pthread_mutex_lock( &radix_initializing_lock );  */
 322   TH_create((void *(*)(void *))radix_init, NULL);
 323 /*  pthread_mutex_lock( &radix_initializing_lock );  */
 324   
 325  
 326   /* Now.... accept() calls block until they get a connection
 327      so to listen on more than one port we need more
 328      than one thread */
 329 
 330   /* Create master thread for whois threads */
 331    SV_concurrent_server(SV_whois_sock, SV_do_whois);
 332 
 333   /* Create master thread for config threads */
 334    SV_concurrent_server(SV_config_sock, SV_do_config);
 335   /* Create master thread for mirror threads */
 336    SV_concurrent_server(SV_mirror_sock, SV_do_mirror);
 337 
 338 /* Walk through the sources and */
 339 /* run update thread for every source with CANUPD == 'y' */
 340    
 341    for(source=0; (source_hdl = ca_get_SourceHandleByPosition(source))!=NULL ; source++){
 342      update_mode = ca_get_srcmode(source_hdl);
 343      source_name= ca_get_srcname(source_hdl);
 344 
 345      if(IS_UPDATE(update_mode)) { 
 346      /* run RIPupdate thread */
 347        fprintf(stderr,"Source [%s] Mode UPDATE\n", source_name);
 348        TH_create((void *(*)(void *))UD_do_updates, (void *)source); 
 349      }
 350      else if(IS_NRTM_CLNT(update_mode)){
 351        /* start NRTM client */
 352        fprintf(stderr,"Source [%s] Mode NRTM\n", source_name);    
 353        TH_create((void *(*)(void *))UD_do_nrtm, (void *)source);
 354      }
 355      else fprintf(stderr,"Source [%s] Mode STATIC\n", source_name);
 356      free(source_name); /* because ca_* functions return copies */   
 357    }    
 358 
 359   pthread_exit(NULL);
 360 
 361 } /* SV_start() */
 362 
 363 /* SV_shutdown() */
 364 /*++++++++++++++++++++++++++++++++++++++
 365 
 366   Shutdown the server.
 367 
 368   More:
 369   +html+ <PRE>
 370   Authors:
 371         andrei
 372   +html+ </PRE>
 373   +html+ Stops the server.
 374   +html+ <OL>
 375   +html+   <LI> Close listening sockets (whois, config, mirror and updates)
 376   +html+   <LI> Stop all threads by triggering do_server variable.
 377   +html+ </OL>
 378   +html+ <A HREF=".DBrc">.properties</A>
 379 
 380   ++++++++++++++++++++++++++++++++++++++*/
 381 void SV_shutdown() {
     /* [<][>][^][v][top][bottom][index][help] */
 382 char print_buf[STR_M];
 383 int source;
 384  
 385  sprintf(print_buf, "%d", 0);
 386  /* Stop updates */
 387  CO_set_const("UD.do_update", print_buf);
 388  /* Stop all servers */
 389  CO_set_const("SV.do_server", print_buf);
 390  sprintf(print_buf, "Stopping all servers\n");
 391  fprintf(stderr, print_buf);
 392  /*log_print(print_buf); */
 393  strcpy(print_buf, "");
 394  
 395  /* Wake up all sleeping threads */
 396  fprintf(stderr, "Going to wake sleeping threads up\n");
 397  write(sv_lockfd[WLOCK_SHTDOWN], " ", 1); 
 398 
 399  /* CLose all listening sockets, so accept call exits */
 400  close(SV_whois_sock);
 401  close(SV_config_sock);
 402  close(SV_mirror_sock);
 403  for (source=0; SV_update_sock[source]!=-1; source++)
 404          if(SV_update_sock[source]!=0)close(SV_update_sock[source]);
 405  
 406  
 407 } /* SV_shutdown() */
 408 
 409 /************************************************************
 410 *  int SV_sleep()                                           *
 411 *                                                           *
 412 * sleeps till shutdown request comes                        * 
 413 * but at most <delay> seconds                               *
 414 *                                                           *
 415 * Returns:                                                  *
 416 * 1 - timeout                                               *
 417 * 0 - shutdown                                              *
 418 *                                                           *
 419 ************************************************************/
 420 
 421 int SV_sleep(int delay)
     /* [<][>][^][v][top][bottom][index][help] */
 422 {
 423  int do_server;
 424  int elapsed_time=0;
 425 
 426  while((do_server=CO_get_do_server()) && (elapsed_time<delay))
 427  {
 428   sleep(TIME_SLICE);
 429   elapsed_time+=TIME_SLICE;
 430  }
 431  if(elapsed_time<delay)return(1); else return(0);       
 432 }
 433 
 434 /*++++++++++++++++++++++++++++++++++++++
 435 
 436   Handle signals.
 437   
 438   Changes the flags:
 439         do_nrtm
 440         do_update
 441         do_whoisd
 442 
 443   More:
 444   +html+ <PRE>
 445   Author:
 446         andrei
 447   +html+ </PRE>
 448   ++++++++++++++++++++++++++++++++++++++*/
 449 void *SV_signal_thread() {
     /* [<][>][^][v][top][bottom][index][help] */
 450 char print_buf[STR_M];
 451 sigset_t sset;
 452 int sigReceived;
 453 int do_update;
 454 
 455         sigemptyset(&sset);
 456         sigaddset(&sset, SIGTERM);
 457         sigaddset(&sset, SIGINT);
 458         sigaddset(&sset, SIGUSR1);
 459         /* This is a bit confusing, but is needed */
 460         /* For more information on signal handling in */
 461         /* threads see for example "Multithreading Programming */
 462         /* Techniques" by Shashi Prasad, ISBN 0-07-912250-7, pp. 94-101 */
 463         pthread_sigmask(SIG_BLOCK, &sset, NULL);
 464         /*      fprintf(stderr, "Signal handler installed\n");*/
 465 
 466         for(;;)
 467         {
 468          sigwait(&sset, &sigReceived);
 469          sprintf(print_buf, "Signal received [%d]\n", sigReceived);
 470          log_print(print_buf); strcpy(print_buf, "");
 471          /*      fprintf(stderr, "Signal received [%d]\n", sigReceived); */
 472          switch (sigReceived)
 473          {
 474            case SIGINT:
 475            /* SIGINT stops all servers */
 476                 SV_shutdown();
 477                 pthread_exit((void *)0);
 478                 break;
 479                 
 480            case SIGTERM:
 481            /* SIGTERM will switch the updates on and off */
 482                 do_update=CO_get_do_update();
 483                 if(do_update)do_update=0; else do_update=1;     
 484                 sprintf(print_buf, "%d", do_update);
 485                 CO_set_const("UD.do_update", print_buf); 
 486                 if(do_update)
 487                   sprintf(print_buf, "Starting updates\n");
 488                 else   
 489                   sprintf(print_buf, "Stopping updates\n");
 490                 log_print(print_buf); strcpy(print_buf, ""); 
 491                 /*              fprintf(stderr, "Stopping updates (SIGTERM received)\n"); */
 492                 break; 
 493          }       
 494         }
 495 } /* SV_signal_thread() */
 496 
 497 /* SV_concurrent_server() */
 498 /*++++++++++++++++++++++++++++++++++++++
 499 
 500   This is the routine that creates the main threads. 
 501 
 502   int     sock        The socket to connect to.
 503   void *  do_function The function to call for each type of service
 504 
 505   More:
 506   +html+ <PRE>
 507   Author:
 508         ottrey
 509         joao
 510   +html+ </PRE>
 511   ++++++++++++++++++++++++++++++++++++++*/
 512 void SV_concurrent_server(int sock, void *do_function(void *)) {
     /* [<][>][^][v][top][bottom][index][help] */
 513   th_args *args;
 514   pthread_t tid;
 515   pthread_attr_t attr;
 516 
 517   dieif( wr_calloc((void **)&args,1,sizeof(th_args)) != UT_OK);  
 518 
 519   args->function=(void *)do_function;
 520   args->sock=sock;
 521 
 522 /*  pthread_mutex_init(&Whois_thread_count_lock,NULL); */
 523 
 524   /* Start a new thread. */
 525 
 526   TH_create(main_loop, (void *)args);
 527 
 528   
 529     /* Start a new thread. */
 530 //  pthread_attr_init(&attr);     /* initialize attr with default attributes */
 531 //  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 532 //  pthread_create(&tid, &attr, main_thread, (void *)args);
 533 
 534 } /* TH_run() */
 535 
 536 /* SV_do_whois() */
 537 /*++++++++++++++++++++++++++++++++++++++
 538 
 539   Handle whois connections.
 540 
 541   void *arg The socket to connect to. (It has to be passed in this way for this thread routine.)
 542 
 543   More:
 544   +html+ <PRE>
 545   Author:
 546         joao
 547   +html+ </PRE>
 548   ++++++++++++++++++++++++++++++++++++++*/
 549 void *SV_do_whois(void *arg) { 
     /* [<][>][^][v][top][bottom][index][help] */
 550   int sock = (int)arg;
 551 
 552   ER_dbg_va(FAC_TH, ASP_TH_NEW,
 553             "Whois: Child thread [%d]: Socket number = %d", 
 554             pthread_self(), sock);
 555 
 556   /* Use a mutex to update the global whois thread counter. */
 557   pthread_mutex_lock(&Whois_thread_count_lock);
 558   Whois_thread_count++;
 559   ER_dbg_va(FAC_TH, ASP_TH_NEW, 
 560             "Whois_thread_count++=%d", Whois_thread_count); 
 561   
 562   pthread_mutex_unlock(&Whois_thread_count_lock);
 563 
 564   TA_add(sock, "whois");
 565   PW_interact(sock);
 566   close(sock);
 567   TA_delete();
 568 
 569   /* Use a mutex to update the global whois thread counter. */
 570   pthread_mutex_lock(&Whois_thread_count_lock);
 571   Whois_thread_count--;
 572   ER_dbg_va(FAC_TH, ASP_TH_NEW, 
 573             "Whois_thread_count--=%d", Whois_thread_count); 
 574   pthread_mutex_unlock(&Whois_thread_count_lock);
 575 
 576   pthread_exit((void *)0);
 577 
 578 } /* SV_do_whois() */
 579 
 580 /* SV_do_mirror() */
 581 /*++++++++++++++++++++++++++++++++++++++
 582 
 583   Handle NRTM connections.
 584 
 585   void *arg The socket to connect to. (It has to be passed in this way for this thread routine.)
 586 
 587   More:
 588   +html+ <PRE>
 589   Author:
 590         joao
 591   +html+ </PRE>
 592   ++++++++++++++++++++++++++++++++++++++*/
 593 void *SV_do_mirror(void *arg) { 
     /* [<][>][^][v][top][bottom][index][help] */
 594   int sock = (int)arg;
 595   char print_buf[STR_M];
 596 
 597   sprintf(print_buf, "NRTM: Child thread [%d]: Socket number = %d\n", pthread_self(), sock); log_print(print_buf); strcpy(print_buf, "");
 598 
 599   /* Use a mutex to update the global mirror thread counter. */
 600   pthread_mutex_lock(&Mirror_thread_count_lock);
 601   Mirror_thread_count++;
 602   sprintf(print_buf, "Mirror_thread_count++=%d\n", Mirror_thread_count); log_print(print_buf); strcpy(print_buf, "");
 603   pthread_mutex_unlock(&Mirror_thread_count_lock);
 604 
 605   TA_add(sock, "mirror");
 606   PM_interact(sock);
 607   TA_delete();
 608 
 609   /* Use a mutex to update the global mirror thread counter. */
 610   pthread_mutex_lock(&Mirror_thread_count_lock);
 611   Mirror_thread_count--;
 612   sprintf(print_buf, "Mirror_thread_count--=%d\n", Mirror_thread_count); log_print(print_buf); strcpy(print_buf, "");
 613   pthread_mutex_unlock(&Mirror_thread_count_lock);
 614 
 615   pthread_exit((void *)0);
 616 
 617 } /* SV_do_mirror() */
 618 
 619 /* SV_do_config() */
 620 /*++++++++++++++++++++++++++++++++++++++
 621 
 622   Handle config connections.
 623 
 624   void *arg The socket to connect to. (It has to be passed in this way for this
 625 thread routine.)
 626 
 627   More:
 628   +html+ <PRE>
 629   Author:
 630         joao
 631   +html+ </PRE>
 632   ++++++++++++++++++++++++++++++++++++++*/
 633 void *SV_do_config(void *arg) {
     /* [<][>][^][v][top][bottom][index][help] */
 634   int sock = (int)arg;
 635   char print_buf[STR_M];
 636 
 637   sprintf(print_buf, "Config: Child thread [%d]: Socket number = %d\n", pthread_self(), sock); log_print(print_buf); strcpy(print_buf, "");
 638 
 639 /*
 640   printf("Hi there, there is nothing to configure yet\nBye..... :-)\n");
 641   fflush(NULL);
 642 
 643   SK_close(sock);
 644 */
 645   TA_add(sock, "config");
 646   PC_interact(sock);
 647   TA_delete();
 648 
 649   pthread_exit((void *)0);
 650 
 651 } /* SV_do_config() */
 652 
 653 
 654 /*++++++++++++++++++++++++++++++++++++++
 655 
 656   This is the routine that creates a watchdog thread. 
 657   
 658   The watchdog will cancel (pthread_cancel()) the calling thread in case the
 659   socket is closed by the client (its read-half is closed). The calling
 660   thread should make necessaruy preparations when calling the watchdog:
 661   
 662   - the socket should be connected
 663   - cancellation points and cleanup routines should be defined
 664   
 665   In case the connection is closed by the calling thread itself, the
 666   watchdog just exits and no action against the calling thread is performed.
 667 
 668   wd_args - a pointer to wd_args_t structure containing
 669             data about socket and thread ID
 670   
 671   More:
 672   +html+ <PRE>
 673   Author:
 674         ottrey
 675         joao
 676         andrei
 677   +html+ </PRE>
 678   ++++++++++++++++++++++++++++++++++++++*/
 679 
 680 void SV_watchdog(wd_args_t *wd_args) {
     /* [<][>][^][v][top][bottom][index][help] */
 681  pthread_t tid;
 682  pthread_attr_t attr;
 683  
 684  /* Start a new thread. */
 685  TH_create((void *(*)(void *))do_watchdog, (void *)wd_args);
 686  
 687 // pthread_attr_init(&attr);     /* initialize attr with default attributes */
 688 // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 689 // pthread_create(&tid, &attr, (void *(*)(void *))do_watchdog, (void *)wd_args);
 690 
 691 }
 692 
 693 
 694 /*++++++++++++++++++++++++++++++++++++++
 695 
 696 The watchdog thread itself
 697 
 698 The watchdog thread makes select() on the connected socket waiting until it
 699 becomes readable. If this happens as a result of some input, it'll simply
 700 dump it. Otherwise, this indicates that the client has closed the
 701 connection. In this case watchdog will cancel (pthread_cancel()) the whois
 702 thread (which in its turn will kill (mysql_kill()) mysql thread as part of
 703 its cleanup routine).
 704 
 705 More:
 706 +html+ <PRE>
 707 Author:
 708       andrei
 709 +html+ </PRE>
 710 ++++++++++++++++++++++++++++++++++++++*/
 711 static void do_watchdog(void *arg) {
     /* [<][>][^][v][top][bottom][index][help] */
 712   wd_args_t *wd_args = (wd_args_t *)arg;
 713   int socket;
 714   pthread_t tid;
 715   int nready;
 716   int n;
 717   fd_set rset;
 718   char buff[STR_S];
 719   
 720   socket = wd_args->connected_socket;
 721   tid = wd_args->tid;
 722   
 723   
 724   FD_ZERO(&rset);
 725   FD_SET(socket, &rset);
 726   
 727   while ((nready=select(socket+1, &rset, NULL, NULL, NULL))!=-1) {
 728    
 729    /* There was some input or client half of connection was closed */
 730    /* Check for the latter */
 731    if (( n=read(socket, buff, sizeof(buff))) == 0) {
 732    /* Connection was closed by client */
 733    /* Now send a cancellation request to the whois thread. */
 734    /* mysql thread will be terminated by thread cleanup routine */
 735    
 736    /* The only possible error is ESRCH, so we do not care about */
 737    pthread_cancel(tid);
 738    
 739    /* Exit the watchdog thread, passing NULL as we don't expect pthread_join() */
 740    pthread_exit(NULL);
 741    }
 742    
 743    /* Otherwise dump input and continue */
 744   }
 745   
 746   /* the only reason that we are here is that the socket has been */
 747   /* closed by the whois thread and not valid. Just exit the watchdog, */
 748   /* passing NULL as we don't expect pthread_join() */
 749    pthread_exit(NULL);
 750   
 751 }  

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