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 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; 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]; 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 ; }; 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; }; 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 { useDefault _ TRUE; } ELSE { [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]; }; }; 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; }; 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]; }; }; }; 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; }; 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]; }; }; 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 ]]; 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]; FSBackdoor.RegisterGuestProcs[newFSProcs]; UserCredentialsBackdoor.RegisterGuestProcs[newCredentialsProcs]; UserProfileBackdoor.RegisterGuestProcs[newProfileProcs]; END. ¨ComputeServerServicesImpl.mesa Copyright c 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 Declarations some counters (for the fun of it) Registered Procedures for Process Monitoring These are registered in ProcessImpl to notify us when FORKs, JOINs and the like occur. Exported to ComputeServerInternal Registered Procedures for FS If there is a process working directory, the name is a global name, or the working directory is explicitly specified. Do the call locally. Must use the default working directory. Run the call on the client's machine. Enumeration Control FS File Procs for My OpenFiles UserCredentials and UserProfile To UserCredentials To UserProfile RPC Error Control Initialization initialize state array to keep track of guest processes, and register process monitoring procedures register procedures for guest FS procedures 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 Ê.– "cedar" style˜headšœ™Icodešœ Ïmœ1™<—Ibody™ÔM™8code1šÏk ˜ N˜Nšœ ˜ N˜N˜!N˜N˜ N˜Nšžœ˜N˜ N˜N˜N˜N˜ N˜ Nšžœ˜N˜Nšœ žœžœ˜*N˜Nšœžœ:˜ON˜ Nšœ˜Nšžœ˜Nšœ ˜ Nšœžœ˜%Nšœ˜Nšœ˜Nšœ ˜ Nšœ˜—šœžœž˜(Nšžœnžœ8žœ>žœJ˜¾Nšžœ˜Nšœž˜N˜—™ Lšžœžœžœ˜Lšžœžœžœžœ˜L˜Lšœžœ'˜@Jšœžœ"˜6L˜Jšœžœžœžœ žœžœžœžœ˜DJš œžœžœžœ žœžœžœ˜?Jšœ žœžœžœ˜+Jšœ žœžœžœ˜-Jšœ žœžœžœ˜.˜J™!—Jšœžœ˜Jšœžœ˜Jšœ žœ˜Jšœžœ˜L˜L˜Lšœžœ,˜DLšœžœžœ˜.šœžœžœ˜#Lšœ žœžœ˜Lšœ.˜.Lšœ žœ žœ˜)Lšœ"žœ˜&Lšœ>ž˜AL˜—L˜Lšœ&žœ˜:—™-J™VJ™šÏbœžœ˜'J˜Jšœ-˜-J˜J˜—šŸœžœ˜'J˜Jšœžœ˜J˜J˜—šŸ œžœ˜%J˜J˜J˜—šŸœžœ˜!J˜Jšœžœ˜J˜—J˜—šœ!™!šÐbnœžœžœžœ žœžœžœžœžœžœ žœžœžœ˜‡Jšœžœ ˜+šžœ$žœžœ˜6Jšœ˜Jšœžœ˜Jšœžœ˜Jšœ˜—Jšœžœžœ˜J˜—J˜š œžœžœžœ žœžœžœžœžœ˜bJšœžœ ˜+Jšžœ˜J˜—J˜š  œžœžœžœ žœžœ˜EJšœžœ ˜+Jšœžœ˜Jšœ˜—J˜š  œžœžœžœ žœžœ˜KJšœžœ ˜+Jšœžœ˜Jšœ˜J˜—š  œžœžœžœ žœžœ˜GJšœžœ ˜+Jšœžœ˜Jšœ˜—J˜š  œžœžœžœ žœžœ˜MJšœžœ ˜+Jšœžœ˜Jšœ˜—J˜J˜—™š Ÿœžœžœ žœžœ˜?LšœQ˜QLšžœžœžœžœ˜KLšœ˜—L˜šŸœžœ žœžœ˜3LšœQ˜QLšœ8žœ˜RLšœ]˜]Lšœ žœžœ˜˜šžœ˜Lšœ žœžœ˜6šžœ˜LšœS˜SLšœ žœ˜Lšžœ žœžœ.žœ˜MLšžœžœF˜NL˜—Lšœ˜—Lšœ˜L˜—L˜L˜—š Ÿœžœžœžœžœ˜6LšœQ˜QLšœ8žœ˜RLšœ]˜]Lšœ žœžœ˜˜šžœ˜Lšœ žœžœ˜6šžœ˜LšœS˜SLšœ žœ˜Lšžœ žœžœ.žœ˜MLšžœžœF˜NL˜—Lšœ˜—Lšžœ˜$L˜—L˜L˜—šŸ œžœžœžœžœžœžœ žœžœ!žœžœžœ˜¢LšœQ˜QLšœ8žœ˜RLšœ]˜]Lšœ žœžœ˜šœ˜L˜šžœ˜Lšœ žœžœ˜6šžœ˜LšœS˜SLšœ žœ˜Lšžœ žœžœ.žœ˜MLšžœžœF˜NL˜—LšžœžœžœF˜`Lšœ˜—Lšœ žœžœ-˜Gšžœžœžœžœžœžœžœ˜‹Lšœ‹™‹Lšœ žœ˜Lšœ˜—šœžœ˜L™NLšœ?˜?Lšœ˜—L˜—L˜L˜—L˜šŸ œžœžœžœžœžœžœžœžœ žœžœžœ˜ÇLšœQ˜QLšœ8žœ˜RLšœ]˜]Lšœ žœžœ˜šœ˜šžœ˜Lšœ žœžœ˜6šžœ˜Lšœh˜hLšœ žœ˜Lšžœ žœžœ.žœ˜MLšžœžœF˜NL˜—LšžœžœžœF˜`Lšœ˜—Lšžœžœžœžœ-˜MLšœp˜pL˜—L˜—L˜š Ÿœžœ žœžœžœžœ˜SLšœQ˜QLšœ8žœ˜RLšœ]˜]Lšœ žœžœ˜šœ˜šžœ˜Lšœ žœžœ˜6šžœ˜Lšœh˜hLšœ žœ˜Lšžœ žœžœ.žœ˜MLšžœžœF˜NL˜—L˜—Lšœžœ˜Lšœžœ˜Lšœžœ˜ Lšœžœ˜Lšœ žœ˜Lšžœ(žœžœžœp˜§Lšžœžœžœžœ-˜MLšœŠ˜Ššžœ ž˜Lšœ=˜=Lšžœ žœz˜ŠLšœžœ;˜@Lšžœ˜—Lšœ!˜!L˜—L˜L˜—L˜š Ÿœžœ žœžœžœžœ˜TLšœQ˜QLšœ8žœ˜RLšœ]˜]Lšœ žœžœ˜šœ˜šžœ˜Lšœ žœžœ˜6šžœ˜Lšœh˜hLšœ žœ˜Lšžœ žœžœ.žœ˜MLšžœžœF˜NL˜—Lšœ˜—Lšœ žœ˜Lšœ žœ˜Lšžœ(žœžœžœp˜§Lšžœžœžœžœ-˜MLšœi˜išžœ ž˜Lšœ˜Lšžœ žœY˜iLšœžœ;˜@Lšžœ˜—Lšœ!˜!L˜—L˜L˜—L˜šŸœžœžœžœ˜SJšœ žœ˜%Lšœ˜˜˜LšœT˜TLšœ6˜6J˜J˜—šŸœžœžœžœ,žœ#žœžœžœžœžœžœ žœ˜½LšœQ˜QLšœ8žœ˜RLšœ7žœ˜MLšœ]˜]Lšœ žœžœ˜šœ˜šžœ˜Lšœ žœžœ˜6šžœ˜Lšœh˜hLšœ žœ˜Lšžœ žœžœ.žœ˜MLšžœžœF˜NL˜—Lšœ˜—Lšœžœ˜5Lšœžœ˜Lšœžœ˜Lšœžœ˜Lšœ žœ˜Lšœ$˜$Lšœ"˜"Lšžœžœžœžœ-˜MLšœ>žœ$˜dšžœpžœ˜xšžœ(žœ˜0Lšœ žœ˜Lšœ žœ ˜Lšœ žœžœ˜LšœJ˜JLšœžœ˜šœžœ8žœ ˜NLšœžœ˜Lšœ˜Lšžœ˜ —Lšœ˜Lšœžœ˜šžœ žœ˜Lšžœ˜ L˜—Lšœžœžœžœ˜!L˜—šœžœ˜Lšžœžœò˜úL˜—L˜—Lšœ¬žœ˜³šžœ#žœÏc&˜SLšœžœžœ˜Jšœžœžœ˜šœ%žœ˜.Jšœžœ˜ J˜—Jšœ@žœ˜`šžœžœ˜Lšœžœ˜Lšœžœ˜Lš œžœžœžœžœ˜dLšœžœ˜L˜—šžœžœ˜šžœžœ¡=˜eLšœ žœ˜Lšœžœ˜Lšœžœžœ˜Lšœ˜Lšœ˜˜šžœ˜Lšœ žœžœ˜6šžœžœ˜Lšžœ ˜L˜—šžœžœ˜"šžœ žœžœ˜Lšœ$žœ˜/L˜—šžœžœ˜Lšœ2˜2Lšœžœ˜L˜—Lšœ˜Lšžœ ˜L˜—Lšœ˜—Lšœ žœ ˜Lšœžœ˜ Lšœžœ˜Lšœžœžœ˜Lšœ žœ˜Lšœ%˜%Lšœ˜Lšœ˜Lšœ žœ˜ Lšœžœ˜Lšœžœžœ˜*Icode2šœ2žœ˜7OšœJ˜JLšœˆžœ˜ŽOšœ,˜,O•StartOfExpansion¨[openFile: FS.OpenFile, accessRights: FS.Lock _ read, initialPosition: FS.InitialPosition _ start, streamOptions: FS.StreamOptions _ (5)[TRUE, TRUE, TRUE, TRUE, TRUE], streamBufferParms: FS.StreamBufferParms _ [vmPagesPerBuffer: 8, nBuffers: 2], extendFileProc: FS.ExtendFileProc]š œžœ:žœžœžœžœžœ+˜›Ošœ‘žœžœ˜«Ošœ8žœ˜QOšœ˜Ošœ8˜8Ošœ,˜,J˜4Jšœžœ˜Jšœ'˜'šžœž˜Ošœ žœ˜Ošœ˜Ošœ=˜=Ošžœ žœžœžœ ˜DOšœ#˜#Ošœ žœ˜%OšœS˜SOšœ˜Ošžœ˜—Ošœ2˜2OšœH˜HOšœ]˜]Lšœlžœžœ˜†Lšœ˜Lšœžœ˜Lšœžœ˜Lš œžœžœžœžœ˜dLšœžœ˜šžœžœ˜Lšœžœ˜Lšžœ!˜'Lšœ˜—šž˜˜šžœ žœžœ˜Lšœ$žœ˜/L˜—Lšžœžœ3˜JLšœ˜L˜—L˜——L˜—šœžœ¡>˜GLšœžœ˜Lš œžœžœžœžœ˜aLšœ˜Lšžœžœžœ˜7L˜—L˜Lšžœžœ­žœ˜ÊL˜—Lšœžœžœ˜$L˜—Lšœ&˜&L˜—˜L˜——šŸœžœžœ žœžœ žœžœžœžœ žœžœžœžœ žœ˜­LšœQ˜QLšœ8žœ˜RLšœ7žœ˜MLšœ]˜]Lšœ žœžœ˜šœ˜šžœ˜Lšœ žœžœ˜6šžœ˜Lšœh˜hLšœ žœ˜Lšžœ žœžœ.žœ˜MLšžœžœF˜NL˜—Lšœ˜—Lšœžœ˜5Lšœžœ˜Lšœžœ˜Lšœ žœ˜Lšœ$˜$Lšœ"˜"Lšžœžœžœžœ-˜MLšœ>žœ$˜dšžœpžœ˜xšžœ(žœ˜0Lšœ žœ˜Lšœ žœ ˜Lšœ žœžœ˜LšœJ˜JLšœžœ˜šœžœ4žœ ˜JLšœžœ˜Lšœ˜Lšžœ˜ —Lšœ˜Lšœžœ˜šžœ žœ˜Lšžœ˜ L˜—Lšœžœžœžœ˜!L˜—šœžœ˜Lšžœžœò˜úL˜—L˜—L˜Lšœx˜xLšœ&˜&L˜—L˜—J˜šŸœžœ žœ žœžœžœžœ žœ žœžœ žœžœ˜´OšœQ˜QOšœ8žœ˜RLšœ]˜]Ošœ žœžœ˜šœ˜šžœ˜Lšœ žœžœ˜6šžœ˜Lšœh˜hLšœ žœ˜Lšžœ žœžœ.žœ˜MLšžœžœF˜NL˜—Lšœ˜—Lšžœžœžœžœ-˜MLšœŒ˜ŒL˜—L˜L˜—š Ÿœžœžœžœžœžœ˜UOšœQ˜QOšœ8žœ˜RLšœ]˜]Ošœ žœžœ˜šœ˜šžœ˜Lšœ žœžœ˜6šžœ˜Lšœh˜hLšœ žœ˜Lšžœ žœžœ.žœ˜MLšžœžœF˜NL˜—Lšœ˜—Lšœžœ˜Lšœžœ˜Lšœ žœ˜Lšžœžœžœžœ-˜MLšœ>žœ$˜dšžœpžœ˜xšžœ(žœ˜0Lšœ žœ˜Lšœ žœ ˜Lšœ žœžœ˜LšœJ˜JLšœžœ˜šžœ'žœ ˜6Lšœžœ˜Lšœ˜Lšžœ˜ —Lšœ˜Lšœžœ˜šžœ žœ˜Lšžœ˜ L˜—Lšœžœžœžœ˜!L˜—šœžœ˜Lšžœžœò˜úL˜—L˜—L˜LšœV˜VL˜—L˜—šŸœžœžœ žœžœžœ žœžœ˜…OšœQ˜QOšœ8žœ˜RLšœ]˜]Ošœ žœžœ˜šœ˜šžœ˜Lšœ žœžœ˜6šžœ˜Lšœh˜hLšœ žœ˜Lšžœ žœžœ.žœ˜MLšžœžœF˜NL˜—Lšœ˜—Lšžœžœžœžœ-˜MLšœi˜iO˜—O˜—š Ÿ œžœ žœžœ žœžœ˜NOšœQ˜QOšœ8žœ˜RLšœ]˜]Ošœ žœžœ˜šœ˜šžœ˜Lšœ žœžœ˜6šžœ˜Lšœh˜hLšœ žœ˜Lšžœ žœžœ.žœ˜MLšžœžœF˜NL˜—Lšœ˜—Lšžœžœžœžœ-˜MLšœJ˜JL˜—L˜O˜——L˜™š Ÿœžœžœ8žœžœžœ˜{Lšžœžœžœžœ˜1Lšœžœ˜"Lšžœžœ˜L˜—L˜šŸœžœžœ;žœ˜cLšœžœ˜#L˜——™š Ÿ œžœžœžœžœ ˜>Jšœžœ ˜+Jšœ žœžœ˜šœ˜šžœ˜Lšœ žœžœ˜6šžœ˜Lšœ<˜˜@L˜—J˜—J˜—J˜šŸœžœžœžœžœžœžœ˜PJšœžœ ˜+Jšœ žœžœ˜šœ˜šžœ˜Lšœ žœžœ˜6šžœ˜Lšœ<˜