-- ReadAheadTestFilePageMgrImpl.mesa Last edit: Kolling December 13, 1983 1:33 pm DIRECTORY AlpineEnvironment USING[FileID, PageCount, PageNumber, PageRun, VolumeID, wordsPerPage], AlpineInternal USING[FileHandle], BasicTime USING[GetClockPulses, MicrosecondsToPulses, Pulses], File USING[FP, NullVolumeRep], FileMap USING[Handle, Initialize, Register], FilePageMgr USING[FileExists, ForceOutEverything, GetSize, InitializeFilePageMgr, ForceOutFile, ReadAheadPages, ReadLeaderPages, ReadPages, ReleaseState, ReleaseVMPageSet, RestoreCacheToCleanState, UsePages, VMPageSet], FS USING[StreamOpen], IO USING[card, Close, GetCard, GetInt, int, PutF, PutRope, rope, STREAM], MyPerfStats USING[CreateTimer, DestroyTimer, Initialize, InitializeTimer, Print, Start, Stop, Timer], Process USING[priorityBackground, priorityNormal, SetPriority, Yield], RandomCard USING[Choose, Init], Rope USING[ROPE], SafeStorage USING[IsCollectorActive, WaitForCollectorDone], SystemVersion USING[machineType]; ReadAheadTestFilePageMgrImpl: PROGRAM IMPORTS BasicTime, FileMap, FPM: FilePageMgr, FS, IO, MyPerfStats, Process, RandomCard, SafeStorage, SystemVersion SHARES File = BEGIN OPEN AI: AlpineInternal, AE: AlpineEnvironment; GetParams: PROCEDURE = BEGIN paramStreamHandle: IO.STREAM _ FS.StreamOpen["AnomaliesReadAhead.Params", $read]; IF (NFiles _ paramStreamHandle.GetCard[]) = 0 THEN ERROR; IF NFiles > 999 THEN ERROR; IF (NNormalChunksInCache _ paramStreamHandle.GetCard[]) = 0 THEN ERROR; IF (NLogChunksInCache _ paramStreamHandle.GetCard[]) = 0 THEN ERROR; IF (NLeaderChunksInCache _ paramStreamHandle.GetCard[]) = 0 THEN ERROR; paramStreamHandle.Close[]; resultsStreamHandle.PutF["\nNFiles: %g\n\nNNormalChunksInCache: %g NLogChunksInCache: %g NLeaderChunksInCache: %g\n\n", IO.card[NFiles], IO.card[NNormalChunksInCache], IO.card[NLogChunksInCache], IO.card[NLeaderChunksInCache]]; END; SetUpFileData: PROCEDURE[] = BEGIN myFilesIDsStreamHandle: IO.STREAM _ FS.StreamOpen["ContiguousFilesFiles.IDs", $read]; IF myFilesIDsStreamHandle.GetCard[] < NFiles THEN ERROR; files _ NEW[Files[NFiles]]; volumeID _ GetVolumeID[myFilesIDsStreamHandle]; FOR index: CARDINAL IN [0..NFiles) DO fileHandle: FileMap.Handle; files[index] _ [fileID: GetFileID[myFilesIDsStreamHandle], inUse: FALSE, exists: TRUE, size: 0]; fileHandle _ FileMap.Register[volumeID, files[index].fileID]; files[index].size _ FPM.GetSize[fileHandle]; fileHandle _ NIL; ENDLOOP; myFilesIDsStreamHandle.Close[]; END; GetFileID: PROCEDURE[stream: IO.STREAM] RETURNS[AE.FileID] = BEGIN fileID: File.FP; id: INT _ stream.GetInt[]; da: INT _ stream.GetInt[]; fileID _ [id: LOOPHOLE[id], da: LOOPHOLE[da]]; RETURN[LOOPHOLE[fileID, AE.FileID]]; END; GetVolumeID: PROCEDURE[stream: IO.STREAM] RETURNS[AE.VolumeID] = BEGIN volumeID: File.NullVolumeRep; a: CARDINAL _ stream.GetCard[]; b: CARDINAL _ stream.GetCard[]; c: CARDINAL _ stream.GetCard[]; d: CARDINAL _ stream.GetCard[]; e: CARDINAL _ stream.GetCard[]; volumeID _ [a: a, b: b, c: c, d: d, e: e]; RETURN[LOOPHOLE[volumeID, AE.VolumeID]]; END; CleanCache: PROCEDURE = BEGIN FPM.ForceOutEverything[]; FPM.RestoreCacheToCleanState[]; resultsStreamHandle.PutRope["Cache cleaned. "]; END; Shell: PROCEDURE[proc: PROCEDURE[fileHandle: FileMap.Handle, fileIndex: CARDINAL, timer: MyPerfStats.Timer, ioMode: IOMode, releaseState: FPM.ReleaseState, keep: BOOLEAN, includeLeader: BOOLEAN, fileInterval: FileInterval], fileIndex: CARDINAL, ioMode: IOMode _ read, releaseState: FPM.ReleaseState _ clean, keep: BOOLEAN _ FALSE, includeLeader: BOOLEAN _ FALSE, fileInterval: FileInterval _ [someRandom[]]] = BEGIN fileID: AE.FileID _ files[fileIndex].fileID; fileHandle: FileMap.Handle _ FileMap.Register[volumeID, fileID]; timer: MyPerfStats.Timer _ MyPerfStats.CreateTimer[""]; proc[fileHandle, fileIndex, timer, ioMode, releaseState, keep, includeLeader, fileInterval]; MyPerfStats.Print[ , resultsStreamHandle, FALSE]; MyPerfStats.DestroyTimer[timer]; fileHandle _ NIL; END; -- varies AllSomeOrSomeRandom: TYPE = {allFixed, allRandom, someFixed, someRandom}; FileInterval: TYPE = RECORD[SELECT allOrSomeRandom: AllSomeOrSomeRandom FROM allFixed => [nPagesEachTime: CARDINAL], allRandom => NULL, someFixed => [firstPage, lastPage, nPagesEachTime: CARDINAL], someRandom => NULL, ENDCASE]; SequentialIO: PROCEDURE[fileHandle: FileMap.Handle, fileIndex: CARDINAL, timer: MyPerfStats.Timer, ioMode: IOMode, releaseState: FPM.ReleaseState, keep: BOOLEAN, includeLeader: BOOLEAN, fileInterval: FileInterval] = BEGIN firstPage, lastPage, nPagesEachTime: CARDINAL; active: BOOLEAN; prevCollectorIncarnation, endingPrevCollectorIncarnation: CARDINAL; attempts: CARDINAL _ 5; DO [active, prevCollectorIncarnation] _ SafeStorage.IsCollectorActive[]; IF active THEN [prevCollectorIncarnation, , , ] _ SafeStorage.WaitForCollectorDone[]; MyPerfStats.Start[timer]; IF includeLeader THEN BEGIN vMPageSet: FPM.VMPageSet _ FPM.ReadLeaderPages[fileHandle]; (IF ioMode = write THEN WriteLeaderPage ELSE ReadLeaderPage)[vMPageSet.pages]; FPM.ReleaseVMPageSet[vMPageSet, releaseState, keep]; END; [firstPage, lastPage, nPagesEachTime] _ SubrReadOrWriteSequentialInterval[fileHandle, fileIndex, ioMode, releaseState, keep, fileInterval]; MyPerfStats.Stop[timer]; IF ioMode = write THEN FPM.ForceOutFile[fileHandle]; [active, endingPrevCollectorIncarnation] _ SafeStorage.IsCollectorActive[]; IF active OR endingPrevCollectorIncarnation # prevCollectorIncarnation THEN BEGIN resultsStreamHandle.PutRope[" SequentialIO interrupted by garbage collection"]; IF (attempts _ attempts - 1) > 0 THEN BEGIN resultsStreamHandle.PutRope[" retrying"]; CleanCache[]; MyPerfStats.InitializeTimer[timer]; [] _ SafeStorage.WaitForCollectorDone[]; LOOP; END ELSE resultsStreamHandle.PutF[" giving up"]; EXIT; END; EXIT; ENDLOOP; IF ioMode IN IOReadMode THEN SubrCheckFile[fileHandle, fileIndex]; resultsStreamHandle.PutF["SeqIO file %g\n size: %g ", IO.card[fileIndex], IO.int[files[fileIndex].size]]; resultsStreamHandle.PutF["pgRange: [%g,%g] nPagesEachTime: %g", IO.card[firstPage], IO.card[lastPage], IO.card[nPagesEachTime]]; IF includeLeader THEN resultsStreamHandle.PutRope[" including LeaderPage"]; resultsStreamHandle.PutF[" %g", IO.rope[(SELECT ioMode FROM read => "read", readWithReadAhead => "read+ReadAhead", write => "write", ENDCASE => "ERROR")]]; resultsStreamHandle.PutF[" %g", IO.rope[(SELECT releaseState FROM writeIndividualWait => "writeIndividualWait", writeBatchedWait => "writeBatchedWait", writeIndividualNoWait => "writeIndividualNoWait", writeBatchedNoWait => "writeBatchedNoWait", clean => "clean", ENDCASE => "ERROR")]]; resultsStreamHandle.PutF[" %g ", IO.rope[(IF keep THEN "keep" ELSE "NOT keep")]]; END; SubrCheckFile: PROCEDURE[fileHandle: FileMap.Handle, fileIndex: CARDINAL] = BEGIN IF FPM.GetSize[fileHandle] # files[fileIndex].size THEN ERROR; IF NOT FPM.FileExists[fileHandle] THEN ERROR; END; ReadLeaderPage: PROCEDURE[pages: LONG POINTER] = BEGIN wordCount: CARDINAL _ RandomCard.Choose[min: 0, max: AE.wordsPerPage - 1]; IF LOOPHOLE[(pages + wordCount)^, CARDINAL] # wordCount THEN ERROR; END; WriteLeaderPage: PROCEDURE[pages: LONG POINTER] = BEGIN FOR wordCount: CARDINAL IN [0..AE.wordsPerPage) DO (pages + wordCount)^ _ wordCount; ENDLOOP; END; ReadDataPage: PROCEDURE[pages: LONG POINTER, pageNumber: CARDINAL] = BEGIN IF LOOPHOLE[(pages + RandomCard.Choose[min: 0, max: AE.wordsPerPage - 1])^, CARDINAL] # pageNumber THEN ERROR; END; WriteDataPage: PROCEDURE[pages: LONG POINTER, pageNumber: CARDINAL] = BEGIN FOR wordCount: CARDINAL IN [0..AE.wordsPerPage) DO (pages + wordCount)^ _ pageNumber; ENDLOOP; END; IOMode: TYPE = {read, readWithReadAhead, write}; IOReadMode: TYPE = IOMode[read..readWithReadAhead]; SubrReadOrWriteSequentialInterval: PROCEDURE[fileHandle: FileMap.Handle, fileIndex: CARDINAL, ioMode: IOMode, release: FPM.ReleaseState, keep: BOOLEAN, fileInterval: FileInterval] RETURNS [firstPage, lastPage, nPagesEachTime: CARDINAL] = BEGIN RandomFirstPage: PROCEDURE RETURNS[CARDINAL] = INLINE BEGIN RETURN[RandomCard.Choose[min: 0, max: files[fileIndex].size - 1]]; END; RandomLastPage: PROCEDURE RETURNS[CARDINAL] = INLINE BEGIN RETURN[RandomCard.Choose[min: firstPage, max: files[fileIndex].size - 1]]; END; RandomNPagesEachTime: PROCEDURE RETURNS[CARDINAL] = INLINE BEGIN RETURN[MIN[RandomCard.Choose[min: 1, max: 25], totalPages]]; END; totalPages: CARDINAL; times: CARDINAL; startPage, nPages: CARDINAL; IF files[fileIndex].size = 0 THEN RETURN[0, 0, 0]; WITH fileInt: fileInterval SELECT FROM allFixed => BEGIN firstPage _ 0; lastPage _ files[fileIndex].size - 1; END; allRandom => BEGIN firstPage _ 0; lastPage _ files[fileIndex].size - 1; END; someFixed => BEGIN firstPage _ fileInt.firstPage; lastPage _ fileInt.lastPage; END; someRandom => BEGIN firstPage _ RandomFirstPage[]; lastPage _ RandomLastPage[]; END; ENDCASE => ERROR; totalPages _ lastPage - firstPage + 1; nPagesEachTime _ (WITH fileInt: fileInterval SELECT FROM allFixed => fileInt.nPagesEachTime, allRandom => RandomNPagesEachTime[], someFixed => fileInt.nPagesEachTime, someRandom => RandomNPagesEachTime[], ENDCASE => ERROR); times _ (totalPages + (nPagesEachTime - 1))/nPagesEachTime; startPage _ firstPage; nPages _ nPagesEachTime; FOR index: CARDINAL IN [0..times) DO IF index = times - 1 THEN nPages _ lastPage - startPage + 1; HandleNPages[fileHandle, fileIndex, ioMode, release, keep, startPage, nPages]; --DelayForNPages[nPages]; startPage _ startPage + nPages; ENDLOOP; END; HandleNPages: PROCEDURE[fileHandle: FileMap.Handle, fileIndex: CARDINAL, ioMode: IOMode, release: FPM.ReleaseState, keep: BOOLEAN, firstPage, nPages: CARDINAL] = BEGIN pageRun: AE.PageRun _ [firstPage: firstPage, count: nPages]; vMPageSet: FPM.VMPageSet; pages: LONG POINTER; pageNumber: CARDINAL _ firstPage; DO vMPageSet _ (IF ioMode IN IOReadMode THEN FPM.ReadPages ELSE FPM.UsePages)[fileHandle, pageRun]; pages _ vMPageSet.pages; IF vMPageSet.pageRun.count > pageRun.count THEN ERROR; FOR index: CARDINAL IN [0..vMPageSet.pageRun.count) DO (IF ioMode IN IOReadMode THEN ReadDataPage ELSE WriteDataPage)[pages, pageNumber]; pageNumber _ pageNumber + 1; pages _ pages + AE.wordsPerPage; ENDLOOP; FPM.ReleaseVMPageSet[vMPageSet, release, keep]; pageRun.firstPage _ pageRun.firstPage + vMPageSet.pageRun.count; pageRun.count _ pageRun.count - vMPageSet.pageRun.count; IF pageRun.count = 0 THEN EXIT; ENDLOOP; IF ((ioMode = readWithReadAhead) AND (pageRun.firstPage < files[fileIndex].size)) THEN BEGIN pageRun.count _ MIN[nPages + nPages, files[fileIndex].size - (firstPage + nPages)]; FPM.ReadAheadPages[fileHandle, pageRun]; END; END; --SetDelayConst: PROCEDURE[const: LONG CARDINAL] = --BEGIN --resultsStreamHandle.PutF["\n\nDelay set to %g ms per page, each transfer.\n\n", IO.card[const]]; --delayConst _ const*LONG[1000]; --END; --delayConst: LONG CARDINAL _ 4000; --DelayForNPages: PROCEDURE[nPages: CARDINAL] = --BEGIN --newPulseLimit: BasicTime.Pulses; --newPulseLimit _ BasicTime.GetClockPulses[] + --BasicTime.MicrosecondsToPulses[delayConst*LONG[nPages]]; --Process.SetPriority[Process.priorityBackground]; --DO --Process.Yield[]; --IF BasicTime.GetClockPulses[] >= newPulseLimit THEN EXIT; --ENDLOOP; --Process.SetPriority[Process.priorityNormal]; --END; MaxFiles: CARDINAL = 6; Main: PROCEDURE = BEGIN -- set up to call from CoPilot for debugging. foo: CARDINAL _ 0; fileIndex: CARDINAL _ 4; expectedSize: CARDINAL _ 499; BEGIN ENABLE ANY => foo _ foo + 1; -- protect us from the tempcedarexec. MyPerfStats.Initialize[]; resultsStreamHandle _ FS.StreamOpen["AnomaliesReadAhead.Results", $append]; resultsStreamHandle.PutF["\nMachine type: %g\n\n", IO.rope[SELECT SystemVersion.machineType FROM dolphin => "Dolphin", dorado => "Dorado", dandelion => "Dandelion", dicentra => "Dicentra", ENDCASE => "unknown"]]; [] _ RandomCard.Init[0]; GetParams[]; FileMap.Initialize[numHashSlotsDesired: 43, fQLength: 60]; FPM.InitializeFilePageMgr[nNormalChunksInCache: NNormalChunksInCache, nLogChunksInCache: NLogChunksInCache, nLeaderChunksInCache: NLeaderChunksInCache]; SetUpFileData[]; --check expected file: IF ((NFiles < 5) OR (files[fileIndex].size # expectedSize)) THEN ERROR; THROUGH [0..10) DO Shell[SequentialIO, fileIndex, write, writeBatchedNoWait, --keep--FALSE, --leader--TRUE, [allFixed[files[fileIndex].size]]]; resultsStreamHandle.PutRope[" "]; CleanCache[]; ENDLOOP; THROUGH [0..0) DO Shell[SequentialIO, fileIndex, read, clean, --keep--FALSE, --leader--FALSE, [allFixed[5]]]; CleanCache[]; Shell[SequentialIO, fileIndex, readWithReadAhead, clean, --keep--FALSE, --leader--FALSE, [allFixed[5]]]; CleanCache[]; ENDLOOP; THROUGH [0..0) DO Shell[SequentialIO, fileIndex, read, clean, --keep--FALSE, --leader--FALSE, [allFixed[4]]]; CleanCache[]; Shell[SequentialIO, fileIndex, readWithReadAhead, clean, --keep--FALSE, --leader--FALSE, [allFixed[4]]]; CleanCache[]; ENDLOOP; THROUGH [0..0) DO Shell[SequentialIO, fileIndex, read, clean, --keep--FALSE, --leader--FALSE, [allFixed[20]]]; CleanCache[]; Shell[SequentialIO, fileIndex, readWithReadAhead, clean, --keep--FALSE, --leader--FALSE, [allFixed[20]]]; CleanCache[]; ENDLOOP; resultsStreamHandle.Close[]; END; END; -- main line code: resultsStreamHandle: IO.STREAM; NFiles: CARDINAL; files: REF Files; Files: TYPE = RECORD[SEQUENCE nFiles: [0..LAST[CARDINAL]] OF FileModel]; FileModel: TYPE = RECORD[fileID: AE.FileID, inUse: BOOLEAN, exists: BOOLEAN, size: CARDINAL]; NNormalChunksInCache: CARDINAL; NLogChunksInCache: CARDINAL; NLeaderChunksInCache: CARDINAL; volumeID: AE.VolumeID; END. Edit Log Initial: Kolling: 19-Apr-82 12:22:00: test for FilePageManager. Ê™˜Jš³œÏcSœÏk œ"žœ_žœ'žœCžœ+žœ:žœòžœ žœžœ žœ9žœžœxžœSžœ#žœžœžœGžœÐblœžœžœžœžœžœFžœ žœžœžœžœÏn œž œžœžœžœžœ4žœ,žœžœžœžœžœžœ:žœžœžœ7žœžœžœ:žœžœ¡žœžœžœ žœžœ  œž œžœžœžœžœ3žœ+žœžœ žœGžœžœžœžœežœžœjžœ)žœžœ(žœ  œž œ žœžœžœžœžœžœžœ%žœ žœ žœžœ žœžœ  œž œ žœžœžœžœžœ(žœžœžœžœžœFžœžœ žœžœ  œž œžœžœžœTžœ  œž œž œ(žœ;žœžœžœ*žœ(žœžœžœžœžœ5žœ žœµžœ7žœžœ œžœ@žœžœžœ&žœ!žœžœ8žœžœžœ  œž œ(žœ<žœžœžœ#žœ)žœ žœ?žœžœ žœMžœžœnžœžœžœ žœ žœ*žœžœžœ<žœ9žœ¼žœžœžœmžœžœAžœžœfž œ)ž œžœÚžœ žœ ž œ:žœžœžœžœžœžœ žœgžœžœgžœžœžœžœžœ[žœžœžœPžœ9žœžœžœßžœ5žœžœžœžœžœ  œž œ(žœžœžœžœ-žœžœžœžœžœžœžœžœ œž œžœžœžœžœ"žœžœžœžœžœžœžœ  œž œžœžœžœžœ žœžœžœžœ#žœžœ   œž œžœžœžœžœžœžœ)žœžœžœžœžœ  œž œžœžœžœžœžœ žœžœžœžœ$žœžœžœ1žœ% !œž œ)žœžœžœžœ(žœžœ œž œžœžœžœžœžœCžœ œž œžœžœžœžœžœTžœ œž œžœžœžœžœžœžœ9žœžœ žœžœžœžœžœžœžœžœžœ6žœžœ6žœžœFžœžœFžœžœžœAžœžœžœ°žœžœ{žœžœžœžœžœžœÏžœžœ   œž œ(žœžœžœžœžœ žœ@žœžœžœžœžœžœžœ žœžœ žœžœ@žœ)žœžœžœžœžœ$žœžœžœ žœžœfžœžœžœ°žœžœžœžœžœžœ:žœžœžœZžœ-žœžœ œž œžœžœžœVžœ'žœ žœžœžœ  œž œ žœžœ‹žœDžœžœ-žœžœž œ7žœžœ  œž œžœ.œžœžœžœ žœžœžœ&œ6žœjžœžœ!žœcžœ~žœ½œžœžœ)žœžœjžœ žœÑžœ žœožœ žœŽžœ žœožœ žœŽžœ žœpžœ žœdžœžœœžœžœ žœ žœžœžœžœ žœžœžœžœžœ žœžœ žœžœžœžœžœ žœ žœb˜ªy—…—<¬DK