ComputeClientControllerCmdsImpl.mesa
Client side of the interface implementation for package submission. Also includes other procedures since ComputeClientImpl is too big.
Last Edited by: Bob Hagmann, January 29, 1986 9:46:21 am PST
Copyright © 1984 by Xerox Corporation. All rights reserved.
DIRECTORY
Atom,
Basics,
BasicTime,
Commander,
CommandTool,
ComputeClient,
ComputeServerClient,
ComputeClientInternal,
ComputeServerControllerRpcControl,
ComputeUtils,
Convert,
DFUtilities,
FileNames,
FS,
IO,
ProcessProps,
PupDefs,
PupErrors,
PupStream,
PupTypes,
Real,
Rope,
RPC;
ComputeClientControllerCmdsImpl: CEDAR MONITOR
IMPORTS BasicTime, Commander, CommandTool, ComputeClientInternal, ComputeServerControllerRpcControl, ComputeUtils, Convert, DFUtilities, FileNames, FS, IO, PupDefs, PupErrors, PupStream, Rope, RPC
EXPORTS ComputeClient
= BEGIN
Declarations
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
Package Submission
SubmitPackage: Commander.CommandProc = {
PROC [cmd: Handle] RETURNS [result: REFNIL, msg: Rope.ROPENIL]
1) Insure .df file has a global attachment
2) Process the .df file, and extract the .remoteCommands and .summonerload files, and build a list of all the exported file.
3) open remoteCommands file. Check that it parses OK and is reasonable.
4) open summonerload file. Check packages in summonerload for export in the .df file, and check to see that the files with these create dates exist.
5) Take package bcd and generate IMPORTs. Check against list of good imports. Complain if needed. (this should be done on the controller, and be protected, but I trust people) This is a noop for now, however.
6) Tell the controller about the new package.
argv: CommandTool.ArgumentVector;
fileName: ROPE;
cleanFName, package: ROPE;
fullDFFName: ROPE;
fullDFcp: FS.ComponentPositions;
attachedFile: ROPE;
dfLog: IO.STREAMIO.ROS[];
dfLogRope: ROPENIL;
controllerError: BOOLFALSE;
tryDifferentController: BOOLFALSE;
controllerMsg: ROPENIL;
lastDir: REF DFUtilities.DirectoryItem ← NIL;
tempControllerInterface: ComputeServerControllerRpcControl.InterfaceRecord;
remoteCommands: ROPENIL;
fullNameOfRemoteCommands: ROPENIL;
summonerLoad: ROPENIL;
fullNameOfSummonerLoad: ROPENIL;
packageDFStream: IO.STREAM;
mainDFFileCreated: BasicTime.GMT;
noIERRyet: BOOLTRUE;
exportedFilesList: LIST OF exportedFiles ← NIL;
exportedFiles: TYPE = RECORD [
path1: ROPENIL,
included: BOOLFALSE,
file: REF DFUtilities.FileItem ← NIL,
name: ROPE
];
{ -- nest to get the EXIT to see variables
DoOneItemFromDFFile: DFUtilities.ProcessItemProc = {
PROC [item: REF ANY] RETURNS [stop: BOOLFALSE]
errors, warnings, filesActedUpon: INT ← 0;
WITH item SELECT FROM
dir: REF DFUtilities.DirectoryItem => {
lastDir ← dir;
};
imports: REF DFUtilities.ImportsItem => {
importsCreated: BasicTime.GMT;
[created: importsCreated] ← FS.FileInfo[name: imports.path1, remoteCheck: TRUE ! FS.Error => {
ERROR DFUtilities.SyntaxError[Rope.Cat["Imported df file ", imports.path1, " does not exist on the file server"]];
};
];
IF BasicTime.Period[from: mainDFFileCreated, to: importsCreated] > 0 THEN {
cmd.out.PutRope[Rope.Cat["Warning: Imported df file ", imports.path1, " newer than package df file.\n"]];
IF noIERRyet THEN {
cmd.out.PutRope["Bringover the package df file and see if new attachments are made for interfaces. If so, rebuild, smodel and submit the package. If no interfaces have changed but there are newer implementations (packages in the summonerLoad file), then a package you depend on has changed. Edit the package df file (replace a space with a space), smodel it, and submit the package."];
};
noIERRyet ← FALSE;
};
IF imports.exported THEN {
IF imports.form # list THEN {
RETURN[FALSE];
};
FOR i:NAT IN [0..imports.list.nEntries) DO
using: DFUtilities.UsingEntry = imports.list[i];
exportedFilesList ← CONS[[path1: imports.path1, name: using.name, included: TRUE], exportedFilesList];
ENDLOOP;
};
};
comment: REF DFUtilities.CommentItem => {
};
white: REF DFUtilities.WhiteSpaceItem => {
};
file: REF DFUtilities.FileItem => {
shortName: ROPE = Rope.Substr[file.name, 0, Rope.Index[s1: file.name, s2: "!"]];
IF lastDir = NIL THEN ERROR DFUtilities.SyntaxError["no directory item before files"]
ELSE {
IF lastDir.exported THEN exportedFilesList ← CONS[[path1: lastDir.path1, file: file, included: FALSE], exportedFilesList];
};
IF Rope.Equal[remoteCommands, shortName, FALSE] THEN fullNameOfRemoteCommands ← Rope.Concat[exportedFilesList.first.path1, exportedFilesList.first.file.name];
IF Rope.Equal[summonerLoad, shortName, FALSE] THEN fullNameOfSummonerLoad ← Rope.Concat[exportedFilesList.first.path1, exportedFilesList.first.file.name];
};
ENDCASE;
};
checkSummonerRemoteCommands: PROC RETURNS [good: BOOLTRUE] = {
fileName: ROPE = fullNameOfRemoteCommands ;
packageListStream: IO.STREAM;
maintainer: LIST OF ROPENIL;
commands: LIST OF ROPENIL;
version: LIST OF ROPENIL;
count: INT ← 0 ;
IF fileName = NIL THEN {msg ← "no remoteCommands file in DF file"; RETURN[FALSE]};
packageListStream ← FS.StreamOpen[fileName
! FS.Error => GOTO cantOpen];
DO
token: ROPENIL;
tokens, tail: LIST OF ROPENIL;
key: ROPENIL;
token ← ComputeUtils.LocalToken[packageListStream, TRUE];
IF (key ← token) = NIL THEN EXIT;
SELECT ComputeUtils.SkipWhite[packageListStream] FROM
': => [] ← packageListStream.GetChar[]; -- flush the ':
ENDCASE => {
key was NOT followed by ':, so flush to the end of line and report the error
DO
IF packageListStream.GetChar[ ! IO.EndOfStream => EXIT] = '\n THEN EXIT;
ENDLOOP;
ReportInternal[msg: IO.PutFR["missing : at [%d]", IO.int[position]]];
LOOP;
};
DO
list: LIST OF ROPENIL;
token ← ComputeUtils.LocalToken[packageListStream];
IF token = NIL THEN EXIT;
list ← LIST[token];
IF tail = NIL
THEN {tail ← tokens ← list}
ELSE {tail.rest ← list; tail ← list};
ENDLOOP;
now the key is key, and the list of tokens is in tokens
SELECT TRUE FROM
Rope.Equal[key, "version", FALSE] => {
IF tail = NIL
THEN {version ← tokens}
ELSE {tail.rest ← version; version ← tokens};
};
Rope.Equal[key, "maintainer", FALSE] => {
IF tail = NIL
THEN {maintainer ← tokens}
ELSE {tail.rest ← maintainer; maintainer ← tokens};
};
Rope.Equal[key, "commands", FALSE] => {
IF tail = NIL
THEN {commands ← tokens}
ELSE {tail.rest ← commands; commands ← tokens};
};
Rope.Equal[key, "exclusive", FALSE] => {
IF tail = NIL OR tail # tokens
THEN {
msg ← "exactly one parameter needed for exclusive in .remoteCommands file";
RETURN [FALSE];
}
ELSE {
SELECT ComputeUtils.trueOrFalse[tail.first] FROM
true => {};
false => {};
ENDCASE => {
msg ← "invalid parameter for exclusive in .remoteCommands file";
RETURN [FALSE];
};
};
};
Rope.Equal[key, "countActive", FALSE] => {
IF tail = NIL OR tail # tokens THEN {
msg ← "exactly one parameter needed for countActive in .remoteCommands file";
RETURN [FALSE];
}
ELSE {
count : INT;
bad: BOOLFALSE;
count ← Convert.IntFromRope[tail.first ! Convert.Error => {bad ← TRUE; CONTINUE}];
IF bad THEN {
msg ← "bad parameter for countActive in .remoteCommands file";
RETURN [FALSE];
};
IF count <= 0 THEN {
msg ← "count <= 0 for countActive in .remoteCommands file";
RETURN [FALSE];
};
};
};
ENDCASE => {
allWhitespace: BOOLFALSE;
tokenKind: IO.TokenKind ← tokenERROR;
[tokenKind: tokenKind] ← IO.GetCedarTokenRope[IO.RIS[key] !
IO.EndOfStream => {
allWhitespace ← TRUE;
CONTINUE;
};
IO.Error => {
CONTINUE;
};
];
IF tokenKind = tokenEOF OR tokenKind = tokenCOMMENT THEN allWhitespace ← TRUE;
IF ~allWhitespace THEN {
packageListStream.Close[];
msg ← Rope.Concat[key, " is an unknown keyword in the remoteCommands file"];
RETURN [FALSE];
};
};
ENDLOOP; -- for that DO way back up there
IF commands = NIL THEN {
packageListStream.Close[];
msg ← "no commands specified in .remoteCommands file";
RETURN [FALSE];
};
packageListStream.Close[];
EXITS
cantOpen => { msg ← "cannot open .remoteCommands file"; RETURN [FALSE];};
};
checkSummonerLoad: PROC RETURNS [good: BOOLTRUE] = {
parseStateType: TYPE = {sawName, sawLeft, sawGFI, sawRight};
packageLoad: ROPE = fullNameOfSummonerLoad ;
packageLoadStream: IO.STREAM;
containedPackage: ROPENIL;
shortBcdName: ROPENIL;
parseState: parseStateType ← sawRight;
count: INT ← 0 ;
IF packageLoad = NIL THEN {msg ← "no summonerLoad file in DF file"; RETURN[FALSE]};
{
packageLoadStream ← FS.StreamOpen[packageLoad ! FS.Error => GOTO cantOpen];
DO
token: ROPENIL;
dfCreated: BasicTime.GMT;
runOK: BOOLFALSE;
differentInStd: BOOLFALSE;
[token: token] ← packageLoadStream.GetTokenRope[IO.TokenProc
! IO.EndOfStream => EXIT];
IF token.Equal["-"] AND packageLoadStream.PeekChar[] = '- THEN {
[] ← packageLoadStream.GetLineRope[ ! IO.EndOfStream => EXIT];
LOOP;
};
SELECT parseState FROM
sawName, sawRight => {
IF token.Equal["("] THEN { parseState ← sawLeft; LOOP;};
parseState ← sawName;
};
sawLeft => {
[] ← Convert.IntFromRope[token ! Convert.Error => {
msg ← Rope.Cat["Expected ", token, " to be the number of GFI's for", shortBcdName];
GOTO return;
};
];
parseState ← sawGFI;
LOOP;
};
sawGFI => {
IF token.Equal[")"] THEN { parseState ← sawLeft; LOOP;};
msg ← Rope.Cat["Expected ')' after gfi number for", shortBcdName];
GOTO return;
};
ENDCASE;
containedPackage ← token.Substr[0, token.Index[0, ".", FALSE]];
shortBcdName ← containedPackage.Concat[".bcd"];
FOR exports: LIST OF exportedFiles ← exportedFilesList, exports.rest WHILE exports # NIL DO
IF (exports.first.included AND Rope.Equal[exports.first.name, shortBcdName, FALSE]) OR (~exports.first.included AND Rope.Equal[exports.first.file.name.Substr[0, Rope.Index[s1: exports.first.file.name, s2: "!"]], shortBcdName, FALSE]) THEN {
IF exports.first.included THEN EXIT; -- too hard to check imports
[created: dfCreated] ← FS.FileInfo[name: shortBcdName, remoteCheck: FALSE, wDir: exports.first.path1
! FS.Error => {
msg ← Rope.Cat[exports.first.path1, shortBcdName, " missing from server"];
GOTO return;
}
];
EXIT;
};
REPEAT
FINISHED => {
msg ← Rope.Cat["cannot find ", shortBcdName, " in df file"];
RETURN [FALSE];
};
ENDLOOP;
ENDLOOP;
packageLoadStream.Close[ ! FS.Error => CONTINUE;];
EXITS
cantOpen => { msg ← "cannot open .remoteCommands file"; RETURN [FALSE];};
return => {};
};
};
checkImports: PROC RETURNS [good: BOOLTRUE] = {
};
Start of body of SubmitPackage
IF ComputeClientInternal.Enabled # true THEN RETURN[msg: "Client is not enabled"];
argv ← CommandTool.Parse[cmd ! CommandTool.Failed => { msg ← errorMsg; CONTINUE; }];
IF argv = NIL THEN RETURN[$Failure, msg];
IF argv.argc < 2 THEN RETURN[$Failure, "No package specified"];
cleanFName ← FileNames.ResolveRelativePath[argv[1]];
cleanFName ← cleanFName.Substr[0, Rope.Index[s1: cleanFName, s2: "."]];
[fullFName: fullDFFName, cp: fullDFcp] ← FS.ExpandName[cleanFName];
package ← fullDFFName.Substr[fullDFcp.base.start, fullDFcp.base.length];
remoteCommands ← Rope.Concat[package, ".remoteCommands"];
summonerLoad ← Rope.Concat[package, ".summonerLoad"];
fileName ← Rope.Concat[cleanFName, ".df"];
1) Insure .df file has a global attachment
[attachedTo: attachedFile] ← FS.FileInfo[name: fileName, remoteCheck: FALSE
! FS.Error => {
msg ← Rope.Concat["Submitted df file is not attached to a global file since ", error.explanation];
GOTO returnError;
};
];
IF attachedFile = NIL THEN {
fullFName: ROPE;
cp: FS.ComponentPositions;
dirOmitted: BOOLEAN;
[fullFName: fullFName, cp: cp, dirOmitted: dirOmitted] ← FS.ExpandName[name: fileName, wDir: NIL];
IF cp.server.length > 0 THEN attachedFile ← fileName
ELSE RETURN[$Failure, "local file submitted, not attached to a global file"];
};
2) Process the .df file, and extract the .remoteCommands and .summonerload files, and build a list of all the exported file.
[created: mainDFFileCreated] ← FS.FileInfo[name: fileName ! FS.Error => {
msg ← Rope.Concat["Could not get info (FS.FileInfo) about submitted df file since ", error.explanation];
GOTO returnError;
}
];
packageDFStream ← FS.StreamOpen[fileName: fileName ! FS.Error => {
msg ← Rope.Concat["Submitted df file could not be opened since ", error.explanation];
GOTO returnError;
}
];
DFUtilities.ParseFromStream[packageDFStream, DoOneItemFromDFFile ! DFUtilities.SyntaxError => {
msg ← reason;
packageDFStream.Close[! FS.Error => CONTINUE];
GOTO returnError;
}
];
packageDFStream.Close[! FS.Error => CONTINUE];
IF msg # NIL THEN RETURN[$Failure, msg];
3) open remoteCommands file. Check that it parses OK and is reasonable.
IF ~checkSummonerRemoteCommands[] THEN GOTO returnError;
4) open summonerload file. Check packages in summonerload for export in the .df file, and check to see that the files with these create dates exist.
IF ~checkSummonerLoad[] THEN GOTO returnError;
5) Take package bcd and generate IMPORTs. Check against list of good imports. Complain if needed. (this should be done on the controller, and be protected, but I trust people) This is a noop for now, however.
IF ~checkImports[] THEN GOTO returnError;
6) Tell the controller about the new package.
tempControllerInterface ← ComputeClientInternal.ControllerInterface;
IF tempControllerInterface = NIL THEN {
ComputeClientInternal.TryToImportController[];
RETURN[$Failure, "Compute Server Controller Down - try again later"] ;
};
[error: controllerError, tryDifferentController: tryDifferentController, msg: controllerMsg] ← tempControllerInterface.NoticeNewPackage[attachedFile
! RPC.CallFailed => {
ComputeClientInternal.ControllerInterface ← NIL;
ComputeClientInternal.TryToImportController[];
msg ← "RPC Call Failed - controller might be down or recovering";
GOTO returnError;
};
];
IF tryDifferentController THEN RETURN[$Failure, "Compute Server Controller Recovering. Package may or may not have been added. - Resubmit package"] ;
IF controllerMsg # NIL THEN RETURN[$Failure, Rope.Concat["Controller rejected package because ", controllerMsg]];
msg ← "New package accepted; please wait about 20 seconds before trying to use it.";
EXITS
returnError => {
RETURN[$Failure, msg]
};
};
};
Package Removal
RemovePackage: Commander.CommandProc = {
PROC [cmd: Handle] RETURNS [result: REFNIL, msg: Rope.ROPENIL]
argv: CommandTool.ArgumentVector;
cleanFName: ROPE;
controllerError: BOOLFALSE;
controllerMsg: ROPENIL;
tryDifferentController: BOOLFALSE;
tempControllerInterface: ComputeServerControllerRpcControl.InterfaceRecord;
IF ComputeClientInternal.Enabled # true THEN RETURN[msg: "Client is not enabled"];
argv ← CommandTool.Parse[cmd ! CommandTool.Failed => { msg ← errorMsg; CONTINUE; }];
IF argv = NIL THEN RETURN[$Failure, msg];
IF argv.argc < 2 THEN RETURN[$Failure, "No package specified"];
cleanFName ← argv[1].Substr[0, Rope.Index[s1: argv[1], s2: "."]];
tempControllerInterface ← ComputeClientInternal.ControllerInterface;
IF tempControllerInterface = NIL THEN {
ComputeClientInternal.TryToImportController[];
RETURN[$Failure, "Compute Server Controller Down - try again later"] ;
};
[error: controllerError, tryDifferentController: tryDifferentController, msg: controllerMsg] ← tempControllerInterface.RemoveOldPackage[cleanFName
! RPC.CallFailed => {
ComputeClientInternal.ControllerInterface ← NIL;
ComputeClientInternal.TryToImportController[];
msg ← "RPC Call Failed - controller might be down or recovering";
GOTO returnError;
};
];
IF tryDifferentController THEN RETURN[$Failure, "Compute Server Controller Recovering. Package may or may not have been removed. - retry"] ;
IF controllerMsg # NIL THEN RETURN[$Failure, Rope.Concat["Controller rejected package removal because ", controllerMsg]];
msg ← "Package Removed.";
EXITS
returnError => {
RETURN[$Failure, msg]
};
};
Info
SummonerInfoProc: Commander.CommandProc = {
PROC [cmd: Handle] RETURNS [result: REFNIL, msg: Rope.ROPENIL]
tempControllerInterface: ComputeServerControllerRpcControl.InterfaceRecord;
controllerError: BOOL;
tryDifferentController: BOOL;
serverList: LIST OF Rope.ROPE;
bestFOM: REAL;
remoteMsg: Rope.ROPE;
IF ComputeClientInternal.Enabled # true THEN RETURN[msg: "Client is not enabled"];
IF ComputeClientInternal.Enabled # true THEN msg ← "Compute Server Client not enabled\n"
ELSE msg ← "Compute Server Client enabled\n";
tempControllerInterface ← ComputeClientInternal.ControllerInterface;
msg ← Rope.Cat[msg, "Cluster: ", ComputeClientInternal.ControllerGVName, "\n"];
IF tempControllerInterface = NIL THEN {
ComputeClientInternal.TryToImportController[];
RETURN[$Failure, msg.Concat["Compute Server Controller Down; can't import controller - try again later"]] ;
};
[error: controllerError, tryDifferentController: tryDifferentController, msg: remoteMsg, serverList: serverList, bestFOM: bestFOM ] ← tempControllerInterface.GetSomeInfo[
! RPC.CallFailed => {
ComputeClientInternal.ControllerInterface ← NIL;
ComputeClientInternal.TryToImportController[];
msg ← msg.Concat["RPC Call Failed - controller might be down or recovering"];
GOTO returnError;
};
];
IF controllerError THEN RETURN[$Failure, msg.Concat[" Controller returned an error"]]
ELSE {
firstItem: BOOLTRUE;
IF tryDifferentController THEN msg ← Rope.Concat[msg, " controller has moved\n"];
FOR l: LIST OF ROPE ← serverList, l.rest WHILE l # NIL DO
IF firstItem THEN {
msg ← Rope.Cat[msg, "Servers: ", l.first];
firstItem ← FALSE;
}
ELSE {
msg ← Rope.Cat[msg, ", ", l.first];
};
ENDLOOP;
IF ~firstItem THEN msg ← Rope.Concat[msg, "\n"];
msg ← Rope.Concat[msg,
IO.PutFR["Best Figure of Merit (0.0 is idle) is %8.3f", IO.real[bestFOM]]];
};
EXITS
returnError => {
RETURN[$Failure, msg]
};
};
Set Bad/Good Commands
BadCommandProc: Commander.CommandProc = {
PROC [cmd: Handle] RETURNS [result: REFNIL, msg: Rope.ROPENIL]
argv: CommandTool.ArgumentVector;
serverName, commandName: ROPENIL;
tempControllerInterface: ComputeServerControllerRpcControl.InterfaceRecord;
IF ComputeClientInternal.Enabled # true THEN RETURN[msg: "Client is not enabled"];
argv ← CommandTool.Parse[cmd ! CommandTool.Failed => { msg ← errorMsg; CONTINUE; }];
IF argv = NIL THEN RETURN[$Failure, msg];
IF argv.argc # 3 THEN RETURN[$Failure, "Wrong number of arguments"];
serverName ← argv[1];
commandName ← argv[2];
IF Rope.Find[serverName, "#"] < 0 THEN {
pupAddress: PupDefs.PupAddress;
pupAddress ← PupDefs.GetPupAddress[[0,0], serverName ! PupStream.PupNameTrouble => GOTO badName];
serverName ← Rope.Cat[Convert.RopeFromCard[pupAddress.net, 8, FALSE],
"#",
Convert.RopeFromCard[pupAddress.host, 8, FALSE],
"#"];
};
tempControllerInterface ← ComputeClientInternal.ControllerInterface;
IF tempControllerInterface = NIL THEN {
ComputeClientInternal.TryToImportController[];
RETURN[$Failure, msg.Concat["Compute Server Controller Down; can't import controller - try again later"]] ;
};
tempControllerInterface.CommandUnavailable[serverMachineName: serverName, commandName: commandName, version: NIL
! RPC.CallFailed => {
ComputeClientInternal.ControllerInterface ← NIL;
ComputeClientInternal.TryToImportController[];
msg ← msg.Concat["RPC Call Failed - controller might be down or recovering"];
GOTO returnError;
};
];
EXITS
returnError => RETURN[$Failure, msg];
badName => RETURN[$Failure, "Cannot find pup address for server"];
};
GoodCommandProc: Commander.CommandProc = {
PROC [cmd: Handle] RETURNS [result: REFNIL, msg: Rope.ROPENIL]
argv: CommandTool.ArgumentVector;
serverName, commandName: ROPENIL;
tempControllerInterface: ComputeServerControllerRpcControl.InterfaceRecord;
IF ComputeClientInternal.Enabled # true THEN RETURN[msg: "Client is not enabled"];
argv ← CommandTool.Parse[cmd ! CommandTool.Failed => { msg ← errorMsg; CONTINUE; }];
IF argv = NIL THEN RETURN[$Failure, msg];
IF argv.argc # 3 THEN RETURN[$Failure, "Wrong number of arguments"];
serverName ← argv[1];
commandName ← argv[2];
IF Rope.Find[serverName, "#"] < 0 THEN {
pupAddress: PupDefs.PupAddress;
pupAddress ← PupDefs.GetPupAddress[[0,0], serverName ! PupStream.PupNameTrouble => GOTO badName];
serverName ← Rope.Cat[Convert.RopeFromCard[pupAddress.net, 8, FALSE],
"#",
Convert.RopeFromCard[pupAddress.host, 8, FALSE],
"#"];
};
tempControllerInterface ← ComputeClientInternal.ControllerInterface;
IF tempControllerInterface = NIL THEN {
ComputeClientInternal.TryToImportController[];
RETURN[$Failure, msg.Concat["Compute Server Controller Down; can't import controller - try again later"]] ;
};
tempControllerInterface.ExtraCommandAvailable[serverMachineName: serverName, commandName: commandName, version: NIL
! RPC.CallFailed => {
ComputeClientInternal.ControllerInterface ← NIL;
ComputeClientInternal.TryToImportController[];
msg ← msg.Concat["RPC Call Failed - controller might be down or recovering"];
GOTO returnError;
};
];
EXITS
returnError => RETURN[$Failure, msg];
badName => RETURN[$Failure, "Cannot find pup address for server"];
};
Change Clusters
ClusterProc: Commander.CommandProc = {
PROC [cmd: Handle] RETURNS [result: REFNIL, msg: Rope.ROPENIL]
argv: CommandTool.ArgumentVector;
IF ComputeClientInternal.Enabled # true THEN RETURN[msg: "Client is not enabled"];
argv ← CommandTool.Parse[cmd ! CommandTool.Failed => { msg ← errorMsg; CONTINUE; }];
IF argv = NIL THEN RETURN[$Failure, msg];
IF argv.argc < 2 THEN RETURN[$Failure, "No cluster specified"];
ComputeClientInternal.ControllerGVName ← argv[1];
ComputeClientInternal.ControllerInterface ← NIL;
ComputeClientInternal.TryToImportController[];
};
Server Stats
BestServerStats: PUBLIC PROC RETURNS[success: ComputeServerClient.RemoteSuccess ← false, selfIsBest: BOOLTRUE, FOM: REAL ← 1.0] = {
bestInstance: RPC.ShortROPE;
bestFOM: REAL;
retryCounter: INT ← 0 ;
tempControllerInterface: ComputeServerControllerRpcControl.InterfaceRecord;
DO
tempControllerInterface ← ComputeClientInternal.ControllerInterface;
IF tempControllerInterface = NIL THEN {
ComputeClientInternal.TryToImportController[];
tempControllerInterface ← ComputeClientInternal.ControllerInterface;
IF tempControllerInterface = NIL THEN RETURN[false, TRUE, 1.0];
};
[instance: bestInstance, FOM: bestFOM] ← tempControllerInterface.BestServerStats[ ! RPC.CallFailed => {
ComputeClientInternal.ControllerInterface ← NIL;
retryCounter ← retryCounter + 1;
IF retryCounter < 3 THEN LOOP ELSE GOTO controllerCallFailed;
};
];
IF bestInstance = NIL OR Rope.Equal[bestInstance, ComputeClientInternal.myNetAddressRope, FALSE] THEN RETURN[true, TRUE, bestFOM]
ELSE RETURN [true, FALSE, bestFOM];
ENDLOOP;
EXITS
controllerCallFailed => RETURN[false, TRUE, 0.0];
};
Initialization
Commander.Register[key: "///Commands/SubmitSummonerPackage", proc: SubmitPackage, doc: "Submit to the Compute Server the .df file specified as the argument into the current cluster"];
Commander.Register[key: "///Commands/RemoveSummonerPackage", proc: RemovePackage, doc: "Remove the package specified by short name as the argument from the current Compute Server cluster"];
Commander.Register[key: "///Commands/SummonerInfo", proc: SummonerInfoProc, doc: "Get and print out some info about the state of the compute server cluster"];
Commander.Register[key: "///Commands/SummonerCluster", proc: ClusterProc, doc: "Set the compute server cluster"];
Commander.Register[key: "///Commands/SummonerBadCommand", proc: BadCommandProc, doc: "SummonerBadCommand server commandname - Set a command bad for a server; servers may be named by pup address (e.g., 3#277#) or by name (e.g., Bataan), the the command is the remote command name (e.g., RemoteCompiler)"];
Commander.Register[key: "///Commands/SummonerGoodCommand", proc: GoodCommandProc, doc: "SummonerGoodCommand server commandname - Set a command good for a server, reversing a previous SummonerBadCommand"];
END.
Bob Hagmann January 29, 1986 10:27:37 am PST
tightened checks on submit by insuring that keywords in summonerLoad file are valid, added checks to try to insure proper create dates on df files
changes to: checkSummonerRemoteCommands (local of SubmitPackage), SubmitPackage, imports (local of DoOneItemFromDFFile, local of SubmitPackage)