-- FullBlownTestFilePageMgrImpl.mesa -- Last edited by: -- Kolling on February 1, 1984 11:19:14 am PST DIRECTORY AlpineEnvironment USING[FileID, nullFileID, PageCount, PageNumber, PageRun, VolumeID, wordsPerPage], AlpineInternal USING[FileHandle], File USING[EraseVolume, FindVolumeFromName, FP, GetVolumeID, Volume], FileMap USING[Handle, Initialize, Register], FilePageMgr USING[Create, CreateProc, Delete, FileExists, ForceOutEverything, ForceOutFile, ForceOutVMPageSet, GetSize, InitializeFilePageMgr, NoSuchFile, PageRunArgIllegal, PageRunExtendsPastEof, ReadAheadPages, ReadAheadLogPages, ReadLeaderPages, ReadPages, ReadLogPages, ReleaseState, ReleaseVMPageSet, RestoreCacheToCleanState, SetSize, ShareVMPageSet, UsePages, UseLogPages,VMPageSet], FS USING[StreamOpen], IO USING[card, Close, GetCard, PutF, PutRope, rope, STREAM], RandomCard USING[Choose, Init], Rope USING[ROPE], SystemVersion USING[machineType]; FullBlownTestFilePageMgrImpl: PROGRAM IMPORTS AI: AlpineInternal, AE: AlpineEnvironment, File, FileMap, FPM: FilePageMgr, FS, IO, RandomCard, SystemVersion = BEGIN GetParams: PROCEDURE = BEGIN paramStreamHandle: IO.STREAM _ FS.StreamOpen["FullBlownTest.Params", $read]; NNormalProcesses _ paramStreamHandle.GetCard[]; NErrorProcesses _ paramStreamHandle.GetCard[]; NSharingProcesses _ paramStreamHandle.GetCard[]; IF (NNormalProcesses + NErrorProcesses + NSharingProcesses) = 0 THEN ERROR; IF (NLoops _ paramStreamHandle.GetCard[]) = 0 THEN ERROR; IF (MaxFilesPerProcess _ paramStreamHandle.GetCard[]) = 0 THEN ERROR; IF (MaxFileSize _ paramStreamHandle.GetCard[]) = 0 THEN ERROR; IF (MaxNPagesEachTime _ paramStreamHandle.GetCard[]) = 0 THEN ERROR; IF (MaxOpsPerFileCycle _ paramStreamHandle.GetCard[]) = 0 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["NNormalChunksInCache: %g NLogChunksInCache: %g NLeaderChunksInCache: %g\n\n", IO.card[NNormalChunksInCache], IO.card[NLogChunksInCache], IO.card[NLeaderChunksInCache]]; resultsStreamHandle.PutF["NNormalProcesses: %g NLoops: %g MaxFilesPerProcess: %g MaxFileSize: %g MaxNPagesEachTime: %g", IO.card[NNormalProcesses], IO.card[NLoops], IO.card[MaxFilesPerProcess], IO.card[MaxFileSize], IO.card[MaxNPagesEachTime]]; resultsStreamHandle.PutF[" MaxOpsPerFileCycle: %g\n", IO.card[MaxOpsPerFileCycle]]; resultsStreamHandle.PutF["NErrorProcesses: %g NSharingProcesses: %g\n", IO.card[NErrorProcesses], IO.card[NSharingProcesses]]; END; CleanCache: PROCEDURE = BEGIN FPM.ForceOutEverything[]; FPM.RestoreCacheToCleanState[]; END; 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]; IOMode: TYPE = {read, readWithReadAhead, write}; IOReadMode: TYPE = IOMode[read..readWithReadAhead]; MapAndSetSizeIllegal: PROCEDURE[fileHandle: FileMap.Handle, fileIndex: CARDINAL] = BEGIN pageRun: AE.PageRun; vMPageSet: FPM.VMPageSet; pages: LONG POINTER; BEGIN pageRun _ [firstPage: files[fileIndex].size - 1, count: 0]; vMPageSet _ (IF files[fileIndex].type = normal THEN FPM.ReadPages ELSE FPM.ReadLogPages)[fileHandle, pageRun ! FPM.PageRunArgIllegal => GOTO okay]; ERROR; EXITS okay => NULL; END; BEGIN IF files[fileIndex].size = 0 THEN RETURN; pageRun _ [firstPage: files[fileIndex].size - 1, count: RandomCard.Choose[min: 2, max: 5]]; vMPageSet _ (IF files[fileIndex].type = normal THEN FPM.ReadPages ELSE FPM.ReadLogPages)[fileHandle, pageRun ! FPM.PageRunExtendsPastEof => GOTO okay]; ERROR; EXITS okay => NULL; END; BEGIN newSize: CARDINAL _ files[fileIndex].size - 1; pageRun _ [firstPage: files[fileIndex].size-1, count: 1]; vMPageSet _ (IF files[fileIndex].type = normal THEN FPM.ReadPages ELSE FPM.ReadLogPages)[fileHandle, pageRun]; ReadDataPage[fileIndex, vMPageSet.pages, vMPageSet.pageRun.firstPage]; WriteDataPage[fileIndex, vMPageSet.pages, vMPageSet.pageRun.firstPage]; FPM.ReleaseVMPageSet[vMPageSet, writeBatchedNoWait, FALSE]; FPM.SetSize[fileHandle, newSize]; files[fileIndex].size _ newSize; END; END; SequentialIO: PROCEDURE[fileHandle: FileMap.Handle, fileIndex: CARDINAL, ioMode: IOMode, releaseState: FPM.ReleaseState, keep: BOOLEAN, includeLeader: BOOLEAN, fileInterval: FileInterval] = 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: MaxNPagesEachTime], totalPages]]; END; totalPages: CARDINAL; times: CARDINAL; startPage, nPages: CARDINAL; firstPage, lastPage, nPagesEachTime: CARDINAL; IF includeLeader THEN BEGIN vMPageSet: FPM.VMPageSet _ FPM.ReadLeaderPages[fileHandle]; (IF ioMode = write THEN WriteLeaderPage ELSE ReadLeaderPage)[fileIndex, vMPageSet.pages]; FPM.ReleaseVMPageSet[vMPageSet, releaseState, keep]; END; IF files[fileIndex].size = 0 THEN RETURN; 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, releaseState, keep, startPage, nPages]; startPage _ startPage + nPages; ENDLOOP; END; HandleNPages: PROCEDURE[fileHandle: FileMap.Handle, fileIndex: CARDINAL, ioMode: IOMode, releaseState: FPM.ReleaseState, keep: BOOLEAN, firstPage, nPages: CARDINAL] = BEGIN pageRun: AE.PageRun _ [firstPage: firstPage, count: nPages]; vMPageSet: FPM.VMPageSet; pages: LONG POINTER; pageNumber: CARDINAL _ firstPage; sharing: BOOLEAN _ FALSE; DO vMPageSet _ (SELECT TRUE FROM ioMode IN IOReadMode => IF files[fileIndex].type = normal THEN FPM.ReadPages ELSE FPM.ReadLogPages, ENDCASE => IF files[fileIndex].type = normal THEN FPM.UsePages ELSE FPM.UseLogPages)[fileHandle, pageRun]; pages _ vMPageSet.pages; IF vMPageSet.pageRun.count > pageRun.count THEN ERROR; IF RandomCard.Choose[min: 0, max: 10] = 1 THEN BEGIN sharing _ TRUE; FPM.ShareVMPageSet[vMPageSet]; END; FOR index: CARDINAL IN [0..vMPageSet.pageRun.count) DO (IF ioMode IN IOReadMode THEN ReadDataPage ELSE WriteDataPage)[fileIndex, pages, vMPageSet.pageRun.firstPage + index]; pageNumber _ pageNumber + 1; pages _ pages + AE.wordsPerPage; ENDLOOP; IF RandomCard.Choose[min: 0, max: 10] = 1 THEN FPM.ForceOutVMPageSet[vMPageSet]; FPM.ReleaseVMPageSet[vMPageSet, releaseState, keep]; IF sharing THEN BEGIN FPM.ReleaseVMPageSet[vMPageSet, releaseState, keep]; sharing _ FALSE; END; 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)]; (IF files[fileIndex].type = normal THEN FPM.ReadAheadPages ELSE FPM.ReadAheadLogPages)[fileHandle, pageRun]; END; END; Halfway: CARDINAL _ AE.wordsPerPage/2; ReadLeaderPage: PROCEDURE[fileIndex: CARDINAL, pages: LONG POINTER] = BEGIN wordCount: CARDINAL _ RandomCard.Choose[min: 0, max: Halfway - 1]; IF LOOPHOLE[(pages + wordCount)^, CARDINAL] # leaderTouch[fileIndex] THEN ERROR; wordCount _ RandomCard.Choose[min: Halfway, max: AE.wordsPerPage - 1]; IF LOOPHOLE[(pages + wordCount)^, CARDINAL] # wordCount + fileIndex THEN ERROR; END; OneThird: CARDINAL _ AE.wordsPerPage/3; TwoThird: CARDINAL _ 2*OneThird; -- close enough. WriteLeaderPage: PROCEDURE[fileIndex: CARDINAL, pages: LONG POINTER] = BEGIN leaderTouch[fileIndex] _ leaderTouch[fileIndex] + 1; FOR wordCount: CARDINAL IN [0..Halfway) DO (pages + wordCount)^ _ leaderTouch[fileIndex]; ENDLOOP; FOR wordCount: CARDINAL IN [Halfway..AE.wordsPerPage) DO (pages + wordCount)^ _ wordCount + fileIndex; ENDLOOP; END; ReadDataPage: PROCEDURE[fileIndex: CARDINAL, pages: LONG POINTER, pageNumber: CARDINAL] = BEGIN IF LOOPHOLE[(pages + RandomCard.Choose[min: 0, max: OneThird - 1])^, CARDINAL] # dataTouch[fileIndex][pageNumber] THEN ERROR; IF LOOPHOLE[(pages + RandomCard.Choose[min: OneThird, max: TwoThird - 1])^, CARDINAL] # fileIndex THEN ERROR; IF LOOPHOLE[(pages + RandomCard.Choose[min: TwoThird, max: AE.wordsPerPage - 1])^, CARDINAL] # pageNumber THEN ERROR; END; WriteDataPage: PROCEDURE[fileIndex: CARDINAL, pages: LONG POINTER, pageNumber: CARDINAL] = BEGIN dataTouch[fileIndex][pageNumber] _ dataTouch[fileIndex][pageNumber] + 1; FOR wordCount: CARDINAL IN [0..OneThird) DO (pages + wordCount)^ _ dataTouch[fileIndex][pageNumber]; ENDLOOP; FOR wordCount: CARDINAL IN [OneThird..TwoThird) DO (pages + wordCount)^ _ fileIndex; ENDLOOP; FOR wordCount: CARDINAL IN [TwoThird..AE.wordsPerPage) DO (pages + wordCount)^ _ pageNumber; ENDLOOP; END; GetSequenceID: PROCEDURE[fileID: AE.FileID] RETURNS[fileSequenceID: LONG CARDINAL] = BEGIN uid: LONG CARDINAL _ LOOPHOLE[LOOPHOLE[fileID, File.FP].id]; RETURN[uid]; END; BasicProcess: PROCEDURE [firstFileIndex, maxFileIndex: CARDINAL]= BEGIN debugArray: DebugArray; debugArrayIndex: INTEGER _ 0; debugSize: CARDINAL; FOR indexLoops: CARDINAL IN[0..NLoops) DO FOR indexFiles: CARDINAL IN [firstFileIndex..maxFileIndex) DO oldSize: CARDINAL; resets: CARDINAL _ 0; fileHandle: FileMap.Handle; IF NOT files[indexFiles].exists THEN BEGIN FileIDProc: FilePageMgr.CreateProc = TRUSTED BEGIN files[indexFiles].fileID _ fileID; END; files[indexFiles].size _ RandomCard.Choose[min: 0, max: MaxFileSize]; FPM.Create[VolumeID, files[indexFiles].size, FileIDProc]; debugArray[debugArrayIndex] _ [GetSequenceID[files[indexFiles].fileID], create, files[indexFiles].size]; debugArrayIndex _ (IF debugArrayIndex = MaxDebugIndex - 1 THEN 0 ELSE debugArrayIndex + 1); files[indexFiles].exists _ TRUE; END; fileHandle _ FileMap.Register[VolumeID, files[indexFiles].fileID]; files[indexFiles].nOps _ RandomCard.Choose[min: 0, max: MaxOpsPerFileCycle]; files[indexFiles].totalNOps _ files[indexFiles].totalNOps + files[indexFiles].nOps; IF (debugSize _ FPM.GetSize[fileHandle]) # files[indexFiles].size THEN ERROR; IF files[indexFiles].nOps # 0 THEN SequentialIO[fileHandle, indexFiles, write, writeBatchedNoWait, --keep--FALSE, --leader--TRUE, [allFixed[files[indexFiles].size]]]; FOR indexOps: CARDINAL IN [0..files[indexFiles].nOps) DO ioMode: IOMode _ (SELECT RandomCard.Choose[0, 2] FROM 0 => read, 1 => readWithReadAhead, 2 => write, ENDCASE => ERROR); release: FPM.ReleaseState _ (SELECT RandomCard.Choose[0, 4] FROM 0 => writeIndividualWait, 1 => writeBatchedWait, 2 => writeIndividualNoWait, 3 => writeBatchedNoWait, 4 => clean, ENDCASE => ERROR); keep: BOOLEAN _ (RandomCard.Choose[0, 1] = 0); leader: BOOLEAN _ (RandomCard.Choose[0, 1] = 0); fileInterval: FileInterval _ (SELECT RandomCard.Choose[0, 2] FROM 0 => [allFixed[RandomCard.Choose[1, MaxNPagesEachTime]]], 1 => [allRandom[]], 2 => [someRandom[]], ENDCASE => ERROR); IF (RandomCard.Choose[0, files[indexFiles].nOps] MOD 10) = 0 THEN BEGIN resets _ resets + 1; oldSize _ files[indexFiles].size; files[indexFiles].size _ RandomCard.Choose[min: 0, max: MaxFileSize]; debugArray[debugArrayIndex] _ [GetSequenceID[files[indexFiles].fileID], setSize, files[indexFiles].size]; debugArrayIndex _ (IF debugArrayIndex = MaxDebugIndex - 1 THEN 0 ELSE debugArrayIndex + 1); FPM.SetSize[fileHandle, files[indexFiles].size]; IF files[indexFiles].size > oldSize THEN SequentialIO[fileHandle, indexFiles, write, writeBatchedNoWait, --keep--FALSE, --leader--TRUE, [someFixed[oldSize, files[indexFiles].size - 1, RandomCard.Choose[1, MaxNPagesEachTime]]]]; END; SequentialIO[fileHandle, indexFiles, ioMode, release, keep, leader, fileInterval]; ENDLOOP; IF RandomCard.Choose[min: 0, max: 10] = 1 THEN FPM.ForceOutFile[fileHandle]; IF RandomCard.Choose[min: 0, max: 1] = 1 THEN BEGIN IF (debugSize _ FPM.GetSize[fileHandle]) # files[indexFiles].size THEN ERROR; debugArray[debugArrayIndex] _ [GetSequenceID[files[indexFiles].fileID], delete, files[indexFiles].size]; debugArrayIndex _ (IF debugArrayIndex = MaxDebugIndex - 1 THEN 0 ELSE debugArrayIndex + 1); FPM.Delete[fileHandle]; files[indexFiles].exists _ FALSE; END; fileHandle _ NIL; ENDLOOP; ENDLOOP; FOR indexFiles: CARDINAL IN [firstFileIndex..maxFileIndex) DO IF files[indexFiles].exists THEN BEGIN fileHandle: FileMap.Handle _ FileMap.Register[VolumeID, files[indexFiles].fileID]; IF (debugSize _ FPM.GetSize[fileHandle]) # files[indexFiles].size THEN ERROR; debugArray[debugArrayIndex] _ [GetSequenceID[files[indexFiles].fileID], delete, files[indexFiles].size]; debugArrayIndex _ (IF debugArrayIndex = MaxDebugIndex - 1 THEN 0 ELSE debugArrayIndex + 1); FPM.Delete[fileHandle]; files[indexFiles].exists _ FALSE; fileHandle _ NIL; END; ENDLOOP; END; ErrorProcess: PROCEDURE [firstFileIndex: CARDINAL]= BEGIN debugArray: DebugArray; debugArrayIndex: INTEGER _ 0; debugSize: CARDINAL; FOR indexLoops: CARDINAL IN[0..100) DO FOR indexFiles: CARDINAL IN [firstFileIndex..firstFileIndex + NFilesPerErrorProcess) DO fileHandle: FileMap.Handle; IF (NOT files[indexFiles].exists) AND (RandomCard.Choose[min: 0, max: 1] = 1) THEN BEGIN FileIDProc: FilePageMgr.CreateProc = TRUSTED BEGIN files[indexFiles].fileID _ fileID; END; tempSize: CARDINAL _ RandomCard.Choose[min: 0, max: MaxFileSize]; FPM.Create[VolumeID, tempSize, FileIDProc]; debugArray[debugArrayIndex] _ [GetSequenceID[files[indexFiles].fileID], create, tempSize]; debugArrayIndex _ (IF debugArrayIndex = MaxDebugIndex - 1 THEN 0 ELSE debugArrayIndex + 1); files[indexFiles].exists _ TRUE; files[indexFiles].size _ tempSize; END; fileHandle _ FileMap.Register[VolumeID, files[indexFiles].fileID]; files[indexFiles].nOps _ RandomCard.Choose[min: 0, max: 4]; files[indexFiles].totalNOps _ files[indexFiles].totalNOps + files[indexFiles].nOps; BEGIN debugSize _ FPM.GetSize[fileHandle ! FPM.NoSuchFile => GOTO noSuchFile]; IF NOT files[indexFiles].exists THEN ERROR; IF debugSize # files[indexFiles].size THEN ERROR; EXITS noSuchFile => IF files[indexFiles].exists THEN ERROR; END; IF files[indexFiles].exists # FPM.FileExists[fileHandle] THEN ERROR; BEGIN SequentialIO[fileHandle, indexFiles, write, writeBatchedNoWait, --keep--FALSE, --leader--TRUE, [allFixed[files[indexFiles].size]] ! FPM.NoSuchFile => GOTO noSuchFile]; IF NOT files[indexFiles].exists THEN ERROR; EXITS noSuchFile => IF files[indexFiles].exists THEN ERROR; END; FOR indexOps: CARDINAL IN [0..files[indexFiles].nOps) DO ioMode: IOMode _ (SELECT RandomCard.Choose[0, 2] FROM 0 => read, 1 => readWithReadAhead, 2 => write, ENDCASE => ERROR); release: FPM.ReleaseState _ (SELECT RandomCard.Choose[0, 4] FROM 0 => writeIndividualWait, 1 => writeBatchedWait, 2 => writeIndividualNoWait, 3 => writeBatchedNoWait, 4 => clean, ENDCASE => ERROR); keep: BOOLEAN _ (RandomCard.Choose[0, 1] = 0); leader: BOOLEAN _ (RandomCard.Choose[0, 1] = 0); fileInterval: FileInterval _ (SELECT RandomCard.Choose[0, 2] FROM 0 => [allFixed[RandomCard.Choose[1, MaxNPagesEachTime]]], 1 => [allRandom[]], 2 => [someRandom[]], ENDCASE => ERROR); IF (RandomCard.Choose[0, files[indexFiles].nOps] MOD 10) = 0 THEN BEGIN newSize: CARDINAL _ RandomCard.Choose[min: 0, max: MaxFileSize]; oldSize: CARDINAL; FPM.SetSize[fileHandle, newSize ! FPM.NoSuchFile => GOTO noSuchFile]; IF NOT files[indexFiles].exists THEN ERROR; oldSize _ files[indexFiles].size; files[indexFiles].size _ newSize; IF newSize > oldSize THEN SequentialIO[fileHandle, indexFiles, write, writeBatchedNoWait, --keep--FALSE, --leader--TRUE, [someFixed[oldSize, files[indexFiles].size - 1, RandomCard.Choose[1, MaxNPagesEachTime]]]]; debugArray[debugArrayIndex] _ [GetSequenceID[files[indexFiles].fileID], setSize, newSize]; debugArrayIndex _ (IF debugArrayIndex = MaxDebugIndex - 1 THEN 0 ELSE debugArrayIndex + 1); EXITS noSuchFile => IF files[indexFiles].exists THEN ERROR; END; SequentialIO[fileHandle, indexFiles, ioMode, release, keep, leader, fileInterval! FPM.NoSuchFile => GOTO noSuchFile]; REPEAT noSuchFile => IF files[indexFiles].exists THEN ERROR; ENDLOOP; IF RandomCard.Choose[min: 0, max: 10] = 1 THEN BEGIN FPM.ForceOutFile[fileHandle ! FPM.NoSuchFile => GOTO noSuchFile]; IF NOT files[indexFiles].exists THEN ERROR; EXITS noSuchFile => IF files[indexFiles].exists THEN ERROR; END; IF ((RandomCard.Choose[min: 0, max: 6] >0) AND (files[indexFiles].exists)) THEN BEGIN -- map in illegal area. MapAndSetSizeIllegal[fileHandle, indexFiles]; debugArray[debugArrayIndex] _ [GetSequenceID[files[indexFiles].fileID], mapAndSetSize, files[indexFiles].size]; debugArrayIndex _ (IF debugArrayIndex = MaxDebugIndex - 1 THEN 0 ELSE debugArrayIndex + 1); END; IF RandomCard.Choose[min: 0, max: 1] = 1 THEN BEGIN debugSize: CARDINAL; BEGIN debugSize _ FPM.GetSize[fileHandle ! FPM.NoSuchFile => GOTO noSuchFile]; IF NOT files[indexFiles].exists THEN ERROR; IF debugSize # files[indexFiles].size THEN ERROR; EXITS noSuchFile => IF files[indexFiles].exists THEN ERROR; END; FPM.Delete[fileHandle! FPM.NoSuchFile => GOTO noSuchFile]; IF NOT files[indexFiles].exists THEN ERROR; debugArray[debugArrayIndex] _ [GetSequenceID[files[indexFiles].fileID], delete, files[indexFiles].size]; debugArrayIndex _ (IF debugArrayIndex = MaxDebugIndex - 1 THEN 0 ELSE debugArrayIndex + 1); files[indexFiles].exists _ FALSE; EXITS noSuchFile => IF files[indexFiles].exists THEN ERROR; END; fileHandle _ NIL; ENDLOOP; ENDLOOP; FOR indexFiles: CARDINAL IN [firstFileIndex..firstFileIndex + NFilesPerErrorProcess) DO fileHandle: FileMap.Handle _ FileMap.Register[VolumeID, files[indexFiles].fileID]; debugSize: CARDINAL; BEGIN debugSize _ FPM.GetSize[fileHandle ! FPM.NoSuchFile => GOTO noSuchFile]; IF NOT files[indexFiles].exists THEN ERROR; IF debugSize # files[indexFiles].size THEN ERROR; EXITS noSuchFile => IF files[indexFiles].exists THEN ERROR; END; BEGIN FPM.Delete[fileHandle! FPM.NoSuchFile => GOTO noSuchFile]; IF NOT files[indexFiles].exists THEN ERROR; files[indexFiles].exists _ FALSE; EXITS noSuchFile => IF files[indexFiles].exists THEN ERROR; END; fileHandle _ NIL; ENDLOOP; END; SubSharingProcess: PROCEDURE [firstFileIndex: CARDINAL] RETURNS [nOps: ARRAY[0..NFilesPerSharingProcess) OF CARDINAL] = BEGIN debugSize: CARDINAL; FOR index: CARDINAL IN [0..NFilesPerSharingProcess) DO nOps[index] _ 0; ENDLOOP; FOR indexLoops: CARDINAL IN[0..NLoops) DO FOR indexFiles: CARDINAL IN [firstFileIndex..firstFileIndex + NFilesPerSharingProcess) DO fileHandle: FileMap.Handle _ FileMap.Register[VolumeID, files[indexFiles].fileID]; tempNOps: CARDINAL _ RandomCard.Choose[min: 0, max: MaxOpsPerFileCycle]; nOps[indexFiles - firstFileIndex] _ nOps[indexFiles - firstFileIndex] + tempNOps; IF (debugSize _ FPM.GetSize[fileHandle]) # files[indexFiles].size THEN ERROR; FOR indexOps: CARDINAL IN [0..tempNOps) DO ioMode: IOMode _ (SELECT RandomCard.Choose[0, 1] FROM 0 => read, 1 => readWithReadAhead, ENDCASE => ERROR); keep: BOOLEAN _ (RandomCard.Choose[0, 1] = 0); leader: BOOLEAN _ (RandomCard.Choose[0, 1] = 0); fileInterval: FileInterval _ (SELECT RandomCard.Choose[0, 2] FROM 0 => [allFixed[RandomCard.Choose[1, MaxNPagesEachTime]]], 1 => [allRandom[]], 2 => [someRandom[]], ENDCASE => ERROR); SequentialIO[fileHandle, indexFiles, ioMode, clean, keep, leader, fileInterval]; ENDLOOP; fileHandle _ NIL; ENDLOOP; ENDLOOP; END; SharingProcess: PROCEDURE [firstFileIndex: CARDINAL]= BEGIN NSubSharingProcesses: CARDINAL = 3; mySubProcesses: ARRAY [0..NSubSharingProcesses) OF PROCESS RETURNS [nOps: ARRAY[0..NFilesPerSharingProcess) OF CARDINAL]; FOR indexFiles: CARDINAL IN [firstFileIndex..firstFileIndex + NFilesPerSharingProcess) DO FileIDProc: FilePageMgr.CreateProc = TRUSTED BEGIN files[indexFiles].fileID _ fileID; END; fileHandle: FileMap.Handle; files[indexFiles].size _ RandomCard.Choose[min: 0, max: MaxFileSize]; FPM.Create[VolumeID, files[indexFiles].size, FileIDProc]; fileHandle _ FileMap.Register[VolumeID, files[indexFiles].fileID]; files[indexFiles].exists _ TRUE; SequentialIO[fileHandle, indexFiles, write, writeBatchedNoWait, --keep--FALSE, --leader--TRUE, [allFixed[files[indexFiles].size]]]; fileHandle _ NIL; ENDLOOP; FOR indexProcesses: CARDINAL IN [0..NSubSharingProcesses) DO mySubProcesses[indexProcesses] _ FORK SubSharingProcess[firstFileIndex]; ENDLOOP; FOR indexProcesses: CARDINAL IN [0..NSubSharingProcesses) DO tempNOps: ARRAY[0..NFilesPerSharingProcess) OF CARDINAL _ JOIN mySubProcesses[indexProcesses]; FOR index: CARDINAL IN [0..NFilesPerSharingProcess) DO files[firstFileIndex + index].totalNOps _ files[firstFileIndex + index].totalNOps + tempNOps[index]; ENDLOOP; ENDLOOP; END; Processes: TYPE = RECORD[SEQUENCE nProcesses: [0..LAST[CARDINAL]] OF ProcessModel]; ProcessModel: TYPE = RECORD[process: PROCESS, nFiles: CARDINAL]; Files: TYPE = RECORD[SEQUENCE nFiles: [0..LAST[CARDINAL]] OF FileModel]; FileModel: TYPE = RECORD[fileID: AE.FileID, type: FileType, exists: BOOLEAN, size: CARDINAL, totalNOps: CARDINAL, nOps: CARDINAL]; FileType: TYPE = {normal, log}; LeaderTouch: TYPE = RECORD[SEQUENCE nFiles: [0..LAST[CARDINAL]] OF CARDINAL]; DataTouch: TYPE = RECORD[SEQUENCE nFiles: [0..LAST[CARDINAL]] OF REF DataArray]; DataArray: TYPE = RECORD[SEQUENCE nPages: [0..LAST[CARDINAL]] OF CARDINAL]; processes: REF Processes; files: REF Files; leaderTouch: REF LeaderTouch; dataTouch: REF DataTouch; MaxDebugIndex: CARDINAL = 100; DebugArray: TYPE = ARRAY [0..MaxDebugIndex) OF RECORD[fileSequenceID: LONG CARDINAL, op: DebugOp _ inited, newSize: CARDINAL]; DebugOp: TYPE = {create, setSize, delete, mapAndSetSize, inited}; PrintFileStats: PROCEDURE = BEGIN PutFileID: PROCEDURE[fileID: AE.FileID] = BEGIN uid: LONG CARDINAL _ LOOPHOLE[LOOPHOLE[fileID, File.FP].id]; resultsStreamHandle.PutF[" %g ", IO.card[uid]]; END; FOR index: CARDINAL IN [0..NFiles) DO resultsStreamHandle.PutRope["file: "]; PutFileID[files[index].fileID]; resultsStreamHandle.PutF[" type: %g final size: %g totalNOps: %g\n", IO.rope[(IF files[index].type = normal THEN "normal" ELSE "log")], IO.card[files[index].size], IO.card[files[index].totalNOps]]; ENDLOOP; FOR index: CARDINAL IN [0..NNormalProcesses) DO resultsStreamHandle.PutF["process: %g nFiles: %g\n", IO.card[index], IO.card[processes[index].nFiles]]; ENDLOOP; resultsStreamHandle.PutF["%g\n", IO.rope["For sharing processes: "]]; FOR index: CARDINAL IN [NNormalFiles..NNormalFiles + NSharingProcesses*NFilesPerSharingProcess) DO resultsStreamHandle.PutRope["file: "]; PutFileID[files[index].fileID]; resultsStreamHandle.PutF[" type: %g final size: %g totalNOps: %g\n", IO.rope[(IF files[index].type = normal THEN "normal" ELSE "log")], IO.card[files[index].size], IO.card[files[index].totalNOps]]; ENDLOOP; END; Main: PROCEDURE [initialize: BOOLEAN]= BEGIN -- set up to call from CoPilot for debugging. foo: CARDINAL _ 0; BEGIN ENABLE ANY => foo _ foo + 1; -- protect us from the tempcedarexec. firstFileIndex, maxFileIndex: CARDINAL; File.EraseVolume[volume]; resultsStreamHandle _ FS.StreamOpen["FullBlownTest.Results", $append]; resultsStreamHandle.PutRope[" Nucleus"]; 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[]; IF initialize THEN FPM.InitializeFilePageMgr[nNormalChunksInCache: NNormalChunksInCache, nLogChunksInCache: NLogChunksInCache, nLeaderChunksInCache: NLeaderChunksInCache]; NProcesses _ NNormalProcesses + NErrorProcesses + NSharingProcesses; processes _ NEW[Processes[NProcesses]]; NNormalFiles _ 0; FOR indexProcesses: CARDINAL IN [0..NNormalProcesses) DO processes[indexProcesses].nFiles _ RandomCard.Choose[1, MaxFilesPerProcess]; NNormalFiles _ NNormalFiles + processes[indexProcesses].nFiles; ENDLOOP; NFiles _ NNormalFiles + (NFilesPerErrorProcess*NErrorProcesses) + (NFilesPerSharingProcess*NSharingProcesses); files _ NEW[Files[NFiles]]; leaderTouch _ NEW[LeaderTouch[NFiles]]; dataTouch _ NEW[DataTouch[NFiles]]; IF NFiles > 100 THEN ERROR; FOR index: CARDINAL IN [0..NFiles) DO files[index] _ [fileID: AE.nullFileID, type: IF RandomCard.Choose[0,1] = 0 THEN normal ELSE log, exists: FALSE, size: 0, totalNOps: 0, nOps: 0]; leaderTouch[index] _ 0; dataTouch[index] _ NEW[DataArray[MaxFileSize]]; FOR index1: CARDINAL IN [0..MaxFileSize) DO dataTouch[index][index1] _ 0; ENDLOOP; ENDLOOP; --SafeStorage.ReclaimCollectibleObjects[TRUE, TRUE]; --SafeStorage.ReclaimCollectibleObjects[TRUE, TRUE]; --IF FileMap.GetNext[NIL] # NIL THEN ERROR; CleanCache[]; firstFileIndex _ 0; FOR indexProcesses: CARDINAL IN [0..NNormalProcesses) DO maxFileIndex _ firstFileIndex + processes[indexProcesses].nFiles; processes[indexProcesses].process _ FORK BasicProcess[firstFileIndex, maxFileIndex]; firstFileIndex _ maxFileIndex; ENDLOOP; FOR indexProcesses: CARDINAL IN [NNormalProcesses..NNormalProcesses + NSharingProcesses) DO processes[indexProcesses].process _ FORK SharingProcess[firstFileIndex]; firstFileIndex _ firstFileIndex + NFilesPerSharingProcess; ENDLOOP; FOR indexProcesses: CARDINAL IN [NNormalProcesses + NSharingProcesses..NNormalProcesses + NSharingProcesses + NErrorProcesses) DO processes[indexProcesses].process _ FORK ErrorProcess[firstFileIndex]; firstFileIndex _ firstFileIndex + NFilesPerErrorProcess; ENDLOOP; FOR indexProcesses: CARDINAL IN [0..NProcesses) DO JOIN processes[indexProcesses].process; IF (indexProcesses MOD 4) = 0 THEN FPM.ForceOutEverything[]; ENDLOOP; CleanCache[]; --SafeStorage.ReclaimCollectibleObjects[TRUE, TRUE]; --SafeStorage.ReclaimCollectibleObjects[TRUE, TRUE]; --IF FileMap.GetNext[NIL] # NIL THEN ERROR; PrintFileStats[]; resultsStreamHandle.Close[]; END; END; -- main line code: resultsStreamHandle: IO.STREAM; volume: File.Volume _ File.FindVolumeFromName["Gentian"]; VolumeID: AE.VolumeID = LOOPHOLE[File.GetVolumeID[volume]]; NNormalProcesses, NLoops: CARDINAL; NErrorProcesses, NSharingProcesses: CARDINAL; MaxFilesPerProcess, MaxFileSize, MaxNPagesEachTime, MaxOpsPerFileCycle: CARDINAL; NFilesPerSharingProcess: CARDINAL = 3; NFilesPerErrorProcess: CARDINAL _ 2; NFiles: CARDINAL; NProcesses: CARDINAL; NNormalChunksInCache: CARDINAL; NLogChunksInCache: CARDINAL; NLeaderChunksInCache: CARDINAL; NNormalFiles: CARDINAL; FileMap.Initialize[101, 1000]; END. Edit Log Initial: Kolling: May 20, 1982 4:15 pm: general test for FilePageManager. ʸ˜Jš·œÏciœÏk œ&žœ~žœ%žœVžœ>žœåžœžœ žœRžœ'žœžœ#žœÐblœžœžœžœžœ$žœžœ žœÏn œž œžœžœÔžœ>žœžœžœ,žœžœžœ8žœžœžœ1žœžœžœ7žœžœžœ8žœžœžœ:žœžœžœ7žœžœžœ:žœžœ‘žœ#žœžœ¦žœžœžœ!žœžœ]žœpžœžœžœ  œž œžœ!žœ žœ%žœ@žœžœžœ&žœ!žœžœ8žœžœžœ žœ1žœ% œž œ(žœžœ žœžœžœžœ žœPžœ&žœžœ žœžœ.žœžœ žœžœ žœžœ žœžœžœžœwžœ&žœžœ žœžœ.žœžœ žœžœ žœžœ žœ žœkžœ&žœžœ žœžœ½žœ1žœžœGžœ žœ  œž œ(žœ!žœžœžœ$žœ œž œžœžœžœžœžœCžœ œž œžœžœžœžœžœRžœ œž œžœžœžœžœžœžœQžœžœ žœžœ*žœžœžœžœ žœ žœ,žœžœžœKžœ?žœžœžœžœžœžœžœžœ6žœžœ6žœžœFžœžœZžœžœžœAžœžœžœ°žœžœ{žœžœžœžœžœžœ´žœžœ  œž œ(žœ!žœžœžœžœ žœ@žœžœžœžœžœžœžœžœžœžœžœžœ/žœžœ žœžœžœžœ žœžœ žœžœCžœ)žœžœžœ.žœžœ žœ žœ'žœžœžœžœ$žœžœžœžœžœžœžœžœ.žœžœ"žœ5žœ žœžœžœOžœžœ…žœžœžœžœžœžœ8žœžœžœ[žœ žœžœžœžœ1žœžœ žœžœ œž œ žœ žœžœžœžœ3žœžœžœ!žœžœ6žœžœžœžœ žœžœžœžœžœžœœ œž œ žœ žœžœžœ<žœ žœžœžœ0žœžœ žœžœ žœžœ/žœžœ   œž œ žœ žœžœžœžœžœžœ@žœ%žœžœžœžœGžœžœžœžœžœ0žœžœžœžœžœ  œž œ žœ žœžœžœžœPžœ žœžœžœ:žœžœ žœžœžœ#žœžœ žœžœ žœžœ$žœžœ   œž œžœžœžœžœ žœžœžœžœ žœ  œž œ žœžœ0žœžœžœ žœžœžœžœ žœžœ&žœžœžœ.žœžœ#žœžœžœàžœ6žœžœ@žœžœ…žœžœ8žœžœžœ%žœMžœ žœ4žœ žœžœ&žœžœžœ<žœžœžœžœžœ—žœžœžœ3žœIžœžœ‘žœžœ žœ/žœžœžœçžœ9žœžœ(žœ?žœ6žœXžœ žœžœsžœžœ(žœžœ(žœ0žœžœžœžœ@žœžœ«žœ9žœžœ%žœ>žœžœžœžœžœ žœ žœžœ&žœžœ#žœžœižœžœ;žœžœžœ9žœžœ žœ9žœžœžœžœžœ  œž œžœžœ0žœžœžœ žœžœžœžœ žœžœDžœ)žœžœPžœžœ¥žœ>žœÓžœ6žœžœ@žœAžœþžœžœžœžœžœžœžœžœžœ$žœžœžœžœžœžœžœžœžœžœžœžœžœSžœ žœ6žœžœžœžœžœžœžœžœžœžœžœžœ žœžœ&žœžœžœ<žœžœžœžœžœ—žœžœžœ3žœIžœžœ‘žœžœ žœ/žœžœžœ žœ^žœžœ3žœžœžœžœžœžœyžœ(žœXžœ žœ°žœ9žœžœ(žœžœžœžœžœižœžœžœžœžœžœ žœžœ1žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ)žœ&žœžœœìžœ6žœžœ%žœžœ0žœžœžœžœžœ'žœžœžœžœžœžœžœ$žœžœžœžœžœžœžœžœžœžœžœžœžœžœ«žœ6žœžœ@žœžœžœžœžœžœžœžœžœ žœ žœžœDžœkžœžœžœžœžœžœžœžœžœžœ$žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ#žœžœžœžœžœžœžœžœ  œž œžœžœ žœžœžœžœžœžœžœžœ$žœžœ žœ žœžœžœžœ žœžœFžœjžœœžœžœ8žœžœžœ žœžœžœžœžœ0žœžœžœ3žœIžœžœ‘žœžœržœžœžœžœžœ  œž œžœžœžœžœžœžœžœžœžœžœ žœ žœžœFžœèžœ¡žœQžœ žœ:žœžœžœžœ!žœ(žœ*žœ žœžœžœ!žœžœžœžœ žœ'žœžœžœ'žœ{žœžœ žœžœžœžœžœžœžœžœžœ žœ žœ žœžœžœ žœžœžœžœžœ žœ!žœ žœ žœžœ žœ žœžœžœ žœžœžœžœžœžœžœ žœžœžœžœžœžœžœ žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ!žœ žœ7 œž œžœ  œž œ žœžœ žœžœžœ?žœžœžœžœžœžœ¯žœžœžœ žœžœžœ&žœžœžœžœžœIžœžœ'žœ/žœ-žœžœžœTžœ¯žœžœžœ žœžœžœ&žœžœ œž œžœ.œžœ žœžœžœ&œ!žœÕžœžœ!žœcžœMžœ ž œ„žœ1žœžœžœžœ žœžœ"žœ&žœžœžœžœžœžœžœžœ4žœ%žœžœžœcžœ žœ žœžœžœ(žœžœ 5œ5œ,œ0žœžœžœžœsžœažœ žœžœžœDžœ+žœhžœžœžœžœjžœ+žœdžœžœžœžœžœžœ*žœžœžœžœžœ"5œ5œ,œ@žœžœœžœNžœ žœ:žœ&žœJžœžœžœžœžœžœžœžœžœ%žœr˜„€—…—€Ä