Diff for /loncom/loncnew between versions 1.42 and 1.55

version 1.42, 2004/02/17 09:43:21 version 1.55, 2004/09/20 18:40:06
Line 82  my $ClientConnection = 0; # Uniquifier f Line 82  my $ClientConnection = 0; # Uniquifier f
   
 my $DebugLevel = 0;  my $DebugLevel = 0;
 my $NextDebugLevel= 2; # So Sigint can toggle this.  my $NextDebugLevel= 2; # So Sigint can toggle this.
 my $IdleTimeout= 3600; # Wait an hour before pruning connections.  my $IdleTimeout= 600; # Wait 10 minutes before pruning connections.
   
 my $LogTransactions = 0; # When True, all transactions/replies get logged.  my $LogTransactions = 0; # When True, all transactions/replies get logged.
   
Line 103  my $RecentLogEntry  = ""; Line 103  my $RecentLogEntry  = "";
 my $ConnectionRetries=2; # Number of connection retries allowed.  my $ConnectionRetries=2; # Number of connection retries allowed.
 my $ConnectionRetriesLeft=2; # Number of connection retries remaining.  my $ConnectionRetriesLeft=2; # Number of connection retries remaining.
 my $LondVersion     = "unknown"; # Version of lond we talk with.  my $LondVersion     = "unknown"; # Version of lond we talk with.
   my $KeyMode         = "";       # e.g. ssl, local, insecure from last connect.
   my $LondConnecting  = 0;       # True when a connection is being built.
   
 #  #
 #   The hash below gives the HTML format for log messages  #   The hash below gives the HTML format for log messages
Line 110  my $LondVersion     = "unknown"; # Versi Line 112  my $LondVersion     = "unknown"; # Versi
 #      #    
 my %LogFormats;  my %LogFormats;
   
 $LogFormats{"CRITICAL"} = "<font color=red>CRITICAL: %s</font>";  $LogFormats{"CRITICAL"} = "<font color='red'>CRITICAL: %s</font>";
 $LogFormats{"SUCCESS"}  = "<font color=green>SUCCESS: %s</font>";  $LogFormats{"SUCCESS"}  = "<font color='green'>SUCCESS: %s</font>";
 $LogFormats{"INFO"}     = "<font color=yellow>INFO: %s</font>";  $LogFormats{"INFO"}     = "<font color='yellow'>INFO: %s</font>";
 $LogFormats{"WARNING"}  = "<font color=blue>WARNING: %s</font>";  $LogFormats{"WARNING"}  = "<font color='blue'>WARNING: %s</font>";
 $LogFormats{"DEFAULT"}  = " %s ";  $LogFormats{"DEFAULT"}  = " %s ";
   
   
Line 156  host and the time will be formatted into Line 158  host and the time will be formatted into
 =cut  =cut
   
 sub Log {  sub Log {
     my $severity = shift;  
     my $message  = shift;      my ($severity, $message) = @_;
      
     if(!$LogFormats{$severity}) {      if(!$LogFormats{$severity}) {
  $severity = "DEFAULT";   $severity = "DEFAULT";
     }      }
Line 193  Returns the name of the host that a sock Line 195  Returns the name of the host that a sock
 =cut  =cut
   
 sub GetPeername {  sub GetPeername {
     my $connection = shift;  
     my $AdrFamily  = shift;  
       my ($connection, $AdrFamily) = @_;
   
     my $peer       = $connection->peername();      my $peer       = $connection->peername();
     my $peerport;      my $peerport;
     my $peerip;      my $peerip;
Line 217  Invoked to issue a debug message. Line 221  Invoked to issue a debug message.
 =cut  =cut
   
 sub Debug {  sub Debug {
     my $level   = shift;  
     my $message = shift;      my ($level, $message) = @_;
   
     if ($level <= $DebugLevel) {      if ($level <= $DebugLevel) {
  Log("INFO", "-Debug- $message host = $RemoteHost");   Log("INFO", "-Debug- $message host = $RemoteHost");
     }      }
 }  }
   
 sub SocketDump {  sub SocketDump {
     my $level = shift;  
     my $socket= shift;      my ($level, $socket) = @_;
   
     if($level <= $DebugLevel) {      if($level <= $DebugLevel) {
  $socket->Dump();   $socket->Dump(-1); # Ensure it will get dumped.
     }      }
 }  }
   
Line 260  sub ShowStatus { Line 266  sub ShowStatus {
 sub SocketTimeout {  sub SocketTimeout {
     my $Socket = shift;      my $Socket = shift;
     Log("WARNING", "A socket timeout was detected");      Log("WARNING", "A socket timeout was detected");
     Debug(0, " SocketTimeout called: ");      Debug(5, " SocketTimeout called: ");
     $Socket->Dump();      $Socket->Dump(0);
     if(exists($ActiveTransactions{$Socket})) {      if(exists($ActiveTransactions{$Socket})) {
       FailTransaction($ActiveTransactions{$Socket});   FailTransaction($ActiveTransactions{$Socket});
     }      }
     KillSocket($Socket); # A transaction timeout also counts as      KillSocket($Socket); # A transaction timeout also counts as
                                 # a connection failure:                                  # a connection failure:
     $ConnectionRetriesLeft--;      $ConnectionRetriesLeft--;
     if($ConnectionRetriesLeft <= 0) {      if($ConnectionRetriesLeft <= 0) {
  Log("CRITICAL", "Host marked dead: ".GetServerHost());   Log("CRITICAL", "Host marked DEAD: ".GetServerHost());
     }      }
   
 }  }
Line 285  Invoked  each timer tick. Line 291  Invoked  each timer tick.
   
   
 sub Tick {  sub Tick {
       my ($Event)       = @_;
       my $clock_watcher = $Event->w;
   
     my $client;      my $client;
     if($ConnectionRetriesLeft > 0) {      if($ConnectionRetriesLeft > 0) {
  ShowStatus(GetServerHost()." Connection count: ".$ConnectionCount   ShowStatus(GetServerHost()." Connection count: ".$ConnectionCount
    ." Retries remaining: ".$ConnectionRetriesLeft);     ." Retries remaining: ".$ConnectionRetriesLeft
      ." ($KeyMode)");
     } else {      } else {
  ShowStatus(GetServerHost()." >> DEAD <<");   ShowStatus(GetServerHost()." >> DEAD <<");
     }      }
Line 301  sub Tick { Line 311  sub Tick {
  if($IdleSeconds > $IdleTimeout) { # Prune a connection...   if($IdleSeconds > $IdleTimeout) { # Prune a connection...
     my $Socket = $IdleConnections->pop();      my $Socket = $IdleConnections->pop();
     KillSocket($Socket);      KillSocket($Socket);
       $IdleSeconds = 0; # Otherwise all connections get trimmed to fast.
  }   }
     } else {      } else {
  $IdleSeconds = 0; # Reset idle count if not idle.   $IdleSeconds = 0; # Reset idle count if not idle.
Line 343  sub Tick { Line 354  sub Tick {
  }   }
                 
     }      }
       if ($ConnectionCount == 0) {
    $KeyMode = ""; 
    $clock_watcher->cancel();
       }
 }  }
   
 =pod  =pod
Line 383  long enough, it will be shut down and re Line 398  long enough, it will be shut down and re
   
 sub ServerToIdle {  sub ServerToIdle {
     my $Socket   = shift; # Get the socket.      my $Socket   = shift; # Get the socket.
       $KeyMode = $Socket->{AuthenticationMode};
     delete($ActiveTransactions{$Socket}); # Server has no transaction      delete($ActiveTransactions{$Socket}); # Server has no transaction
   
     &Debug(5, "Server to idle");      &Debug(5, "Server to idle");
Line 462  sub ClientWritable { Line 478  sub ClientWritable {
     } else { # Partial string sent.      } else { # Partial string sent.
  $Watcher->data(substr($Data, $result));   $Watcher->data(substr($Data, $result));
  if($result == 0) {    # client hung up on us!!   if($result == 0) {    # client hung up on us!!
     Log("INFO", "lonc pipe client hung up on us!");      # Log("INFO", "lonc pipe client hung up on us!");
     $Watcher->cancel;      $Watcher->cancel;
     $Socket->shutdown(2);      $Socket->shutdown(2);
     $Socket->close();      $Socket->close();
Line 515  The transaction that is being completed. Line 531  The transaction that is being completed.
   
 sub CompleteTransaction {  sub CompleteTransaction {
     &Debug(5,"Complete transaction");      &Debug(5,"Complete transaction");
     my $Socket = shift;  
     my $Transaction = shift;      my ($Socket, $Transaction) = @_;
   
     if (!$Transaction->isDeferred()) { # Normal transaction      if (!$Transaction->isDeferred()) { # Normal transaction
  my $data   = $Socket->GetReply(); # Data to send.   my $data   = $Socket->GetReply(); # Data to send.
Line 550  sub CompleteTransaction { Line 566  sub CompleteTransaction {
 =cut  =cut
   
 sub StartClientReply {  sub StartClientReply {
     my $Transaction   = shift;  
     my $data     = shift;  
   
       my ($Transaction, $data) = @_;
   
     my $Client   = $Transaction->getClient();      my $Client   = $Transaction->getClient();
   
Line 591  Parameters: Line 606  Parameters:
   
 sub FailTransaction {  sub FailTransaction {
     my $transaction = shift;      my $transaction = shift;
     Log("WARNING", "Failing transaction ".$transaction->getRequest());      
       #  If the socket is dead, that's already logged.
   
       if ($ConnectionRetriesLeft > 0) {
    Log("WARNING", "Failing transaction "
       .$transaction->getRequest());
       }
     Debug(1, "Failing transaction: ".$transaction->getRequest());      Debug(1, "Failing transaction: ".$transaction->getRequest());
     if (!$transaction->isDeferred()) { # If the transaction is deferred we'll get to it.      if (!$transaction->isDeferred()) { # If the transaction is deferred we'll get to it.
  my $client  = $transaction->getClient();   my $client  = $transaction->getClient();
Line 852  sub LondReadable { Line 873  sub LondReadable {
  .$RemoteHost." now ready for action");   .$RemoteHost." now ready for action");
  }   }
  ServerToIdle($Socket); # Next work unit or idle.   ServerToIdle($Socket); # Next work unit or idle.
   
    #
    $LondConnecting = 0; # Best spot I can think of for this.
    # 
   
     } elsif ($State eq "SendingRequest") {      } elsif ($State eq "SendingRequest") {
  #  We need to be writable for this and probably don't belong   #  We need to be writable for this and probably don't belong
Line 959  sub LondWritable { Line 984  sub LondWritable {
     # so that the writing states are actually NO-OPs.      # so that the writing states are actually NO-OPs.
   
     if ($Socket->Writable() != 0) {      if ($Socket->Writable() != 0) {
       #  The write resulted in an error.   #  The write resulted in an error.
       # We'll treat this as if the socket got disconnected:   # We'll treat this as if the socket got disconnected:
       Log("WARNING", "Connection to ".$RemoteHost.   Log("WARNING", "Connection to ".$RemoteHost.
   " has been disconnected");      " has been disconnected");
       if(exists($ActiveTransactions{$Socket})) {   if(exists($ActiveTransactions{$Socket})) {
  FailTransaction($ActiveTransactions{$Socket});      FailTransaction($ActiveTransactions{$Socket});
       }   }
       $Watcher->cancel();   $Watcher->cancel();
       KillSocket($Socket);   KillSocket($Socket);
       return;   return;
     }      }
   
   
Line 1125  sub MakeLondConnection { Line 1150  sub MakeLondConnection {
    data     => $Connection,     data     => $Connection,
    desc => 'Connection to lond server');     desc => 'Connection to lond server');
  $ActiveConnections{$Connection} = $event;   $ActiveConnections{$Connection} = $event;
    if ($ConnectionCount == 0) {
       &SetupTimer; # Need to handle timeouts with connections...
    }
  $ConnectionCount++;   $ConnectionCount++;
  Debug(4, "Connection count = ".$ConnectionCount);   Debug(4, "Connection count = ".$ConnectionCount);
  if($ConnectionCount == 1) { # First Connection:   if($ConnectionCount == 1) { # First Connection:
Line 1133  sub MakeLondConnection { Line 1160  sub MakeLondConnection {
  }   }
  Log("SUCESS", "Created connection ".$ConnectionCount   Log("SUCESS", "Created connection ".$ConnectionCount
     ." to host ".GetServerHost());      ." to host ".GetServerHost());
    $LondConnecting = 1; # Connection in progress.
  return 1; # Return success.   return 1; # Return success.
     }      }
           
Line 1164  The text of the request to send. Line 1192  The text of the request to send.
 =cut  =cut
   
 sub StartRequest {  sub StartRequest {
     my $Lond     = shift;  
     my $Request  = shift; # This is a LondTransaction.      my ($Lond, $Request) = @_;
           
     Debug(6, "StartRequest: ".$Request->getRequest());      Debug(6, "StartRequest: ".$Request->getRequest());
   
Line 1216  sub QueueTransaction { Line 1244  sub QueueTransaction {
     if(!defined $LondSocket) { # Need to queue request.      if(!defined $LondSocket) { # Need to queue request.
  Debug(5,"Must queue...");   Debug(5,"Must queue...");
  $WorkQueue->enqueue($requestData);   $WorkQueue->enqueue($requestData);
  if($ConnectionCount < $MaxConnectionCount) {   if(($ConnectionCount < $MaxConnectionCount) && !$LondConnecting) {
     if($ConnectionRetriesLeft > 0) {      if($ConnectionRetriesLeft > 0) {
  Debug(5,"Starting additional lond connection");   Debug(5,"Starting additional lond connection");
  if(MakeLondConnection() == 0) {   if(MakeLondConnection() == 0) {
Line 1269  sub ClientRequest { Line 1297  sub ClientRequest {
     Debug(8,"Data: ".$data." this read: ".$thisread);      Debug(8,"Data: ".$data." this read: ".$thisread);
     $data = $data.$thisread; # Append new data.      $data = $data.$thisread; # Append new data.
     $watcher->data($data);      $watcher->data($data);
     if($data =~ /(.*\n)/) { # Request entirely read.      if($data =~ /\n$/) { # Request entirely read.
  if($data eq "close_connection_exit\n") {   if($data eq "close_connection_exit\n") {
     Log("CRITICAL",      Log("CRITICAL",
  "Request Close Connection ... exiting");   "Request Close Connection ... exiting");
Line 1378  sub SetupLoncListener { Line 1406  sub SetupLoncListener {
     my $SocketName = GetLoncSocketPath();      my $SocketName = GetLoncSocketPath();
     unlink($SocketName);      unlink($SocketName);
     unless ($socket =IO::Socket::UNIX->new(Local  => $SocketName,      unless ($socket =IO::Socket::UNIX->new(Local  => $SocketName,
     Listen => 10,       Listen => 250, 
     Type   => SOCK_STREAM)) {      Type   => SOCK_STREAM)) {
  die "Failed to create a lonc listner socket";   die "Failed to create a lonc listner socket";
     }      }
Line 1416  into the status file. Line 1444  into the status file.
 We also use this to reset the retries count in order to allow the  We also use this to reset the retries count in order to allow the
 client to retry connections with a previously dead server.  client to retry connections with a previously dead server.
 =cut  =cut
   
 sub ChildStatus {  sub ChildStatus {
     my $event = shift;      my $event = shift;
     my $watcher = $event->w;      my $watcher = $event->w;
Line 1428  sub ChildStatus { Line 1457  sub ChildStatus {
     #      #
     #  Write out information about each of the connections:      #  Write out information about each of the connections:
     #      #
     print $fh "Active connection statuses: \n";      if ($DebugLevel > 2) {
     my $i = 1;   print $fh "Active connection statuses: \n";
     print STDERR  "================================= Socket Status Dump:\n";   my $i = 1;
     foreach my $item (keys %ActiveConnections) {   print STDERR  "================================= Socket Status Dump:\n";
  my $Socket = $ActiveConnections{$item}->data;   foreach my $item (keys %ActiveConnections) {
  my $state  = $Socket->GetState();      my $Socket = $ActiveConnections{$item}->data;
  print $fh "Connection $i State: $state\n";      my $state  = $Socket->GetState();
  print STDERR "---------------------- Connection $i \n";      print $fh "Connection $i State: $state\n";
  $Socket->Dump();      print STDERR "---------------------- Connection $i \n";
  $i++;      $Socket->Dump(-1); # Ensure it gets dumped..
       $i++;
    }
     }      }
     $ConnectionRetriesLeft = $ConnectionRetries;      $ConnectionRetriesLeft = $ConnectionRetries;
 }  }
Line 1509  sub ChildProcess { Line 1540  sub ChildProcess {
   cb       => \&ToggleDebug,    cb       => \&ToggleDebug,
   data     => "INT");    data     => "INT");
   
     SetupTimer();  
           
     SetupLoncListener();      SetupLoncListener();
           
Line 1532  sub ChildProcess { Line 1562  sub ChildProcess {
 #  Create a new child for host passed in:  #  Create a new child for host passed in:
   
 sub CreateChild {  sub CreateChild {
       my $host = shift;
   
     my $sigset = POSIX::SigSet->new(SIGINT);      my $sigset = POSIX::SigSet->new(SIGINT);
     sigprocmask(SIG_BLOCK, $sigset);      sigprocmask(SIG_BLOCK, $sigset);
     my $host = shift;  
     $RemoteHost = $host;      $RemoteHost = $host;
     Log("CRITICAL", "Forking server for ".$host);      Log("CRITICAL", "Forking server for ".$host);
     my $pid          = fork;      my $pid          = fork;
Line 1805  sub KillThemAll { Line 1836  sub KillThemAll {
     local($SIG{CHLD}) = 'IGNORE';      # Our children >will< die.      local($SIG{CHLD}) = 'IGNORE';      # Our children >will< die.
     foreach my $pid (keys %ChildHash) {      foreach my $pid (keys %ChildHash) {
  my $serving = $ChildHash{$pid};   my $serving = $ChildHash{$pid};
  Debug(2, "Killing lonc for $serving pid = $pid");   ShowStatus("Nicely Killing lonc for $serving pid = $pid");
  ShowStatus("Killing lonc for $serving pid = $pid");   Log("CRITICAL", "Nicely Killing lonc for $serving pid = $pid");
  Log("CRITICAL", "Killing lonc for $serving pid = $pid");  
  kill 'QUIT' => $pid;   kill 'QUIT' => $pid;
  delete($ChildHash{$pid});  
     }      }
     my $execdir = $perlvar{'lonDaemons'};  
     unlink("$execdir/logs/lonc.pid");  
   
 }  }
   
   
   #
   #  Kill all children via KILL.  Just in case the
   #  first shot didn't get them.
   
   sub really_kill_them_all_dammit
   {
       Debug(2, "Kill them all Dammit");
       local($SIG{CHLD} = 'IGNORE'); # In case some purist reenabled them.
       foreach my $pid (keys %ChildHash) {
    my $serving = $ChildHash{$pid};
    &ShowStatus("Nastily killing lonc for $serving pid = $pid");
    Log("CRITICAL", "Nastily killing lonc for $serving pid = $pid");
    kill 'KILL' => $pid;
    delete($ChildHash{$pid});
    my $execdir = $perlvar{'lonDaemons'};
    unlink("$execdir/logs/lonc.pid");
       }
   }
 =pod  =pod
   
 =head1 Terminate  =head1 Terminate
Line 1825  Terminate the system. Line 1872  Terminate the system.
 =cut  =cut
   
 sub Terminate {  sub Terminate {
     KillThemAll;      &Log("CRITICAL", "Asked to kill children.. first be nice...");
       &KillThemAll;
       #
       #  By now they really should all be dead.. but just in case 
       #  send them all SIGKILL's after a bit of waiting:
   
       sleep(4);
       &Log("CRITICAL", "Now kill children nasty");
       &really_kill_them_all_dammit;
     Log("CRITICAL","Master process exiting");      Log("CRITICAL","Master process exiting");
     exit 0;      exit 0;
   

Removed from v.1.42  
changed lines
  Added in v.1.55


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>