--- loncom/loncnew 2003/04/18 03:10:36 1.3 +++ loncom/loncnew 2003/04/24 10:56:55 1.4 @@ -2,7 +2,7 @@ # The LearningOnline Network with CAPA # lonc maintains the connections to remote computers # -# $Id: loncnew,v 1.3 2003/04/18 03:10:36 albertel Exp $ +# $Id: loncnew,v 1.4 2003/04/24 10:56:55 foxr Exp $ # # Copyright Michigan State University Board of Trustees # @@ -100,7 +100,7 @@ my %ActiveClients; # Serial numbers of my $WorkQueue = Queue->new(); # Queue of pending transactions. my $ClientQueue = Queue->new(); # Queue of clients causing xactinos. my $ConnectionCount = 0; - +my $IdleSeconds = 0; # Number of seconds idle. # @@ -163,11 +163,25 @@ Invoked each timer tick. sub Tick { my $client; + $0 = 'lonc: '.GetServerHost()." Connection count: ".$ConnectionCount; Debug(6, "Tick"); Debug(6, " Current connection count: ".$ConnectionCount); foreach $client (keys %ActiveClients) { Debug(7, " Have client: with id: ".$ActiveClients{$client}); } + # Is it time to prune connection count: + + + if($IdleConnections->Count() && + ($WorkQueue->Count() == 0)) { # Idle connections and nothing to do? + $IdleSeconds++; + if($IdleSeconds > $IdleTimeout) { # Prune a connection... + $Socket = $IdleConnections->pop(); + KillSocket($Socket, 0); + } + } else { + $IdleSeconds = 0; # Reset idle count if not idle. + } } =pod @@ -348,7 +362,77 @@ sub CompleteTransaction { cb => \&ClientWritable, data => $data); } +=pod +=head2 FailTransaction + + Finishes a transaction with failure because the associated lond socket + disconnected. It is up to our client to retry if desired. + +Parameters: + +=item client + + The UNIX domain socket open on our client. + +=cut + +sub FailTransaction { + my $client = shift; + + &Debug(8, "Failing transaction due to disconnect"); + my $Serial = $ActiveClients{$client}; + 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); + +} + +=pod + +=head2 KillSocket + +Destroys a socket. This function can be called either when a socket +has died of 'natural' causes or because a socket needs to be pruned due to +idleness. If the socket has died naturally, if there are no longer any +live connections a new connection is created (in case there are transactions +in the queue). If the socket has been pruned, it is never re-created. + +Parameters: +=item Socket + + The socket to kill off. + +=item Restart + +nonzero if we are allowed to create a new connection. + + +=cut +sub KillSocket { + my $Socket = shift; + my $Restart= shift; + + # If the socket came from the active connection set, delete it. + # otherwise it came from the idle set and has already been destroyed: + + if(exists($ActiveTransactions{$Socket})) { + delete ($ActiveTransactions{$Socket}); + } + if(exists($ActiveConnections{$Socket})) { + delete($ActiveConnections{$Socket}); + } + $ConnectionCount--; + if( ($ConnectionCount = 0) && ($Restart)) { + MakeLondConnection(); + } + +} =pod @@ -421,7 +505,16 @@ sub LondReadable { SocketDump(6, $Socket); if($Socket->Readable() != 0) { - # bad return from socket read. + # bad return from socket read. Currently this means that + # The socket has become disconnected. We fail the transaction. + + if(exists($ActiveTransactions{$Socket})) { + Debug(3,"Lond connection lost failing transaction"); + FailTransaction($ActiveTransactions{$Socket}); + } + $Watcher->cancel(); + KillSocket($Socket, 1); + return; } SocketDump(6,$Socket); @@ -557,11 +650,20 @@ sub LondWritable { SocketDump(6,$Socket); if ($State eq "Connected") { - # "init" is being sent... if ($Socket->Writable() != 0) { # The write resulted in an error. + # We'll treat this as if the socket got disconnected: + if(exists($ActiveTransactions{$Socket})) { + Debug(3, "Lond connection lost, failing transactions"); + FailTransaction($ActiveTransactions{$Socket}); + } + $Watcher->cancel(); + KillSocket($Socket, 1); + return; } + # "init" is being sent... + } elsif ($State eq "Initialized") { @@ -672,7 +774,7 @@ sub MakeLondConnection { cb => \&LondWritable, data => ($Connection, undef), desc => 'Connection to lond server'); - $ActiveConnections{$Lond} = $event; + $ActiveConnections{$Connection} = $event; $ConnectionCount++;