[LON-CAPA-cvs] cvs: loncom / loncnew

foxr lon-capa-cvs@mail.lon-capa.org
Mon, 05 May 2003 23:40:27 -0000


This is a MIME encoded message

--foxr1052178027
Content-Type: text/plain

foxr		Mon May  5 19:40:27 2003 EDT

  Modified files:              
    /loncom	loncnew 
  Log:
  >>>>UNTESTED<<<<<
    Add beginnings of code for delayed transactions...
    Add code to fork off into separate session...
  >>>>UNTESTED<<<<
    Comitting prior to ripping guts out to re-cast the transaction as an object
  so that state/history/etc. can be more easily carried with it (need to do that
  to know when to retire a delayed transaction).
  
  
  
--foxr1052178027
Content-Type: text/plain
Content-Disposition: attachment; filename="foxr-20030505194027.txt"

Index: loncom/loncnew
diff -u loncom/loncnew:1.5 loncom/loncnew:1.6
--- loncom/loncnew:1.5	Mon Apr 28 23:24:51 2003
+++ loncom/loncnew	Mon May  5 19:40:27 2003
@@ -2,7 +2,7 @@
 # The LearningOnline Network with CAPA
 # lonc maintains the connections to remote computers
 #
-# $Id: loncnew,v 1.5 2003/04/29 03:24:51 foxr Exp $
+# $Id: loncnew,v 1.6 2003/05/05 23:40:27 foxr Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -49,6 +49,7 @@
 use IO::Socket;
 use IO::Socket::INET;
 use IO::Socket::UNIX;
+use IO::Handle;
 use Socket;
 use Crypt::IDEA;
 use LONCAPA::Queue;
@@ -103,6 +104,12 @@
 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
 
@@ -190,7 +197,7 @@
 	$IdleSeconds++;
 	if($IdleSeconds > $IdleTimeout) { # Prune a connection...
 	    $Socket = $IdleConnections->pop();
-	    KillSocket($Socket, 0);
+	    KillSocket($Socket);
 	}
     } else {
 	$IdleSeconds = 0;	# Reset idle count if not idle.
@@ -302,51 +309,55 @@
     &Debug(6, "ClientWritable writing".$Data);
     &Debug(9, "Socket is: ".$Socket);
 
-    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));
-	}
+    if($Socket->connected) {
+	my $result = $Socket->send($Data, 0);
 	
-    } 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.
-	}
+	# $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...
+	    
+	    # 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.
     }
 }
 
@@ -379,10 +390,22 @@
     my $Client = shift;
 
     my $data   = $Socket->GetReply(); # Data to send.
+    StartClientReply($Client, $data);
+}
+=pod
+=head1 StartClientReply
+
+   Initiates a reply to a client where the reply data is a parameter.
+
+=cut
+sub StartClientReply {
+    my $Client   = shift;
+    my $data     = shift;
 
     &Debug(8," Reply was: ".$data);
     my $Serial         = $ActiveClients{$Client};
     my $desc           = sprintf("Connection to lonc client %d",
+
 				 $Serial);
     Event->io(fd       => $Client,
 	      poll     => "w",
@@ -407,20 +430,23 @@
 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);
+    StartClientReply($client, "con_lost");
 
 }
 
 =pod
+=head1  EmptyQueue
+  Fails all items in the work queue with con_lost.
+=cut
+sub EmptyQueue {
+    while($WorkQueue->Count()) {
+	my $request = $WorkQUeue->dequeue(); # Just to help it become empty.
+	my $client  = $ClientQueue->dequeue(); #  Need to con_lost this guy.
+	FailTransaction($client);
+    }
+}
+
+=pod
 
 =head2 KillSocket
  
@@ -444,7 +470,6 @@
 =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:
@@ -456,10 +481,13 @@
 	delete($ActiveConnections{$Socket});
     }
     $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
@@ -541,7 +569,7 @@
 	    FailTransaction($ActiveTransactions{$Socket});
 	}
 	$Watcher->cancel();
-	KillSocket($Socket, 1);
+	KillSocket($Socket);
 	return;
     }
     SocketDump(6,$Socket);
@@ -582,7 +610,7 @@
 	}
 	$Watcher->cancel();
 	ServerToIdle($Socket);	# Next work unit or idle.
-
+	
     } elsif ($State eq "SendingRequest") {
 	#  We need to be writable for this and probably don't belong
 	#  here inthe first place.
@@ -684,7 +712,7 @@
 	    # We'll treat this as if the socket got disconnected:
 
 	    $Watcher->cancel();
-	    KillSocket($Socket, 1);
+	    KillSocket($Socket);
 	    return;
 	}
 	#  "init" is being sent...
@@ -706,7 +734,7 @@
 	if($Socket->Writable() != 0) {
 
 	    $Watcher->cancel();
-	    KillSocket($Socket, 1);
+	    KillSocket($Socket);
 	    return;
 	}
 	
@@ -727,7 +755,7 @@
 	    # Write resulted in an error.
 
 	    $Watcher->cancel();
-	    KillSocket($Socket, 1);
+	    KillSocket($Socket);
 	    return;
 
 	}
@@ -749,7 +777,7 @@
 		FailTransaction($ActiveTransactions{$Socket});
 	    }
 	    $Watcher->cancel();
-	    KillSocket($Socket, 1);
+	    KillSocket($Socket);
 	    return;
 	    
 	}
@@ -771,6 +799,25 @@
     }
     
 }
+=pod
+    
+=cut
+sub QueueDelayed {
+    my $path = "$perlvar{'lonSockDir'}/delayed";
+    opendir(DIRHANDLE, $path);
+    @alldelayed = grep /\.$RemoteHost$/, readdir DIRHANDLE;
+    closedir(DIRHANDLE);
+    my $dfname;
+    my $reqfile
+    foreach $reqfile (sort @alldelayed) {
+	$reqfile = $path/$reqfile;
+	my $Handle = IO::File->new($reqfile);
+	my $cmd    = <$Handle>;
+	chomp($cmd);
+	QueueTransaction($NullSocket, $cmd);
+    }
+    
+}
 
 =pod
 
@@ -815,6 +862,9 @@
 	$ActiveConnections{$Connection} = $event;
 	
 	$ConnectionCount++;
+	if($ConnectionCount == 1) { # First Connection:
+	    QueueDelayed;
+	}
     }
     
 }
@@ -1125,11 +1175,25 @@
 #
 
 
+
+
 ShowStatus("Parent writing pid file:");
 $execdir = $perlvar{'lonDaemons'};
 open (PIDSAVE, ">$execdir/logs/lonc.pid");
 print PIDSAVE "$$\n";
 close(PIDSAVE);
+
+ShowStatus("Forming new session");
+my $childpid = fork;
+if ($childpid != 0) {
+    sleep 4;			# Give child a chacne to break to
+    exit 0;			# a new sesion.
+}
+
+if (POSIX::setsid() < 0) {
+    print "Could not create new session\n";
+    exit -1;
+}
 
 ShowStatus("Forking node servers");
 

--foxr1052178027--