DIRECTORY Atom, Basics, BasicTime, Commander, CommandTool, ComputeClient, ComputeServerClient, ComputeClientInternal, ComputeServerControllerRpcControl, ComputeUtils, Convert, DFUtilities, FileNames, FS, IO, ProcessProps, Pup USING [Address, nullSocket], PupName USING [AddressToRope, Error, NameLookup], Real, Rope, RPC; ComputeClientControllerCmdsImpl: CEDAR MONITOR IMPORTS BasicTime, Commander, CommandTool, ComputeClientInternal, ComputeServerControllerRpcControl, ComputeUtils, Convert, DFUtilities, FileNames, FS, IO, PupName, Rope, RPC EXPORTS ComputeClient = BEGIN ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; SubmitPackage: Commander.CommandProc = { argv: CommandTool.ArgumentVector; fileName: ROPE; cleanFName, package: ROPE; fullDFFName: ROPE; fullDFcp: FS.ComponentPositions; attachedFile: ROPE; dfLog: IO.STREAM _ IO.ROS[]; dfLogRope: ROPE _ NIL; controllerError: BOOL _ FALSE; tryDifferentController: BOOL _ FALSE; controllerMsg: ROPE _ NIL; lastDir: REF DFUtilities.DirectoryItem _ NIL; tempControllerInterface: ComputeServerControllerRpcControl.InterfaceRecord; remoteCommands: ROPE _ NIL; fullNameOfRemoteCommands: ROPE _ NIL; summonerLoad: ROPE _ NIL; fullNameOfSummonerLoad: ROPE _ NIL; packageDFStream: IO.STREAM; mainDFFileCreated: BasicTime.GMT; noIERRyet: BOOL _ TRUE; exportedFilesList: LIST OF exportedFiles _ NIL; exportedFiles: TYPE = RECORD [ path1: ROPE _ NIL, included: BOOL _ FALSE, file: REF DFUtilities.FileItem _ NIL, name: ROPE ]; { -- nest to get the EXIT to see variables DoOneItemFromDFFile: DFUtilities.ProcessItemProc = { 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: BOOL _ TRUE] = { fileName: ROPE = fullNameOfRemoteCommands ; packageListStream: IO.STREAM; maintainer: LIST OF ROPE _ NIL; commands: LIST OF ROPE _ NIL; version: LIST OF ROPE _ NIL; 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: ROPE _ NIL; tokens, tail: LIST OF ROPE _ NIL; key: ROPE _ NIL; token _ ComputeUtils.LocalToken[packageListStream, TRUE]; IF (key _ token) = NIL THEN EXIT; SELECT ComputeUtils.SkipWhite[packageListStream] FROM ': => [] _ packageListStream.GetChar[]; -- flush the ': ENDCASE => { DO IF packageListStream.GetChar[ ! IO.EndOfStream => EXIT] = '\n THEN EXIT; ENDLOOP; LOOP; }; DO list: LIST OF ROPE _ NIL; 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; 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: BOOL _ FALSE; 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: BOOL _ FALSE; 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: BOOL _ TRUE] = { parseStateType: TYPE = {sawName, sawLeft, sawGFI, sawRight}; packageLoad: ROPE = fullNameOfSummonerLoad ; packageLoadStream: IO.STREAM; containedPackage: ROPE _ NIL; shortBcdName: ROPE _ NIL; 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: ROPE _ NIL; dfCreated: BasicTime.GMT; runOK: BOOL _ FALSE; differentInStd: BOOL _ FALSE; [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: BOOL _ TRUE] = { }; 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"]; [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"]; }; [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]; IF ~checkSummonerRemoteCommands[] THEN GOTO returnError; IF ~checkSummonerLoad[] THEN GOTO returnError; IF ~checkImports[] THEN GOTO returnError; 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] }; }; }; RemovePackage: Commander.CommandProc = { argv: CommandTool.ArgumentVector; cleanFName: ROPE; controllerError: BOOL _ FALSE; controllerMsg: ROPE _ NIL; tryDifferentController: BOOL _ FALSE; 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] }; }; SummonerInfoProc: Commander.CommandProc = { tempControllerInterface: ComputeServerControllerRpcControl.InterfaceRecord; controllerError: BOOL; tryDifferentController: BOOL; serverList: LIST OF Rope.ROPE; bestFOM: REAL; remoteMsg: Rope.ROPE; 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: BOOL _ TRUE; 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] }; }; BadCommandProc: Commander.CommandProc = { argv: CommandTool.ArgumentVector; serverName, commandName: ROPE _ NIL; 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: Pup.Address; pupAddress _ PupName.NameLookup[serverName, Pup.nullSocket ! PupName.Error => GOTO badName]; serverName _ PupName.AddressToRope[pupAddress]; }; 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 = { argv: CommandTool.ArgumentVector; serverName, commandName: ROPE _ NIL; 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: Pup.Address; pupAddress _ PupName.NameLookup[serverName, Pup.nullSocket ! PupName.Error => GOTO badName]; serverName _ PupName.AddressToRope[pupAddress]; }; 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"]; }; ClusterProc: Commander.CommandProc = { 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[]; }; BestServerStats: PUBLIC PROC RETURNS[success: ComputeServerClient.RemoteSuccess _ false, selfIsBest: BOOL_ TRUE, 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]; }; 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. DComputeClientControllerCmdsImpl.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 Hal Murray, March 22, 1986 10:46:22 pm PST Copyright c 1984 by Xerox Corporation. All rights reserved. Declarations Package Submission PROC [cmd: Handle] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] 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. PROC [item: REF ANY] RETURNS [stop: BOOL _ FALSE] key was NOT followed by ':, so flush to the end of line and report the error ReportInternal[msg: IO.PutFR["missing : at [%d]", IO.int[position]]]; now the key is key, and the list of tokens is in tokens Start of body of SubmitPackage 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. Package Removal PROC [cmd: Handle] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] Info PROC [cmd: Handle] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] IF ComputeClientInternal.Enabled # true THEN RETURN[msg: "Client is not enabled"]; Set Bad/Good Commands PROC [cmd: Handle] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] PROC [cmd: Handle] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] Change Clusters PROC [cmd: Handle] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] Server Stats Initialization 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) ส– "Cedar" style˜headšœ$™$Ibodyšœ‡™‡L™<code™*Jšœ ฯmœ1™˜>Jšžœžœ˜Jšœ˜—šžœ žœ˜Jšœ;˜;Jšžœžœ˜Jšœ˜—Jšœ˜—J˜—šžœ˜ Jšœžœžœ˜Jšœ%˜%šœžœžœžœ˜;šžœ˜Jšœžœ˜Jšžœ˜ J˜—šžœ ˜ Jšžœ˜ J˜——J˜Jšžœžœžœžœ˜Nšžœžœ˜Jšœ˜JšœL˜LJšžœžœ˜J˜—Jšœ˜——Jšžœ  ˜*—J˜šžœ žœžœ˜Jšœ˜Jšœ6˜6Jšžœžœ˜Jšœ˜—J˜Jšœ˜šž˜Ošœ8žœžœ˜I—J˜—J˜š Ÿœžœžœžœžœ˜7Jšœžœ(˜Nšžœ˜N˜—šžœ ž˜šœ˜Mšžœžœžœ˜8Mšœ˜M˜—šœ ˜ šœ3˜3MšœS˜SMšžœ˜ M˜—M˜Mšœ˜Mšžœ˜Mšœ˜—šœ ˜ Mšžœžœžœ˜8MšœB˜BMšžœ˜ M˜—Mšžœ˜—Nšœ7žœ˜?Nšœ/˜/š žœ žœžœ1žœ žœžœ˜\šžœžœ.žœžœžœožœžœ˜๑Ošžœžœžœ ˜Bšœžœ+žœžœ ˜tOšœJ˜JOšžœ˜ N˜—N˜Nšžœ˜N˜—šž˜šžœ˜ Nšœ=˜=Nšžœžœ˜N˜——Nšžœ˜—Nšžœ˜—Jšœžœ žœ˜2šž˜Ošœ8žœžœ˜IO˜ —J˜—J˜—J˜š Ÿ œžœžœžœžœ˜2J˜—˜J™Jšฯl™—Jšžœ&žœžœ˜RJšœHžœ˜UJšžœžœžœžœ˜)Jšžœžœžœ#˜?Jšœ4˜4JšœG˜GJšœ)žœ˜CJšœH˜HJšœ9˜9Jšœ5˜5šœ*˜*J™*—šœžœ'žœžœ ˜\Jšœb˜bJšžœ ˜Jšœ˜—Jšœ˜šžœžœžœ˜Jšœ žœ˜Jšœžœ˜Jšœ žœ˜Jšœ9žœ"žœ˜bJšžœžœžœžœB˜ƒJ˜J™J™|—šœžœžœ ˜IJšœ'žœ?˜hJšžœ ˜Jšœ˜—Jšœ˜šœžœ!žœ ˜CJšœU˜UJšžœ ˜Jšœ˜—Jšœ˜šœ_˜_Jšœ ˜ Jšœžœ žœ˜.Jšžœ ˜Jšœ˜—Jšœ˜Jšœžœ žœ˜.Jšžœžœžœžœ˜(˜J™H—šžœ žœžœ ˜8J™•—šžœžœžœ ˜.J™ำ—Jšžœžœžœ ˜)˜J™-—JšœD˜Dšžœžœž˜'Jšœ.˜.Jšžœ@˜FJ˜—šœ”˜”šœžœ˜Jšœ,žœ˜0Jšœ.˜.J˜AJšžœ ˜Jšœ˜—Jšœ˜—Jšžœžœžœq˜–JšžœžœžœžœO˜qJšœT˜Tšž˜šœ˜Jšžœ˜J˜——J˜—Jšœ˜—J˜—™šŸ œ˜)Jš žœžœ žœžœ žœžœ™DJšœ!˜!Jšœ žœ˜Jšœžœžœ˜Jšœžœžœ˜Jšœžœžœ˜%JšœK˜KJšžœ&žœžœ˜RJšœHžœ˜UJšžœžœžœžœ˜)Jšžœžœžœ#˜?JšœA˜AJšœD˜Dšžœžœžœ˜'Jšœ.˜.Jšžœ@˜FJ˜—šœ’˜’šœžœ˜Jšœ,žœ˜0Jšœ.˜.J˜AJšžœ ˜Jšœ˜—Jšœ˜—Jšžœžœžœh˜JšžœžœžœžœW˜yJšœ˜šž˜šœ˜Jšžœ˜J˜——J˜——™šŸœ˜,Jš žœžœ žœžœ žœžœ™DJšœL˜LJšœžœ˜Jšœžœ˜Jšœ žœžœžœ˜Jšœ žœ˜Jšœžœ˜Jšžœ&žœžœ™RJšžœ&žœ-žœ)˜†JšœD˜DJšœO˜Ošžœžœžœ˜'Jšœ.˜.Jšžœe˜kJ˜—šœช˜ชšœžœ˜Jšœ,žœ˜0Jšœ.˜.JšœM˜MJšžœ ˜Jšœ˜—Jšœ˜—Jšžœžœžœ8˜Všœžœ˜Jšœ žœžœ˜Jšžœžœ3˜Qš žœžœžœžœžœžœž˜9šžœ žœ˜Jšœ*˜*Jšœ žœ˜J˜—šœžœ˜Jšœ#˜#Jšœ˜—Jšžœ˜—Jšžœ žœ˜0Jšœžœ6žœ˜cJ˜—šž˜šœ˜Jšžœ˜J˜——J˜J˜——™šŸœ˜*Jš žœžœ žœžœ žœžœ™DJšœ!˜!Jšœžœžœ˜$JšœK˜KJšžœ&žœžœ˜RJšœHžœ˜UJšžœžœžœžœ˜)Jšžœžœžœ(˜DJšœ˜Jšœ˜šžœ žœ˜(Jšœ˜JšœNžœ ˜\Mšœ/˜/J˜—JšœD˜Dšžœžœžœ˜'Jšœ.˜.Jšžœe˜kJ˜—šœmž˜pšœžœ˜Jšœ,žœ˜0Jšœ.˜.JšœM˜MJšžœ ˜Jšœ˜—Jšœ˜—šž˜Jšœžœ˜%Jšœ žœ1˜B—J˜J˜—šŸœ˜+Jš žœžœ žœžœ žœžœ™DJšœ!˜!Jšœžœžœ˜$JšœK˜KJšžœ&žœžœ˜RJšœHžœ˜UJšžœžœžœžœ˜)Jšžœžœžœ(˜DJšœ˜Jšœ˜šžœ žœ˜(Jšœ˜JšœNžœ ˜\Mšœ/˜/J˜—JšœD˜Dšžœžœžœ˜'Jšœ.˜.Jšžœe˜kJ˜—šœpž˜sšœžœ˜Jšœ,žœ˜0Jšœ.˜.JšœM˜MJšžœ ˜Jšœ˜—Jšœ˜—šž˜Jšœžœ˜%Jšœ žœ1˜B—J˜J˜—J˜—™šŸ œ˜'Jš žœžœ žœžœ žœžœ™DJšœ!˜!Jšžœ&žœžœ˜RJšœHžœ˜UJšžœžœžœžœ˜)Jšžœžœžœ#˜?Jšœ1˜1Jšœ,žœ˜0Jšœ.˜.J˜J˜——™ šฯnœžœžœžœAžœžœžœžœ ˜…Nšœžœ ˜Nšœ žœ˜Nšœžœ˜NšœK˜Kšž˜NšœD˜Dšžœžœžœ˜'Nšœ.˜.NšœD˜DNš žœžœžœžœžœ˜?N˜—šœžœ8žœ˜hNšœ,žœ˜0Nšœ ˜ Nš žœžœžœžœžœ˜=Nšœ˜—Nšœ˜NšžœžœžœBžœžœžœžœ ˜Nšœžœžœžœ ˜$Nšžœ˜—šž˜Nšœžœžœ˜1—N˜——šœ™Nšœท˜ทNšœฝ˜ฝNšœž˜žNšœq˜qNšœฐ˜ฐNšœฬ˜ฬN˜Nšžœ˜—™,M™’Mšœ ขœขœ7™—M™M™—…—Qคt๙