<> <> 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.ROPE _ NIL; 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; <> 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. <<>>