--- loncom/loncnew	2003/09/30 11:11:17	1.26
+++ loncom/loncnew	2003/10/21 14:24:42	1.29
@@ -2,7 +2,7 @@
 # The LearningOnline Network with CAPA
 # lonc maintains the connections to remote computers
 #
-# $Id: loncnew,v 1.26 2003/09/30 11:11:17 foxr Exp $
+# $Id: loncnew,v 1.29 2003/10/21 14:24:42 foxr Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -45,6 +45,18 @@
 
 # Change log:
 #    $Log: loncnew,v $
+#    Revision 1.29  2003/10/21 14:24:42  foxr
+#    Fix little typo that may explain growth of connections
+#
+#    Revision 1.28  2003/10/14 15:36:21  albertel
+#    - making it easier to run loncnew,
+#       /etc/init.d/loncontrol startnew
+#       /etc/init.d/loncontrol restartnew
+#      will now start loncnew in place of lonc
+#
+#    Revision 1.27  2003/10/07 11:23:03  foxr
+#    Installed and tested code to process reinit in parent server.
+#
 #    Revision 1.26  2003/09/30 11:11:17  foxr
 #    Add book-keeping hashes to support the re-init procedure.
 #
@@ -172,7 +184,7 @@ my $MaxConnectionCount = 10;	# Will get
 my $ClientConnection = 0;	# Uniquifier for client events.
 
 my $DebugLevel = 0;
-my $NextDebugLevel= 10;		# So Sigint can toggle this.
+my $NextDebugLevel= 2;		# So Sigint can toggle this.
 my $IdleTimeout= 3600;		# Wait an hour before pruning connections.
 
 #
@@ -400,18 +412,18 @@ sub Tick {
 	if ($ConnectionRetriesLeft > 0) {
 	    my $Connections = ($Requests <= $MaxConnectionCount) ?
 		$Requests : $MaxConnectionCount;
-	    Debug(1,"Work but no connections, start ".$Connections." of them");
+	    Debug(5,"Work but no connections, start ".$Connections." of them");
 	    my $successCount = 0;
 	    for (my $i =0; $i < $Connections; $i++) {
 		$successCount += MakeLondConnection();
 	    }
 	    if($successCount == 0) { # All connections failed:
-		Debug(1,"Work in queue failed to make any connectiouns\n");
+		Debug(5,"Work in queue failed to make any connectiouns\n");
 		EmptyQueue();	# Fail pending transactions with con_lost.
 	    }
 	} else {
 	    ShowStatus(GetServerHost()." >>> DEAD!!! <<<");
-	    Debug(1,"Work in queue, but gave up on connections..flushing\n");
+	    Debug(5,"Work in queue, but gave up on connections..flushing\n");
 	    EmptyQueue();	# Connections can't be established.
 	}
        
@@ -458,19 +470,19 @@ sub ServerToIdle {
     my $Socket   = shift;	# Get the socket.
     delete($ActiveTransactions{$Socket}); # Server has no transaction
 
-    &Debug(6, "Server to idle");
+    &Debug(5, "Server to idle");
 
     #  If there's work to do, start the transaction:
 
     my $reqdata = $WorkQueue->dequeue(); # This is a LondTransaction
-    unless($reqdata eq undef)  {
-	Debug(9, "Queue gave request data: ".$reqdata->getRequest());
+    if ($reqdata ne undef)  {
+	Debug(5, "Queue gave request data: ".$reqdata->getRequest());
 	&StartRequest($Socket,  $reqdata);
 
     } else {
 	
     #  There's no work waiting, so push the server to idle list.
-	&Debug(8, "No new work requests, server connection going idle");
+	&Debug(5, "No new work requests, server connection going idle");
 	$IdleConnections->push($Socket);
     }
 }
@@ -516,7 +528,7 @@ sub ClientWritable {
 	# request.
 	
 	&Debug(9,"Send result is ".$result." Defined: ".defined($result));
-	if(defined($result)) {
+	if($result ne undef) {
 	    &Debug(9, "send result was defined");
 	    if($result == length($Data)) { # Entire string sent.
 		&Debug(9, "ClientWritable data all written");
@@ -587,7 +599,7 @@ The transaction that is being completed.
 =cut
 
 sub CompleteTransaction {
-    &Debug(6,"Complete transaction");
+    &Debug(5,"Complete transaction");
     my $Socket = shift;
     my $Transaction = shift;
 
@@ -626,7 +638,6 @@ sub StartClientReply {
     &Debug(8," Reply was: ".$data);
     my $Serial         = $ActiveClients{$Client};
     my $desc           = sprintf("Connection to lonc client %d",
-
 				 $Serial);
     Event->io(fd       => $Client,
 	      poll     => "w",
@@ -658,10 +669,10 @@ Parameters:
 sub FailTransaction {
     my $transaction = shift;
     Log("WARNING", "Failing transaction ".$transaction->getRequest());
-    Debug(1, "Failing transaction: ".$transaction->getRequest());
+    Debug(5, "Failing transaction: ".$transaction->getRequest());
     if (!$transaction->isDeferred()) { # If the transaction is deferred we'll get to it.
 	my $client  = $transaction->getClient();
-	Debug(1," Replying con_lost to ".$transaction->getRequest());
+	Debug(5," Replying con_lost to ".$transaction->getRequest());
 	StartClientReply($transaction, "con_lost\n");
     }
     if($ConnectionRetriesLeft <= 0) {
@@ -875,7 +886,7 @@ sub LondReadable {
 	$ConnectionRetriesLeft = $ConnectionRetries; # success resets the count
 	$Watcher->cancel();
 	if(exists($ActiveTransactions{$Socket})) {
-	    Debug(8,"Completing transaction!!");
+	    Debug(5,"Completing transaction!!");
 	    CompleteTransaction($Socket, 
 				$ActiveTransactions{$Socket});
 	} else {
@@ -1237,11 +1248,11 @@ sub QueueTransaction {
 
     my $LondSocket    = $IdleConnections->pop();
     if(!defined $LondSocket) {	# Need to queue request.
-	Debug(8,"Must queue...");
+	Debug(5,"Must queue...");
 	$WorkQueue->enqueue($requestData);
 	if($ConnectionCount < $MaxConnectionCount) {
 	    if($ConnectionRetriesLeft > 0) {
-		Debug(4,"Starting additional lond connection");
+		Debug(5,"Starting additional lond connection");
 		if(MakeLondConnection() == 0) {
 		    EmptyQueue();	# Fail transactions, can't make connection.
 		}
@@ -1279,7 +1290,7 @@ sub ClientRequest {
     my $rv = $socket->recv($thisread, POSIX::BUFSIZ, 0);
     Debug(8, "rcv:  data length = ".length($thisread)
 	  ." read =".$thisread);
-    unless (defined $rv && length($thisread)) {
+    unless (defined $rv  && length($thisread)) {
 	 # Likely eof on socket.
 	Debug(5,"Client Socket closed on lonc for ".$RemoteHost);
 	close($socket);
@@ -1524,7 +1535,7 @@ sub CreateChild {
     my $pid          = fork;
     if($pid) {			# Parent
 	$RemoteHost = "Parent";
-	$ChildHash{$pid} = $RemoteHost;
+	$ChildHash{$pid} = $host;
 	$HostToPid{$host}= $pid;
 	sigprocmask(SIG_UNBLOCK, $sigset);
 
@@ -1664,7 +1675,7 @@ Kills off (via sigint) children for host
 
 =item
 
-HUP's children for hosts that already exist (this just forces a status display
+QUITs  children for hosts that already exist (this just forces a status display
 and resets the connection retry count for that host.
 
 =item
@@ -1675,7 +1686,84 @@ the start of the master program and main
 =cut
 
 sub UpdateKids {
+
     Log("INFO", "Updating connections via SIGUSR2");
+
+    #  Just in case we need to kill our own lonc, we wait a few seconds to
+    #  give it a chance to receive and relay lond's response to the 
+    #  re-init command.
+    #
+
+    sleep(2);			# Wait a couple of seconds.
+
+    my %hosts;                   # Indexed by loncapa hostname, value=ip.
+    
+    # Need to re-read  the host table:
+    
+    
+    LondConnection::ReadConfig();
+    my $I = LondConnection::GetHostIterator;
+    while (! $I->end()) {
+	my $item = $I->get();
+	$hosts{$item->[0]} = $item->[4];
+	$I->next();
+    }
+
+    #  The logic below is written for clarity not for efficiency.
+    #  Since I anticipate that this function is only rarely called, that's
+    #  appropriate.  There are certainly ways to combine the loops below,
+    #  and anyone wishing to obscure the logic is welcome to go for it.
+    #  Note that we don't re-direct sigchild.  Instead we do what's needed
+    #  to the data structures that keep track of children to ensure that
+    #  when sigchild is honored, no new child is born.
+    #
+
+    #  For each existing child; if it's host doesn't exist, kill the child.
+
+    foreach my $child (keys %ChildHash) {
+	my $oldhost = $ChildHash{$child};
+	if (!(exists $hosts{$oldhost})) {
+	    Log("CRITICAL", "Killing child for $oldhost  host no longer exists");
+	    delete $ChildHash{$child};
+	    delete $HostToPid{$oldhost};
+	    kill 'QUIT' => $child;
+	}
+    }
+    # For each remaining existing child; if it's host's ip has changed,
+    # Restart the child on the new IP.
+
+    foreach my $child (keys %ChildHash) {
+	my $oldhost = $ChildHash{$child};
+	my $oldip   = $HostHash{$oldhost};
+	if ($hosts{$oldhost} ne $oldip) {
+
+	    # kill the old child.
+
+	    Log("CRITICAL", "Killing child for $oldhost host ip has changed...");
+	    delete $ChildHash{$child};
+	    delete $HostToPid{$oldhost};
+	    kill 'QUIT' => $child;
+
+	    # Do the book-keeping needed to start a new child on the
+	    # new ip.
+
+	    $HostHash{$oldhost} = $hosts{$oldhost};
+	    CreateChild($oldhost);
+	}
+    }
+    # Finally, for each new host, not in the host hash, create a
+    # enter the host and create a new child.
+    # Force a status display of any existing process.
+
+    foreach my $host (keys %hosts) {
+	if(!(exists $HostHash{$host})) {
+	    Log("INFO", "New host $host discovered in hosts.tab...");
+	    $HostHash{$host} = $hosts{$host};
+	    CreateChild($host);
+	} else {
+	    kill 'HUP' => $HostToPid{$host};    # status display.
+	}
+    }
 }
 
 
@@ -1694,7 +1782,7 @@ sub Restart {
     Log("CRITICAL", "Restarting");
     my $execdir = $perlvar{'lonDaemons'};
     unlink("$execdir/logs/lonc.pid");
-    exec("$execdir/lonc");
+    exec("$execdir/loncnew");
 }
 
 =pod