Diff for /loncom/loncnew between versions 1.6 and 1.7

version 1.6, 2003/05/05 23:40:27 version 1.7, 2003/06/03 01:59:39
Line 34 Line 34
 #    - Add timer dispatch.       (done)  #    - Add timer dispatch.       (done)
 #    - Add ability to accept lonc UNIX domain sockets.  (done)  #    - Add ability to accept lonc UNIX domain sockets.  (done)
 #    - Add ability to create/negotiate lond connections (done).  #    - Add ability to create/negotiate lond connections (done).
 #    - Add general logic for dispatching requests and timeouts.  #    - Add general logic for dispatching requests and timeouts. (done).
 #    - Add support for the lonc/lond requests.  #    - Add support for the lonc/lond requests.          (done).
 #    - Add logging/status monitoring.  #    - Add logging/status monitoring.
 #    - Add Signal handling - HUP restarts. USR1 status report.  #    - Add Signal handling - HUP restarts. USR1 status report.
 #    - Add Configuration file I/O  #    - Add Configuration file I/O                       (done).
 #    - Add Pending request processing on startup.  #    - Add Pending request processing on startup.
 #    - Add management/status request interface.  #    - Add management/status request interface.
   #    - Add deferred request capability.
   #
   
   # Change log:
   #    $Log$
   #    Revision 1.7  2003/06/03 01:59:39  foxr
   #    complete coding to support deferred transactions.
   #
   #
   
 use lib "/home/httpd/lib/perl/";  use lib "/home/httpd/lib/perl/";
 use lib "/home/foxr/newloncapa/types";  use lib "/home/foxr/newloncapa/types";
Line 55  use Crypt::IDEA; Line 64  use Crypt::IDEA;
 use LONCAPA::Queue;  use LONCAPA::Queue;
 use LONCAPA::Stack;  use LONCAPA::Stack;
 use LONCAPA::LondConnection;  use LONCAPA::LondConnection;
   use LONCAPA::LondTransaction;
 use LONCAPA::Configuration;  use LONCAPA::Configuration;
 use LONCAPA::HashIterator;  use LONCAPA::HashIterator;
   
Line 96  my $RemoteHost;   # Name of host child i Line 106  my $RemoteHost;   # Name of host child i
 my $UnixSocketDir= "/home/httpd/sockets";   my $UnixSocketDir= "/home/httpd/sockets"; 
 my $IdleConnections = Stack->new(); # Set of idle connections  my $IdleConnections = Stack->new(); # Set of idle connections
 my %ActiveConnections; # Connections to the remote lond.  my %ActiveConnections; # Connections to the remote lond.
 my %ActiveTransactions; # Transactions in flight.  my %ActiveTransactions; # LondTransactions in flight.
 my %ActiveClients; # Serial numbers of active clients by socket.  my %ActiveClients; # Serial numbers of active clients by socket.
 my $WorkQueue       = Queue->new(); # Queue of pending transactions.  my $WorkQueue       = Queue->new(); # Queue of pending transactions.
 my $ClientQueue     = Queue->new(); # Queue of clients causing xactinos.  #  my $ClientQueue     = Queue->new(); # Queue of clients causing xactinos.
 my $ConnectionCount = 0;  my $ConnectionCount = 0;
 my $IdleSeconds     = 0; # Number of seconds idle.  my $IdleSeconds     = 0; # Number of seconds idle.
   
Line 257  long enough, it will be shut down and re Line 267  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.
       delete($ActiveTransactions{$Socket}); # Server has no transaction
   
     &Debug(6, "Server to idle");      &Debug(6, "Server to idle");
   
     #  If there's work to do, start the transaction:      #  If there's work to do, start the transaction:
   
     $reqdata = $WorkQueue->dequeue();      $reqdata = $WorkQueue->dequeue(); # This is a LondTransaction
     Debug(9, "Queue gave request data: ".$reqdata);  
     unless($reqdata eq undef)  {      unless($reqdata eq undef)  {
  my $unixSocket = $ClientQueue->dequeue();   Debug(9, "Queue gave request data: ".$reqdata->getRequest());
  &Debug(6, "Starting new work request");   &StartRequest($Socket,  $reqdata);
  &Debug(7, "Request: ".$reqdata);  
   
  &StartRequest($Socket, $unixSocket, $reqdata);  
     } else {      } else {
   
     #  There's no work waiting, so push the server to idle list.      #  There's no work waiting, so push the server to idle list.
  &Debug(8, "No new work requests, server connection going idle");   &Debug(8, "No new work requests, server connection going idle");
  delete($ActiveTransactions{$Socket});  
  $IdleConnections->push($Socket);   $IdleConnections->push($Socket);
     }      }
 }  }
Line 378  Parameters: Line 384  Parameters:
 Socket on which the lond transaction occured.  This is a  Socket on which the lond transaction occured.  This is a
 LondConnection. The data received is in the TransactionReply member.  LondConnection. The data received is in the TransactionReply member.
   
 =item Client  =item Transaction
   
 Unix domain socket open on the ultimate client.  The transaction that is being completed.
   
 =cut  =cut
   
 sub CompleteTransaction {  sub CompleteTransaction {
     &Debug(6,"Complete transaction");      &Debug(6,"Complete transaction");
     my $Socket = shift;      my $Socket = shift;
     my $Client = shift;      my $Transaction = shift;
   
     my $data   = $Socket->GetReply(); # Data to send.      if (!$Transaction->isDeferred()) { # Normal transaction
     StartClientReply($Client, $data);   my $data   = $Socket->GetReply(); # Data to send.
    StartClientReply($Transaction, $data);
       } else { # Delete deferred transaction file.
    unlink $Transaction->getFile();
       }
 }  }
 =pod  =pod
 =head1 StartClientReply  =head1 StartClientReply
   
    Initiates a reply to a client where the reply data is a parameter.     Initiates a reply to a client where the reply data is a parameter.
   
   =head2  parameters:
   
   =item Transaction
   
       The transaction for which we are responding to the client.
   
   =item data
   
       The data to send to apached client.
   
 =cut  =cut
 sub StartClientReply {  sub StartClientReply {
     my $Client   = shift;      my $Transaction   = shift;
     my $data     = shift;      my $data     = shift;
   
       my $Client   = $Transaction->getClient();
   
     &Debug(8," Reply was: ".$data);      &Debug(8," Reply was: ".$data);
     my $Serial         = $ActiveClients{$Client};      my $Serial         = $ActiveClients{$Client};
     my $desc           = sprintf("Connection to lonc client %d",      my $desc           = sprintf("Connection to lonc client %d",
Line 417  sub StartClientReply { Line 439  sub StartClientReply {
 =head2 FailTransaction  =head2 FailTransaction
   
   Finishes a transaction with failure because the associated lond socket    Finishes a transaction with failure because the associated lond socket
   disconnected.  It is up to our client to retry if desired.      disconnected.  There are two possibilities:
     - The transaction is deferred: in which case we just quietly
       delete the transaction since there is no client connection.
     - The transaction is 'live' in which case we initiate the sending
       of "con_lost" to the client.
   
   Deleting the transaction means killing it from the 
   %ActiveTransactions hash.
   
 Parameters:  Parameters:
   
 =item client    =item client  
     
    The UNIX domain socket open on our client.     The LondTransaction we are failing.
    
 =cut  =cut
   
 sub FailTransaction {  sub FailTransaction {
     my $client = shift;      my $transaction = shift;
       my $Lond        = $transaction->getServer();
     StartClientReply($client, "con_lost");      if (!$client->isDeferred()) { # If the transaction is deferred we'll get to it.
    my $client  = $transcation->getClient();
    StartClientReply($client, "con_lost");
       }
   # not needed, done elsewhere if active.
   #    delete $ActiveTransactions{$Lond};
   
 }  }
   
 =pod  =pod
 =head1  EmptyQueue  =head1  EmptyQueue
   
   Fails all items in the work queue with con_lost.    Fails all items in the work queue with con_lost.
     Note that each item in the work queue is a transaction.
   
 =cut  =cut
 sub EmptyQueue {  sub EmptyQueue {
     while($WorkQueue->Count()) {      while($WorkQueue->Count()) {
  my $request = $WorkQUeue->dequeue(); # Just to help it become empty.   my $request = $Workqueue->dequeue(); # This is a transaction
  my $client  = $ClientQueue->dequeue(); #  Need to con_lost this guy.   FailTransaction($request);
  FailTransaction($client);  
     }      }
 }  }
   
Line 471  nonzero if we are allowed to create a ne Line 507  nonzero if we are allowed to create a ne
 sub KillSocket {  sub KillSocket {
     my $Socket = shift;      my $Socket = shift;
   
     #  If the socket came from the active connection set, delete it.      #  If the socket came from the active connection set,
     # otherwise it came from the idle set and has already been destroyed:      #  delete its transaction... note that FailTransaction should
       #  already have been called!!!
       #  otherwise it came from the idle set.
       #  
           
     if(exists($ActiveTransactions{$Socket})) {      if(exists($ActiveTransactions{$Socket})) {
  delete ($ActiveTransactions{$Socket});   delete ($ActiveTransactions{$Socket});
Line 695  sub LondWritable { Line 734  sub LondWritable {
     my @data    = $Watcher->data;      my @data    = $Watcher->data;
     Debug(6,"LondWritable State = ".$State." data has ".@data." elts.\n");      Debug(6,"LondWritable State = ".$State." data has ".@data." elts.\n");
   
     my $Socket  = $data[0]; # I know there's at least a socket.      my $Socket  = $data; # I know there's at least a socket.
   
     #  Figure out what to do depending on the state of the socket:      #  Figure out what to do depending on the state of the socket:
           
Line 814  sub QueueDelayed { Line 853  sub QueueDelayed {
  my $Handle = IO::File->new($reqfile);   my $Handle = IO::File->new($reqfile);
  my $cmd    = <$Handle>;   my $cmd    = <$Handle>;
  chomp($cmd);   chomp($cmd);
  QueueTransaction($NullSocket, $cmd);   my $Transaction = LondTransaction->new($cmd);
    $Transaction->SetDeferred($reqfile);
    QueueTransaction($Transaction);
     }      }
           
 }  }
Line 857  sub MakeLondConnection { Line 898  sub MakeLondConnection {
  $event = Event->io(fd       => $Socket,   $event = Event->io(fd       => $Socket,
    poll     => 'w',     poll     => 'w',
    cb       => \&LondWritable,     cb       => \&LondWritable,
    data     => ($Connection, undef),     data     => \$Connection,
    desc => 'Connection to lond server');     desc => 'Connection to lond server');
  $ActiveConnections{$Connection} = $event;   $ActiveConnections{$Connection} = $event;
   
Line 896  The text of the request to send. Line 937  The text of the request to send.
   
 sub StartRequest {  sub StartRequest {
     my $Lond     = shift;      my $Lond     = shift;
     my $Client   = shift;      my $Request  = shift; # This is a LondTransaction.
     my $Request  = shift;  
           
     Debug(6, "StartRequest: ".$Request);      Debug(6, "StartRequest: ".$Request->getRequest());
   
     my $Socket = $Lond->GetSocket();      my $Socket = $Lond->GetSocket();
           
     $ActiveTransactions{$Lond} = $Client; # Socket to relay to client.      $Request->Activate($Lond);
       $ActiveTransactions{$Lond} = $Request;
   
     $Lond->InitiateTransaction($Request);      $Lond->InitiateTransaction($Request->getRequest());
     $event = Event->io(fd      => $Lond->GetSocket(),      $event = Event->io(fd      => $Lond->GetSocket(),
        poll    => "w",         poll    => "w",
        cb      => \&LondWritable,         cb      => \&LondWritable,
Line 937  data to send to the lond. Line 978  data to send to the lond.
 =cut  =cut
   
 sub QueueTransaction {  sub QueueTransaction {
     my $requestSocket = shift;  
     my $requestData   = shift;  
   
     Debug(6,"QueueTransaction: ".$requestData);      my $requestData   = shift; # This is a LondTransaction.
       my $cmd           = $requestData->getRequest();
   
       Debug(6,"QueueTransaction: ".$cmd);
   
     my $LondSocket    = $IdleConnections->pop();      my $LondSocket    = $IdleConnections->pop();
     if(!defined $LondSocket) { # Need to queue request.      if(!defined $LondSocket) { # Need to queue request.
  Debug(8,"Must queue...");   Debug(8,"Must queue...");
  $ClientQueue->enqueue($requestSocket);  
  $WorkQueue->enqueue($requestData);   $WorkQueue->enqueue($requestData);
  if($ConnectionCount < $MaxConnectionCount) {   if($ConnectionCount < $MaxConnectionCount) {
     Debug(4,"Starting additional lond connection");      Debug(4,"Starting additional lond connection");
Line 953  sub QueueTransaction { Line 994  sub QueueTransaction {
  }   }
     } else { # Can start the request:      } else { # Can start the request:
  Debug(8,"Can start...");   Debug(8,"Can start...");
  StartRequest($LondSocket, $requestSocket, $requestData);   StartRequest($LondSocket,  $requestData);
     }      }
 }  }
   
Line 993  sub ClientRequest { Line 1034  sub ClientRequest {
     $watcher->data($data);      $watcher->data($data);
     if($data =~ /(.*\n)/) { # Request entirely read.      if($data =~ /(.*\n)/) { # Request entirely read.
  Debug(8, "Complete transaction received: ".$data);   Debug(8, "Complete transaction received: ".$data);
  QueueTransaction($socket, $data);   my $Transaction = new LondTransaction->new($data);
    $Transaction->SetClient($socket);
    QueueTransaction($Transaction);
  $watcher->cancel(); # Done looking for input data.   $watcher->cancel(); # Done looking for input data.
     }      }
   
Line 1055  Returns the host whose lond we talk with Line 1098  Returns the host whose lond we talk with
   
 =cut  =cut
   
 sub GetServerHost { # Stub - get this from config.  sub GetServerHost {
     return $RemoteHost; # Setup by the fork.      return $RemoteHost; # Setup by the fork.
 }  }
   
Line 1067  Returns the lond port number. Line 1110  Returns the lond port number.
   
 =cut  =cut
   
 sub GetServerPort { # Stub - get this from config.  sub GetServerPort {
     return $perlvar{londPort};      return $perlvar{londPort};
 }  }
   
Line 1088  sub SetupLoncListener { Line 1131  sub SetupLoncListener {
     my $socket;      my $socket;
     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 => 10, 
     Type   => SOCK_STREAM)) {      Type   => SOCK_STREAM)) {
  die "Failed to create a lonc listner socket";   die "Failed to create a lonc listner socket";

Removed from v.1.6  
changed lines
  Added in v.1.7


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