FSUtil.mesa
Last Edited by: Schroeder, December 13, 1983 9:58 am
DIRECTORY
BasicTime USING [GMT, Now, Period, Update],
Commander USING [CommandProc, Handle, Register],
CommandTool USING [ArgumentVector, Failed, Parse, ResolveRelativePath],
Convert USING [Error, IntFromRope, RopeFromTime],
File USING [FP, Open, SystemVolume],
FileStreamPrivate USING [FSDataHandle],
FS USING [Close, Error, ExpandName, GetName],
FSBackdoor USING [MakeFName, Version],
FSLock,
FSLockTableImpl,
FSFileOps USING [GetNameBodyAndVersion],
FSFileSpaceImpl,
FSOpenFileImpl,
FSPkgRefImpl,
IO USING [card, char, int, PutChar, PutF, PutRope, rope],
Rope USING [Cat, Equal, Fetch, Find, Length, Replace, ROPE, Text];
FSUtil: MONITOR
LOCKS @FSPkgRefImpl.LOCK
IMPORTS BasicTime, Commander, CommandTool, Convert, File, FS, FSBackdoor, FSLockTableImpl, FSFileOps, FSFileSpaceImpl, FSOpenFileImpl, FSPkgRefImpl, IO, Rope
SHARES FSFileSpaceImpl, FSLockTableImpl, FSOpenFileImpl, FSPkgRefImpl
= BEGIN
ForceClose: Commander.CommandProc = CHECKED
BEGIN
Search: ENTRY SAFE PROC = TRUSTED
BEGIN
FOR i: CARDINAL IN [0 .. FSPkgRefImpl.buckets) DO
FOR p: REF FSPkgRefImpl.PRTEntry ← FSPkgRefImpl.prt[i], p.chain UNTIL p = NIL DO
WITH p.ref SELECT FROM
f: FSOpenFileImpl.OpenFile => BEGIN
openName: Rope.ROPE ← NIL;
openName ← FS.GetName[[f]
! FS.Error => CONTINUE
].fullFName;
IF Rope.Equal[name, openName, FALSE]
THEN BEGIN
ENABLE FS.Error =>
{cmd.out.PutF[" %g\n", IO.rope[error.explanation]]; CONTINUE};
FS.Close[[f]];
count ← count + 1;
END;
END;
ENDCASE;
ENDLOOP;
ENDLOOP;
END;
argv: CommandTool.ArgumentVector;
name: Rope.ROPE;
count: CARDINAL ← 0;
argv ← CommandTool.Parse[cmd: cmd
! CommandTool.Failed => { msg ← errorMsg; CONTINUE; }];
IF argv = NIL THEN GOTO Failed;
IF argv.argc # 2 THEN GOTO Usage;
name ← FS.ExpandName[CommandTool.ResolveRelativePath[argv[1]]
! FS.Error => { msg ← Rope.Cat[" ", error.explanation, "\n"]; GOTO Failed }
].fullFName;
Search[];
cmd.out.PutF[" Closed %g open files.\n", IO.card[count]];
EXITS
Failed => RETURN[$Failure, msg];
Usage => RETURN[$Failure, " Usage: ForceClose FullFName\n"];
END;
PrintActiveFiles: Commander.CommandProc = CHECKED
BEGIN
Print: ENTRY SAFE PROC = TRUSTED
BEGIN
FOR i: CARDINAL IN [0 .. FSLockTableImpl.buckets) DO
FOR a: FSLock.ActiveFile ← FSLockTableImpl.lockTbl[i], a.next UNTIL a = NIL DO
IF a.nameBody # NIL
THEN BEGIN
cmd.out.PutF["%3d. %g %g%g %g\n", IO.card[i], IO.rope[FSBackdoor.MakeFName[a.nameBody, a.version]], IO.card[a.fileLockCount], IO.char[SELECT a.fileLock FROM none => 'N, read => 'R, ENDCASE => 'W], IO.rope[IF a.recordLock THEN "record locked" ELSE NIL]];
IF a.attachedTo # NIL
THEN cmd.out.PutF[" <- %g\n", IO.rope[FSBackdoor.MakeFName[a.attachedTo.nameBody, a.attachedTo.version]]];
END;
ENDLOOP;
ENDLOOP;
END;
Print[];
END;
PrintOpenFiles: Commander.CommandProc = CHECKED
BEGIN
Print: ENTRY SAFE PROC = TRUSTED
BEGIN
FOR i: CARDINAL IN [0 .. FSPkgRefImpl.buckets) DO
FOR p: REF FSPkgRefImpl.PRTEntry ← FSPkgRefImpl.prt[i], p.chain UNTIL p = NIL DO
WITH p.ref SELECT FROM
f: FSOpenFileImpl.OpenFile => BEGIN
openName: Rope.ROPENIL;
openName ← FS.GetName[[f]
! FS.Error => CONTINUE
].fullFName;
IF openName # NIL
THEN cmd.out.PutF["%3d. %g\n", IO.card[i], IO.rope[openName]];
END;
ENDCASE;
ENDLOOP;
ENDLOOP;
END;
Print[];
END;
PrintFileStreams: Commander.CommandProc = CHECKED
BEGIN
Print: ENTRY SAFE PROC = TRUSTED
BEGIN
FOR i: CARDINAL IN [0 .. FSPkgRefImpl.buckets) DO
FOR p: REF FSPkgRefImpl.PRTEntry ← FSPkgRefImpl.prt[i], p.chain UNTIL p = NIL DO
WITH p.ref SELECT FROM
f: FileStreamPrivate.FSDataHandle =>
IF NOT f.streamIsClosed
THEN BEGIN
lock: Rope.ROPE = (IF f.fileData.accessRights = $read THEN "read" ELSE "write");
cmd.out.PutF["%3d. %g %g\n", IO.card[i], IO.rope[f.fileData.fileName], IO.rope[lock]];
END;
ENDCASE;
ENDLOOP;
ENDLOOP;
END;
Print[];
END;
LRUFlush: Commander.CommandProc = CHECKED
BEGIN
argv: CommandTool.ArgumentVector;
n: INT ← LAST[INT];
timeLimit: BasicTime.GMT ← BasicTime.Now[];
argv ← CommandTool.Parse[cmd: cmd
! CommandTool.Failed => { msg ← errorMsg; CONTINUE }];
IF argv = NIL THEN RETURN[$Failure, msg];
IF argv.argc < 2 THEN GOTO Usage;
IF Rope.Fetch[argv[1], 0] = '-
THEN BEGIN
IF Rope.Fetch[argv[1], 1] = 't AND argv.argc = 3
THEN BEGIN
hoursOld: INT = 60*60*Convert.IntFromRope[argv[2] ! Convert.Error => GOTO Usage];
timeLimit ← BasicTime.Update[timeLimit, - hoursOld];
END
ELSE GOTO Usage;
END
ELSE n ← Convert.IntFromRope[argv[1] ! Convert.Error => GOTO Usage];
THROUGH [1 .. n] UNTIL FSFileSpaceImpl.lru.first # NIL AND BasicTime.Period[from: FSFileSpaceImpl.lru.first.used, to: timeLimit] < 0 DO
IF NOT FSFileSpaceImpl.MakePagesAvailable[NIL, 0, NIL]
THEN { cmd.out.PutRope[" -- no more files to flush!"]; EXIT };
cmd.out.PutChar['.];
ENDLOOP;
cmd.out.PutRope["\n"];
EXITS Usage => RETURN[$Failure, "Usage: LRUFlush numberToFlush -OR- LRUFlush -t hoursOld"];
END;
PrintLRUChain: Commander.CommandProc = CHECKED
BEGIN
IF FSFileSpaceImpl.lru.first = NIL
THEN BEGIN
cmd.out.PutRope[" LRU chain currently empty.\n"];
RETURN;
END;
FOR useR: REF FSFileSpaceImpl.UseRecord ← FSFileSpaceImpl.lru.first, useR.next UNTIL useR = NIL DO
cmd.out.PutF[" %g %g\n", IO.rope[NameFromFP[useR.fp]], IO.rope[RopeFromTime[useR.used]]];
ENDLOOP;
END;
PrintLRUInfo: Commander.CommandProc = CHECKED
BEGIN
IF FSFileSpaceImpl.lru.vDesc = NIL
THEN cmd.out.PutF[" Flusher disabled; killed = %g\n", IO.int[FSFileSpaceImpl.lru.killed] ]
ELSE BEGIN
cmd.out.PutF[" Flusher enabled; killed = %g; sorts = %g;\n", IO.int[FSFileSpaceImpl.lru.killed], IO.int[FSFileSpaceImpl.lru.sorts] ];
IF FSFileSpaceImpl.lru.sorts > 0
THEN BEGIN
free: INT = FSFileSpaceImpl.lru.cumCount - FSFileSpaceImpl.lru.flushed - FSFileSpaceImpl.lru.error - FSFileSpaceImpl.lru.deleted - FSFileSpaceImpl.lru.superseded - FSFileSpaceImpl.lru.open;
cmd.out.PutF[" last sort length = %g; total length = %g; remaining = %g\n", IO.int[FSFileSpaceImpl.lru.count], IO.int[FSFileSpaceImpl.lru.cumCount], IO.int[free] ];
cmd.out.PutF[" flushed = %g; error = %g; deleted = %g; superseded = %g; open = %g;\n", IO.int[FSFileSpaceImpl.lru.flushed], IO.int[FSFileSpaceImpl.lru.error], IO.int[FSFileSpaceImpl.lru.deleted], IO.int[FSFileSpaceImpl.lru.superseded], IO.int[FSFileSpaceImpl.lru.open] ];
END;
END;
END;
months: ARRAY [1..12] OF Rope.ROPE = ["January ", "February ", "March ", "April ", "May ", "June ", "July ", "August ", "September ", "October ", "November ", "December "];
numericMonths: ARRAY [1..12] OF Rope.ROPE = ["1/", "2/", "3/", "4/", "5/", "6/", "7/", "8/", "9/", "10/", "11/", "12/"];
RopeFromTime: SAFE PROC [ time: BasicTime.GMT ] RETURNS [rope: Rope.ROPE] = CHECKED
BEGIN
rope ← Convert.RopeFromTime[from: time, start: $months, end: $seconds, useAMPM: FALSE];
FOR i: [1..12] IN [1..12] DO
IF Rope.Find[rope, months[i]] # -1
THEN rope ← Rope.Replace[base: rope, len: Rope.Length[months[i]] , with: numericMonths[i]];
ENDLOOP;
END;
NameFromFP: SAFE PROC [ fp: File.FP ] RETURNS [fName: Rope.ROPE] = CHECKED
BEGIN
nameBody: Rope.Text;
version: FSBackdoor.Version;
[nameBody, version] ← FSFileOps.GetNameBodyAndVersion
[File.Open[File.SystemVolume[], fp]];
fName ← FSBackdoor.MakeFName[nameBody, version];
END;
Start code
CHECKED BEGIN
Commander.Register[key: "OpenFiles", proc: PrintOpenFiles, doc: "Shows all FS.OpenFiles"];
Commander.Register[key: "ActiveFiles", proc: PrintActiveFiles, doc: "Shows all FS.ActiveFiles"];
Commander.Register[key: "FileStreams", proc: PrintFileStreams, doc: "Shows all file streams"];
Commander.Register[key: "LRUChain", proc: PrintLRUChain, doc: "Shows FS cache lru chain"];
Commander.Register[key: "LRUInfo", proc: PrintLRUInfo, doc: "Shows FS cache lru statistics"];
Commander.Register[key: "LRUFlush", proc: LRUFlush, doc: "Flushes GNames from cache lru"];
Commander.Register[key: "ForceClose", proc: ForceClose, doc: "Closes all FS.OpenFiles for an FName"];
END;
END.