ComputeServerServicesImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Server implementation of the FS abstraction. This must be run on the server workstation to register procedures to monitor process activity, and to register procedures in FS to handle some FS functions specially.
Last Edited by: Bob Hagmann, May 14, 1986 7:40:22 am PDT
DIRECTORY
Basics,
BasicTime,
ComputeServerCallbacks,
ComputeServerCallbacksRpcControl,
ComputeServerInternal,
CountedVM,
File,
FS,
FSBackdoor,
FSDir,
FSName,
FSLock,
FSFileOps,
FSReport,
IO,
Loader,
PrincOps USING [ PDA, PsbIndex, StartPsb],
PrincOpsUtils,
ProcessBackdoor USING[ParentChildCallback, RegisterEventProcs, SingleCallback],
ProcessProps,
Rope,
RPC,
SafeStorage,
UnsafeStorage USING [GetSystemUZone],
UserCredentials,
UserCredentialsBackdoor,
UserProfile,
UserProfileBackdoor;
ComputeServerServicesImpl:
CEDAR
MONITOR
IMPORTS BasicTime, ComputeServerCallbacks, ComputeServerCallbacksRpcControl, ComputeServerInternal, CountedVM, File, FS, FSBackdoor, FSDir, FSFileOps, FSLock, FSName, FSReport, IO, Loader, ProcessBackdoor, ProcessProps, PrincOpsUtils, Rope, RPC, SafeStorage, UnsafeStorage, UserCredentialsBackdoor, UserProfileBackdoor
EXPORTS ComputeServerInternal
= BEGIN
Declarations
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
ParentChildCallback: TYPE = ProcessBackdoor.ParentChildCallback;
SingleCallback: TYPE = ProcessBackdoor.SingleCallback;
StateArrayRec: TYPE ~ RECORD [SEQUENCE length: NAT OF LONG POINTER];
OverrideArrayRec: TYPE ~ RECORD [SEQUENCE length: NAT OF BOOL];
stateArray: LONG POINTER TO StateArrayRec ;
fsOverride: LONG POINTER TO OverrideArrayRec;
allOverride: LONG POINTER TO OverrideArrayRec;
some counters (for the fun of it)
forks: INT ← 0 ;
joins: INT ← 0 ;
detatchs: INT ← 0 ;
ends: INT ← 0 ;
ActiveServicesItem: TYPE = ComputeServerInternal.ActiveServicesItem;
localOpenFile: TYPE = REF localOpenFileObject;
localOpenFileObject:
TYPE =
RECORD[
remoteFile: BOOL ← TRUE,
remoteFileID: ComputeServerCallbacks.OpenFile,
localFile: FS.OpenFile ← FS.nullOpenFile,
serviceItem: ActiveServicesItem ← NIL,
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← NIL
];
LocalOpenFileType: SafeStorage.Type ← CODE[localOpenFile];
Registered Procedures for Process Monitoring
These are registered in ProcessImpl to notify us when FORKs, JOINs and the like occur.
myFork: ParentChildCallback =
TRUSTED {
forks ← forks + 1;
stateArray[childPsb] ← stateArray[parentPsb];
};
myJoin: ParentChildCallback =
TRUSTED {
joins ← joins + 1;
stateArray[childPsb] ← NIL ;
};
myDetatch: SingleCallback =
TRUSTED {
detatchs ← detatchs + 1;
};
myEnd: SingleCallback =
TRUSTED {
ends ← ends + 1;
stateArray[Psb] ← NIL ;
};
Exported to ComputeServerInternal
MarkGuestProcess:
PUBLIC
ENTRY
PROC [process:
PROCESS, data:
LONG
POINTER]
RETURNS [ok:
BOOL ←
TRUE, oldData:
LONG
POINTER] =
TRUSTED {
psb: PrincOps.PsbIndex = LOOPHOLE[process];
IF psb < PrincOps.StartPsb + PrincOps.
PDA.count
THEN {
stateArray[psb] ← data ;
fsOverride[psb] ← FALSE;
allOverride[psb] ← FALSE;
}
ELSE ok ← FALSE;
};
GetGuestProcessData:
PUBLIC
ENTRY
PROC [process:
PROCESS]
RETURNS [data:
LONG
POINTER] =
TRUSTED {
psb: PrincOps.PsbIndex = LOOPHOLE[process];
RETURN [stateArray[psb]];
};
MarkProcessNotGuest:
PUBLIC
ENTRY
PROC [process:
PROCESS] =
TRUSTED {
psb: PrincOps.PsbIndex = LOOPHOLE[process];
allOverride[psb] ← TRUE;
};
RemoveMarkProcessNotGuest:
PUBLIC
ENTRY
PROC [process:
PROCESS] =
TRUSTED {
psb: PrincOps.PsbIndex = LOOPHOLE[process];
allOverride[psb] ← FALSE;
};
MarkProcessUseLocalFS:
PUBLIC
ENTRY
PROC [process:
PROCESS] =
TRUSTED {
psb: PrincOps.PsbIndex = LOOPHOLE[process];
fsOverride[psb] ← TRUE;
};
RemoveMarkProcessUseLocalFS:
PUBLIC
ENTRY
PROC [process:
PROCESS] =
TRUSTED {
psb: PrincOps.PsbIndex = LOOPHOLE[process];
fsOverride[psb] ← FALSE;
};
Registered Procedures for FS
myFSIsGuestProcess:
PROC []
RETURNS [isGuest:
BOOL] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
RETURN [~fsOverride[psb] AND ~allOverride[psb] AND stateArray[psb] # NIL] ;
};
mySetDefaultWDir:
PROC [dir: Rope.
ROPE] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem ← LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface ← TryRPCRecovery[interface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
interface.rSetDefaultWDir[dir];
};
};
myGetDefaultWDir:
PROC
RETURNS [Rope.
ROPE] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem ← LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface ← TryRPCRecovery[interface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
RETURN[interface.rGetDefaultWDir[]];
};
};
myExpandName:
PROC[name:
ROPE, wDir:
ROPE]
RETURNS [useDefault:
BOOL ←
FALSE, fullFName:
ROPE, cp:
FS.ComponentPositions, dirOmitted:
BOOLEAN ←
FALSE] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface ← TryRPCRecovery[interface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
RPC.CallFailed => ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
processWDIR: ROPE ← NARROW [ ProcessProps.GetProp[$WorkingDirectory] ];
IF processWDIR #
NIL
OR (Rope.Length[name] > 0
AND (Rope.Fetch[name, 0] = '[
OR Rope.Fetch[name, 0] = '[ ))
OR Rope.Length[wDir] # 0
THEN {
If there is a process working directory, the name is a global name, or the working directory is explicitly specified. Do the call locally.
useDefault ← TRUE;
}
ELSE {
Must use the default working directory. Run the call on the client's machine.
[fullFName, cp, dirOmitted] ← interface.rExpandName[name,wDir];
};
};
};
myFileInfo:
PROC [name:
ROPE, wantedCreatedTime: BasicTime.
GMT, remoteCheck:
BOOLEAN, wDir:
ROPE]
RETURNS [fullFName, attachedTo:
ROPE, keep:
CARDINAL, bytes:
INT, created: BasicTime.
GMT] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface ← TryRPCRecovery[serviceItem.callbacksInterface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
RPC.CallFailed => ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
IF wDir = NIL THEN wDir ← NARROW [ ProcessProps.GetProp[$WorkingDirectory] ];
[fullFName, attachedTo, keep, bytes, created] ← interface.rFileInfo[name, wantedCreatedTime, remoteCheck, wDir];
};
};
myEnumerateForInfo:
PROC [pattern:
ROPE, proc:
FS.InfoProc, wDir:
ROPE] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface ← TryRPCRecovery[serviceItem.callbacksInterface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
fullFName, attachedTo: ROPE;
created: BasicTime.GMT;
bytes: INT;
keep: CARDINAL;
continue: BOOLEAN;
IF ~testAndSetDoingEnumerate[serviceItem] THEN ERROR FS.Error[[group: client, code: $nestedEnumerate, explanation: "Enumeration cannot be nested using the Summoner"]];
IF wDir = NIL THEN wDir ← NARROW [ ProcessProps.GetProp[$WorkingDirectory] ];
[fullFName, attachedTo, created, bytes, keep, continue] ← interface.rStartEnumerateForInfo[serviceItem.listenerPupAddress, pattern, wDir];
WHILE continue
DO
continue ← proc[fullFName, attachedTo, created, bytes, keep];
IF continue THEN [fullFName, attachedTo, created, bytes, keep, continue] ← interface.rNextEnumerateForInfo[serviceItem.listenerPupAddress]
ELSE interface.rDoneEnumerate[serviceItem.listenerPupAddress];
ENDLOOP;
clearDoingEnumerate[serviceItem];
};
};
myEnumerateForNames:
PROC [pattern:
ROPE, proc:
FS.NameProc, wDir:
ROPE] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface ← TryRPCRecovery[serviceItem.callbacksInterface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
fullFName: ROPE;
continue: BOOLEAN;
IF ~testAndSetDoingEnumerate[serviceItem] THEN ERROR FS.Error[[group: client, code: $nestedEnumerate, explanation: "Enumeration cannot be nested using the Summoner"]];
IF wDir = NIL THEN wDir ← NARROW [ ProcessProps.GetProp[$WorkingDirectory] ];
[fullFName, continue] ← interface.rStartEnumerateForNames[serviceItem.listenerPupAddress, pattern, wDir];
WHILE continue
DO
continue ← proc[fullFName];
IF continue THEN [fullFName, continue] ← interface.rNextEnumerateForNames[serviceItem.listenerPupAddress]
ELSE interface.rDoneEnumerate[serviceItem.listenerPupAddress];
ENDLOOP;
clearDoingEnumerate[serviceItem];
};
};
makeFileFromMyFile:
PROC[myOpenFile: localOpenFile]
RETURNS [file:
FS.OpenFile] = {
fileProcs: REF FSBackdoor.FileProcs ;
fileProcs ← FSBackdoor.CreateFileProcs [
GetClass: getClassProc,
SameFile: sameFileProc,
GetName: getNameProc,
GetInfo: getInfoProc,
SetPageCount: setPageCountProc,
SetByteCountAndCreatedTime: setByteCountAndCreatedTimeProc,
Read: readProc,
Write: writeProc,
Close: closeProc
] ;
file ← FSBackdoor.CreateProcsOpenFile[clientFile: myOpenFile, fileProcs: fileProcs];
LocalOpenFileType ← SafeStorage.GetReferentType[file];
};
myOpen:
PROC [name:
ROPE, lock:
FS.Lock ← $read, wantedCreatedTime: BasicTime.
GMT ← BasicTime.nullGMT, remoteCheck:
BOOLEAN ←
TRUE, wDir:
ROPE ←
NIL]
RETURNS [file:
FS.OpenFile] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
serviceREF: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[serviceItem];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface ← TryRPCRecovery[serviceItem.callbacksInterface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
myOpenFile: localOpenFile ← NEW[localOpenFileObject];
globalNameToOpen: ROPE;
localFullFName: ROPE;
cp: FS.ComponentPositions;
dirOmitted: BOOL;
myOpenFile.serviceItem ← serviceREF;
myOpenFile.interface ← interface ;
IF wDir = NIL THEN wDir ← NARROW [ ProcessProps.GetProp[$WorkingDirectory] ];
[fullFName: localFullFName, cp: cp, dirOmitted: dirOmitted] ← FS.ExpandName[name: name, wDir: wDir];
IF Rope.Equal[Rope.Substr[base: localFullFName, start: cp.server.start, len: cp.server.length], "SummonerServer"]
THEN {
IF ComputeServerInternal.OKToUseLocalDisk
THEN {
localName: ROPE;
savedError: FS.ErrorDesc;
localOpenOK: BOOL ← TRUE;
localName ← Rope.Concat["[]<", Rope.Substr[localFullFName, cp.dir.start]];
fsOverride[psb] ← TRUE;
file ←
FS.Open[localName, lock, wantedCreatedTime, remoteCheck !
FS.Error => {
localOpenOK ← FALSE;
savedError ← error;
CONTINUE;
} ];
fsOverride[psb] ← FALSE;
IF localOpenOK
THEN {
RETURN[file];
}
ELSE ERROR FS.Error[savedError];
}
ELSE {
ERROR FS.Error[[ environment, $SeverMachineWillNotAllowUseOfLocalDisk, Rope.Cat["Attempt to open a file on logical server 'SummonerServer' for file name ", localFullFName, "while the Server was not setup to allow access to it's local file system"]]];
};
};
[globalNameToOpen: globalNameToOpen, openFile: myOpenFile.remoteFileID] ← interface.rOpen[serviceItem.listenerPupAddress, name, lock, wantedCreatedTime, remoteCheck, wDir, FALSE];
IF Rope.Length[globalNameToOpen] > 0
THEN {
-- We are trying to open an attachment
localOpenFailed: BOOL ← TRUE;
gotIt: BOOL ← FALSE;
cacheNameProc: FSBackdoor.NameProc =
TRUSTED {
gotIt ← TRUE;
};
FSBackdoor.EnumerateCacheForNames[proc: cacheNameProc, volName: NIL, pattern: globalNameToOpen];
IF gotIt
THEN {
fsOverride[psb] ← TRUE;
localOpenFailed ← FALSE;
myOpenFile.localFile ← FS.Open[globalNameToOpen !
FS.Error => {localOpenFailed ← TRUE; CONTINUE;} ];
fsOverride[psb] ← FALSE;
};
IF localOpenFailed
THEN {
IF myOpenFile.remoteFileID = -1
THEN {
-- Flag for read file from client's cache into server's cache
newFP: File.FP ← File.nullFP;
newFile: File.Handle ← NIL;
retreiveStarted: BOOL ← FALSE;
pn: FSName.ParsedFName;
a: FSLock.ActiveFile ← NIL;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed =>
TRUSTED {
GOTO skipOnError;
};
FS.Error, File.Error,
ABORTED => {
IF newFile #
NIL
THEN {
File.Delete[newFile ! File.Error => CONTINUE;];
};
IF retreiveStarted
THEN {
FSReport.ReportRemote[endRetrieving, pn.fullName];
retreiveStarted ← FALSE;
};
FSLock.ReleaseRecord[a];
GOTO skipOnError;
};
};
remoteFile: FS.OpenFile;
bytes: INT;
created: BasicTime.GMT;
remoteFileStream: STREAM ← NIL;
bytesLeft: INT;
unsafeDataBlock: Basics.UnsafeBlock ;
bufferHandle: CountedVM.Handle;
nowPage: File.PageNumber ← [0];
fp: File.FP;
pagesInABuffer: INT = 8;
bytesInABuffer: INT = FS.BytesForPages[8];
[pn, ] ← FSName.ParseClientName[globalNameToOpen, NIL];
[fp, a] ← FSDir.AcquireOldOrNewGName[pn.volDesc, pn.nameBody, pn.version];
[openFile: myOpenFile.remoteFileID] ← interface.rOpen[serviceItem.listenerPupAddress, name, lock, wantedCreatedTime, remoteCheck, wDir, TRUE];
remoteFile ← makeFileFromMyFile[myOpenFile];
remoteFileStream ← FS.StreamFromOpenFile[openFile: remoteFile, streamOptions: [FALSE, FALSE, FALSE, FALSE, FALSE], streamBufferParms: [pagesInABuffer, 2]];
[bytes: bytes, created: created] ← interface.rGetInfo[serviceItem.listenerPupAddress, myOpenFile.remoteFileID ! ComputeServerCallbacks.Error => {ERROR FS.Error[error]; }];
[newFP, newFile] ← FSFileOps.CreateFile[pn.volDesc.vol, FS.PagesForBytes[bytes]];
bytesLeft ← bytes;
bufferHandle ← CountedVM.SimpleAllocate[bytesInABuffer];
unsafeDataBlock.base ← bufferHandle.pointer;
FSReport.ReportRemote[startRetrieving, pn.fullName];
retreiveStarted ← TRUE;
unsafeDataBlock.count ← bytesInABuffer;
WHILE bytesLeft > 0
DO
readCount: INT;
nPages: File.PageCount;
readCount ← remoteFileStream.UnsafeGetBlock[unsafeDataBlock];
IF readCount # MIN[bytesLeft, bytesInABuffer] THEN GOTO skipOnError;
bytesLeft ← bytesLeft - readCount ;
nPages ← FS.PagesForBytes[readCount];
File.Write[file: newFile, to: nowPage, nPages: nPages, from: bufferHandle.pointer];
nowPage ← [nowPage + nPages];
ENDLOOP;
FSReport.ReportRemote[endRetrieving, pn.fullName];
FSFileOps.SetProps[newFile, bytes, 0, created, pn.nameBody, pn.version];
FSDir.UpdateCachedEntry[pn.volDesc, pn.nameBody, pn.version, BasicTime.Now[], newFP, insert];
interface.rClose[serviceItem.listenerPupAddress, myOpenFile.remoteFileID ! ComputeServerCallbacks.Error => {ERROR FS.Error[error]; }];
FSLock.ReleaseRecord[a];
fsOverride[psb] ← TRUE;
localOpenFailed ← FALSE;
myOpenFile.localFile ← FS.Open[globalNameToOpen !
FS.Error => {localOpenFailed ← TRUE; CONTINUE;} ];
fsOverride[psb] ← FALSE;
IF ~localOpenFailed
THEN {
myOpenFile.remoteFile ← FALSE;
RETURN[makeFileFromMyFile[myOpenFile]];
};
EXITS
skipOnError => {
IF newFile #
NIL
THEN {
File.Delete[newFile ! File.Error => CONTINUE;];
};
IF retreiveStarted THEN FSReport.ReportRemote[endRetrieving, pn.fullName];
FSLock.ReleaseRecord[a];
};
};
}
ELSE {
-- myOpenFile.remoteFileID # -1 => load cache from file server
localOpenFailed ← FALSE;
myOpenFile.localFile ← FS.Open[globalNameToOpen !
FS.Error => {localOpenFailed ← TRUE; CONTINUE;}
];
IF ~localOpenFailed THEN myOpenFile.remoteFile ← FALSE;
};
IF localOpenFailed THEN [globalNameToOpen: globalNameToOpen, openFile: myOpenFile.remoteFileID] ← interface.rOpen[serviceItem.listenerPupAddress, name, lock, wantedCreatedTime, remoteCheck, wDir, TRUE];
}
ELSE myOpenFile.remoteFile ← FALSE;
};
file ← makeFileFromMyFile[myOpenFile];
};
myCreate:
PROC [name:
ROPE, setPages:
BOOLEAN ←
TRUE, pages:
INT ← 0, setKeep:
BOOLEAN ←
FALSE, keep:
CARDINAL ← 1, wDir:
ROPE ←
NIL]
RETURNS [file:
FS.OpenFile] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
serviceREF: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[serviceItem];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface ← TryRPCRecovery[serviceItem.callbacksInterface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
myOpenFile: localOpenFile ← NEW[localOpenFileObject];
localFullFName: ROPE;
cp: FS.ComponentPositions;
dirOmitted: BOOL;
myOpenFile.serviceItem ← serviceREF;
myOpenFile.interface ← interface ;
IF wDir = NIL THEN wDir ← NARROW [ ProcessProps.GetProp[$WorkingDirectory] ];
[fullFName: localFullFName, cp: cp, dirOmitted: dirOmitted] ← FS.ExpandName[name: name, wDir: wDir];
IF Rope.Equal[Rope.Substr[base: localFullFName, start: cp.server.start, len: cp.server.length], "SummonerServer"]
THEN {
IF ComputeServerInternal.OKToUseLocalDisk
THEN {
localName: ROPE;
savedError: FS.ErrorDesc;
localOpenOK: BOOL ← TRUE;
localName ← Rope.Concat["[]<", Rope.Substr[localFullFName, cp.dir.start]];
fsOverride[psb] ← TRUE;
file ←
FS.Create[localName, setPages, pages, setKeep, keep !
FS.Error => {
localOpenOK ← FALSE;
savedError ← error;
CONTINUE;
} ];
fsOverride[psb] ← FALSE;
IF localOpenOK
THEN {
RETURN[file];
}
ELSE ERROR FS.Error[savedError];
}
ELSE {
ERROR FS.Error[[ environment, $SeverMachineWillNotAllowUseOfLocalDisk, Rope.Cat["Attempt to open a file on logical server 'SummonerServer' for file name ", localFullFName, "while the Server was not setup to allow access to it's local file system"]]];
};
};
myOpenFile.remoteFileID ← interface.rCreate[serviceItem.listenerPupAddress, name, setPages, pages, setKeep, keep, wDir];
file ← makeFileFromMyFile[myOpenFile];
};
};
myCopy:
PROC [from, to:
ROPE, setKeep:
BOOL, keep:
CARDINAL, wantedCreatedTime: BasicTime.
GMT, remoteCheck:
BOOL, attach:
BOOL, wDir: Rope.
ROPE]
RETURNS [toFName:
ROPE] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface ← TryRPCRecovery[serviceItem.callbacksInterface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
IF wDir = NIL THEN wDir ← NARROW [ ProcessProps.GetProp[$WorkingDirectory] ];
[toFName: toFName] ← interface.rCopy[serviceItem.listenerPupAddress, from, to, setKeep, keep, wantedCreatedTime, remoteCheck, attach, wDir];
};
};
myDelete:
PROC [name:
ROPE, wantedCreatedTime: BasicTime.
GMT, wDir:
ROPE] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface ← TryRPCRecovery[serviceItem.callbacksInterface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
localFullFName: ROPE;
cp: FS.ComponentPositions;
dirOmitted: BOOL;
IF wDir = NIL THEN wDir ← NARROW [ ProcessProps.GetProp[$WorkingDirectory] ];
[fullFName: localFullFName, cp: cp, dirOmitted: dirOmitted] ← FS.ExpandName[name: name, wDir: wDir];
IF Rope.Equal[Rope.Substr[base: localFullFName, start: cp.server.start, len: cp.server.length], "SummonerServer"]
THEN {
IF ComputeServerInternal.OKToUseLocalDisk
THEN {
localName: ROPE;
savedError: FS.ErrorDesc;
localOpenOK: BOOL ← TRUE;
localName ← Rope.Concat["[]<", Rope.Substr[localFullFName, cp.dir.start]];
fsOverride[psb] ← TRUE;
FS.Delete[localName, wantedCreatedTime !
FS.Error => {
localOpenOK ← FALSE;
savedError ← error;
CONTINUE;
} ];
fsOverride[psb] ← FALSE;
IF localOpenOK
THEN {
RETURN[];
}
ELSE ERROR FS.Error[savedError];
}
ELSE {
ERROR FS.Error[[ environment, $SeverMachineWillNotAllowUseOfLocalDisk, Rope.Cat["Attempt to open a file on logical server 'SummonerServer' for file name ", localFullFName, "while the Server was not setup to allow access to it's local file system"]]];
};
};
[] ← interface.rDelete[serviceItem.listenerPupAddress, name, wantedCreatedTime, wDir];
};
};
myRename:
PROC [from, to: Rope.
ROPE, setKeep:
BOOLEAN, keep:
CARDINAL, wantedCreatedTime: BasicTime.
GMT, wDir: Rope.
ROPE] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface ← TryRPCRecovery[serviceItem.callbacksInterface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
IF wDir = NIL THEN wDir ← NARROW [ ProcessProps.GetProp[$WorkingDirectory] ];
[] ← interface.rRename[serviceItem.listenerPupAddress, from, to, setKeep, keep, wantedCreatedTime, wDir];
};
};
mySetKeep:
PROC [name: Rope.
ROPE, keep:
CARDINAL, wDir: Rope.
ROPE] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface ← TryRPCRecovery[serviceItem.callbacksInterface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
IF wDir = NIL THEN wDir ← NARROW [ ProcessProps.GetProp[$WorkingDirectory] ];
[] ← interface.rSetKeep[serviceItem.listenerPupAddress, name, keep, wDir];
};
};
Enumeration Control
testAndSetDoingEnumerate:
ENTRY
PROC[serviceItem: ComputeServerInternal.ActiveServicesItem]
RETURNS [ok:
BOOL] =
TRUSTED {
IF serviceItem.doingEnumerate THEN RETURN[FALSE];
serviceItem.doingEnumerate ← TRUE;
RETURN[ TRUE];
};
clearDoingEnumerate:
ENTRY
PROC[serviceItem: ComputeServerInternal.ActiveServicesItem] =
TRUSTED {
serviceItem.doingEnumerate ← FALSE;
};
FS File Procs for My OpenFiles
getClassProc:
PROC [clientFile:
REF]
RETURNS [
ATOM ← $NIL] = {
myFile: localOpenFile ← NARROW[clientFile];
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface: ComputeServerCallbacksRpcControl.InterfaceRecord;
interface ← TryRPCRecovery[myFile.interface, firstCall, myFile.serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface #
NIL
THEN {
myFile.interface ← interface;
myFile.serviceItem.callbacksInterface ← interface;
RETRY;
};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
IF myFile.remoteFile
THEN {
IF myFile.serviceItem.callOver THEN ERROR FS.Error[ [bug, $remoteRequestFinished ,"compute server remote file operation attempted after the end of the request"]];
RETURN[myFile.interface.rGetClass[myFile.serviceItem.listenerPupAddress, myFile.remoteFileID]];
}
ELSE {
RETURN[FS.GetClass[myFile.localFile]];
};
};
};
sameFileProc:
PROC [clientFile1, clientFile2:
REF]
RETURNS [
BOOLEAN ←
FALSE] = {
myFile1: localOpenFile ← NARROW[clientFile1];
myFile2: localOpenFile ← NARROW[clientFile2];
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface: ComputeServerCallbacksRpcControl.InterfaceRecord;
interface ← TryRPCRecovery[myFile1.interface, firstCall, myFile1.serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface #
NIL
THEN {
myFile1.interface ← interface;
myFile1.serviceItem.callbacksInterface ← interface;
RETRY;
};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
IF myFile1.remoteFile ~= myFile2.remoteFile THEN RETURN [FALSE];
IF myFile1.remoteFile
THEN {
IF myFile1.serviceItem.callOver THEN ERROR FS.Error[ [bug, $remoteRequestFinished ,"compute server remote file operation attempted after the end of the request"]];
RETURN[myFile1.interface.rSameFile[myFile1.serviceItem.listenerPupAddress, myFile1.remoteFileID, myFile2.remoteFileID]];
}
ELSE {
RETURN[FS.SameFile[myFile1.localFile, myFile2.localFile]]
};
};
};
getNameProc:
PROC [clientFile:
REF]
RETURNS [fullFName, attachedTo: Rope.
ROPE] = {
myFile: localOpenFile ← NARROW[clientFile];
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface: ComputeServerCallbacksRpcControl.InterfaceRecord;
interface ← TryRPCRecovery[myFile.interface, firstCall, myFile.serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface #
NIL
THEN {
myFile.interface ← interface;
myFile.serviceItem.callbacksInterface ← interface;
RETRY;
};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
IF myFile.remoteFile
THEN {
IF myFile.serviceItem.callOver THEN ERROR FS.Error[ [bug, $remoteRequestFinished ,"compute server remote file operation attempted after the end of the request"]];
[fullFName, attachedTo] ← myFile.interface.rGetName[ myFile.serviceItem.listenerPupAddress, myFile.remoteFileID];
}
ELSE {
[fullFName, attachedTo] ← FS.GetName[myFile.localFile];
};
};
};
getInfoProc:
PROC [clientFile:
REF]
RETURNS [keep:
CARDINAL, pages, bytes:
INT, created: BasicTime.
GMT, lock:
FS.Lock] = {
myFile: localOpenFile ← NARROW[clientFile];
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface: ComputeServerCallbacksRpcControl.InterfaceRecord;
interface ← TryRPCRecovery[myFile.interface, firstCall, myFile.serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface #
NIL
THEN {
myFile.interface ← interface;
myFile.serviceItem.callbacksInterface ← interface;
RETRY;
};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
IF myFile.remoteFile
THEN {
IF myFile.serviceItem.callOver THEN ERROR FS.Error[ [bug, $remoteRequestFinished ,"compute server remote file operation attempted after the end of the request"]];
[keep, pages, bytes, created, lock] ← myFile.interface.rGetInfo[ myFile.serviceItem.listenerPupAddress, myFile.remoteFileID];
}
ELSE {
[keep, pages, bytes, created, lock] ← FS.GetInfo[myFile.localFile];
};
};
};
setPageCountProc:
PROC [clientFile:
REF, pages:
INT] = {
myFile: localOpenFile ← NARROW[clientFile];
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface: ComputeServerCallbacksRpcControl.InterfaceRecord;
interface ← TryRPCRecovery[myFile.interface, firstCall, myFile.serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface #
NIL
THEN {
myFile.interface ← interface;
myFile.serviceItem.callbacksInterface ← interface;
RETRY;
};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
IF myFile.remoteFile
THEN {
IF myFile.serviceItem.callOver THEN ERROR FS.Error[ [bug, $remoteRequestFinished ,"compute server remote file operation attempted after the end of the request"]];
myFile.interface.rSetPageCount[myFile.serviceItem.listenerPupAddress, myFile.remoteFileID, pages];
}
ELSE {
FS.SetPageCount[myFile.localFile, pages];
};
};
};
setByteCountAndCreatedTimeProc:
PROC [clientFile:
REF, bytes:
INT, created: BasicTime.
GMT] = {
myFile: localOpenFile ← NARROW[clientFile];
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface: ComputeServerCallbacksRpcControl.InterfaceRecord;
interface ← TryRPCRecovery[myFile.interface, firstCall, myFile.serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface #
NIL
THEN {
myFile.interface ← interface;
myFile.serviceItem.callbacksInterface ← interface;
RETRY;
};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
IF myFile.remoteFile
THEN {
IF myFile.serviceItem.callOver THEN ERROR FS.Error[ [bug, $remoteRequestFinished ,"compute server remote file operation attempted after the end of the request"]];
myFile.interface.rSetByteCountAndCreatedTime[myFile.serviceItem.listenerPupAddress, myFile.remoteFileID, bytes, created];
}
ELSE {
FS.SetByteCountAndCreatedTime[myFile.localFile, bytes, created];
};
};
};
readProc:
UNSAFE
PROC [clientFile:
REF, from, nPages:
INT, to:
LONG
POINTER] = {
myFile: localOpenFile ← NARROW[clientFile];
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface: ComputeServerCallbacksRpcControl.InterfaceRecord;
interface ← TryRPCRecovery[myFile.interface, firstCall, myFile.serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface #
NIL
THEN {
myFile.interface ← interface;
myFile.serviceItem.callbacksInterface ← interface;
RETRY;
};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
IF myFile.remoteFile
THEN {
pageBuffer: ComputeServerCallbacks.RESULTPageBuffer ;
IF myFile.serviceItem.callOver THEN ERROR FS.Error[ [bug, $remoteRequestFinished ,"compute server remote file operation attempted after the end of the request"]];
TRUSTED {pageBuffer ← DESCRIPTOR[to, nPages*File.wordsPerPage]; };
myFile.interface.rRead[myFile.serviceItem.listenerPupAddress, myFile.remoteFileID, from, nPages, pageBuffer];
}
ELSE
TRUSTED {
FS.Read[myFile.localFile, from, nPages, to];
};
};
};
writeProc:
PROC [clientFile:
REF, to:
INT, nPages:
INT, from:
LONG
POINTER] = {
myFile: localOpenFile ← NARROW[clientFile];
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface: ComputeServerCallbacksRpcControl.InterfaceRecord;
interface ← TryRPCRecovery[myFile.interface, firstCall, myFile.serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface #
NIL
THEN {
myFile.interface ← interface;
myFile.serviceItem.callbacksInterface ← interface;
RETRY;
};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
IF myFile.remoteFile
THEN {
pageBuffer: ComputeServerCallbacks.VALUEPageBuffer ;
IF myFile.serviceItem.callOver THEN ERROR FS.Error[ [bug, $remoteRequestFinished ,"compute server remote file operation attempted after the end of the request"]];
TRUSTED {pageBuffer ← DESCRIPTOR[from, nPages*File.wordsPerPage]; };
myFile.interface.rWrite[myFile.serviceItem.listenerPupAddress, myFile.remoteFileID, to, nPages, pageBuffer];
}
ELSE {
ERROR FS.Error[ [bug, $CannotWriteToServerDisk, "Writing onto the compute servers local file system is illegal"]];
};
};
};
closeProc:
PROC [clientFile:
REF] = {
myFile: localOpenFile ← NARROW[clientFile];
firstCall: BOOL ← TRUE;
{
ENABLE {
ComputeServerCallbacks.Error => ERROR FS.Error[error];
RPC.CallFailed => {
interface: ComputeServerCallbacksRpcControl.InterfaceRecord;
interface ← TryRPCRecovery[myFile.interface, firstCall, myFile.serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface #
NIL
THEN {
myFile.interface ← interface;
myFile.serviceItem.callbacksInterface ← interface;
RETRY;
};
ERROR FS.Error[ [environment, $serverInaccessible ,"remote rpc call failed"]];
};
};
IF myFile.remoteFile
THEN {
IF myFile.serviceItem.callOver THEN ERROR FS.Error[ [bug, $remoteRequestFinished ,"compute server remote file operation attempted after the end of the request"]];
myFile.interface.rClose[myFile.serviceItem.listenerPupAddress, myFile.remoteFileID ! ComputeServerCallbacks.Error => {ERROR FS.Error[error]; }];
}
ELSE
TRUSTED {
FS.Close[myFile.localFile];
};
};
};
UserCredentials and UserProfile
IsGuestProcess:
PUBLIC
PROC []
RETURNS [isGuest:
BOOL] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
RETURN [~allOverride[psb] AND stateArray[psb] # NIL] ;
};
GetState:
PROC
RETURNS [UserCredentials.State] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
RPC.CallFailed => {
interface ← TryRPCRecovery[serviceItem.callbacksInterface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
};
};
RETURN[interface.rGetState[serviceItem.listenerPupAddress]];
};
};
ChangeState:
PROC [new: UserCredentials.State]
RETURNS [old: UserCredentials.State] = {
ERROR;
};
Login:
PROC [startInteraction:
PROC
RETURNS [in, out:
IO.
STREAM],
endInteraction:
PROC [in, out:
IO.
STREAM], options: UserCredentials.LoginOptions ← UserCredentials.defaultOptions] = {
ERROR;
};
Get:
PROC
RETURNS [name, password: Rope.
ROPE] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
RPC.CallFailed => {
interface ← TryRPCRecovery[serviceItem.callbacksInterface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
};
};
[name, password] ← interface.rGet[serviceItem.listenerPupAddress];
};
};
Boolean:
PROC [key: Rope.
ROPE, default:
BOOLEAN ←
FALSE]
RETURNS [value:
BOOLEAN] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
RPC.CallFailed => {
interface ← TryRPCRecovery[serviceItem.callbacksInterface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
};
};
RETURN[interface.rBoolean[serviceItem.listenerPupAddress, key, default]];
};
};
Number:
PROC [key: Rope.
ROPE, default:
INT ← 0]
RETURNS [value:
INT] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
RPC.CallFailed => {
interface ← TryRPCRecovery[serviceItem.callbacksInterface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
};
};
RETURN[interface.rNumber[serviceItem.listenerPupAddress, key, default]];
};
};
Token:
PROC [key: Rope.
ROPE, default: Rope.
ROPE ←
NIL]
RETURNS [value: Rope.
ROPE] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
RPC.CallFailed => {
interface ← TryRPCRecovery[serviceItem.callbacksInterface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
};
};
RETURN[interface.rToken[serviceItem.listenerPupAddress, key, default]];
};
};
ListOfTokens:
PROC [key: Rope.
ROPE, default:
LIST
OF Rope.
ROPE ←
NIL]
RETURNS [value:
LIST
OF Rope.
ROPE] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
RPC.CallFailed => {
interface ← TryRPCRecovery[serviceItem.callbacksInterface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
};
};
RETURN[interface.rListOfTokens[serviceItem.listenerPupAddress, key, default]];
};
};
Line:
PROC [key: Rope.
ROPE, default: Rope.
ROPE ←
NIL]
RETURNS [value: Rope.
ROPE] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
RPC.CallFailed => {
interface ← TryRPCRecovery[serviceItem.callbacksInterface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
};
};
RETURN[interface.rLine[serviceItem.listenerPupAddress, key, default]];
};
};
GetProfileName:
PROC
RETURNS [Rope.
ROPE] =
TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOL ← TRUE;
{
ENABLE {
RPC.CallFailed => {
interface ← TryRPCRecovery[serviceItem.callbacksInterface, firstCall, serviceItem.clientNetAddressRope];
firstCall ← FALSE;
IF interface # NIL THEN {serviceItem.callbacksInterface ← interface; RETRY;};
};
};
RETURN[interface.rGetProfileName[serviceItem.listenerPupAddress]];
};
};
CallWhenProfileChanges:
PROC [ proc: UserProfile.ProfileChangedProc ] = {
ERROR;
};
ProfileChanged:
PROC [reason: UserProfile.ProfileChangeReason] = {
ERROR;
};
RPC Error Control
TryRPCRecovery:
PROC [oldInterface: ComputeServerCallbacksRpcControl.InterfaceRecord, firstCall:
BOOL, clientNetAddressRope:
ROPE]
RETURNS [newInterface: ComputeServerCallbacksRpcControl.InterfaceRecord ←
NIL] = {
IF firstCall
THEN {
newInterface ← ComputeServerInternal.GetClientInterfaceFromCache[clientNetAddressRope, TRUE];
}
ELSE {
[] ← ComputeServerInternal.DeleteClientInterfaceFromCache[oldInterface];
};
};
Initialization
newFSProcs:
REF FSBackdoor.GuestProcsRec ←
NEW[FSBackdoor.GuestProcsRec ← [
IsGuestProcess: myFSIsGuestProcess,
SetDefaultWDir: mySetDefaultWDir,
GetDefaultWDir: myGetDefaultWDir,
ExpandName: myExpandName,
FileInfo: myFileInfo,
EnumerateForInfo: myEnumerateForInfo ,
EnumerateForNames: myEnumerateForNames,
Open: myOpen,
Create: myCreate,
Copy: myCopy,
Delete: myDelete,
Rename: myRename,
SetKeep: mySetKeep
]];
newCredentialsProcs:
REF UserCredentialsBackdoor.GuestProcsRec ←
NEW[UserCredentialsBackdoor.GuestProcsRec ← [
IsGuestProcess: IsGuestProcess,
GetState: GetState,
ChangeState: ChangeState,
Login: Login,
Get: Get
]];
newProfileProcs:
REF UserProfileBackdoor.GuestProcsRec ←
NEW[UserProfileBackdoor.GuestProcsRec ← [
IsGuestProcess: IsGuestProcess,
Boolean: Boolean,
Number: Number,
Token: Token,
ListOfTokens: ListOfTokens,
Line: Line,
GetProfileName: GetProfileName,
CallWhenProfileChanges: CallWhenProfileChanges,
ProfileChanged: ProfileChanged
]];
initialize state array to keep track of guest processes, and register process monitoring procedures
TRUSTED {
size: NAT = PrincOps.StartPsb + PrincOps.PDA.count;
stateArray ← UnsafeStorage.GetSystemUZone[].NEW[StateArrayRec[size]];
fsOverride ← UnsafeStorage.GetSystemUZone[].NEW[OverrideArrayRec[size]];
allOverride ← UnsafeStorage.GetSystemUZone[].NEW[OverrideArrayRec[size]];
FOR i:
NAT
IN [0..size)
DO
stateArray[i] ← NIL;
fsOverride[i] ← FALSE;
allOverride[i] ← FALSE;
ENDLOOP;
};
Loader.MakeProcedureResident[myFork];
Loader.MakeProcedureResident[myDetatch];
Loader.MakeGlobalFrameResident[myFork];
[] ← ProcessBackdoor.RegisterEventProcs[forkProc: myFork, joinProc: myJoin, endProc: myEnd, detachProc: myDetatch];
register procedures for guest FS procedures
FSBackdoor.RegisterGuestProcs[newFSProcs];
UserCredentialsBackdoor.RegisterGuestProcs[newCredentialsProcs];
UserProfileBackdoor.RegisterGuestProcs[newProfileProcs];
END.
Bob Hagmann February 11, 1985 11:35:31 am PST
added Loader calls to avoid page faults
Bob Hagmann March 12, 1985 9:30:55 am PST
changes
Bob Hagmann May 4, 1985 10:41:28 pm PDT
changes to: myCopy
Bob Hagmann June 5, 1985 9:15:24 am PDT
changes to: getClassProc, sameFileProc, getNameProc, getInfoProc, setPageCountProc, setByteCountAndCreatedTimeProc, readProc, writeProc, closeProc
Bob Hagmann June 11, 1985 2:40:23 pm PDT
changes to: bindUpUserInterface
Bob Hagmann September 24, 1985 10:47:15 am PDT
changes to: mySetDefaultWDir, myGetDefaultWDir, myExpandName, myFileInfo, myEnumerateForInfo, myEnumerateForNames, myOpen, myCreate, myCopy, myDelete, myRename, mySetKeep, testAndSetDoingEnumerate, clearDoingEnumerate, GetState, Get, Boolean, Number, Token, ListOfTokens, Line, GetProfileName, bindUpUserInterface
Bob Hagmann September 24, 1985 4:31:05 pm PDT
changes to: myGetDefaultWDir, DIRECTORY, ComputeServerServicesImpl, MarkGuestProcess, GetGuestProcessData, MarkProcessNotGuest, RemoveMarkProcessNotGuest, mySetDefaultWDir, myExpandName, myFileInfo, myEnumerateForInfo, myEnumerateForNames, myOpen, myCreate, myCopy, myDelete, myRename, mySetKeep, getClassProc, sameFileProc, getNameProc, getInfoProc, setPageCountProc, setByteCountAndCreatedTimeProc, readProc, writeProc, closeProc, IsGuestProcess, GetState, ChangeState, Login, Get, Boolean, Number, Token, ListOfTokens, Line, GetProfileName, CallWhenProfileChanges, ProfileChanged, TryRPCRecovery
Bob Hagmann October 9, 1985 8:57:39 am PDT
changes to: MarkGuestProcess, GetGuestProcessData, MarkProcessNotGuest, RemoveMarkProcessNotGuest, IsGuestProcess, GetState, ChangeState, Login, Get, Boolean, Number, Token, ListOfTokens, Line, GetProfileName, CallWhenProfileChanges, ProfileChanged, TryRPCRecovery
Bob Hagmann October 23, 1985 7:45:56 am PDT
changes to: RemoveMarkProcessNotGuest, MarkProcessUseLocalFS, RemoveMarkProcessUseLocalFS
Bob Hagmann February 7, 1986 9:17:28 am PST
changes to: myOpen, DIRECTORY, ComputeServerServicesImpl, ROPE, STREAM
Bob Hagmann February 10, 1986 2:24:01 pm PST
changes to: ComputeServerServicesImpl, MarkGuestProcess, GetGuestProcessData, MarkProcessNotGuest, RemoveMarkProcessNotGuest, MarkProcessUseLocalFS, RemoveMarkProcessUseLocalFS, mySetDefaultWDir, myGetDefaultWDir, myExpandName, myFileInfo, myEnumerateForInfo, myEnumerateForNames, myOpen, myCreate, myCopy, myDelete, myRename, mySetKeep, getClassProc, sameFileProc, getNameProc, getInfoProc, setPageCountProc, setByteCountAndCreatedTimeProc, readProc, writeProc, closeProc, IsGuestProcess, GetState, ChangeState, Login, Get, Boolean, Number, Token, ListOfTokens, Line, GetProfileName, CallWhenProfileChanges, ProfileChanged, TryRPCRecovery
Bob Hagmann February 11, 1986 8:29:04 am PST
changes to: myOpen, DIRECTORY, ComputeServerServicesImpl
Bob Hagmann February 11, 1986 9:03:46 am PST
changes to: DIRECTORY, ComputeServerServicesImpl
Bob Hagmann April 18, 1986 12:22:28 pm PST
changes to: GetState, Get, Boolean, Number, Token, ListOfTokens, Line, GetProfileName, DIRECTORY, ComputeServerServicesImpl
Bob Hagmann May 14, 1986 7:26:03 am PDT
changes to: myOpen