-- 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.