DIRECTORY Commander, CommandTool, File, FileBackdoor, IO, Real, RealFns, Rope USING[ROPE ], VM; HistoVAM: CEDAR PROGRAM IMPORTS Commander, CommandTool, File, FileBackdoor, IO, Real, RealFns, VM = BEGIN LogRunLenght: TYPE = [2..6]; Histogram: TYPE = RECORD[ counts: ARRAY LogRunLenght OF INT, freeSpace: ARRAY LogRunLenght OF INT, mixEndsAlloc: INT, mixEndsFree: INT, mixAdjMix: INT ] _ [ALL[0], ALL[0], 0, 0, 0]; computeHistogram: PROCEDURE[volume: File.Volume] RETURNS[ histogram: Histogram ] = TRUSTED BEGIN vamFile: File.Handle = File.Open[volume, FileBackdoor.GetRoot[volume, VAM].fp]; filePages: INT = File.Info[vamFile].size; fileWords: INT = File.wordsPerPage * filePages; limit: INT = FileBackdoor.GetVolumePages[volume].size; interval: VM.Interval = VM.Allocate[VM.PagesForWords[fileWords]]; buffer: LONG POINTER TO bufferObject _ VM.AddressForPageNumber[interval.page]; bufferObject: TYPE = RECORD[ SEQUENCE COMPUTED CARDINAL OF WORD ]; state: {alloc, free, mixed} _ alloc; all0: WORD = 000000B; all1: WORD = 177777B; updateHistogram: SAFE PROCEDURE = CHECKED BEGIN OPEN histogram; logRun _ MIN[ Real.Fix[RealFns.Log[4, runCount]], 6 ]; counts[logRun] _ counts[logRun]+1; freeSpace[logRun] _ freeSpace[logRun]+runCount; END; runCount: INT _ 0; -- Length of the current free run logRun: LogRunLenght; File.Read[file: vamFile, from: [0], to: LOOPHOLE[buffer], nPages: filePages]; BEGIN OPEN histogram; FOR i: INT _ 0, i+1 WHILE i < limit/16 DO SELECT state FROM alloc => { SELECT buffer[i] FROM all1 => NULL; all0 => { state _ free; runCount _ 16; }; ENDCASE => { state _ mixed; mixEndsAlloc _ mixEndsAlloc+1; }; }; free => { SELECT buffer[i] FROM all1 => { updateHistogram; state _ alloc; }; all0 => { runCount _ runCount+16; }; ENDCASE => { updateHistogram; state _ mixed; mixEndsFree _ mixEndsFree+1; }; }; mixed => { SELECT buffer[i] FROM all1 => { state _ alloc; }; all0 => { state _ free; runCount _ 16; }; ENDCASE => { mixAdjMix _ mixAdjMix+1; }; }; ENDCASE; ENDLOOP; IF state=free THEN { updateHistogram; }; VM.Free[interval]; END; END; HistoVAMProc: Commander.CommandProc = { argv: CommandTool.ArgumentVector; volume: File.Volume; volumeName: Rope.ROPE; histogram: Histogram; argv _ CommandTool.Parse[cmd: cmd ! CommandTool.Failed => { msg _ errorMsg; CONTINUE; }]; IF argv = NIL THEN GOTO Failed; IF argv.argc = 1 THEN { volume _ File.SystemVolume[]; volumeName _ File.GetVolumeName[volume]; } ELSE { IF argv.argc # 2 THEN GOTO Usage; volume _ File.FindVolumeFromName[argv[1]]; volumeName _ argv[1]; }; IF volume = NIL THEN GOTO NoVolume; histogram _ computeHistogram[volume]; cmd.out.PutF[ "Distribution of free page run sizes on Volume: %g:\n", IO.rope[volumeName] ]; cmd.out.PutF[ "\tSizes\t\tnRuns\t\tSpace\n" ]; cmd.out.PutF[ "\t1..15\t\t\t%g\t\t~8*%g\n", IO.int[histogram.mixEndsAlloc+histogram.mixEndsFree+histogram.mixAdjMix], IO.int[histogram.mixEndsAlloc+histogram.mixEndsFree+histogram.mixAdjMix] ]; cmd.out.PutF[ "\t16..63\t\t\t%g\t\t%g\n", IO.int[histogram.counts[2]], IO.int[histogram.freeSpace[2]] ]; cmd.out.PutF[ "\t64..255\t\t%g\t\t%g\n", IO.int[histogram.counts[3]], IO.int[histogram.freeSpace[3]] ]; cmd.out.PutF[ "\t256..1023\t\t%g\t\t%g\n", IO.int[histogram.counts[4]], IO.int[histogram.freeSpace[4]] ]; cmd.out.PutF[ "\t1024..4095\t\t%g\t\t%g\n", IO.int[histogram.counts[5]], IO.int[histogram.freeSpace[5]] ]; cmd.out.PutF[ "\t4096...\t\t\t%g\t\t%g\n", IO.int[histogram.counts[6]], IO.int[histogram.freeSpace[6]] ]; EXITS Failed => RETURN[$Failure, msg]; Usage => RETURN[$Failure, " Usage: ShowVAM volumename\n"]; NoVolume => RETURN[$Failure, " No such volume\n"]; }; Commander.Register[key: "HistoVAM", proc: HistoVAMProc, doc: "Show a histogram of free run lenghts in the VAM (volume allocation map) of the given logical volume (SystemVolume if omitted)"]; END. ήHistoVAM.mesa Hauser, May 13, 1985 12:58:13 pm PDT Compute and print a logarithmic histogram of the sizes and numbers of free blocks on a logical volume. Proceed with an FSM analysis of the VAM. Sixteen bit blocks containing both 0s and 1s are counted as "Mixed", and are distinguished as to whether they follow a free block, an allocated block or a mixed block. As a result, the computed lenght of any particular run may be up to 30 blocks shorter than it really is. [cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL] Hauser, March 17, 1985 3:55:59 pm PST Created from ShowVAM changes to: HistoVAM, HistoVAMProc, DIRECTORY, state, BEGIN Hauser, March 18, 1985 3:51:08 pm PST Clean up a few types. Κ6˜šœ ™ Icode™$—K™gJ˜šΟk ˜ J˜ J˜ J˜J˜ J˜J˜J˜Jšœœœ˜Jšœ˜—J˜šœ œ˜Jšœ@œ˜K—J˜š˜J˜Jšœœ ˜šœ  œ˜Jšœœœœ˜#Jšœ œœœ˜&Jšœœ˜Jšœ œ˜Jšœ ˜Jšœœœ˜—šΟbœ œœ˜[Jš˜JšœFœ˜OJšœ œ˜)Jšœ œ!˜/J˜7Jšœ œ œ œ˜AJš œœœœœ%˜NJšœœœœœœœœ˜CJ˜$J˜J˜šœœ œ˜!š ˜ Jšœ ˜Jšœ œ*˜6J˜"J˜/—Jšœ˜—Jšœ œ(˜5J˜Jšœ(œ˜MJšœœ ˜J™Όšœœ œ˜)šœ˜šœ ˜ šœ ˜J˜ šœ ˜ J˜ J˜Jšœ˜—šœ˜ J˜J˜Jšœ˜——Jšœ˜—šœ ˜ šœ ˜šœ ˜ J˜J˜Jšœ˜—šœ ˜ J˜Jšœ˜—šœ˜ J˜J˜J˜Jšœ˜——Jšœ˜—šœ ˜ šœ ˜šœ ˜ J˜Jšœ˜—šœ ˜ J˜ J˜Jšœ˜—šœ˜ J˜Jšœ˜——Jšœ˜—Jšœ˜——Jšœ˜šœ œ˜J˜Jšœ˜—Jšœ˜Jšœ˜Jšœ˜—J˜J˜•StartOfExpansionL -- [cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL]šž œ˜'JšœΠckG™HJšœ!˜!Jšœ˜Jšœœ˜J˜šœ!˜!Icode1šœ+œ˜8—Jšœœœœ˜šœœ˜Jšœ˜Jšœ(˜(J˜—šœœ˜Jšœœœ˜!Jšœ*˜*Jšœ˜J˜—Jšœ œœœ ˜#Jšœ%˜%Jšœ\˜\J˜.JšœΑ˜ΑJšœh˜hJšœg˜gJšœi˜iJšœj˜jJšœi˜iš˜Lšœ œ˜ Lšœ œ-˜