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.37 $
   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 "socket.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 #if 0
 146   {
 147       er_path_t erlogstr;
 148       
 149       erlogstr.fdes = stdout;
 150       erlogstr.asp  = 0xfffff000;
 151       erlogstr.fac  = 0; /* FAC_SQ; */
 152       erlogstr.sev  = ER_SEV_D;
 153       erlogstr.mode = ER_M_SEVCHAR | ER_M_FACSYMB | ER_M_TEXTLONG;
 154       
 155       ER_setpath(& erlogstr);  
 156   }
 157 #endif
 158   wr_log_set(0); /* switch on/off the memory leak detector */
 159 /*  pthread_mutex_unlock( &radix_initializing_lock );  */
 160   
 161   pthread_exit((void *)0);
 162 }
 163 
 164 /* main_loop() */
 165 /*++++++++++++++++++++++++++++++++++++++
 166 
 167   Waits for an incoming connection on the and spawns a new thread to handle it.
 168 
 169   void *arg Pointer to a struct containing the socket to talk to the client and
 170             the function to call depending on the incoming connection.
 171 
 172   More:
 173   +html+ <PRE>
 174   Author:
 175         ottrey
 176         joao
 177         andrei (do_server)
 178   +html+ </PRE>
 179   ++++++++++++++++++++++++++++++++++++++*/
 180 static void  *main_loop(void *arg) {
     /* [<][>][^][v][top][bottom][index][help] */
 181   th_args *args = (th_args *)arg;
 182   int connected_socket;
 183   int do_server;
 184 
 185   while(do_server=CO_get_do_server()) {
 186 
 187     connected_socket = SK_accept_connection(args->sock);
 188     if(connected_socket==-1) break;
 189 
 190 
 191     ER_dbg_va(FAC_TH, ASP_TH_NEW, "Starting a new thread");
 192 
 193     /* Start a new thread. */
 194 
 195 
 196     TH_create((void *(*)(void *))(args->function), (void *)connected_socket);
 197 //      
 198 //    pthread_attr_init(&attr);    /* initialize attr with default attributes */
 199 //    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 200 //    pthread_create(&tid, &attr, (void *(*)(void *))(args->function), (void *)connected_socket); 
 201   }
 202 
 203    ER_dbg_va(FAC_TH, ASP_TH_NEW, "Exiting from the main loop");
 204 
 205 } /* main_loop() */
 206 
 207 
 208 /* SV_start() */
 209 /*++++++++++++++++++++++++++++++++++++++
 210 
 211   Start the server.
 212 
 213   More:
 214   +html+ <PRE>
 215   Authors:
 216         ottrey
 217         joao
 218   +html+ </PRE>
 219   +html+ Starts up the server.
 220   +html+ <OL>
 221   +html+   <LI> Create sockets on the necessary ports (whois, config and mirror)
 222   +html+   <LI> Start new threads for each service.
 223   +html+ </OL>
 224   +html+ <A HREF=".DBrc">.properties</A>
 225 
 226   ++++++++++++++++++++++++++++++++++++++*/
 227 void SV_start() {
     /* [<][>][^][v][top][bottom][index][help] */
 228   /* Make listening sockets global variables  */
 229   /*  int whois_sock,config_sock,mirror_sock,update_sock; */
 230   /* uint32_t whois_addr,sock_addr,mirror_addr; */
 231   int whois_port = -1;
 232   int config_port = -1;
 233   int mirror_port = -1; 
 234   int update_port = -1;
 235   int update_mode = 0;
 236   sigset_t sset;
 237   int fdes[2];
 238   struct timeval tval;
 239   ca_dbSource_t *source_hdl;
 240   char *source_name;
 241   int source;
 242 
 243   /* Store the starting time */
 244   gettimeofday(&tval, NULL);
 245   SV_starttime = tval.tv_sec;/* seconds since Jan. 1, 1970 */
 246   
 247   /* Create interrupt pipe */
 248   /* Writing to this pipe will cause sleeping threads */
 249   /* to wake up */
 250   fprintf(stderr, "Creating an interrupt pipe\n");
 251   if(pipe(fdes)==-1) {
 252    printf("Cannot open interrupt pipe\n");
 253    exit(-1);
 254   } 
 255   /* Save the pipe descriptors in sv_lock array */
 256   sv_lockfd[WLOCK_SHTDOWN]=fdes[0];
 257   sv_lockfd[LOCK_SHTDOWN]=fdes[1];
 258 
 259   
 260   /* Initialise the access control list. */
 261   AC_build();
 262   AC_acc_load();
 263   /* explicitly start the decay thread */
 264   TH_create((void *(*)(void *))AC_decay, NULL);
 265 
 266   /* Initialise the radix tree (separate thread[s])
 267      already can allow socket connections, because the trees will 
 268      be created locked, and will be unlocked when loaded */
 269 
 270 /*   pthread_mutex_lock( &radix_initializing_lock );  */
 271   TH_create((void *(*)(void *))radix_init, NULL);
 272 /*  pthread_mutex_lock( &radix_initializing_lock );  */
 273   
 274   
 275   /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */
 276   /* Get port information for each service */
 277   whois_port = SK_atoport(CO_get_whois_port(), "tcp");
 278   printf("XXX htons(whois_port)=%d\n", htons(whois_port));
 279   if(whois_port == -1) {
 280     printf("Invalid service/port: %d\n", htons(whois_port));
 281     exit(-1);
 282   }
 283 
 284   /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */
 285   config_port = SK_atoport(CO_get_config_port(), "tcp");
 286   printf("XXX htons(config_port)=%d\n", htons(config_port));
 287   if(config_port == -1) {
 288     printf("Invalid service/port: %d\n", htons(config_port));
 289     exit(-1); 
 290   }
 291   mirror_port = SK_atoport(CO_get_mirror_port(), "tcp");
 292   printf("XXX htons(mirror_port)=%d\n", htons(mirror_port));
 293   if(mirror_port == -1) {
 294     printf("Invalid service/port: %d\n", mirror_port);
 295     exit(-1);
 296   }
 297 
 298   /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */
 299 /*  update_port = SK_atoport(CO_get_update_port(), "tcp"); */
 300 /*  printf("XXX htons(update_port)=%d\n", htons(update_port)); */
 301 /*  if(update_port == -1) { */
 302 /*    printf("Invalid service/port: %d\n", htons(update_port)); */
 303 /*    exit(-1); */
 304 /*  } */
 305 
 306 
 307 
 308   /* 6. Create a socket on the necessary ports/addresses and bind to them. */
 309   /* whois socket */
 310   SV_whois_sock = SK_getsock(SOCK_STREAM, whois_port, INADDR_ANY);
 311 /* Currently binds to INADDR_ANY. Will need to get specific address */
 312 /*  SV_whois_sock = SK_getsock(SOCK_STREAM,whois_port,whois_addr); */
 313   /* config interface socket */
 314   SV_config_sock = SK_getsock(SOCK_STREAM, config_port, INADDR_ANY);
 315   /* nrt socket */
 316   SV_mirror_sock = SK_getsock(SOCK_STREAM,mirror_port,INADDR_ANY);
 317   
 318   
 319   
 320   /* update interface socket */
 321   /* we need first to create and bind all of them */
 322   /* so that in case of failure we do not start any */
 323   /* update thread */
 324   for(source=0; (source_hdl = ca_get_SourceHandleByPosition(source))!=NULL ; source++){
 325      update_mode = ca_get_srcmode(source_hdl);
 326      if(IS_UPDATE(update_mode)) {
 327        /* update_port = SK_atoport(CO_get_update_port(), "tcp"); */
 328        update_port = htons(ca_get_srcupdateport(source_hdl)); 
 329        printf("XXX htons(update_port)=%d\n", htons(update_port));
 330        /* XXX ask AMRM to change the name of the function */
 331  
 332        SV_update_sock[source] = SK_getsock(SOCK_STREAM, update_port, INADDR_ANY);
 333      }
 334      else SV_update_sock[source] = 0;
 335   }   
 336   SV_update_sock[source+1]=-1; /* end of socket array */
 337    
 338   /* Now.... accept() calls block until they get a connection
 339      so to listen on more than one port we need more
 340      than one thread */
 341 
 342   /* Create master thread for whois threads */
 343    SV_concurrent_server(SV_whois_sock, SV_do_whois);
 344 
 345   /* Create master thread for config threads */
 346    SV_concurrent_server(SV_config_sock, SV_do_config);
 347   /* Create master thread for mirror threads */
 348    SV_concurrent_server(SV_mirror_sock, SV_do_mirror);
 349 
 350 /* Walk through the sources and */
 351 /* run update thread for every source with CANUPD == 'y' */
 352    
 353    for(source=0; (source_hdl = ca_get_SourceHandleByPosition(source))!=NULL ; source++){
 354      update_mode = ca_get_srcmode(source_hdl);
 355      source_name= ca_get_srcname(source_hdl);
 356 
 357      if(IS_UPDATE(update_mode)) { 
 358      /* run RIPupdate thread */
 359        fprintf(stderr,"Source [%s] Mode UPDATE\n", source_name);
 360        TH_create((void *(*)(void *))UD_do_updates, (void *)source); 
 361      }
 362      else {
 363        /* start NRTM client */
 364        fprintf(stderr,"Source [%s] Mode NRTM\n", source_name);    
 365        TH_create((void *(*)(void *))UD_do_nrtm, (void *)source);
 366      }
 367      free(source_name); /* because ca_* functions return copies */   
 368    }    
 369 
 370    
 371 
 372   /* XXX Is this needed? */
 373   pthread_exit(NULL);
 374 
 375 } /* SV_start() */
 376 
 377 /* SV_shutdown() */
 378 /*++++++++++++++++++++++++++++++++++++++
 379 
 380   Shutdown the server.
 381 
 382   More:
 383   +html+ <PRE>
 384   Authors:
 385         andrei
 386   +html+ </PRE>
 387   +html+ Stops the server.
 388   +html+ <OL>
 389   +html+   <LI> Close listening sockets (whois, config, mirror and updates)
 390   +html+   <LI> Stop all threads by triggering do_server variable.
 391   +html+ </OL>
 392   +html+ <A HREF=".DBrc">.properties</A>
 393 
 394   ++++++++++++++++++++++++++++++++++++++*/
 395 void SV_shutdown() {
     /* [<][>][^][v][top][bottom][index][help] */
 396 char print_buf[STR_M];
 397 int source;
 398  
 399  sprintf(print_buf, "%d", 0);
 400  /* Stop updates */
 401  CO_set_const("UD.do_update", print_buf);
 402  /* Stop all servers */
 403  CO_set_const("SV.do_server", print_buf);
 404  sprintf(print_buf, "Stopping all servers\n");
 405  fprintf(stderr, print_buf);
 406  /*log_print(print_buf); */
 407  strcpy(print_buf, "");
 408  
 409  /* Wake up all sleeping threads */
 410  fprintf(stderr, "Going to wake sleeping threads up\n");
 411  write(sv_lockfd[WLOCK_SHTDOWN], " ", 1); 
 412 
 413  /* CLose all listening sockets, so accept call exits */
 414  close(SV_whois_sock);
 415  close(SV_config_sock);
 416  close(SV_mirror_sock);
 417  for (source=0; SV_update_sock[source]!=-1; source++)
 418          if(SV_update_sock[source]!=0)close(SV_update_sock[source]);
 419  
 420  
 421 } /* SV_shutdown() */
 422 
 423 
 424 /* SV_sleep() */
 425 /*++++++++++++++++++++++++++++++++++++++
 426 
 427   Sleep and wake up on special events.
 428 
 429   More:
 430   +html+ <PRE>
 431   Authors:
 432         andrei
 433   +html+ </PRE>
 434   +html+ Sleeps timeout but wakes up when an envent occures.
 435 
 436   ++++++++++++++++++++++++++++++++++++++*/
 437 int SV_sleep(int lock, int sleeptime) {
     /* [<][>][^][v][top][bottom][index][help] */
 438 struct timeval timeout;
 439 struct stat st;
 440 fd_set set;
 441 
 442  if (fstat(sv_lockfd[lock], &st) ==-1) {
 443   fprintf(stderr, "Error stat-ing the lock file\n");
 444   return(-1);
 445  } 
 446  
 447  timeout.tv_sec=sleeptime;
 448  timeout.tv_usec=0;
 449    
 450  FD_ZERO(&set);
 451  FD_SET(sv_lockfd[lock], &set);
 452  
 453  fprintf(stderr, "Going to sleep\n");
 454  select(sv_lockfd[lock]+1, &set, NULL, NULL, &timeout);
 455  
 456  fprintf(stderr, "Select returned\n");
 457       
 458  return(0);
 459 }
 460 
 461 /*++++++++++++++++++++++++++++++++++++++
 462 
 463   Handle signals.
 464   
 465   Changes the flags:
 466         do_nrtm
 467         do_update
 468         do_whoisd
 469 
 470   More:
 471   +html+ <PRE>
 472   Author:
 473         andrei
 474   +html+ </PRE>
 475   ++++++++++++++++++++++++++++++++++++++*/
 476 void *SV_signal_thread() {
     /* [<][>][^][v][top][bottom][index][help] */
 477 char print_buf[STR_M];
 478 sigset_t sset;
 479 int sigReceived;
 480 int do_update;
 481 
 482         sigemptyset(&sset);
 483         sigaddset(&sset, SIGTERM);
 484         sigaddset(&sset, SIGINT);
 485         sigaddset(&sset, SIGUSR1);
 486         /* This is a bit confusing, but is needed */
 487         /* For more information on signal handling in */
 488         /* threads see for example "Multithreading Programming */
 489         /* Techniques" by Shashi Prasad, ISBN 0-07-912250-7, pp. 94-101 */
 490         pthread_sigmask(SIG_BLOCK, &sset, NULL);
 491         /*      fprintf(stderr, "Signal handler installed\n");*/
 492 
 493         for(;;)
 494         {
 495          sigwait(&sset, &sigReceived);
 496          sprintf(print_buf, "Signal received [%d]\n", sigReceived);
 497          log_print(print_buf); strcpy(print_buf, "");
 498          /*      fprintf(stderr, "Signal received [%d]\n", sigReceived); */
 499          switch (sigReceived)
 500          {
 501            case SIGINT:
 502            /* SIGINT stops all servers */
 503                 SV_shutdown();
 504                 pthread_exit((void *)0);
 505                 break;
 506                 
 507            case SIGTERM:
 508            /* SIGTERM will switch the updates on and off */
 509                 do_update=CO_get_do_update();
 510                 if(do_update)do_update=0; else do_update=1;     
 511                 sprintf(print_buf, "%d", do_update);
 512                 CO_set_const("UD.do_update", print_buf); 
 513                 if(do_update)
 514                   sprintf(print_buf, "Starting updates\n");
 515                 else   
 516                   sprintf(print_buf, "Stopping updates\n");
 517                 log_print(print_buf); strcpy(print_buf, ""); 
 518                 /*              fprintf(stderr, "Stopping updates (SIGTERM received)\n"); */
 519                 break; 
 520          }       
 521         }
 522 } /* SV_signal_thread() */
 523 
 524 /* SV_concurrent_server() */
 525 /*++++++++++++++++++++++++++++++++++++++
 526 
 527   This is the routine that creates the main threads. 
 528 
 529   int     sock        The socket to connect to.
 530   void *  do_function The function to call for each type of service
 531 
 532   More:
 533   +html+ <PRE>
 534   Author:
 535         ottrey
 536         joao
 537   +html+ </PRE>
 538   ++++++++++++++++++++++++++++++++++++++*/
 539 void SV_concurrent_server(int sock, void *do_function(void *)) {
     /* [<][>][^][v][top][bottom][index][help] */
 540   th_args *args;
 541   pthread_t tid;
 542   pthread_attr_t attr;
 543 
 544   dieif( wr_calloc((void **)&args,1,sizeof(th_args)) != UT_OK);  
 545 
 546   args->function=(void *)do_function;
 547   args->sock=sock;
 548 
 549 /*  pthread_mutex_init(&Whois_thread_count_lock,NULL); */
 550 
 551   /* Start a new thread. */
 552 
 553   TH_create(main_loop, (void *)args);
 554 
 555   
 556     /* Start a new thread. */
 557 //  pthread_attr_init(&attr);     /* initialize attr with default attributes */
 558 //  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 559 //  pthread_create(&tid, &attr, main_thread, (void *)args);
 560 
 561 } /* TH_run() */
 562 
 563 /* SV_do_whois() */
 564 /*++++++++++++++++++++++++++++++++++++++
 565 
 566   Handle whois connections.
 567 
 568   void *arg The socket to connect to. (It has to be passed in this way for this thread routine.)
 569 
 570   More:
 571   +html+ <PRE>
 572   Author:
 573         joao
 574   +html+ </PRE>
 575   ++++++++++++++++++++++++++++++++++++++*/
 576 void *SV_do_whois(void *arg) { 
     /* [<][>][^][v][top][bottom][index][help] */
 577   int sock = (int)arg;
 578 
 579   ER_dbg_va(FAC_TH, ASP_TH_NEW,
 580             "Whois: Child thread [%d]: Socket number = %d", 
 581             pthread_self(), sock);
 582 
 583   /* Use a mutex to update the global whois thread counter. */
 584   pthread_mutex_lock(&Whois_thread_count_lock);
 585   Whois_thread_count++;
 586   ER_dbg_va(FAC_TH, ASP_TH_NEW, 
 587             "Whois_thread_count++=%d", Whois_thread_count); 
 588   
 589   pthread_mutex_unlock(&Whois_thread_count_lock);
 590 
 591   TA_add(sock, "whois");
 592   PW_interact(sock);
 593   TA_delete();
 594 
 595   /* Use a mutex to update the global whois thread counter. */
 596   pthread_mutex_lock(&Whois_thread_count_lock);
 597   Whois_thread_count--;
 598   ER_dbg_va(FAC_TH, ASP_TH_NEW, 
 599             "Whois_thread_count--=%d", Whois_thread_count); 
 600   pthread_mutex_unlock(&Whois_thread_count_lock);
 601 
 602   pthread_exit((void *)0);
 603 
 604 } /* SV_do_whois() */
 605 
 606 /* SV_do_mirror() */
 607 /*++++++++++++++++++++++++++++++++++++++
 608 
 609   Handle NRTM connections.
 610 
 611   void *arg The socket to connect to. (It has to be passed in this way for this thread routine.)
 612 
 613   More:
 614   +html+ <PRE>
 615   Author:
 616         joao
 617   +html+ </PRE>
 618   ++++++++++++++++++++++++++++++++++++++*/
 619 void *SV_do_mirror(void *arg) { 
     /* [<][>][^][v][top][bottom][index][help] */
 620   int sock = (int)arg;
 621   char print_buf[STR_M];
 622 
 623   sprintf(print_buf, "NRTM: Child thread [%d]: Socket number = %d\n", pthread_self(), sock); log_print(print_buf); strcpy(print_buf, "");
 624 
 625   /* Use a mutex to update the global mirror thread counter. */
 626   pthread_mutex_lock(&Mirror_thread_count_lock);
 627   Mirror_thread_count++;
 628   sprintf(print_buf, "Mirror_thread_count++=%d\n", Mirror_thread_count); log_print(print_buf); strcpy(print_buf, "");
 629   pthread_mutex_unlock(&Mirror_thread_count_lock);
 630 
 631   TA_add(sock, "mirror");
 632   PM_interact(sock);
 633   TA_delete();
 634 
 635   /* Use a mutex to update the global mirror thread counter. */
 636   pthread_mutex_lock(&Mirror_thread_count_lock);
 637   Mirror_thread_count--;
 638   sprintf(print_buf, "Mirror_thread_count--=%d\n", Mirror_thread_count); log_print(print_buf); strcpy(print_buf, "");
 639   pthread_mutex_unlock(&Mirror_thread_count_lock);
 640 
 641   pthread_exit((void *)0);
 642 
 643 } /* SV_do_mirror() */
 644 
 645 /* SV_do_config() */
 646 /*++++++++++++++++++++++++++++++++++++++
 647 
 648   Handle config connections.
 649 
 650   void *arg The socket to connect to. (It has to be passed in this way for this
 651 thread routine.)
 652 
 653   More:
 654   +html+ <PRE>
 655   Author:
 656         joao
 657   +html+ </PRE>
 658   ++++++++++++++++++++++++++++++++++++++*/
 659 void *SV_do_config(void *arg) {
     /* [<][>][^][v][top][bottom][index][help] */
 660   int sock = (int)arg;
 661   char print_buf[STR_M];
 662 
 663   sprintf(print_buf, "Config: Child thread [%d]: Socket number = %d\n", pthread_self(), sock); log_print(print_buf); strcpy(print_buf, "");
 664 
 665 /*
 666   printf("Hi there, there is nothing to configure yet\nBye..... :-)\n");
 667   fflush(NULL);
 668 
 669   SK_close(sock);
 670 */
 671   TA_add(sock, "config");
 672   PC_interact(sock);
 673   TA_delete();
 674 
 675   pthread_exit((void *)0);
 676 
 677 } /* SV_do_config() */
 678 
 679 
 680 /*++++++++++++++++++++++++++++++++++++++
 681 
 682   This is the routine that creates a watchdog thread. 
 683   
 684   The watchdog will cancel (pthread_cancel()) the calling thread in case the
 685   socket is closed by the client (its read-half is closed). The calling
 686   thread should make necessaruy preparations when calling the watchdog:
 687   
 688   - the socket should be connected
 689   - cancellation points and cleanup routines should be defined
 690   
 691   In case the connection is closed by the calling thread itself, the
 692   watchdog just exits and no action against the calling thread is performed.
 693 
 694   wd_args - a pointer to wd_args_t structure containing
 695             data about socket and thread ID
 696   
 697   More:
 698   +html+ <PRE>
 699   Author:
 700         ottrey
 701         joao
 702         andrei
 703   +html+ </PRE>
 704   ++++++++++++++++++++++++++++++++++++++*/
 705 
 706 void SV_watchdog(wd_args_t *wd_args) {
     /* [<][>][^][v][top][bottom][index][help] */
 707  pthread_t tid;
 708  pthread_attr_t attr;
 709  
 710  /* Start a new thread. */
 711  TH_create((void *(*)(void *))do_watchdog, (void *)wd_args);
 712  
 713 // pthread_attr_init(&attr);     /* initialize attr with default attributes */
 714 // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 715 // pthread_create(&tid, &attr, (void *(*)(void *))do_watchdog, (void *)wd_args);
 716 
 717 }
 718 
 719 
 720 /*++++++++++++++++++++++++++++++++++++++
 721 
 722 The watchdog thread itself
 723 
 724 The watchdog thread makes select() on the connected socket waiting until it
 725 becomes readable. If this happens as a result of some input, it'll simply
 726 dump it. Otherwise, this indicates that the client has closed the
 727 connection. In this case watchdog will cancel (pthread_cancel()) the whois
 728 thread (which in its turn will kill (mysql_kill()) mysql thread as part of
 729 its cleanup routine).
 730 
 731 More:
 732 +html+ <PRE>
 733 Author:
 734       andrei
 735 +html+ </PRE>
 736 ++++++++++++++++++++++++++++++++++++++*/
 737 static void do_watchdog(void *arg) {
     /* [<][>][^][v][top][bottom][index][help] */
 738   wd_args_t *wd_args = (wd_args_t *)arg;
 739   int socket;
 740   pthread_t tid;
 741   int nready;
 742   int n;
 743   fd_set rset;
 744   char buff[STR_S];
 745   
 746   socket = wd_args->connected_socket;
 747   tid = wd_args->tid;
 748   
 749   
 750   FD_ZERO(&rset);
 751   FD_SET(socket, &rset);
 752   
 753   while ((nready=select(socket+1, &rset, NULL, NULL, NULL))!=-1) {
 754    
 755    /* There was some input or client half of connection was closed */
 756    /* Check for the latter */
 757    if (( n=read(socket, buff, sizeof(buff))) == 0) {
 758    /* Connection was closed by client */
 759    /* Now send a cancellation request to the whois thread. */
 760    /* mysql thread will be terminated by thread cleanup routine */
 761    
 762    /* The only possible error is ESRCH, so we do not care about */
 763    pthread_cancel(tid);
 764    
 765    /* Exit the watchdog thread, passing NULL as we don't expect pthread_join() */
 766    pthread_exit(NULL);
 767    }
 768    
 769    /* Otherwise dump input and continue */
 770   }
 771   
 772   /* the only reason that we are here is that the socket has been */
 773   /* closed by the whois thread and not valid. Just exit the watchdog, */
 774   /* passing NULL as we don't expect pthread_join() */
 775    pthread_exit(NULL);
 776   
 777 }  

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