--- loncom/Attic/lonManage 2003/11/04 11:36:04 1.24 +++ 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.24 2003/11/04 11:36:04 foxr Exp $ +# $Id: lonManage,v 1.25 2003/11/04 11:52:06 foxr Exp $ # -# $Id: lonManage,v 1.24 2003/11/04 11:36:04 foxr Exp $ +# $Id: lonManage,v 1.25 2003/11/04 11:52:06 foxr Exp $ # # Copyright Michigan State University Board of Trustees # @@ -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,37 +219,8 @@ 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. @@ -210,43 +237,18 @@ 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 $error = 0; - my $Socket = $connection->GetSocket; - my $state; - 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"; - $retval = "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"; - $retval = "error"; - $error = 1; - } - } - } - # - # Fetch the reply from the transaction - # - if(! $error) { + my $status = SequenceStateMachine($connection, $TransitionTimeout); + if($status eq "ok") { $retval = $connection->GetReply; + } else { + $retval = $status; } return $retval; @@ -273,7 +275,6 @@ sub subreply { if($reply ne "ok") { return "connection negotiation failed"; } - print "Connection negotiated\n"; my $reply = PerformTransaction($connection, $cmd); return $reply;