ComputeControllerPackagesImpl.mesa
Implement the controller functions for packages. This runs on any machine that is also a compute server.
Last Edited by: Bob Hagmann, October 1, 1985 11:02:11 am PDT
Copyright © 1984 by Xerox Corporation. All rights reserved.
DIRECTORY
BasicTime,
Commander,
ComputeControllerImpl,
ComputeControllerInternal,
ComputeServerController,
ComputeServer,
ComputeServerInternal,
DFUtilities,
FS,
IO,
PrincOps,
PrincOpsUtils,
Process,
PupDefs,
PupTypes,
Rope,
RPC,
SummonerControllerControl;
ComputeControllerPackagesImpl: CEDAR MONITOR LOCKS ComputeControllerImpl.LOCK
IMPORTS BasicTime, Commander, ComputeControllerImpl, ComputeControllerInternal, ComputeServerInternal, DFUtilities, FS, IO, Process, Rope
EXPORTS ComputeServerController
SHARES ComputeControllerImpl
= BEGIN
ROPE: TYPE = Rope.ROPE;
ServerStatus: TYPE = ComputeControllerInternal.ServerStatus;
NoticeNewPackageCondition: CONDITION;
NoticeNewPackage: PUBLIC ENTRY PROC [package: RPC.ShortROPE] RETURNS [error: BOOLFALSE, tryDifferentController: BOOLFALSE, msg: ROPENIL]= {
ENABLE UNWIND => NULL;
statusList: LIST OF ServerStatus;
packageListInStream: IO.STREAM;
packageListGlobalName: ROPENIL;
packageListOutStream: IO.STREAM;
packageListTempName: ROPENIL;
foundItem: BOOLFALSE;
fullFName: ROPE;
fsErrMsg: ROPE;
cp: FS.ComponentPositions;
dirOmitted: BOOLEAN;
dfPrefix: ROPE;
shortPackage: ROPENIL;
shortPackageAndDF: ROPENIL;
packageDFDate: BasicTime.GMT ← BasicTime.nullGMT;
sawDir: BOOLFALSE;
blankAfterDir: BOOLFALSE;
lastDir: REF DFUtilities.DirectoryItem ← NIL;
wroteDir: BOOLFALSE;
defaultDirectory: REF DFUtilities.DirectoryItem ← NIL ;
whiteItem: REF DFUtilities.WhiteSpaceItem ← NEW[DFUtilities.WhiteSpaceItem ← [1]];
writeUpdatedItem: PROC[] = {
file: REF DFUtilities.FileItem;
file ← NEW[DFUtilities.FileItem ← [
name: shortPackageAndDF, -- a short name
date: [explicit, packageDFDate],
verifyRoot: FALSE]];
IF lastDir = NIL OR ~Rope.Equal[lastDir.path1, dfPrefix, FALSE] THEN {
dir: REF DFUtilities.DirectoryItem ← NEW [DFUtilities.DirectoryItem ← [
path1: dfPrefix,
path2: NIL,
path2IsCameFrom: FALSE,
exported: FALSE,
readOnly: FALSE
]];
DFUtilities.WriteItemToStream[out: packageListOutStream, item: whiteItem];
DFUtilities.WriteItemToStream[out: packageListOutStream, item: dir];
DFUtilities.WriteItemToStream[out: packageListOutStream, item: whiteItem];
lastDir ← dir;
};
DFUtilities.WriteItemToStream[out: packageListOutStream, item: file];
};
DoOneItem: DFUtilities.ProcessItemProc = {
PROC [item: REF ANY] RETURNS [stop: BOOLFALSE]
errors, warnings, filesActedUpon: INT ← 0;
WITH item SELECT FROM
dir: REF DFUtilities.DirectoryItem => {
IF lastDir = NIL OR ~Rope.Equal[lastDir.path1, dir.path1, FALSE] THEN {
wroteDir ← FALSE;
lastDir ← dir;
};
};
comment: REF DFUtilities.CommentItem => {
DFUtilities.WriteItemToStream[out: packageListOutStream, item: comment];
};
white: REF DFUtilities.WhiteSpaceItem => {
};
file: REF DFUtilities.FileItem => {
shortName: ROPE = Rope.Substr[file.name, 0, Rope.Index[s1: file.name, s2: "!"]];
packageDFDate: BasicTime.GMT ← BasicTime.nullGMT;
currentDFDate: BasicTime.GMT ← BasicTime.nullGMT;
IF ~wroteDir THEN {
wroteDir ← TRUE;
IF lastDir = NIL THEN lastDir ← defaultDirectory;
DFUtilities.WriteItemToStream[out: packageListOutStream, item: whiteItem];
DFUtilities.WriteItemToStream[out: packageListOutStream, item: lastDir];
DFUtilities.WriteItemToStream[out: packageListOutStream, item: whiteItem];
};
IF Rope.Equal[shortPackageAndDF, shortName, FALSE] THEN {
writeUpdatedItem[];
foundItem ← TRUE;
}
ELSE {
DFUtilities.WriteItemToStream[out: packageListOutStream, item: file];
};
};
ENDCASE;
};
{
ENABLE UNWIND => {
IF packageListInStream # NIL THEN packageListInStream.Close[! FS.Error => CONTINUE];
IF packageListOutStream # NIL THEN packageListOutStream.Close[! FS.Error => CONTINUE];
FS.Delete[name: packageListTempName ! FS.Error => CONTINUE];
};
IF package.IsEmpty[] THEN RETURN [ TRUE, FALSE, "null package name"];
IF ~ComputeControllerInternal.IAmTheController THEN RETURN [ FALSE, TRUE, "controller has moved"];
WHILE ComputeControllerInternal.IAmTheController AND
BasicTime.Period[ComputeControllerInternal.TimeIBecameTheController, BasicTime.Now[]] < 22 DO
WAIT NoticeNewPackageCondition;
ENDLOOP;
IF ~ComputeControllerInternal.IAmTheController THEN RETURN [ FALSE, TRUE, "controller has moved"];
[fullFName: fullFName, cp: cp, dirOmitted: dirOmitted] ← FS.ExpandName[name: package, wDir: NIL ! FS.Error => GOTO badPackageName ];
shortPackage ← fullFName.Substr[cp.base.start, cp.base.length];
shortPackageAndDF ← Rope.Concat[shortPackage, ".df"];
dfPrefix ← fullFName.Substr[0, cp.base.start];
defaultDirectory ← NEW [DFUtilities.DirectoryItem ← [
path1: dfPrefix,
path2: NIL,
path2IsCameFrom: FALSE,
exported: FALSE,
readOnly: FALSE
]];
[created: packageDFDate] ← FS.FileInfo[name: package, remoteCheck: TRUE ! FS.Error => GOTO noDFFile];
packageListGlobalName ← Rope.Concat[ComputeServerInternal.RemoteCommandDir, "PackageList"];
packageListInStream ← FS.StreamOpen[packageListGlobalName
! FS.Error => GOTO cantOpenPackageList];
packageListTempName ← Rope.Concat[ComputeServerInternal.LocalCommandDir, "PackageList.temp"];
packageListOutStream ← FS.StreamOpen[fileName: packageListTempName, accessOptions: $create];
DFUtilities.ParseFromStream[packageListInStream, DoOneItem ! DFUtilities.SyntaxError => GOTO syntaxErrorInPackageList];
IF ~foundItem THEN writeUpdatedItem[];
packageListInStream.Close[! FS.Error => CONTINUE];
packageListOutStream.Close[! FS.Error => CONTINUE];
[] ← FS.Copy[from: packageListTempName, to: packageListGlobalName, attach: FALSE ! FS.Error => { fsErrMsg ← error.explanation; GOTO cantCopyToServer}];
FS.Delete[name: packageListTempName ! FS.Error => CONTINUE];
IF ~ComputeControllerInternal.IAmTheController THEN RETURN [ FALSE, TRUE, "controller has moved"];
FOR statusList ← ComputeControllerInternal.ServerStatusList, statusList.rest UNTIL statusList = NIL DO
statusList.first.newPackage ← TRUE;
ENDLOOP;
EXITS
cantOpenPackageList => RETURN [ TRUE, FALSE, "controller could not open package list"];
noDFFile => RETURN [ TRUE, FALSE, "controller could not open specified df file - "];
syntaxErrorInPackageList => RETURN [ TRUE, FALSE, "controller could not parse the package list - call an implementor"];
badPackageName => RETURN [ TRUE, FALSE, "bad package df file name"];
cantCopyToServer => RETURN [ TRUE, FALSE, Rope.Concat["could not copy new package list to the file server because ", fsErrMsg]];
};
};
RemoveOldPackage: PUBLIC ENTRY PROC [package: RPC.ShortROPE] RETURNS [error: BOOL, tryDifferentController: BOOL, msg: Rope.ROPE] = {
ENABLE UNWIND => NULL;
statusList: LIST OF ServerStatus;
packageListInStream: IO.STREAM;
packageListGlobalName: ROPENIL;
packageListOutStream: IO.STREAM;
packageListTempName: ROPENIL;
foundItem: BOOLFALSE;
fullFName: ROPE;
cp: FS.ComponentPositions;
dirOmitted: BOOLEAN;
dfPrefix: ROPE;
shortPackage: ROPENIL;
shortPackageAndDF: ROPENIL;
wroteDir: BOOLFALSE;
lastDir: REF DFUtilities.DirectoryItem ← NIL;
defaultDirectory: REF DFUtilities.DirectoryItem ← NIL ;
whiteItem: REF DFUtilities.WhiteSpaceItem ← NEW[DFUtilities.WhiteSpaceItem ← [1]];
DoOneItem: DFUtilities.ProcessItemProc = {
PROC [item: REF ANY] RETURNS [stop: BOOLFALSE]
errors, warnings, filesActedUpon: INT ← 0;
WITH item SELECT FROM
dir: REF DFUtilities.DirectoryItem => {
IF lastDir = NIL OR ~Rope.Equal[lastDir.path1, dir.path1, FALSE] THEN {
DFUtilities.WriteItemToStream[out: packageListOutStream, item: dir];
wroteDir ← FALSE;
lastDir ← dir;
};
};
comment: REF DFUtilities.CommentItem => {
DFUtilities.WriteItemToStream[out: packageListOutStream, item: comment];
};
white: REF DFUtilities.WhiteSpaceItem => {
DFUtilities.WriteItemToStream[out: packageListOutStream, item: white];
};
file: REF DFUtilities.FileItem => {
shortName: ROPE = Rope.Substr[file.name, 0, Rope.Index[s1: file.name, s2: "!"]];
currentDFDate: BasicTime.GMT ← BasicTime.nullGMT;
IF Rope.Equal[shortPackageAndDF, shortName, FALSE] THEN {
foundItem ← TRUE;
}
ELSE {
IF ~wroteDir THEN {
wroteDir ← TRUE;
IF lastDir = NIL THEN lastDir ← defaultDirectory;
DFUtilities.WriteItemToStream[out: packageListOutStream, item: whiteItem];
DFUtilities.WriteItemToStream[out: packageListOutStream, item: lastDir];
DFUtilities.WriteItemToStream[out: packageListOutStream, item: whiteItem];
};
DFUtilities.WriteItemToStream[out: packageListOutStream, item: file];
};
};
ENDCASE;
};
{
ENABLE UNWIND => {
IF packageListInStream # NIL THEN packageListInStream.Close[! FS.Error => CONTINUE];
IF packageListOutStream # NIL THEN packageListOutStream.Close[! FS.Error => CONTINUE];
FS.Delete[name: packageListTempName ! FS.Error => CONTINUE];
};
IF package.IsEmpty[] THEN RETURN [ TRUE, FALSE, "null package name"];
IF ~ComputeControllerInternal.IAmTheController THEN RETURN [ FALSE, TRUE, "controller has moved"];
WHILE ComputeControllerInternal.IAmTheController AND
BasicTime.Period[ComputeControllerInternal.TimeIBecameTheController, BasicTime.Now[]] < 22 DO
WAIT NoticeNewPackageCondition;
ENDLOOP;
IF ~ComputeControllerInternal.IAmTheController THEN RETURN [ FALSE, TRUE, "controller has moved"];
[fullFName: fullFName, cp: cp, dirOmitted: dirOmitted] ← FS.ExpandName[name: package, wDir: NIL ! FS.Error => GOTO badPackageName ];
shortPackage ← fullFName.Substr[cp.base.start, cp.base.length];
shortPackageAndDF ← Rope.Concat[shortPackage, ".df"];
dfPrefix ← fullFName.Substr[0, cp.base.start];
defaultDirectory ← NEW [DFUtilities.DirectoryItem ← [
path1: dfPrefix,
path2: NIL,
path2IsCameFrom: FALSE,
exported: FALSE,
readOnly: FALSE
]];
packageListGlobalName ← Rope.Concat[ComputeServerInternal.RemoteCommandDir, "PackageList"];
packageListInStream ← FS.StreamOpen[packageListGlobalName
! FS.Error => GOTO cantOpenPackageList];
packageListTempName ← Rope.Concat[ComputeServerInternal.LocalCommandDir, "PackageList.temp"];
packageListOutStream ← FS.StreamOpen[fileName: packageListTempName, accessOptions: $create];
DFUtilities.ParseFromStream[packageListInStream, DoOneItem ! DFUtilities.SyntaxError => GOTO syntaxErrorInPackageList];
packageListInStream.Close[! FS.Error => CONTINUE];
packageListOutStream.Close[! FS.Error => CONTINUE];
IF ~foundItem THEN {
FS.Delete[name: packageListTempName ! FS.Error => CONTINUE];
RETURN [ TRUE, FALSE, "package not found"]
};
[] ← FS.Copy[from: packageListTempName, to: packageListGlobalName, attach: FALSE];
FS.Delete[name: packageListTempName ! FS.Error => CONTINUE];
IF ~ComputeControllerInternal.IAmTheController THEN RETURN [ FALSE, TRUE, "controller has moved"];
FOR statusList ← ComputeControllerInternal.ServerStatusList, statusList.rest UNTIL statusList = NIL DO
statusList.first.newPackage ← TRUE;
ENDLOOP;
EXITS
cantOpenPackageList => RETURN [ TRUE, FALSE, "controller could not open package list"];
syntaxErrorInPackageList => RETURN [ TRUE, FALSE, "controller could not parse the package list - call an implementor"];
badPackageName => RETURN [ TRUE, FALSE, "bad package df file name"];
};
};
Grap Controller
SetGrabController: Commander.CommandProc = {
ComputeControllerInternal.GrabController ← TRUE;
};
Commander.Register[key: "///Commands/SummonerBecomeController", proc: SetGrabController, doc: "Try to force the Compute Server Controller to this machine"];
TRUSTED {Process.InitializeCondition[@NoticeNewPackageCondition, Process.SecondsToTicks[1]];};
END.
Bob Hagmann February 12, 1985 12:22:33 pm PST
changes to: writeUpdatedItem (local of NoticeNewPackage), dir (local of DoOneItem, local of NoticeNewPackage), file (local of DoOneItem, local of NoticeNewPackage)