File: FileStreamTestImpl.mesa
Last edited by MBrown on July 11, 1983 11:05 pm
Last Edited by: Hagmann, December 6, 1983 3:48 pm
Last Edited by: Taft, December 1, 1983 4:51 pm
Bob Hagmann May 16, 1985 3:35:41 pm PDT
DIRECTORY
AlpineFS,
BasicTime USING [GetClockPulses, GMT, Now, Period, Pulses, PulsesToMicroseconds],
Commander USING [CommandProc, Handle, Register],
FileStream USING [ErrorFromStream, FinalizationProc, GetFinalizationProc,
GetStreamClassData, OpenFileFromStream, SetFinalizationProc,
SetStreamClassData, SaveStreamError],
FileStreamTestInterface USING [ OneTest ],
FileStats USING [Data, GetData],
FS,
IO,
Basics USING [LongNumber, LowByte, UnsafeBlock],
Process USING [Pause],
Random USING [Create, NextInt, ChooseInt, RandomStream],
Real USING [PairToReal, SqRt],
Rope USING [Cat, Find, ROPE],
UserCredentials USING [Get],
VM;
FileStreamTestImpl: PROGRAM
IMPORTS
AlpineFS,
BasicTime,
Commander,
FileStats,
FileStream,
FileStreamTestInterface,
FS,
IO,
I: Basics,
Process,
RAN: Random,
Real,
Rope,
UserCredentials,
VM
EXPORTS
FileStreamTestInterface
= BEGIN
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
dpy: PUBLIC STREAM ;
fileSystem: {local, alpine} ← local;
fileNamePrefix: ROPENIL;
FilePos: INT ;
CatchCount: INT ;    -- for ChaseBuffers
StopChase: BOOLFALSE ;
randomDataBlockSize: CARDINAL = 1000;
maxFileBytes: LONG CARDINALVM.BytesForPages[140] + 1;
randomSeed: CARDINAL ← 12314B;
chaseCount: INT = 800000 ;
backupChaseCount: INT = 30000 ;
debugTrace: BOOLFALSE;
GoSlow: BOOLFALSE;
Alarm: SIGNAL = CODE;
TickStop: SIGNAL = CODE;
Word Count Test - execise preread
WordCount: PROC [fileName: ROPE, vmPagesPerBuffer: INT [1 .. 128], nBuffers: INT [1 .. 4]] = {
Expects a file name as the argument, and counts the number of words in the indicated file.
totalWordCount: INT ← 0;
totalLineCount: INT ← 0;
headerWritten: BOOLFALSE;
verbose: BOOLTRUE;
Start: BasicTime.GMT ← BasicTime.Now[];
Finish: BasicTime.GMT ;
in: IO.STREAM ← StreamOpen[fileName: fileName, streamBufferParms: [vmPagesPerBuffer: vmPagesPerBuffer, nBuffers: nBuffers ]
! FS.Error => GOTO openFailed ];
charCount, wordCount, newLineCount: INT;
dpy.PutF["\n\n\nStart of Word Count Test: vmPages: %g, nBuffers: %g\n\n\n",
IO.int[vmPagesPerBuffer], IO.int[nBuffers]];
[charCount, wordCount, newLineCount] ← CountFile[in];
totalWordCount ← totalWordCount + wordCount;
totalLineCount ← totalLineCount + newLineCount;
in.Close[];
in ← NIL ;
IF verbose AND ~headerWritten THEN {
headerWritten ← TRUE;
dpy.PutF["Lines\tWords\t\tFile\n"];
};
dpy.PutF["%6d\t%6d\t\t%g\n\n\n", IO.int[newLineCount],
IO.int[wordCount], IO.rope[fileName]];
Finish ← BasicTime.Now[];
dpy.PutF["\n\n Seconds: %g\n", IO.int[BasicTime.Period[Start, Finish]]];
EXITS
openFailed => dpy.PutF["Could not open \"%g\"\n\n\n", IO.rope[fileName]];
};
CountFile: PROC[ file: IO.STREAM ]
RETURNS [ charCount: INT ← 0, wordCount: INT ← 0, newLineCount: INT ← 0 ] = {
Counts the number of words in the indicated stream.
State: TYPE = { inWord, inJunk, oneNull };
state: State ← inJunk;
DO c: CHARIO.GetChar[file ! IO.EndOfStream => GOTO eof];
SELECT c FROM
IN ['0..'9], IN ['A..'Z], IN ['a..'z] => IF state ~= inWord THEN {
state ← inWord;
wordCount ← wordCount + 1;
};
= 0C => IF state = oneNull THEN EXIT ELSE state ← oneNull;
ENDCASE => {
state ← inJunk;
IF c = '\n THEN newLineCount ← newLineCount + 1;
};
charCount ← charCount + 1;
REPEAT
eof => NULL;
ENDLOOP;
};
TypeAFile: PROC[fileName: ROPE] = {
readStream: IO.STREAM ← StreamOpen[fileName: fileName];
DO c: CHARIO.GetChar[readStream ! IO.EndOfStream => GOTO eof];
dpy.PutF["%g",IO.char[c]];
REPEAT
eof => NULL;
ENDLOOP;
};
Chase Buffers - test parallel buffering logic
ChaseBuffers: PROC[fileName: ROPE, vmPagesPerBuffer: INT [1 .. 128], nBuffers: INT [1 .. 4],
readPause: INT ← 2, writePause: INT ← 1]= {
Creates a reader process to chase a writer process through 1,000,000 bytes of output.
randomStream: RAN.RandomStream;
Start: BasicTime.GMT ← BasicTime.Now[];
Finish: BasicTime.GMT ;
biggie: CARDINAL ;
writeStream: IO.STREAM ← StreamOpen[fileName: fileName, accessOptions: $create,
streamBufferParms: [vmPagesPerBuffer: vmPagesPerBuffer, nBuffers: nBuffers ] ];
process: PROCESS ;
FilePos ← 0 ;
CatchCount ← 0 ;
dpy.PutF["\n\n\n\nStart of Chase Buffers test: vmPages: %g, nBuffers: %g\n",
IO.int[vmPagesPerBuffer], IO.int[nBuffers]];
dpy.PutF[" readPause: %g, writePause: %g\n\n\n",
IO.int[readPause], IO.int[writePause]];
process ← FORK readprocess[writeStream,readPause];
randomStream ← RAN.Create[seed: randomSeed];
UNTIL FilePos >= chaseCount DO
fill: INT ;
fill ← randomStream.ChooseInt[min: 1, max: 311];
biggie ← FilePos MOD 127 ;
FOR i:INT IN [1..fill] DO
char: CHAR ;
TRUSTED {char ← LOOPHOLE[I.LowByte[biggie]] ;};
IF StopChase THEN Alarm[];
writeStream.PutChar[ char ];
FilePos ← FilePos + 1;
IF (biggie ← biggie + 1 ) >= 127 THEN biggie ← 0 ;
ENDLOOP;
IF FilePos >= chaseCount THEN { IF StopChase THEN Alarm[]; };
IF fill < 13 AND writePause > 0 THEN Process.Pause[writePause];
ENDLOOP;
IF NOT writeStream.EndOf THEN Alarm[];
writeStream.Flush[];
writeStream.Close[];
writeStream ← NIL ;
dpy.PutF["\nAbout to JOIN\n"];
TRUSTED {JOIN process ;};
Finish ← BasicTime.Now[];
dpy.PutF["\n\n Seconds: %g\n", IO.int[BasicTime.Period[Start, Finish]]];
dpy.PutF["\nRead Process caught writer %g times\nEnd of Chase Buffers test\n",
IO.int[CatchCount]];
};
readprocess: PROC [ writestream: IO.STREAM , readPause: INT] = {
myPos: INT ← 0 ;
dupMyPos: INT ← 0 ;
dupFilePos: INT ;
biggie: CARDINAL ← 0 ;
readStream: IO.STREAM ← FS.StreamFromOpenStream[writestream];
readStream.SetIndex[0];
IF readStream.CharsAvail <= 0 THEN {StopChase ← TRUE; Alarm[]};
WHILE myPos < chaseCount DO
dupFilePos ← FilePos ;
IF myPos = FilePos THEN {
CatchCount ← CatchCount + 1 ;
IF readPause > 0 THEN Process.Pause[readPause];
}
ELSE {
readChar, char: CHAR ;
TRUSTED {char ← LOOPHOLE[I.LowByte[biggie]] ;};
IF readStream.EndOf THEN Alarm[];
readChar ← readStream.GetChar[! IO.EndOfStream => {StopChase ← TRUE; Alarm[]} ];
myPos ← myPos + 1 ;
dupMyPos ← dupMyPos + 1 ;
IF myPos # dupMyPos THEN {StopChase ← TRUE; Alarm[]} ;
IF readChar # char THEN Alarm[] ;
IF (biggie ← biggie + 1 ) >= 127 THEN biggie ← 0 ;
};
ENDLOOP;
myPos ← chaseCount-1 ;
biggie ← myPos MOD 127 ;
WHILE myPos > (chaseCount-backupChaseCount) DO
char: CHAR ;
TRUSTED {char ← LOOPHOLE[I.LowByte[biggie]] ;};
readStream.Backup[char: char];
myPos ← myPos - 1 ;
IF (biggie = 0 ) THEN biggie ← 126 ELSE biggie ← biggie - 1 ;
IF readStream.EndOf THEN Alarm[];
ENDLOOP;
readStream.Reset[];
IF NOT readStream.EndOf THEN Alarm[];
readStream.Close[];
readStream← NIL ;
};
DropSomeStreams: PROC[fileName1: ROPE, fileName2: ROPE] = {
writeStream1, readStream1, writeStream2: IO.STREAM ;
dpy.PutF["\n\nStart of DropSomeStreams test:"];
writeStream1 ← StreamOpen[fileName: fileName1, accessOptions: $create];
readStream1 ← FS.StreamFromOpenStream[writeStream1];
writeStream2 ← StreamOpen[fileName: fileName2, accessOptions: $create];
writeStream1 ← NIL ;
readStream1 ← NIL ;
writeStream2 ← NIL ;
dpy.PutF["\n\nEnd of DropSomeStreams test:"];
};
extendCount: INT ← 0 ;
didExtend: BOOLFALSE ;
extendSize: ARRAY [1 .. 6] OF INT
[ 5120+512, 10240, 10240+512, 20480, 20480, 1048576+512] ;
myExtend: INT ← 0 ;
extend: SAFE PROC [ count: FS.ByteCount] RETURNS [FS.ByteCount] = TRUSTED {
IF extendCount < 6 THEN extendCount ← extendCount + 1 ;
didExtend ← TRUE ;
myExtend ← extendSize[extendCount];
RETURN[extendSize[extendCount]]
};
ExtendFileTest: PROC[fileName: ROPE,
vmPagesPerBuffer: INT [1 .. 128] ← 4 , nBuffers: INT [1 .. 4] ← 2 ,
vmPagesPerWrite: INT [1 .. 128] ← 4 ] = {
bytesLeft: INT ← 1048576 ;
bytesPerFilePage: INT = FS.BytesForPages[1];
unsafeDataBlock: I.UnsafeBlock ;
UnsafeBlockInterval: VM.Interval;
writeStream: IO.STREAM ;
writeFile: FS.OpenFile ;
Start: BasicTime.GMT ;
Finish: BasicTime.GMT ;
startReadFileData, startWriteFileData, finishReadFileData, finishWriteFileData: FileStats.Data ;
dpy.PutF["\n\nStart of extend file test:"];
dpy.PutF["\n vmPages: %g, nBuffers: %g, pagesPerWrite %g\n",
IO.int[vmPagesPerBuffer], IO.int[nBuffers], IO.int[vmPagesPerWrite] ];
UnsafeBlockInterval ← VM.Allocate[count: vmPagesPerWrite];
unsafeDataBlock.base ← VM.AddressForPageNumber[UnsafeBlockInterval.page];
unsafeDataBlock.count ← vmPagesPerWrite*bytesPerFilePage;
startReadFileData ← FileStats.GetData[read];
startWriteFileData ← FileStats.GetData[write];
Start ← BasicTime.Now[];
writeStream ← StreamOpen[fileName: fileName, accessOptions: $create,
streamBufferParms: [vmPagesPerBuffer: vmPagesPerBuffer, nBuffers: nBuffers ] ,
createByteCount: 5120,
extendFileProc: extend ];
writeFile ← FS.OpenFileFromStream[writeStream];
WHILE bytesLeft > 0 DO
writeStream.UnsafePutBlock[unsafeDataBlock];
IF didExtend THEN {
pageAllocation: VM.PageNumber;
byteLength: FS.ByteCount ;
didExtend ← FALSE ;
[pages: pageAllocation, bytes: byteLength] ← writeFile.GetInfo[];
dpy.PutF["\n Extend to : %g pageAllocation %g, byteLength %g",
IO.int[myExtend], IO.int[pageAllocation], IO.int[byteLength] ];
};
bytesLeft ← bytesLeft - unsafeDataBlock.count ;
ENDLOOP;
writeStream.Close[];
writeStream ← NIL ;
Finish ← BasicTime.Now[];
finishReadFileData ← FileStats.GetData[read];
finishWriteFileData ← FileStats.GetData[write];
TRUSTED{VM.Free[UnsafeBlockInterval]};
dpy.PutF["\n\n Seconds: %g File reads %g pages %g, Writes %g pages %g\n",
IO.int[BasicTime.Period[Start, Finish]],
IO.int[finishReadFileData.calls-startReadFileData.calls],
IO.int[finishReadFileData.pages-startReadFileData.pages],
IO.int[finishWriteFileData.calls-startWriteFileData.calls],
IO.int[finishWriteFileData.pages-startWriteFileData.pages]
];
dpy.PutF[" reads/sec %g, writes/sec %g\n",
IO.int[ (finishReadFileData.calls-startReadFileData.calls)/BasicTime.Period[Start, Finish]],
IO.int[ (finishWriteFileData.calls-startWriteFileData.calls)/BasicTime.Period[Start, Finish]] ];
dpy.PutF["\nEnd of extend file test\n"];
};
WriteAMegabyte: PROC[fileName: ROPE,
vmPagesPerBuffer: INT [1 .. 128], nBuffers: INT [1 .. 4], vmPagesPerWrite: INT [1 .. 128]] = {
extend: SAFE PROC [ count: FS.ByteCount] RETURNS [FS.ByteCount] = TRUSTED {
RETURN[count + 20480]
};
Start: BasicTime.GMT ;
Finish: BasicTime.GMT ;
startPulse: BasicTime.Pulses ;
endPulse: BasicTime.Pulses ;
requestNo: INT ;
microsecondsPerRequest: ARRAY [1..100] OF INT ;
startReadFileData, startWriteFileData, finishReadFileData, finishWriteFileData: FileStats.Data ;
bytesLeft: INT ← 1048576 ;
bytesPerFilePage: INT = FS.BytesForPages[1];
unsafeDataBlock: I.UnsafeBlock ;
UnsafeBlockInterval: VM.Interval;
writeStream: IO.STREAM ;
dpy.PutF["\n\nStart of write megabyte test:"];
dpy.PutF["\n vmPages: %g, nBuffers: %g, pagesPerWrite %g\n",
IO.int[vmPagesPerBuffer], IO.int[nBuffers], IO.int[vmPagesPerWrite] ];
UnsafeBlockInterval ← VM.Allocate[count: vmPagesPerWrite];
unsafeDataBlock.base ← VM.AddressForPageNumber[UnsafeBlockInterval.page];
unsafeDataBlock.count ← vmPagesPerWrite*bytesPerFilePage;
startReadFileData ← FileStats.GetData[read];
startWriteFileData ← FileStats.GetData[write];
Start ← BasicTime.Now[];
writeStream ← StreamOpen[fileName: fileName, accessOptions: $create,
streamBufferParms: [vmPagesPerBuffer: vmPagesPerBuffer, nBuffers: nBuffers ] ,
createByteCount: 1048576 ];
requestNo ← 1 ;
startPulse ← BasicTime.GetClockPulses[] ;
WHILE bytesLeft > 0 DO
writeStream.UnsafePutBlock[unsafeDataBlock];
endPulse ← BasicTime.GetClockPulses[] ;
IF requestNo <= 100 THEN {
microsecondsPerRequest[requestNo] ←
BasicTime.PulsesToMicroseconds[endPulse - startPulse] ;
startPulse ← endPulse ;
requestNo ← requestNo + 1 ;
};
bytesLeft ← bytesLeft - unsafeDataBlock.count ;
ENDLOOP;
writeStream.Close[];
writeStream ← NIL ;
Finish ← BasicTime.Now[];
finishReadFileData ← FileStats.GetData[read];
finishWriteFileData ← FileStats.GetData[write];
TRUSTED{VM.Free[UnsafeBlockInterval]};
dpy.PutF["\n\n Seconds: %g File reads %g pages %g, Writes %g pages %g\n",
IO.int[BasicTime.Period[Start, Finish]],
IO.int[finishReadFileData.calls-startReadFileData.calls],
IO.int[finishReadFileData.pages-startReadFileData.pages],
IO.int[finishWriteFileData.calls-startWriteFileData.calls],
IO.int[finishWriteFileData.pages-startWriteFileData.pages]
];
dpy.PutF[" reads/sec %g, writes/sec %g\n",
IO.int[ (finishReadFileData.calls-startReadFileData.calls)/BasicTime.Period[Start, Finish]],
IO.int[ (finishWriteFileData.calls-startWriteFileData.calls)/BasicTime.Period[Start, Finish]] ];
FOR requestNo IN [1..100] DO
IF requestNo MOD 10 = 1 THEN dpy.PutF["%g-%g: ",IO.int[requestNo],
IO.int[requestNo+9]];
dpy.PutF["%g ",IO.int[microsecondsPerRequest[requestNo]]];
IF requestNo MOD 10 = 0 THEN dpy.PutF["\n"];
ENDLOOP;
dpy.PutF["\nEnd of WriteAMegabyte\n"];
};
ReadAMegabyte: PROC[fileName: ROPE, pause: INT,
vmPagesPerBuffer: INT [1 .. 128], nBuffers: INT [1 .. 4], vmPagesPerRead: INT [1 .. 128]] = {
randomStream: RAN.RandomStream;
Start: BasicTime.GMT ;
Finish: BasicTime.GMT ;
startReadFileData, startWriteFileData, finishReadFileData, finishWriteFileData: FileStats.Data ;
bytesLeft: INT ← 1048576 ;
readCount: INT ;
realOne: REAL ← Real.PairToReal[1,0];
microsecondsPerRequest: ARRAY [1..100] OF INT ;
requestNo: INT ;
startPulse: BasicTime.Pulses ;
endPulse: BasicTime.Pulses ;
bytesPerFilePage: INT = FS.BytesForPages[1];
unsafeDataBlock: I.UnsafeBlock ;
UnsafeBlockInterval: VM.Interval;
readStream: IO.STREAM ;
randomStream ← RAN.Create[seed: randomSeed];
dpy.PutF["\n\nStart of read megabyte test:"];
dpy.PutF["\n pause %g, vmPages: %g, nBuffers: %g, pagesPerRead %g\n",
IO.int[pause], IO.int[vmPagesPerBuffer], IO.int[nBuffers], IO.int[vmPagesPerRead] ];
UnsafeBlockInterval ← VM.Allocate[count: vmPagesPerRead];
unsafeDataBlock.base ← VM.AddressForPageNumber[UnsafeBlockInterval.page];
unsafeDataBlock.count ← vmPagesPerRead*bytesPerFilePage;
startReadFileData ← FileStats.GetData[read];
startWriteFileData ← FileStats.GetData[write];
Start ← BasicTime.Now[];
readStream ← StreamOpen[fileName: fileName, accessOptions: $read,
streamBufferParms: [vmPagesPerBuffer: vmPagesPerBuffer, nBuffers: nBuffers ] ];
readCount ← unsafeDataBlock.count ;
requestNo ← 1 ;
startPulse ← BasicTime.GetClockPulses[] ;
WHILE bytesLeft > 0 DO
IF pause >= 0 THEN readCount ← readStream.UnsafeGetBlock[unsafeDataBlock];
endPulse ← BasicTime.GetClockPulses[] ;
IF requestNo <= 100 THEN {
microsecondsPerRequest[requestNo] ←
BasicTime.PulsesToMicroseconds[endPulse - startPulse] ;
startPulse ← endPulse ;
requestNo ← requestNo + 1 ;
};
IF readCount # unsafeDataBlock.count AND unsafeDataBlock.count <= bytesLeft
THEN Alarm[];
bytesLeft ← bytesLeft - unsafeDataBlock.count ;
IF pause # 0 THEN {
zc, nzc: INT ← 0 ;
FOR I: INT IN [0..readCount) DO
IF unsafeDataBlock.base[I] = 0 THEN zc ← zc +1 ELSE nzc ← nzc + 1;
IF randomStream.NextInt[] = zc THEN zc ← zc + 1 ;
IF zc = 0 THEN zc ← 1 ;
IF zc # 0 THEN nzc ← nzc / zc ;
IF (I MOD 64) = 0 THEN realOne ← Real.SqRt[realOne];
ENDLOOP;
Process.Pause[pause]
}
ELSE IF pause < 0 THEN Process.Pause[-pause];
ENDLOOP;
readStream.Close[];
readStream ← NIL ;
Finish ← BasicTime.Now[];
finishReadFileData ← FileStats.GetData[read];
finishWriteFileData ← FileStats.GetData[write];
TRUSTED{VM.Free[UnsafeBlockInterval]};
dpy.PutF["\n\n Seconds: %g File reads %g pages %g, Writes %g pages %g\n",
IO.int[BasicTime.Period[Start, Finish]],
IO.int[finishReadFileData.calls-startReadFileData.calls],
IO.int[finishReadFileData.pages-startReadFileData.pages],
IO.int[finishWriteFileData.calls-startWriteFileData.calls],
IO.int[finishWriteFileData.pages-startWriteFileData.pages]
];
dpy.PutF[" reads/sec %g, writes/sec %g\n",
IO.int[ (finishReadFileData.calls-startReadFileData.calls)/BasicTime.Period[Start, Finish]],
IO.int[ (finishWriteFileData.calls-startWriteFileData.calls)/BasicTime.Period[Start, Finish]] ];
dpy.PutF["Times to do request\n"];
FOR requestNo IN [1..100] DO
IF requestNo MOD 10 = 1 THEN dpy.PutF["%g-%g: ",IO.int[requestNo],
IO.int[requestNo+9]];
dpy.PutF["%g ",IO.int[microsecondsPerRequest[requestNo]]];
IF requestNo MOD 10 = 0 THEN dpy.PutF["\n"];
ENDLOOP;
dpy.PutF["\nEnd of ReadAMegabyte\n"];
};
WriteAMegabyteWithPattern: PROC[fileName: ROPE,
vmPagesPerBuffer: INT [1 .. 128], nBuffers: INT [1 .. 4], vmPagesPerWrite: INT [1 .. 1024]] = {
extend: SAFE PROC [ count: FS.ByteCount] RETURNS [FS.ByteCount] = TRUSTED {
RETURN[count + 20480]
};
Start: BasicTime.GMT ;
Finish: BasicTime.GMT ;
startReadFileData, startWriteFileData, finishReadFileData, finishWriteFileData: FileStats.Data ;
bytesLeft: INT ← 1048576 ;
bytesPerFilePage: INT = FS.BytesForPages[1];
unsafeDataBlock: I.UnsafeBlock ;
UnsafeBlockInterval: VM.Interval;
writeStream: IO.STREAM ;
dpy.PutF["\n\nStart of write megabyte with pattern test:"];
dpy.PutF["\n vmPages: %g, nBuffers: %g, pagesPerWrite %g\n",
IO.int[vmPagesPerBuffer], IO.int[nBuffers], IO.int[vmPagesPerWrite] ];
UnsafeBlockInterval ← VM.Allocate[count: vmPagesPerWrite];
unsafeDataBlock.base ← VM.AddressForPageNumber[UnsafeBlockInterval.page];
unsafeDataBlock.count ← vmPagesPerWrite*bytesPerFilePage;
startReadFileData ← FileStats.GetData[read];
startWriteFileData ← FileStats.GetData[write];
Start ← BasicTime.Now[];
writeStream ← StreamOpen[fileName: fileName, accessOptions: $create,
streamBufferParms: [vmPagesPerBuffer: vmPagesPerBuffer, nBuffers: nBuffers ] ,
createByteCount: 1048576 ];
WHILE bytesLeft > 0 DO
byteNo: INT ← 1048576 - bytesLeft ;
biggie: CARDINAL ← byteNo MOD 127 ;
charNo: INT ;
charNo ← 0 ;
FOR requestNo: INT IN [0..unsafeDataBlock.count) DO
char: CHAR ;
TRUSTED {char ← LOOPHOLE[I.LowByte[biggie]] ;};
IF charNo >= 1024 THEN {
charNo ← charNo - 1024;
unsafeDataBlock.base ← unsafeDataBlock.base + 512 ;
};
unsafeDataBlock.base[charNo] ← LOOPHOLE[char] ;
byteNo ← byteNo + 1 ;
IF (biggie ← biggie + 1 ) >= 127 THEN biggie ← 0 ;
charNo ← charNo + 1 ;
ENDLOOP;
unsafeDataBlock.base ← VM.AddressForPageNumber[UnsafeBlockInterval.page];
writeStream.UnsafePutBlock[unsafeDataBlock];
bytesLeft ← bytesLeft - unsafeDataBlock.count ;
ENDLOOP;
writeStream.Close[];
writeStream ← NIL ;
Finish ← BasicTime.Now[];
finishReadFileData ← FileStats.GetData[read];
finishWriteFileData ← FileStats.GetData[write];
TRUSTED{VM.Free[UnsafeBlockInterval]};
dpy.PutF["\n\n Seconds: %g File reads %g pages %g, Writes %g pages %g\n",
IO.int[BasicTime.Period[Start, Finish]],
IO.int[finishReadFileData.calls-startReadFileData.calls],
IO.int[finishReadFileData.pages-startReadFileData.pages],
IO.int[finishWriteFileData.calls-startWriteFileData.calls],
IO.int[finishWriteFileData.pages-startWriteFileData.pages]
];
dpy.PutF[" reads/sec %g, writes/sec %g\n",
IO.int[ (finishReadFileData.calls-startReadFileData.calls)/BasicTime.Period[Start, Finish]],
IO.int[ (finishWriteFileData.calls-startWriteFileData.calls)/BasicTime.Period[Start, Finish]] ];
dpy.PutF["\nEnd of WriteAMegabyteWithPattern\n"];
};
ReadAMegabyteWithPattern: PROC[fileName: ROPE, pause: INT,
vmPagesPerBuffer: INT [1 .. 128], nBuffers: INT [1 .. 4], vmPagesPerRead: INT [1 .. 1024]] = {
Start: BasicTime.GMT ;
Finish: BasicTime.GMT ;
startReadFileData, startWriteFileData, finishReadFileData, finishWriteFileData: FileStats.Data ;
bytesLeft: INT ← 1048576 ;
byteNo: INT ← 0 ;
readCount: INT ;
errorCount: INT ← 0 ;
requestNo: INT ;
biggie: CARDINAL ;
bytesPerFilePage: INT = FS.BytesForPages[1];
unsafeDataBlock: I.UnsafeBlock ;
UnsafeBlockInterval: VM.Interval;
readStream: IO.STREAM ;
dpy.PutF["\n\nStart of read megabyte with pattern test:"];
dpy.PutF["\n pause %g, vmPages: %g, nBuffers: %g, pagesPerRead %g\n",
IO.int[pause], IO.int[vmPagesPerBuffer], IO.int[nBuffers], IO.int[vmPagesPerRead] ];
UnsafeBlockInterval ← VM.Allocate[count: vmPagesPerRead];
unsafeDataBlock.base ← VM.AddressForPageNumber[UnsafeBlockInterval.page];
unsafeDataBlock.count ← vmPagesPerRead*bytesPerFilePage;
startReadFileData ← FileStats.GetData[read];
startWriteFileData ← FileStats.GetData[write];
Start ← BasicTime.Now[];
readStream ← StreamOpen[fileName: fileName, accessOptions: $read,
streamBufferParms: [vmPagesPerBuffer: vmPagesPerBuffer, nBuffers: nBuffers ] ];
readCount ← unsafeDataBlock.count ;
requestNo ← 1 ;
WHILE bytesLeft > 0 DO
charNo: INT ;
IF pause >= 0 THEN readCount ← readStream.UnsafeGetBlock[unsafeDataBlock];
IF readCount # unsafeDataBlock.count AND unsafeDataBlock.count <= bytesLeft
THEN Alarm[];
biggie ← byteNo MOD 127 ;
charNo ← 0 ;
FOR requestNo: INT IN [0..readCount) DO
char: CHAR ;
TRUSTED {char ← LOOPHOLE[I.LowByte[biggie]] ;};
IF charNo >= 1024 THEN {
charNo ← charNo - 1024;
unsafeDataBlock.base ← unsafeDataBlock.base + 512 ;
};
IF unsafeDataBlock.base[charNo] # LOOPHOLE[char] THEN {
dpy.PutF["\n >>>> byte %g, was : %g, should be: %g",
IO.int[byteNo], IO.char[LOOPHOLE[unsafeDataBlock.base[charNo]]], IO.char[char]];
errorCount ← errorCount + 1 ;
IF errorCount > 20 THEN bytesLeft ← 0 ;
};
byteNo ← byteNo + 1 ;
IF (biggie ← biggie + 1 ) >= 127 THEN biggie ← 0 ;
charNo ← charNo + 1 ;
ENDLOOP;
unsafeDataBlock.base ← VM.AddressForPageNumber[UnsafeBlockInterval.page];
bytesLeft ← bytesLeft - unsafeDataBlock.count ;
ENDLOOP;
readStream.Close[];
readStream ← NIL ;
Finish ← BasicTime.Now[];
finishReadFileData ← FileStats.GetData[read];
finishWriteFileData ← FileStats.GetData[write];
TRUSTED{VM.Free[UnsafeBlockInterval]};
dpy.PutF["\n\n Seconds: %g File reads %g pages %g, Writes %g pages %g\n",
IO.int[BasicTime.Period[Start, Finish]],
IO.int[finishReadFileData.calls-startReadFileData.calls],
IO.int[finishReadFileData.pages-startReadFileData.pages],
IO.int[finishWriteFileData.calls-startWriteFileData.calls],
IO.int[finishWriteFileData.pages-startWriteFileData.pages]
];
dpy.PutF[" reads/sec %g, writes/sec %g\n",
IO.int[ (finishReadFileData.calls-startReadFileData.calls)/BasicTime.Period[Start, Finish]],
IO.int[ (finishWriteFileData.calls-startWriteFileData.calls)/BasicTime.Period[Start, Finish]] ];
dpy.PutF["Times to do request\n"];
dpy.PutF["\nEnd of ReadAMegabyteWithPattern\n"];
};
nullFinalizationProc: FileStream.FinalizationProc = TRUSTED {
dpy.PutF["\nnullFinalizationProc got called:"];
};
ErrorTests: PROC[fileName: ROPE] = {
writeStream: IO.STREAM ;
hitEOF: BOOL ;
dpy.PutF["\n\nStart of error tests:"];
writeStream ← StreamOpen[fileName: fileName, accessOptions: $create,
streamBufferParms: [vmPagesPerBuffer: 4, nBuffers: 2 ] ,
createByteCount: 40000 ];
FOR I:INT IN [0 .. 55) DO
writeStream.PutChar[0C];
ENDLOOP;
hitEOF ← FALSE ;
[] ← writeStream.GetChar[! IO.EndOfStream => {hitEOF ← TRUE ; CONTINUE;}];
IF NOT hitEOF THEN { dpy.PutF["\n OOPS: should have hit eof\n"];};
IF FileStream.ErrorFromStream[ writeStream ] # [ok, NIL, NIL] THEN
{ dpy.PutF["\n OOPS: should have NIL error at first\n"];};
FileStream.SaveStreamError[self: writeStream, error: [bug, NIL, "Some rope"]];
IF FileStream.ErrorFromStream[ writeStream ] = [ok, NIL, NIL] THEN
{ dpy.PutF["\n OOPS: should have NON-NIL error later\n"];};
IF fileSystem=local THEN
BEGIN
IF FileStream.GetStreamClassData[ writeStream ] # NIL THEN
{ dpy.PutF["\n OOPS: should have NIL class data at first\n"];};
FileStream.SetStreamClassData[self: writeStream, data: writeStream];
IF FileStream.GetStreamClassData[ writeStream ] = NIL THEN
{ dpy.PutF["\n OOPS: should have NON-NIL error later\n"];};
FileStream.SetStreamClassData[self: writeStream, data: NIL];
IF FileStream.GetFinalizationProc[ writeStream ] # NIL THEN
{ dpy.PutF["\n OOPS: should have NIL FinalizationProc at first\n"];};
FileStream.SetFinalizationProc[self: writeStream, proc: nullFinalizationProc];
IF FileStream.GetFinalizationProc[ writeStream ] = NIL THEN
{ dpy.PutF["\n OOPS: should have NON-NIL FinalizationProc later\n"];};
END;
[] ← FileStream.OpenFileFromStream[ writeStream ];
writeStream.Close[];
dpy.PutF["\nEnd of error tests:"];
};
StreamOpen: PUBLIC SAFE PROC [fileName: ROPE, accessOptions: FS.AccessOptions ← $read, createByteCount: FS.ByteCount ← 2560, streamBufferParms: FS.StreamBufferParms ← FS.defaultStreamBufferParms, extendFileProc: FS.ExtendFileProc ← NIL] RETURNS [STREAM] = CHECKED
BEGIN
RETURN [SELECT fileSystem FROM
local => FS.StreamOpen[fileName: fileName, accessOptions: accessOptions, createByteCount: createByteCount, streamBufferParms: streamBufferParms, extendFileProc: extendFileProc],
alpine => AlpineFS.StreamOpen[name: Rope.Cat[fileNamePrefix, fileName], accessOptions: accessOptions, createByteCount: createByteCount, streamBufferParms: streamBufferParms, extendFileProc: extendFileProc],
ENDCASE => ERROR]
END;
RunReadForever: PROC = {
WriteAMegabyteWithPattern["AMegabyte.file", 8, 2, 8];
DO
ReadAMegabyteWithPattern["AMegabyte.file", 0, 4, 2, 4];
ENDLOOP;
};
RunTests: PROC = {
the tests
ErrorTests["FileStreamTest.file"];
WriteAMegabyte["AMegabyte.file", 32, 2, 4];
ReadAMegabyte["AMegabyte.file", 0, 1, 1, 1];
ReadAMegabyte["AMegabyte.file", 0, 1, 2, 1];
ReadAMegabyte["AMegabyte.file", 0, 1, 3, 1];
ReadAMegabyte["AMegabyte.file", 0, 1, 4, 1];
ReadAMegabyte["AMegabyte.file", 1, 1, 1, 1];
ReadAMegabyte["AMegabyte.file", -1, 1, 1, 1];
ReadAMegabyte["AMegabyte.file", 1, 1, 2, 1];
-- ReadAMegabyte["AMegabyte.file", 1, 2, 1, 2];
-- ReadAMegabyte["AMegabyte.file", 1, 2, 2, 2];
-- ReadAMegabyte["AMegabyte.file", 1, 4, 1, 4];
-- ReadAMegabyte["AMegabyte.file", 1, 4, 2, 4];
-- ReadAMegabyte["AMegabyte.file", 1, 8, 1, 8];
-- ReadAMegabyte["AMegabyte.file", 1, 8, 2, 8];
-- ReadAMegabyte["AMegabyte.file", 1, 16, 2, 16];
DropSomeStreams["DropStream1.file", "DropStream2.file"] ;
ExtendFileTest[fileName: "extendA.file"];
WriteAMegabyte["AMegabyte.file", 1, 1, 1];
WriteAMegabyte["AMegabyte.file", 1, 2, 1];
WriteAMegabyte["AMegabyte.file", 1, 3, 1];
WriteAMegabyte["AMegabyte.file", 1, 4, 1];
WriteAMegabyte["AMegabyte.file", 1, 3, 32];
WriteAMegabyte["AMegabyte.file", 2, 2, 2];
WriteAMegabyte["AMegabyte.file", 4, 2, 1];
WriteAMegabyte["AMegabyte.file", 4, 2, 4];
WriteAMegabyte["AMegabyte.file", 8, 4, 2];
WriteAMegabyte["AMegabyte.file", 16, 1, 1];
WriteAMegabyte["AMegabyte.file", 16, 2, 1];
WriteAMegabyte["AMegabyte.file", 16, 2, 16];
WriteAMegabyte["AMegabyte.file", 16, 2, 32];
WriteAMegabyte["AMegabyte.file", 32, 2, 4];
ReadAMegabyte["AMegabyte.file", 0, 32, 2, 4];
WriteAMegabyteWithPattern["AMegabyte.file", 8, 2, 8];
ReadAMegabyteWithPattern["AMegabyte.file", 0, 16, 2, 16];
WriteAMegabyteWithPattern["AMegabyte.file", 16, 2, 16];
ReadAMegabyteWithPattern["AMegabyte.file", 0, 16, 2, 16];
WriteAMegabyteWithPattern["AMegabyte.file", 5, 2, 16];
ReadAMegabyteWithPattern["AMegabyte.file", 0, 16, 2, 16];
WriteAMegabyteWithPattern["AMegabyte.file", 16, 2, 7];
ReadAMegabyteWithPattern["AMegabyte.file", 0, 16, 2, 16];
ReadAMegabyteWithPattern["AMegabyte.file", 0, 16, 2, 32];
ReadAMegabyteWithPattern["AMegabyte.file", 0, 16, 2, 64];
ReadAMegabyteWithPattern["AMegabyte.file", 0, 16, 2, 128];
ReadAMegabyteWithPattern["AMegabyte.file", 0, 16, 2, 256];
WriteAMegabyteWithPattern["AMegabyte.file", 16, 2, 32];
ReadAMegabyteWithPattern["AMegabyte.file", 0, 16, 2, 16];
WriteAMegabyteWithPattern["AMegabyte.file", 16, 2, 64];
ReadAMegabyteWithPattern["AMegabyte.file", 0, 16, 2, 16];
WriteAMegabyteWithPattern["AMegabyte.file", 16, 2, 128];
ReadAMegabyteWithPattern["AMegabyte.file", 0, 16, 2, 16];
WriteAMegabyteWithPattern["AMegabyte.file", 16, 2, 256];
ReadAMegabyteWithPattern["AMegabyte.file", 0, 16, 2, 16];
TypeAFile["FileStreamTest.tioga"];
ChaseBuffers["ChaseBuffers.TestFile", 1, 1];
ChaseBuffers["ChaseBuffers.TestFile", 16, 2];
WordCount["ChaseBuffers.TestFile",16,2];
WordCount["ChaseBuffers.TestFile",1,2];
WordCount["ChaseBuffers.TestFile",1,1];
WordCount["ChaseBuffers.TestFile",11,2];
FileStreamTestInterface.OneTest["FileStreamTest.file"];
WordCount["FileStreamImpl.mesa",16,2];
ChaseBuffers["ChaseBuffers.TestFile", 4, 2, 5, 0];
ChaseBuffers["ChaseBuffers.TestFile", 4, 2, 1, 9];
ChaseBuffers["ChaseBuffers.TestFile", 1, 3];
WordCount["ChaseBuffers.TestFile",8,3];
ChaseBuffers["ChaseBuffers.TestFile", 7, 4];
dpy.PutF["\nEnd of all the Tests!!\n\n\n"];
};
FileStreamTestCmd: Commander.CommandProc = TRUSTED
BEGIN
initOnly: BOOLEAN ← cmd.commandLine.Find[s2: "Init", case: FALSE]>=0;
readForever: BOOLEAN ← cmd.commandLine.Find[s2: "ReadForever", case: FALSE]>=0;
fileSystem ← IF cmd.commandLine.Find[s2: "Alpine", case: FALSE]>=0 THEN alpine ELSE local;
fileNamePrefix ← SELECT fileSystem FROM
local => NIL,
alpine => IO.PutFR["[Luther.alpine]<%g>", [rope[UserCredentials.Get[].name]]],
ENDCASE => ERROR;
dpy ← cmd.out;
IF ~initOnly THEN {
 IF readForever THEN RunReadForever[] ELSE RunTests[];
 };
END;
Commander.Register[key: "FileStreamTest", proc: FileStreamTestCmd, doc: "FileStreamTest [Init] [Alpine] [ReadForever]\n Init - just init the package, don't run the test\n Alpine - use Alpine rather than local file system\n ReadForever - write a file on the local disk and read it forever"];
END.