Diff for /loncom/loncnew between versions 1.5 and 1.8

version 1.5, 2003/04/29 03:24:51 version 1.8, 2003/06/11 02:04:35
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 management/status request interface.  #    - Add management/status request interface.
   #    - Add deferred request capability.                  (done)
   #
   
   # Change log:
   #    $Log$
   #    Revision 1.8  2003/06/11 02:04:35  foxr
   #    Support delayed transactions... this is done uniformly by encapsulating
   #    transactions in an object ... a LondTransaction that is implemented by
   #    LondTransaction.pm
   #
   #    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 49  use POSIX qw(:signal_h); Line 62  use POSIX qw(:signal_h);
 use IO::Socket;  use IO::Socket;
 use IO::Socket::INET;  use IO::Socket::INET;
 use IO::Socket::UNIX;  use IO::Socket::UNIX;
   use IO::Handle;
 use Socket;  use Socket;
 use Crypt::IDEA;  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 85  my %ChildHash;   # by pid -> host. Line 100  my %ChildHash;   # by pid -> host.
 my $MaxConnectionCount = 5; # Will get from config later.  my $MaxConnectionCount = 5; # Will get from config later.
 my $ClientConnection = 0; # Uniquifier for client events.  my $ClientConnection = 0; # Uniquifier for client events.
   
 my $DebugLevel = 5;  my $DebugLevel = 2;
 my $IdleTimeout= 3600; # Wait an hour before pruning connections.  my $IdleTimeout= 3600; # Wait an hour before pruning connections.
   
 #  #
Line 95  my $RemoteHost;   # Name of host child i Line 110  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.
   
 #  #
   #   This disconnected socket makes posible a bit more regular
   #   code when processing delayed requests:
   #
   my $NullSocket = IO::Socket->new();
   
   #
   
 =pod  =pod
   
Line 190  sub Tick { Line 211  sub Tick {
  $IdleSeconds++;   $IdleSeconds++;
  if($IdleSeconds > $IdleTimeout) { # Prune a connection...   if($IdleSeconds > $IdleTimeout) { # Prune a connection...
     $Socket = $IdleConnections->pop();      $Socket = $IdleConnections->pop();
     KillSocket($Socket, 0);      KillSocket($Socket);
  }   }
     } else {      } else {
  $IdleSeconds = 0; # Reset idle count if not idle.   $IdleSeconds = 0; # Reset idle count if not idle.
Line 250  long enough, it will be shut down and re Line 271  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 302  sub ClientWritable { Line 320  sub ClientWritable {
     &Debug(6, "ClientWritable writing".$Data);      &Debug(6, "ClientWritable writing".$Data);
     &Debug(9, "Socket is: ".$Socket);      &Debug(9, "Socket is: ".$Socket);
   
     my $result = $Socket->send($Data, 0);      if($Socket->connected) {
    my $result = $Socket->send($Data, 0);
     # $result undefined: the write failed.  
     # otherwise $result is the number of bytes written.  
     # Remove that preceding string from the data.  
     # If the resulting data is empty, destroy the watcher  
     # and set up a read event handler to accept the next  
     # request.  
   
     &Debug(9,"Send result is ".$result." Defined: ".defined($result));  
     if(defined($result)) {  
  &Debug(9, "send result was defined");  
  if($result == length($Data)) { # Entire string sent.  
     &Debug(9, "ClientWritable data all written");  
     $Watcher->cancel();  
     #  
     #  Set up to read next request from socket:  
       
     my $descr     = sprintf("Connection to lonc client %d",  
     $ActiveClients{$Socket});  
     Event->io(cb    => \&ClientRequest,  
       poll  => 'r',  
       desc  => $descr,  
       data  => "",  
       fd    => $Socket);  
   
  } else { # Partial string sent.  
     $Watcher->data(substr($Data, $result));  
  }  
   
     } else { # Error of some sort...   # $result undefined: the write failed.
    # otherwise $result is the number of bytes written.
  # Some errnos are possible:   # Remove that preceding string from the data.
  my $errno = $!;   # If the resulting data is empty, destroy the watcher
  if($errno == POSIX::EWOULDBLOCK   ||   # and set up a read event handler to accept the next
    $errno == POSIX::EAGAIN        ||   # request.
    $errno == POSIX::EINTR) {  
     # No action taken?  
  } else { # Unanticipated errno.  
     &Debug(5,"ClientWritable error or peer shutdown".$RemoteHost);  
     $Watcher->cancel; # Stop the watcher.  
     $Socket->shutdown(2); # Kill connection  
     $Socket->close(); # Close the socket.  
  }  
   
    &Debug(9,"Send result is ".$result." Defined: ".defined($result));
    if(defined($result)) {
       &Debug(9, "send result was defined");
       if($result == length($Data)) { # Entire string sent.
    &Debug(9, "ClientWritable data all written");
    $Watcher->cancel();
    #
    #  Set up to read next request from socket:
   
    my $descr     = sprintf("Connection to lonc client %d",
    $ActiveClients{$Socket});
    Event->io(cb    => \&ClientRequest,
     poll  => 'r',
     desc  => $descr,
     data  => "",
     fd    => $Socket);
   
       } else { # Partial string sent.
    $Watcher->data(substr($Data, $result));
       }
       
    } else { # Error of some sort...
       
       # Some errnos are possible:
       my $errno = $!;
       if($errno == POSIX::EWOULDBLOCK   ||
          $errno == POSIX::EAGAIN        ||
          $errno == POSIX::EINTR) {
    # No action taken?
       } else { # Unanticipated errno.
    &Debug(5,"ClientWritable error or peer shutdown".$RemoteHost);
    $Watcher->cancel; # Stop the watcher.
    $Socket->shutdown(2); # Kill connection
    $Socket->close(); # Close the socket.
       }
       
    }
       } else {
    $Watcher->cancel(); # A delayed request...just cancel.
     }      }
 }  }
   
Line 367  Parameters: Line 389  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
    my $data   = $Socket->GetReply(); # Data to send.
    StartClientReply($Transaction, $data);
       } else { # Delete deferred transaction file.
    &Debug(4, "Deferred transaction complete: ".$Transaction->getFile().
          " request: ".$Transaction->getRequest().
          " answer: ".$Socket->GetReply());
    unlink $Transaction->getFile();
       }
   }
   =pod
   =head1 StartClientReply
   
      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
   sub StartClientReply {
       my $Transaction   = 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",
   
  $Serial);   $Serial);
     Event->io(fd       => $Client,      Event->io(fd       => $Client,
       poll     => "w",        poll     => "w",
Line 394  sub CompleteTransaction { Line 447  sub CompleteTransaction {
 =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();
       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
   =head1  EmptyQueue
   
     &Debug(8, "Failing transaction due to disconnect");    Fails all items in the work queue with con_lost.
     my $Serial = $ActiveClients{$client};    Note that each item in the work queue is a transaction.
     my $desc   = sprintf("Connection to lonc client %d", $Serial);  
     my $data   = "error: Connection to lond lost\n";  
   
     Event->io(fd     => $client,  
       poll   => "w",  
       desc   => $desc,  
       cb     => \&ClientWritable,  
       data   => $data);  
   
   =cut
   sub EmptyQueue {
       while($WorkQueue->Count()) {
    my $request = $Workqueue->dequeue(); # This is a transaction
    FailTransaction($request);
       }
 }  }
   
 =pod  =pod
Line 444  nonzero if we are allowed to create a ne Line 514  nonzero if we are allowed to create a ne
 =cut  =cut
 sub KillSocket {  sub KillSocket {
     my $Socket = shift;      my $Socket = shift;
     my $Restart= 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 456  sub KillSocket { Line 528  sub KillSocket {
  delete($ActiveConnections{$Socket});   delete($ActiveConnections{$Socket});
     }      }
     $ConnectionCount--;      $ConnectionCount--;
     if( ($ConnectionCount = 0) && ($Restart)) {  
  MakeLondConnection();  
     }  
   
       #  If the connection count has gone to zero and there is work in the
       #  work queue, the work all gets failed with con_lost.
       #
       if($ConnectionCount == 0) {
    EmptyQueue;
       }
 }  }
   
 =pod  =pod
Line 521  transaction is in progress, the socket a Line 596  transaction is in progress, the socket a
 =cut  =cut
   
 sub LondReadable {  sub LondReadable {
   
     my $Event      = shift;      my $Event      = shift;
     my $Watcher    = $Event->w;      my $Watcher    = $Event->w;
     my $Socket     = $Watcher->data;      my $Socket     = $Watcher->data;
     my $client     = undef;      my $client     = undef;
   
       &Debug(6,"LondReadable called state = ".$State);
   
   
     my $State = $Socket->GetState(); # All action depends on the state.      my $State = $Socket->GetState(); # All action depends on the state.
   
     &Debug(6,"LondReadable called state = ".$State);  
     SocketDump(6, $Socket);      SocketDump(6, $Socket);
   
     if($Socket->Readable() != 0) {      if($Socket->Readable() != 0) {
Line 541  sub LondReadable { Line 618  sub LondReadable {
     FailTransaction($ActiveTransactions{$Socket});      FailTransaction($ActiveTransactions{$Socket});
  }   }
  $Watcher->cancel();   $Watcher->cancel();
  KillSocket($Socket, 1);   KillSocket($Socket);
  return;   return;
     }      }
     SocketDump(6,$Socket);      SocketDump(6,$Socket);
Line 557  sub LondReadable { Line 634  sub LondReadable {
  # in the connection takes care of setting that up.  Just   # in the connection takes care of setting that up.  Just
  # need to transition to writable:   # need to transition to writable:
   
  $Watcher->poll("w");  
  $Watcher->cb(\&LondWritable);   $Watcher->cb(\&LondWritable);
    $Watcher->poll("w");
   
     } elsif ($State eq "ChallengeReplied") {      } elsif ($State eq "ChallengeReplied") {
   
Line 567  sub LondReadable { Line 644  sub LondReadable {
  #  The ok was received.  Now we need to request the key   #  The ok was received.  Now we need to request the key
  #  That requires us to be writable:   #  That requires us to be writable:
   
  $Watcher->poll("w");  
  $Watcher->cb(\&LondWritable);   $Watcher->cb(\&LondWritable);
    $Watcher->poll("w");
   
     } elsif ($State eq "ReceivingKey") {      } elsif ($State eq "ReceivingKey") {
   
     } elsif ($State eq "Idle") {      } elsif ($State eq "Idle") {
  # If necessary, complete a transaction and then go into the   # If necessary, complete a transaction and then go into the
  # idle queue.   # idle queue.
    $Watcher->cancel();
  if(exists($ActiveTransactions{$Socket})) {   if(exists($ActiveTransactions{$Socket})) {
     Debug(8,"Completing transaction!!");      Debug(8,"Completing transaction!!");
     CompleteTransaction($Socket,       CompleteTransaction($Socket, 
  $ActiveTransactions{$Socket});   $ActiveTransactions{$Socket});
  }   }
  $Watcher->cancel();  
  ServerToIdle($Socket); # Next work unit or idle.   ServerToIdle($Socket); # Next work unit or idle.
   
     } 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
  #  here inthe first place.   #  here inthe first place.
Line 664  is the socket on which to return a reply Line 741  is the socket on which to return a reply
 sub LondWritable {  sub LondWritable {
     my $Event   = shift;      my $Event   = shift;
     my $Watcher = $Event->w;      my $Watcher = $Event->w;
     my @data    = $Watcher->data;      my $Socket  = $Watcher->data;
     Debug(6,"LondWritable State = ".$State." data has ".@data." elts.\n");      my $State   = $Socket->GetState();
   
     my $Socket  = $data[0]; # I know there's at least a socket.      Debug(6,"LondWritable State = ".$State."\n");
   
    
     #  Figure out what to do depending on the state of the socket:      #  Figure out what to do depending on the state of the socket:
           
   
     my $State   = $Socket->GetState();  
   
   
     SocketDump(6,$Socket);      SocketDump(6,$Socket);
Line 684  sub LondWritable { Line 761  sub LondWritable {
     # We'll treat this as if the socket got disconnected:      # We'll treat this as if the socket got disconnected:
   
     $Watcher->cancel();      $Watcher->cancel();
     KillSocket($Socket, 1);      KillSocket($Socket);
     return;      return;
  }   }
  #  "init" is being sent...   #  "init" is being sent...
Line 695  sub LondWritable { Line 772  sub LondWritable {
  # Now that init was sent, we switch    # Now that init was sent, we switch 
  # to watching for readability:   # to watching for readability:
   
  $Watcher->poll("r");  
  $Watcher->cb(\&LondReadable);   $Watcher->cb(\&LondReadable);
    $Watcher->poll("r");
   
     } elsif ($State eq "ChallengeReceived") {      } elsif ($State eq "ChallengeReceived") {
  # We received the challenge, now we    # We received the challenge, now we 
Line 706  sub LondWritable { Line 783  sub LondWritable {
  if($Socket->Writable() != 0) {   if($Socket->Writable() != 0) {
   
     $Watcher->cancel();      $Watcher->cancel();
     KillSocket($Socket, 1);      KillSocket($Socket);
     return;      return;
  }   }
   
Line 714  sub LondWritable { Line 791  sub LondWritable {
  # The echo was sent back, so we switch   # The echo was sent back, so we switch
  # to watching readability.   # to watching readability.
   
  $Watcher->poll("r");  
  $Watcher->cb(\&LondReadable);   $Watcher->cb(\&LondReadable);
    $Watcher->poll("r");
   
     } elsif ($State eq "RequestingKey")     {      } elsif ($State eq "RequestingKey")     {
  # At this time we're requesting the key.   # At this time we're requesting the key.
Line 727  sub LondWritable { Line 804  sub LondWritable {
     # Write resulted in an error.      # Write resulted in an error.
   
     $Watcher->cancel();      $Watcher->cancel();
     KillSocket($Socket, 1);      KillSocket($Socket);
     return;      return;
   
  }   }
Line 735  sub LondWritable { Line 812  sub LondWritable {
  # Now we need to wait for the key   # Now we need to wait for the key
  # to come back from the peer:   # to come back from the peer:
   
  $Watcher->poll("r");  
  $Watcher->cb(\&LondReadable);   $Watcher->cb(\&LondReadable);
    $Watcher->poll("r");
   
     } elsif ($State eq "SendingRequest")    {      } elsif ($State eq "SendingRequest")    {
  # At this time we are sending a request to the   # At this time we are sending a request to the
Line 749  sub LondWritable { Line 826  sub LondWritable {
  FailTransaction($ActiveTransactions{$Socket});   FailTransaction($ActiveTransactions{$Socket});
     }      }
     $Watcher->cancel();      $Watcher->cancel();
     KillSocket($Socket, 1);      KillSocket($Socket);
     return;      return;
           
  }   }
Line 758  sub LondWritable { Line 835  sub LondWritable {
  # The send has completed.  Wait for the   # The send has completed.  Wait for the
  # data to come in for a reply.   # data to come in for a reply.
  Debug(8,"Writable sent request/receiving reply");   Debug(8,"Writable sent request/receiving reply");
  $Watcher->poll("r");  
  $Watcher->cb(\&LondReadable);   $Watcher->cb(\&LondReadable);
    $Watcher->poll("r");
   
     } else {      } else {
  #  Control only passes here on an error:    #  Control only passes here on an error: 
Line 771  sub LondWritable { Line 848  sub LondWritable {
     }      }
           
 }  }
   =pod
       
   =cut
   sub QueueDelayed {
       Debug(3,"QueueDelayed called");
   
       my $path = "$perlvar{'lonSockDir'}/delayed";
   
       Debug(4, "Delayed path: ".$path);
       opendir(DIRHANDLE, $path);
       
       @alldelayed = grep /\.$RemoteHost$/, readdir DIRHANDLE;
       Debug(4, "Got ".$alldelayed." delayed files");
       closedir(DIRHANDLE);
       my $dfname;
       my $reqfile;
       foreach $dfname (sort  @alldelayed) {
    $reqfile = "$path/$dfname";
    Debug(4, "queueing ".$reqfile);
    my $Handle = IO::File->new($reqfile);
    my $cmd    = <$Handle>;
    chomp $cmd; # There may or may not be a newline...
    $cmd = $cmd."\ny"; # now for sure there's exactly one newline.
    my $Transaction = LondTransaction->new($cmd);
    $Transaction->SetDeferred($reqfile);
    QueueTransaction($Transaction);
       }
       
   }
   
 =pod  =pod
   
Line 810  sub MakeLondConnection { Line 916  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;
   
  $ConnectionCount++;   $ConnectionCount++;
    Debug(4, "Connection count = ".$ConnectionCount);
    if($ConnectionCount == 1) { # First Connection:
       QueueDelayed;
    }
     }      }
           
 }  }
Line 846  The text of the request to send. Line 956  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      => $Socket,
        poll    => "w",         poll    => "w",
        cb      => \&LondWritable,         cb      => \&LondWritable,
        data    => $Lond,         data    => $Lond,
Line 887  data to send to the lond. Line 997  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 903  sub QueueTransaction { Line 1013  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 943  sub ClientRequest { Line 1053  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 = LondTransaction->new($data);
    $Transaction->SetClient($socket);
    QueueTransaction($Transaction);
  $watcher->cancel(); # Done looking for input data.   $watcher->cancel(); # Done looking for input data.
     }      }
   
Line 1005  Returns the host whose lond we talk with Line 1117  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 1017  Returns the lond port number. Line 1129  Returns the lond port number.
   
 =cut  =cut
   
 sub GetServerPort { # Stub - get this from config.  sub GetServerPort {
     return $perlvar{londPort};      return $perlvar{londPort};
 }  }
   
Line 1038  sub SetupLoncListener { Line 1150  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";
Line 1125  sub CreateChild { Line 1237  sub CreateChild {
 #  #
   
   
   
   
   
   
   ShowStatus("Forming new session");
   my $childpid = fork;
   if ($childpid != 0) {
       sleep 4; # Give child a chacne to break to
       exit 0; # a new sesion.
   }
   #
   #   Write my pid into the pid file so I can be located
   #
   
 ShowStatus("Parent writing pid file:");  ShowStatus("Parent writing pid file:");
 $execdir = $perlvar{'lonDaemons'};  $execdir = $perlvar{'lonDaemons'};
 open (PIDSAVE, ">$execdir/logs/lonc.pid");  open (PIDSAVE, ">$execdir/logs/lonc.pid");
 print PIDSAVE "$$\n";  print PIDSAVE "$$\n";
 close(PIDSAVE);  close(PIDSAVE);
   
   if (POSIX::setsid() < 0) {
       print "Could not create new session\n";
       exit -1;
   }
   
 ShowStatus("Forking node servers");  ShowStatus("Forking node servers");
   
 my $HostIterator = LondConnection::GetHostIterator;  my $HostIterator = LondConnection::GetHostIterator;

Removed from v.1.5  
changed lines
  Added in v.1.8


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