FlushUnneededTempFiles.mesa
last edited by Levin on November 21, 1982 10:32 am
DIRECTORY
CachedSpace USING [Desc],
Environment USING [wordsPerPage],
File
USING [
Capability, Delete, GetAttributes, GetSize, ID, nullID, PageCount, Permissions, Unknown],
Hierarchy USING [GetDescriptor],
Inline USING [LowHalf],
IO USING [int, Handle, NewLine, PutChar, PutF, PutRope],
KernelFile USING [GetRootFile],
PilotFileTypes USING [tTempFileList],
Rope USING [ROPE],
Space
USING [
CopyIn, Create, Delete, GetAttributes, Handle, LongPointer, Map, nullHandle,
PageCount, virtualMemory],
SpaceImplInternal USING [EnterSpace],
UserExec USING [CommandProc, Confirm, GetExecHandle, GetStreams, RegisterCommand],
Volume USING [systemID];
FlushUnneededTempFiles:
PROGRAM
IMPORTS
File, Hierarchy, Inline, IO, KernelFile, Space, SpaceImplInternal,
UserExec, Volume
SHARES File =
BEGIN
FlushTempFiles: UserExec.CommandProc =
TRUSTED {
out: IO.Handle;
tempFiles, recoverableFiles, tempPages, recoverablePages: INT ← 0;
CheckSpace:
PROC [space: Space.Handle] = {
IF Space.GetAttributes[space].mapped
THEN {
CheckIfThisFile:
PROC [file: File.Capability]
RETURNS [stop, zap:
BOOL ←
FALSE] = {
CheckBackingFile:
PROC = {
desc: CachedSpace.Desc;
validSpace, validSwapUnit: BOOL;
[validSpace, validSwapUnit] ← Hierarchy.GetDescriptor[@desc, LOOPHOLE[space]];
IF ~(validSpace OR validSwapUnit) THEN RETURN;
IF desc.window.file.fID = file.fID THEN stop ← zap ← TRUE;
};
SpaceImplInternal.EnterSpace[CheckBackingFile];
};
EnumerateTempFiles[CheckIfThisFile];
}
ELSE EnumerateChildren[space, CheckSpace];
};
GetBeforeStats:
PROC [file: File.Capability]
RETURNS [stop, zap:
BOOL ←
FALSE] = {
size: File.PageCount = File.GetSize[file ! File.Unknown => GO TO notInteresting];
IF File.GetAttributes[file].temporary
THEN {
tempFiles ← tempFiles + 1;
tempPages ← tempPages + size;
}
ELSE GO TO notInteresting;
EXITS
notInteresting => zap ← TRUE;
};
GetAfterStats:
PROC [file: File.Capability]
RETURNS [stop, zap:
BOOL ←
FALSE] = {
size: File.PageCount = File.GetSize[file ! File.Unknown => GO TO notAFile];
recoverableFiles ← recoverableFiles + 1;
recoverablePages ← recoverablePages + size;
};
DoOneFile:
PROC [file: File.Capability]
RETURNS [stop, zap:
BOOL ←
FALSE] = {
File.Delete[file ! File.Unknown => GO TO notAFile];
out.PutChar['#];
};
[out: out] ← UserExec.GetStreams[exec];
out.PutRope["Enumerating temp files..."];
EnumerateTempFiles[GetBeforeStats];
out.PutRope["enumerating spaces..."];
EnumerateChildren[Space.virtualMemory, CheckSpace];
out.PutRope["done\N"];
EnumerateTempFiles[GetAfterStats];
out.PutF[
"There are %g temporary files comprising %g total pages.\NOf these, %g can be deleted to recover %g pages.\N",
IO.int[tempFiles], IO.int[tempPages], IO.int[recoverableFiles], IO.int[recoverablePages]
];
IF recoverableFiles > 0
AND
UserExec.Confirm[msg: "Shall I delete them", exec: exec]
THEN {
out.PutRope["Deleting..."];
EnumerateTempFiles[DoOneFile];
out.NewLine[];
};
Cleanup[];
};
idsPerPage: NAT = Environment.wordsPerPage/SIZE[File.ID];
TempsPage:
TYPE =
MACHINE
DEPENDENT
RECORD [
ids: ARRAY [0..idsPerPage) OF File.ID,
fill: ARRAY [0..Environment.wordsPerPage-idsPerPage*SIZE[File.ID]) OF WORD
];
TempsFile: TYPE = RECORD [pages: SEQUENCE COMPUTED Space.PageCount OF TempsPage];
tempFile: File.Capability;
tempFilePages: File.PageCount;
tempsSpace: Space.Handle;
temps: LONG POINTER TO TempsFile ← NIL;
EnumerateTempFiles:
PROC [proc:
PROC [File.Capability]
RETURNS [stop, zap:
BOOL]] = {
IF temps =
NIL
THEN {
tempFile ← KernelFile.GetRootFile[PilotFileTypes.tTempFileList, Volume.systemID];
tempFilePages ← File.GetSize[tempFile];
tempsSpace ← Space.Create[size: Inline.LowHalf[tempFilePages], parent: Space.virtualMemory];
temps ← Space.LongPointer[tempsSpace];
We copy the temp file to avoid messing up Pilot. There is no danger of a race, but even
if there were, the subsequent checking would.
Space.Map[tempsSpace];
Space.CopyIn[tempsSpace, [tempFile, 0]];
};
FOR page: Space.PageCount
IN [0..tempFilePages)
DO
tempPage: LONG POINTER TO TempsPage = @temps.pages[page];
FOR i: [0..idsPerPage)
IN [0..idsPerPage)
DO
id: File.ID = tempPage.ids[i];
IF id ~= File.nullID
THEN {
stop, zap: BOOL;
[stop, zap] ← proc[[id, LAST[File.Permissions]]];
IF zap THEN tempPage.ids[i] ← File.nullID;
IF stop THEN EXIT;
};
ENDLOOP;
ENDLOOP;
};
Cleanup:
PROC = {
Space.Delete[tempsSpace];
temps ← NIL;
};
EnumerateChildren:
PROC [space: Space.Handle, proc:
PROC [Space.Handle]] = {
FOR child: Space.Handle ← Space.GetAttributes[space].lowestChild, Space.GetAttributes[child].nextSibling
UNTIL child = Space.nullHandle DO proc[child]; ENDLOOP;
};
UserExec.RegisterCommand[
name: "FlushUnneededTempFiles",
proc: FlushTempFiles,
briefDoc: "Eliminates unnecessary temporary files from the local disk."
];
[] ← FlushTempFiles[event: NIL, exec: UserExec.GetExecHandle[]];
END.