-- ParseObjectDirs.mesa
-- M. D. Schroeder, February 8, 1983 8:42 am
DIRECTORY
CIFS USING [Error, Reset],
FileIO USING [Open, OpenFailed],
IO USING [Close, EndOf, Error, GetRope, int, PutF, PutRope, real, STREAM,
UnsafeBlock, UnsafeGetBlock],
ObjectDirDefs USING [ObjectType],
ObjectDirXDefs,
Process USING [Detach],
Rope USING [Cat, Equal, ROPE],
ViewerIO USING [CreateViewerStreams],
VMDefs USING [PageIndex, PageNumber, pageSize, pageByteSize];
ParseObjectDirs: PROGRAM
IMPORTS CIFS, FileIO, IO, Process, Rope, ViewerIO =
BEGIN
ObjectCount: TYPE = CARDINAL;
ObjDirPageSpace: TYPE = [0..255];
DirData: TYPE = RECORD[ SELECT freedom: * --w0,b15-- FROM
free => [ next: VMDefs.PageIndex,--w0,b[7..0]--
dopc: ObjectDirXDefs.DOPC --w[1..2]-- ],
used => [ type: ObjectDirDefs.ObjectType,--w0,b[14..11]--
word: VMDefs.PageIndex,--w0,b[7..0]--
page: VMDefs.PageNumber,--w1--
count: ObjectCount --w2-- ],
ENDCASE];
DirPageHeader: TYPE = RECORD[ nextFreePage: ObjDirPageSpace,
nextFreeIndex: VMDefs.PageIndex ];
entriesPerPage: CARDINAL =
(VMDefs.pageSize-SIZE[DirPageHeader])/SIZE[DirData];
DirIndex: TYPE = [ 0 .. entriesPerPage );
-- NOTE: DirIndex values must fit in the "index" field of an object number --
DirPage: TYPE = RECORD[ header: DirPageHeader,
data: ARRAY DirIndex OF DirData ];
CountsIndex: TYPE = [0 .. 999);
Counts: TYPE = ARRAY CountsIndex OF INT ← ALL[0];
DoIt: PROCEDURE =
BEGIN
in, out: IO.STREAM;
server, total: REF Counts;
dirPage: DirPage;
dirPagePtr: LONG POINTER = @dirPage;
serverName: Rope.ROPE;
grandNum, grandProd: INT ← 0;
total ← NEW [Counts];
[in, out] ← ViewerIO.CreateViewerStreams[name: "ParseObjectDirs"];
DO
server ← NEW [Counts];
out.PutF["\n\nServer name: "];
serverName ← in.GetRope[ ! IO.Error => EXIT ];
IF Rope.Equal[serverName, "*"]
THEN BEGIN
out.PutRope["\n\n\n\nTotals for all servers\n\n"];
FOR i: CountsIndex IN CountsIndex DO
IF total[i] # 0 THEN out.PutF["%g %g\n", IO.int[i], IO.int[total[i]]];
ENDLOOP;
IF grandNum#0 THEN
out.PutF["\nmessage bodies: %g, ave. references: %3.2f",
IO.int[grandNum], IO.real[REAL[grandProd]/REAL[grandNum]]];
END
ELSE BEGIN
num, prod: INT ← 0;
objectDirName: Rope.ROPE = Rope.Cat["/", serverName, "/Heap.ObjectDir"];
file: IO.STREAM;
--Parse the file--
CIFS.Reset[objectDirName ! CIFS.Error => CHECKED {CONTINUE}];
file ← FileIO.Open[objectDirName ! FileIO.OpenFailed, CIFS.Error =>
CHECKED {out.PutRope["\nOpen failed"]; LOOP}];
UNTIL file.EndOf[] DO
IF file.UnsafeGetBlock[
block: IO.UnsafeBlock[dirPagePtr, 0, VMDefs.pageByteSize]]
# VMDefs.pageByteSize THEN ERROR;
FOR i: DirIndex IN DirIndex DO
WITH entry: dirPage.data[i] SELECT FROM
free => NULL;
used => IF entry.type = body THEN BEGIN
server[entry.count] ← server[entry.count] + 1;
total[entry.count] ← total[entry.count] + 1;
END;
ENDCASE => ERROR;
ENDLOOP;
ENDLOOP;
out.PutF["\n\n"];
FOR i: CountsIndex IN CountsIndex DO
IF server[i]#0 THEN BEGIN
out.PutF["%g %g\n", IO.int[i], IO.int[server[i]]];
IF i#0 THEN {num ← num + server[i]; prod ← prod + server[i]*i};
END;
ENDLOOP;
IF num#0 THEN
out.PutF["\nmessage bodies: %g, ave. references: %3.2f",
IO.int[num], IO.real[REAL[prod]/REAL[num]]];
grandNum ← grandNum + num;
grandProd ← grandProd + prod;
file.Close[];
END
ENDLOOP;
END;
Process.Detach[FORK DoIt];
END.