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: BOOLTRUE,
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: BOOLTRUE, 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: BOOLTRUE;
{
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: BOOLTRUE;
{
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: BOOLFALSE, fullFName: ROPE, cp: FS.ComponentPositions, dirOmitted: BOOLEANFALSE] = TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOLTRUE;
{
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: ROPENARROW [ 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: BOOLTRUE;
{
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: BOOLTRUE;
{
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: BOOLTRUE;
{
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: BOOLEANTRUE, wDir: ROPENIL] 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: BOOLTRUE;
{
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: BOOLTRUE;
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: BOOLTRUE;
gotIt: BOOLFALSE;
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: BOOLFALSE;
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: STREAMNIL;
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: BOOLEANTRUE, pages: INT ← 0, setKeep: BOOLEANFALSE, keep: CARDINAL ← 1, wDir: ROPENIL] 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: BOOLTRUE;
{
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: BOOLTRUE;
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: BOOLTRUE;
{
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: BOOLTRUE;
{
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: BOOLTRUE;
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: BOOLTRUE;
{
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: BOOLTRUE;
{
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: BOOLTRUE;
{
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 [BOOLEANFALSE] = {
myFile1: localOpenFile ← NARROW[clientFile1];
myFile2: localOpenFile ← NARROW[clientFile2];
firstCall: BOOLTRUE;
{
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: BOOLTRUE;
{
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: BOOLTRUE;
{
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: BOOLTRUE;
{
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: BOOLTRUE;
{
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: BOOLTRUE;
{
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: BOOLTRUE;
{
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: BOOLTRUE;
{
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] ;
};
To UserCredentials
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: BOOLTRUE;
{
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: BOOLTRUE;
{
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];
};
};
To UserProfile
Boolean: PROC [key: Rope.ROPE, default: BOOLEANFALSE] RETURNS [value: BOOLEAN] = TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOLTRUE;
{
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: BOOLTRUE;
{
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.ROPENIL] RETURNS [value: Rope.ROPE] = TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOLTRUE;
{
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.ROPENIL] 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: BOOLTRUE;
{
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.ROPENIL] RETURNS [value: Rope.ROPE] = TRUSTED {
psb: PrincOps.PsbIndex = PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]];
serviceItem: ComputeServerInternal.ActiveServicesItem = LOOPHOLE[stateArray[psb]];
interface: ComputeServerCallbacksRpcControl.InterfaceRecord ← serviceItem.callbacksInterface;
firstCall: BOOLTRUE;
{
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: BOOLTRUE;
{
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