-- file VirtSS.Mesa -- edited by Schroeder, January 18, 1981 3:08 PM. -- edited by Brotz, 10-Nov-80 15:32:49. DIRECTORY crD: FROM "CoreDefs", exD: FROM "ExceptionDefs", gsD: FROM "GlobalStorageDefs", InlineDefs, ovD: FROM "OverviewDefs", ProcessDefs, SystemDefs, tfD: FROM "TempFileDefs", vmD: FROM "VirtualMgrDefs"; VirtSS: PROGRAM IMPORTS crD, exD, gsD, ProcessDefs, SystemDefs, tfD, vmD EXPORTS vmD SHARES vmD = PUBLIC BEGIN OPEN vmD; -- Data Structures and Types. tOCPageTable: TOCPageTable; tOCPtr: POINTER TO TOC = @tOC; tOC: TOC _ VirtualObject [file: NIL, memoryHeader: NIL, open: FALSE, vOVar: TOC [pageTableHeader: @tOCPageTable, filePageFF: 0, -- Next avail page in TOC file. indexFF: 1, -- Next avail message index. firstChange: 0, -- No changes yet. mailFile: NIL]]; vMORoot: VirtualMessagePtr _ NIL; tOCBufferPoolSize: CARDINAL = 3; dMBufferPoolSize: CARDINAL = 3; cMBufferPoolSize: CARDINAL = 3; -- This is VirtSS, Start/Stop routines. See also VirtTOC. VirtualizeTOC: PROCEDURE [user: crD.DMSUser, tOCFileName: crD.UFilename, mailFileHandle: crD.UFileHandle, option: VirtualizeTOCOption] RETURNS [firstUnSeen: TOCIndex, err: ovD.ErrorCode] = -- Initializes the TOC virtual structure from the indicated file. Before calling this -- procedure, the client is expected to have called CleanupTOC if necessary. BEGIN mtPtr: MemoryTableEntryPtr_NIL; pages, lpn: PageNumber; byte: CARDINAL; index: TOCIndex; tOCFPPtr: TOCFixedPartPtr; zerothFP: TOCFixedPart _ [FALSE, FALSE, FALSE, FALSE, '~, 0, 0, bugTrapValue, 0, 0]; BEGIN -- for EXITS DoSomeYields: PROCEDURE = {THROUGH [1 .. 3] DO ProcessDefs.Yield[]; ENDLOOP}; IF tOCPtr.open THEN exD.SysBug[]; [err, tOCPtr.file] _ crD.OpenFile[user, tOCFileName, update]; IF err # ovD.ok THEN RETURN; --toc file is not open yet DoSomeYields[]; tOCPtr.open _ TRUE; --now a call to CleanupTOC[dontResetChanges or delete] will work. [err, pages, byte] _ crD.UFileLength[tOCPtr.file]; IF err # ovD.ok THEN RETURN; lpn _ firstUnSeen _ tOCPtr.indexFF _ tOCPtr.firstChange _ 0; tOCPtr.filePageFF _ pages; --now a call to CleanupTOC[resetChanges] will work. tOCPtr.mailFile _ mailFileHandle; IF tOCPtr.memoryHeader = NIL THEN SetBufferPoolSize[tOCPtr, tOCBufferPoolSize]; IF option = new OR pages = 0 OR pages > tOCPageTableSize OR byte # 0 THEN GOTO truncateTOC; FOR lpn IN [0 .. pages) DO DoSomeYields[]; [mtPtr, ] _ GetMtPtr[tOCPtr, lpn, active]; -- can cause SysBug IF mtPtr.address.numberOfEntries = 0 OR mtPtr.address.garbageDetector # tOCType THEN {mtPtr.state _ unused; GOTO truncateTOC}; tOCPtr.pageTableHeader^[lpn] _ [tOCPtr.indexFF]; -- 1st entry on page. tOCPtr.indexFF _ tOCPtr.indexFF + mtPtr.address.numberOfEntries; FOR index IN [tOCPtr.pageTableHeader[lpn] .. tOCPtr.indexFF) WHILE tOCPtr.firstChange = 0 OR firstUnSeen = 0 DO tOCFPPtr _ GetTOCAddressOnPage[index, mtPtr]; IF tOCFPPtr.changed AND tOCPtr.firstChange = 0 THEN tOCPtr.firstChange _ index; IF ~tOCFPPtr.seen AND firstUnSeen = 0 THEN firstUnSeen _ index; ENDLOOP; ENDLOOP; EXITS truncateTOC => BEGIN IF pages # lpn THEN BEGIN err _ crD.UFileTruncate[lpn, 0, tOCPtr.file]; IF err # ovD.ok THEN RETURN; END; tOCPtr.filePageFF _ lpn; IF lpn = 0 THEN err _ ExtendTOC[@zerothFP, "dummy"L]; END; END; -- for EXITS END; -- of VirtualizeTOC. CleanupTOC: PROCEDURE [option: CleanupTOCOption] = BEGIN p: MemoryTableEntryPtr; pageHdrPtr: POINTER TO TOCPageHdr; lastPage: PageNumber; IF tOCPtr.open THEN BEGIN tOCPtr.open _ FALSE; IF option = delete THEN GOTO deleteTOC; IF option = resetChanges AND tOCPtr.firstChange # 0 THEN BEGIN [, p] _ FindTOCAddress[tOCPtr.firstChange]; lastPage _ p.logicalPageNumber; pageHdrPtr _ LOOPHOLE[p.address]; pageHdrPtr.numberOfEntries _ tOCPtr.firstChange - tOCPtr.pageTableHeader[lastPage]; p.state _ dirty; IF pageHdrPtr.numberOfEntries = 0 THEN lastPage _ lastPage - 1; END ELSE lastPage _ tOCPtr.filePageFF - 1; FOR p _ tOCPtr.memoryHeader, p.next UNTIL p = NIL DO IF p.logicalPageNumber <= lastPage AND p.state = dirty THEN IF crD.WritePages[p.address, 512, p.filePageNumber, tOCPtr.file] # ovD.ok THEN GOTO deleteTOC; p.state _ unused; ENDLOOP; IF option = resetChanges AND lastPage + 1 < tOCPtr.filePageFF THEN IF crD.UFileTruncate[lastPage + 1, 0, tOCPtr.file] # ovD.ok THEN GOTO deleteTOC; IF crD.CloseFile[tOCPtr.file] # ovD.ok THEN GOTO deleteTOC; EXITS deleteTOC => BEGIN FOR p _ tOCPtr.memoryHeader, p.next UNTIL p = NIL DO p.state _ unused; ENDLOOP; [] _ crD.DeleteFile[tOCPtr.file]; --ignore disk error on purpose END; END; -- of IF tOCPtr.open. END; -- of CleanupTOC -- SetTOCValidity: PROCEDURE [valid: BOOLEAN] = BEGIN mtP: MemoryTableEntryPtr = GetMtPtr[tOCPtr, 0, active].mtPtr; mtP^.address^.garbageDetector _ tOCType + (IF valid THEN 0 ELSE 1); mtP^.state _ dirty; WritePageToFile[tOCPtr, mtP]; mtP^.state _ clean; END; --ofSetTOCValidity-- GetTOCPtr: PROCEDURE RETURNS [POINTER TO TOC] = {RETURN[tOCPtr]}; -- Used to communicate between the departments of this division. -- Needed when broken into more than one file. AllocateDisplayMessageObject: PROCEDURE RETURNS [dMPtr: DisplayMessagePtr] = BEGIN dMPtr _ SystemDefs.AllocateHeapNode[SIZE[DisplayMessageObject]]; dMPtr^ _ [file: , memoryHeader: NIL, open: FALSE, vOVar: VMO[vMORoot, , , DM[ , ]]]; vMORoot _ dMPtr; -- Splice new one into the list. SetBufferPoolSize[dMPtr, dMBufferPoolSize]; END; -- of AllocateDisplayMessageObject -- FreeVirtualMessageObject: PROCEDURE [vMPtr: VirtualMessagePtr] = -- DM or CM. BEGIN p, back: VirtualMessagePtr; mtPtr, mtPtr1: MemoryTableEntryPtr; -- err: ovD.ErrorCode; -- pages: crD.PageNumber; IF (p _ vMORoot) = vMPtr THEN vMORoot _ vMPtr.next -- Was at head. ELSE BEGIN UNTIL p = NIL DO back_p; p_p^.next; IF p = vMPtr THEN EXIT; REPEAT FINISHED => exD.SysBug[]; ENDLOOP; back.next _ vMPtr.next; --Splice it out. END; WITH msg: vMPtr^ SELECT FROM DM => NULL; CM => BEGIN SystemDefs.FreeHeapNode [msg.charMap]; IF msg.file # NIL THEN tfD.FreeTempFile[msg.file]; END; ENDCASE => exD.SysBug[]; FOR mtPtr _ vMPtr.memoryHeader, mtPtr _ mtPtr1 UNTIL mtPtr = NIL DO -- Free pages and mte's. IF mtPtr.address # NIL THEN gsD.ReturnMemoryPages[1, mtPtr.address]; mtPtr1 _ mtPtr.next; SystemDefs.FreeHeapNode[mtPtr]; ENDLOOP; SystemDefs.FreeHeapNode[vMPtr] END; -- of FreeVirtualMessageObject -- CleanupCMs: PROCEDURE= -- Truncates all backing files. BEGIN vMPtr: VirtualMessagePtr; FOR vMPtr _ vMORoot, vMPtr.next UNTIL vMPtr = NIL DO WITH msg: vMPtr^ SELECT FROM DM => NULL; CM => BEGIN IF msg.file # NIL THEN tfD.FreeTempFile[msg.file]; msg.open _ FALSE; END; ENDCASE => exD.SysBug[]; ENDLOOP; END; -- of CleanupCMs. AllocateComposeMessageObject: PROCEDURE RETURNS [cMPtr: ComposeMessagePtr] = BEGIN cMPtr _ SystemDefs.AllocateHeapNode[SIZE[ComposeMessageObject]]; cMPtr^ _ [file: NIL,memoryHeader: NIL, open: FALSE, vOVar: VMO[vMORoot, , , CM[FALSE, , , SystemDefs.AllocateHeapNode[SIZE[CMOCharMapTable]], 0]]]; vMORoot _ cMPtr; -- Splice new one into the list. SetBufferPoolSize[cMPtr, cMBufferPoolSize]; END; -- of AllocateComposeMessageObject -- SetBufferPoolSize: PROCEDURE[vop: VirtualObjectPtr, size: CARDINAL] = --Sets the number of Mte's in the buffer pool of the designated object to --the specified value. May add or delete Mte's, and works if there are --no Mte's at all. BEGIN delta: INTEGER; c: INTEGER _ 0; mtPtr: MemoryTableEntryPtr; last: MemoryTableEntryPtr_NIL; IF size < 2 THEN exD.SysBug[]; -- Must be at least 2. FOR mtPtr _ vop.memoryHeader, mtPtr.next UNTIL mtPtr = NIL DO last _ mtPtr; c _ c + 1; ENDLOOP; -- c is current size. delta _ size - c; -- Note: only one (or none) of the below THROUGHs will happen.. SELECT delta FROM > 0 => THROUGH [0 .. delta) DO -- To add pages. mtPtr _ SystemDefs.AllocateHeapNode[SIZE[MemoryTableEntry]]; mtPtr.state _ unused; mtPtr.address _ NIL; IF last = NIL THEN vop.memoryHeader _ mtPtr ELSE last.next _ mtPtr; mtPtr.next _ NIL; last _ mtPtr; ENDLOOP; < 0 => BEGIN THROUGH [delta .. 0) DO -- To delete pages. [] _ MakeBufferPoolHeadUnused[vop]; mtPtr _ vop.memoryHeader; --We will delete mtPtr. vop.memoryHeader _ mtPtr.next; -- First splice it out. IF mtPtr.address # NIL THEN gsD.ReturnMemoryPages[1, mtPtr.address]; SystemDefs.FreeHeapNode[mtPtr]; ENDLOOP; WITH vo: vop^ SELECT FROM VMO => VoidCharCache[@vo.get]; ENDCASE; END; ENDCASE; END; -- of SetBufferPoolSize -- SetTOCBufferPoolSize: PROCEDURE [size: CARDINAL] = -- Adjust the size of the TOC buffer pool. BEGIN SetBufferPoolSize[GetTOCPtr[], size]; END; -- of SetTOCBufferPoolSize -- END. -- of VirtSS. (635)\f1