--- loncom/Attic/lonManage 2003/11/03 10:48:18 1.22 +++ loncom/Attic/lonManage 2003/11/04 11:23:37 1.23 @@ -3,9 +3,9 @@ # # lonManage supports remote management of nodes in a LonCAPA cluster. # -# $Id: lonManage,v 1.22 2003/11/03 10:48:18 foxr Exp $ +# $Id: lonManage,v 1.23 2003/11/04 11:23:37 foxr Exp $ # -# $Id: lonManage,v 1.22 2003/11/03 10:48:18 foxr Exp $ +# $Id: lonManage,v 1.23 2003/11/04 11:23:37 foxr Exp $ # # Copyright Michigan State University Board of Trustees # @@ -63,8 +63,8 @@ use lib "."; use strict; # Because it's good practice. use English; # Cause I like meaningful names. use Getopt::Long; -use IO::Socket::UNIX; # To communicate with lonc. use LondConnection; +use IO::Poll qw(POLLRDNORM POLLWRNORM POLLIN POLLHUP POLLOUT); # File scoped variables: @@ -73,8 +73,16 @@ my %hostshash; # Host table as a host my $MyHost=""; # Host name to use as me. my $ForeignHostTab=""; # Name of foreign hosts table. + +my $DefaultServerPort = 5663; # Default server port if standalone. my $ServerPort; # Port used to connect to lond. +my $TransitionTimeout = 5; # Poll timeout in seconds. + + +LondConnection::SetDebug(10); + + # # prints out utility's command usage info. # @@ -112,17 +120,80 @@ USAGE } +# +# Make a direct connection to the lond in 'host'. The port is +# gotten from the global variable: ServerPort. +# Returns: +# The connection or undef if one could not be formed. +# sub MakeLondConnection { my $host = shift; my $Connection = LondConnection->new($host, $ServerPort); return return $Connection; } - +# +# This function runs through the section of the connection +# state machine that has to do with negotiating the startup +# sequence with lond. The general strategy is to loop +# until the connection state becomes idle or disconnected. +# Disconnected indicates an error or rejection of the +# connection at some point in the negotiation. +# idle indicates a connection ready for a request. +# The main loop consults the object to determine if it +# wants to be writeable or readable, waits for that +# condition on the socket (with timeout) and then issues +# the appropriate LondConnection call. Note that +# LondConnection is capable of doing everything necessary +# to get to the initial idle state. +# +# +# Parameters: +# connection - A connection that has been created with +# the remote lond. This connection should +# be in the Connected state ready to send +# the init sequence. +# sub NegotiateStartup { my $connection = shift; + my $returnstatus = "ok"; # Optimistic!!. - return "ok"; + my $state = $connection->GetState; + if($state ne "Connected") { + print "Error: Initial lond connection state: $state should be Connected\n"; + return "error"; + } + my $Socket = $connection->GetSocket; # This is a IO:Socket::INET object. + + # Ready now to enter the main loop: + # + my $error = 0; + while (($connection->GetState ne "Idle") && (!$error)) { + # + # Wait for the socket to get into the appropriate state: + # + my $wantread = $connection->WantReadable; + my $poll = new IO::Poll; + $poll->mask($Socket => $wantread ? POLLIN : POLLOUT); + $poll->poll($TransitionTimeout); + my $done = $poll->handles(); + if(scalar($done) == 0) { # Timeout!!! + print "Error: Timeout in state : $state negotiating connection\n"; + $returnstatus = "error"; + $error = 1; + } else { + my $status; + $status = $wantread ? $connection->Readable : $connection->Writable; + if ($status != 0) { + print "Error: I/O failed in state : $state negotiating connection\n"; + $returnstatus = "error"; + $error = 1; + } + } + } + + + return $returnstatus; } sub PerformTransaction { my $connection = shift; @@ -149,9 +220,10 @@ sub subreply { return "Connect Failed"; } my $reply = NegotiateStartup($connection); - if($reply != "ok") { + if($reply ne "ok") { return "connection negotiation failed"; } + print "Connection negotiated\n"; my $reply = PerformTransaction($connection, $cmd); return $reply; @@ -279,11 +351,13 @@ sub ReadConfig { $MyHost = $perlvar{lonHostID}; # Set hostname from vars. $ServerPort = $perlvar{londPort}; } else { - my $hoststab = LondConnection::read_hosts($ForeignHostTab); - %hostshash = %{$hoststab}; - $ServerPort = 5663; - } - + + LondConnection::ReadForeignConfig($MyHost, $ForeignHostTab); + my $hoststab = LondConnection::read_hosts($ForeignHostTab); # we need to know too. + %hostshash = %{$hoststab}; + $ServerPort = $DefaultServerPort; + } + } # # Determine if the target host is valid.