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