--- loncom/Attic/lonManage 2003/11/04 11:23:37 1.23 +++ loncom/Attic/lonManage 2003/11/04 11:52:06 1.25 @@ -3,9 +3,9 @@ # # lonManage supports remote management of nodes in a LonCAPA cluster. # -# $Id: lonManage,v 1.23 2003/11/04 11:23:37 foxr Exp $ +# $Id: lonManage,v 1.25 2003/11/04 11:52:06 foxr Exp $ # -# $Id: lonManage,v 1.23 2003/11/04 11:23:37 foxr Exp $ +# $Id: lonManage,v 1.25 2003/11/04 11:52:06 foxr Exp $ # # Copyright Michigan State University Board of Trustees # @@ -80,7 +80,7 @@ my $ServerPort; # Port used to connect my $TransitionTimeout = 5; # Poll timeout in seconds. -LondConnection::SetDebug(10); +# LondConnection::SetDebug(10); # @@ -133,6 +133,62 @@ sub MakeLondConnection { return return $Connection; } # +# Process the connection state machine until the connection +# becomes idle. This is used both to negotiate the initial +# connection, during which the LondConnection sequences a rather +# complex state machine and during the transaction itself +# for a simpler set of transitions. +# All we really need to be concerned with is whether or not +# we're readable or writable and the final state: +# +# Parameter: +# connection - Represents the LondConnection to be sequenced. +# timeout - Maximum time to wait for readable/writable sockets. +# in seconds. < 0 waits forever. +# Return: +# 'ok' - We got to idle ok. +# 'error:msg' - An error occured. msg describes the error. +# +sub SequenceStateMachine { + my $connection = shift; + my $timeout = shift; + + my $Socket = $connection->GetSocket; + my $returnstatus = "ok"; # optimist!!! + my $error = 0; # Used to force early loop termination + # damned perl has no break!!. + my $state = $connection->GetState; + + while(($connection->GetState ne "Idle") && (!$error)) { + # + # Figure out what the connection wants. read/write and wait for it + # or for the timeout. + # + my $wantread = $connection->WantReadable; + my $poll = new IO::Poll; + $poll->mask($Socket, => $wantread ? POLLIN : POLLOUT); + $poll->poll($timeout); + my $done = $poll->handles(); + if(scalar($done) == 0) { # no handles ready... timeout!! + $returnstatus = "error:"; + $returnstatus .= "Timeout in state $state\n"; + $error = 1; + } else { + my $status; + $status = $wantread ? $connection->Readable : + $connection->Writable; + if($status != 0) { + $returnstatus = "error:"; + $returnstatus .= " I/O failed in state $state\n"; + $error = 1; + } + } + $state = $connection->GetState; + } + return $returnstatus; +} + +# # 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 @@ -163,43 +219,39 @@ sub NegotiateStartup { 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; + return SequenceStateMachine($connection, $TransitionTimeout); } +# +# Perform a transaction with the remote lond. +# Paramters: +# connection - the connection object that represents +# a LondConnection to the remote lond. +# command - The request to send to the remote system. +# Returns: +# The 'reaction' of the lond to this command. +# However if the connection to lond is lost during the transaction +# or some other error occurs, the text "error:con_lost" is returned. +# sub PerformTransaction { my $connection = shift; my $command = shift; + my $retval; # What we'll returnl. + + + # Set up the connection to do the transaction then + # do the I/O until idle or error. + # + $connection->InitiateTransaction($command); + + my $status = SequenceStateMachine($connection, $TransitionTimeout); + if($status eq "ok") { + $retval = $connection->GetReply; + } else { + $retval = $status; + } - return "ok"; + return $retval; } # # Performs a transaction direct to a remote lond. @@ -223,7 +275,6 @@ sub subreply { if($reply ne "ok") { return "connection negotiation failed"; } - print "Connection negotiated\n"; my $reply = PerformTransaction($connection, $cmd); return $reply;