-- DummyFileMapImpl.mesa Last edit: KK October 27, 1982 10:35 am DIRECTORY AlpineInternal, AlpineEnvironment USING[FileID, VolumeID], FileMap USING[nullHandle], DummyFileMapPrivate USING[FileObject, HorribleError, MonitoredRegisterHandle, MonitoredUnregisterHandle], FilePageMgrPrivateFile USING[FPMFileHandle], SafeStorage USING[NewZone], SystemInternal USING[UniversalID]; DummyFileMapImpl: MONITOR IMPORTS AE: AlpineEnvironment, FMP: DummyFileMapPrivate, SafeStorage EXPORTS AlpineInternal, FileMap, DummyFileMapPrivate = BEGIN HorribleError: PUBLIC -- PROGRAMMING -- ERROR = CODE; FileObject: PUBLIC TYPE = FMP.FileObject; Handle: TYPE = REF FileObject; DebugArray: ARRAY [0..MaxDebugArray) OF DebugRec; DebugRec: TYPE = RECORD[file: LONG CARDINAL, what: {add, remove, inited}]; debugIndex: CARDINAL ← 0; MaxDebugArray: CARDINAL = 200; -- Finds or creates a Handle for the supplied volume and file, and increments use count on the handle. Register: PUBLIC ENTRY PROCEDURE[volume: AE.VolumeID, file: AE.FileID] RETURNS[handle: Handle] = BEGIN ENABLE UNWIND => NULL; handle ← GetFile[GetVolume[volume, oldOrNew], file, oldOrNew].handle; FMP.MonitoredRegisterHandle[handle]; RETURN[handle]; END; -- Decrements use count on handle, and deletes object from map if count reaches zero. Unregister: PUBLIC ENTRY PROCEDURE[handle: Handle] = BEGIN ENABLE UNWIND => NULL; FMP.MonitoredUnregisterHandle[handle, RemoveFile]; END; -- Obtains the next in the enumeration of Handles. Handle = nullHandle starts a new -- enumeration, and GetNext returns nextHandle = nullHandle when the enumeration is exhausted. -- The only guaranteed property of the enumeration is that all Handles in existence -- during the entire enumeration will be visited at least once. GetNext: PUBLIC ENTRY PROCEDURE[handle: Handle] RETURNS [nextHandle: Handle] = BEGIN ENABLE UNWIND => NULL; RETURN[GetNextEnum[handle]]; END; -- crock of a data structure, just for debugging. volumes: REF Volume ← NIL; Volume: TYPE = RECORD[next, prev: REF Volume, volID: AE.VolumeID, files: REF File]; File: TYPE = RECORD[next, prev: REF File, handle: Handle]; enumHandles: REF EnumHandle; EnumHandle: TYPE = RECORD[next, prev: REF EnumHandle, file: REF File]; enumNumber: CARDINAL ← 0; GetVolume: INTERNAL PROCEDURE[volID: AE.VolumeID, exists: Exists] RETURNS [volume: REF Volume] = BEGIN FOR volume ← volumes, volume.next UNTIL volume = NIL DO IF volume.volID = volID THEN EXIT; REPEAT FINISHED => BEGIN IF exists = old THEN ERROR FMP.HorribleError; volume ← VolumeZone.NEW[Volume ← [next: volumes, prev: NIL, volID: volID, files: NIL]]; IF volumes # NIL THEN volumes.prev ← volume; volumes ← volume; END; ENDLOOP; END; Exists: TYPE = {oldOrNew, old}; GetFile: INTERNAL PROCEDURE[volume: REF Volume, fileID: AE.FileID, exists: Exists] RETURNS [file: REF File] = BEGIN FOR file ← volume.files, file.next UNTIL file = NIL DO IF file.handle.fileID = fileID THEN EXIT; REPEAT FINISHED => BEGIN IF exists = old THEN ERROR FMP.HorribleError; file ← FileZone.NEW[File ← [next: volume.files, prev: NIL, handle: FileObjectZone.NEW[FileObject ← [fileID: fileID, volID: volume.volID, fPMFileHandle: NIL, logMapHandle: NIL, useCount: 0, enumNum: (enumNumber ← enumNumber + 1)]]]]; IF volume.files # NIL THEN volume.files.prev ← file; volume.files ← file; DebugArray[debugIndex] ← [GetSequenceID[fileID], add]; debugIndex ← (IF debugIndex = MaxDebugArray - 1 THEN 0 ELSE debugIndex + 1); AddEnum[file]; END; ENDLOOP; END; RemoveFile: INTERNAL PROCEDURE[handle: Handle] = BEGIN volume: REF Volume ← GetVolume[handle.volID, old]; file: REF File ← GetFile[volume, handle.fileID, old]; IF LOOPHOLE[handle.fPMFileHandle, FilePageMgrPrivateFile.FPMFileHandle] # NIL AND LOOPHOLE[handle.fPMFileHandle, FilePageMgrPrivateFile.FPMFileHandle].nMappedChunks # 0 THEN ERROR FMP.HorribleError; IF file.next # NIL THEN file.next.prev ← file.prev; IF file.prev # NIL THEN file.prev.next ← file.next ELSE volume.files ← file.next; IF volume.files = NIL THEN BEGIN IF volume.next # NIL THEN volume.next.prev ← volume.prev; IF volume.prev # NIL THEN volume.prev.next ← volume.next ELSE volumes ← volume.next; END; DebugArray[debugIndex] ← [GetSequenceID[handle.fileID], remove]; debugIndex ← (IF debugIndex = MaxDebugArray - 1 THEN 0 ELSE debugIndex + 1); RemoveEnum[file]; END; GetSequenceID: INTERNAL PROCEDURE[fileID: AE.FileID] RETURNS[fileSequenceID: LONG CARDINAL] = BEGIN uid: SystemInternal.UniversalID ← LOOPHOLE[fileID]; RETURN[uid.sequence]; END; AddEnum: INTERNAL PROCEDURE[file: REF File] = BEGIN enumHandle: REF EnumHandle ← EnumZone.NEW[EnumHandle ← [next: enumHandles, prev: enumHandles.prev, file: file]]; enumHandles.prev.next ← enumHandle; enumHandles.prev ← enumHandle; END; RemoveEnum: INTERNAL PROCEDURE[file: REF File] = BEGIN enumHandle: REF EnumHandle ← enumHandles; DO IF enumHandle.file = file THEN EXIT; enumHandle ← enumHandle.next; IF enumHandle = enumHandles THEN ERROR FMP.HorribleError; ENDLOOP; enumHandle.prev.next ← enumHandle.next; enumHandle.next.prev ← enumHandle.prev; END; GetNextEnum: INTERNAL PROCEDURE[handle: Handle] RETURNS [nextHandle: Handle] = BEGIN enumHandle: REF EnumHandle ← enumHandles.next; IF handle # FileMap.nullHandle THEN BEGIN enumNumber: CARDINAL ← handle.enumNum; UNTIL enumHandle = enumHandles DO IF enumHandle.file.handle.enumNum > enumNumber THEN EXIT; enumHandle ← enumHandle.next; ENDLOOP; END; RETURN[IF enumHandle = enumHandles THEN FileMap.nullHandle ELSE enumHandle.file.handle]; END; InitializeFileMap: PUBLIC PROCEDURE[range: CARDINAL] = BEGIN IF range = 0 THEN ERROR; END; -- main line code: VolumeZone: ZONE ← SafeStorage.NewZone[quantized, , ]; FileZone: ZONE ← SafeStorage.NewZone[quantized, , ]; FileObjectZone: ZONE ← SafeStorage.NewZone[quantized, , ]; EnumZone: ZONE ← SafeStorage.NewZone[quantized, , ]; enumHandles ← EnumZone.NEW[EnumHandle ← [next: NIL, prev: NIL, file: NIL]]; enumHandles.prev ← enumHandles; enumHandles.next ← enumHandles; FOR index: CARDINAL IN [0..MaxDebugArray) DO DebugArray[index].what ← inited; ENDLOOP; END. Edit Log Initial: Kolling: 13-Apr-82 12:23:40: an impl module for FileMap.