--ILTScavengeImpl.mesa
--Created by
--   JFung.PASA	  	29-Sep-83 16:16:16
--	Modified version from VolumeInitImplA.mesa

--last edited by
--   JFung.PASA	   	19-Dec-83 16:56:57



DIRECTORY
     Cursor USING [Set],
     Environment,
     File,
     Format,
     LispToolOps USING [Data, DataHandle, toolData, GetVolumeID],
     OthelloDefs,
     OthelloOps,
     PhysicalVolume,
     Process,
     Put,
     Scavenger,
     Space,
     Transaction,
     Volume;



ILTScavengeImpl: PROGRAM
     IMPORTS Cursor, File, LispToolOps, Process, Put, 
     Scavenger, Space, Transaction, Volume

     EXPORTS LispToolOps

     SHARES File =

     BEGIN OPEN ILT: LispToolOps, OthelloDefs, OthelloOps;
     
     debug: BOOLEAN ← FALSE;
     scavLogSp: Space.Handle = Space.Create[1, Space.virtualMemory];


     ScavengeProc: PUBLIC PROCEDURE [vName: LONG STRING] =
          BEGIN
          logFile: File.Capability;
          logPage: File.PageNumber ← 0;
          logWd: CARDINAL ← Environment.wordsPerPage;
          volumeID: Volume.ID ← Volume.nullID;
          volumeOpen: BOOLEAN ← FALSE;


          GetWds: PROC [p: POINTER, c: CARDINAL] =
               BEGIN
               IF debug THEN {
                    Put.Line[ILT.toolData.fileSW, "Enter GetWds..."L];
                    --Process.Pause[Process.SecondsToTicks[5]];
                    };

               WHILE c # 0 DO
                    IF logWd = Environment.wordsPerPage THEN
                         BEGIN
                         IF logPage # 0 THEN {  --Put.Line[ILT.toolData.fileSW, "Space.Unmap..."L];
                              --Process.Pause[Process.SecondsToTicks[5]];
                              Space.Unmap[scavLogSp]; };

                         --Put.Line[ILT.toolData.fileSW, "Space.Map..."L];
                         --Process.Pause[Process.SecondsToTicks[5]];
                         Space.Map[scavLogSp, [logFile, logPage]];
                         logPage ← logPage + 1;
                         logWd ← 0;
                         END;

                    p↑ ← (Space.LongPointer[scavLogSp] + logWd)↑;
                    p ← p + 1;
                    c ← c - 1;
                    logWd ← logWd + 1;
                    ENDLOOP;
               END;  -- GetWds



          DisplayScavLog: PROC =
               BEGIN
               fileCount: LONG CARDINAL;
               problems: BOOLEAN ← FALSE;

               --BEGIN
               hd: Scavenger.Header;

               GetWds[@hd, SIZE[Scavenger.Header]];
               Put.Text[ILT.toolData.fileSW, " volume"L];
               IF ~hd.repaired THEN Put.Text[ILT.toolData.fileSW, " not"L];
               Put.Text[ILT.toolData.fileSW, " repaired, log file"L];
               IF hd.incomplete THEN Put.Text[ILT.toolData.fileSW, " not"L];
               Put.Line[ILT.toolData.fileSW, " complete "L];
               fileCount ← hd.numberOfFiles;
               Put.Text[ILT.toolData.fileSW, " "L];
               Put.LongNumber[
                    ILT.toolData.fileSW, fileCount, Format.DecimalFormat];
               Put.Line[ILT.toolData.fileSW, " files on volume"L];
               --END;


               WHILE fileCount # 0 DO
                    OpenID: TYPE = ARRAY [0..SIZE[File.ID]) OF CARDINAL;
                    fe: Scavenger.FileEntry;

                    GetWds[@fe, SIZE[Scavenger.FileEntry]];

                    THROUGH [0..fe.numberOfProblems) DO
                         fp: Scavenger.Problem;

                         GetWds[@fp, SIZE[Scavenger.Problem]];
                         Put.Char[ILT.toolData.fileSW, '[];
                         Process.Pause[Process.SecondsToTicks[5]];
                         FOR i: CARDINAL IN [0..SIZE[File.ID] - 1) DO
                              Put.Octal[
                                   ILT.toolData.fileSW, LOOPHOLE[fe.file, OpenID][
                                   i]];
                              Put.Text[ILT.toolData.fileSW, ", "L];
                              ENDLOOP;

                         Put.Octal[
                              ILT.toolData.fileSW, LOOPHOLE[fe.file, OpenID][
                              SIZE[File.ID] - 1]];
                         Put.Text[ILT.toolData.fileSW, "] type = "L];

                         BEGIN
                         ENABLE File.Unknown => GOTO noType;
                         f: File.Type = File.GetAttributes[
                              [fe.file, File.read]].type;
                         Put.LongDecimal[
                              ILT.toolData.fileSW, LONG[LOOPHOLE[f, CARDINAL]]];
                         EXITS noType => Put.Text[ILT.toolData.fileSW, "unknown"L];
                         END;

                         Put.Text[ILT.toolData.fileSW, "; "L];
                         WITH fp SELECT FROM
                              unreadable =>
                                   BEGIN
                                   Put.Text[
                                        ILT.toolData.fileSW,
                                        "unreadable pages ["L];
                                   Put.LongDecimal[ILT.toolData.fileSW, first];
                                   Put.Text[ILT.toolData.fileSW, ".."L];
                                   Put.LongDecimal[
                                        ILT.toolData.fileSW, first + count];
                                   Put.Line[ILT.toolData.fileSW, ")"L];
                                   END;
                              missing =>
                                   BEGIN
                                   Put.Text[
                                        ILT.toolData.fileSW, "missing pages ["L];
                                   Put.LongDecimal[ILT.toolData.fileSW, first];
                                   Put.Text[ILT.toolData.fileSW, ".."L];
                                   Put.LongDecimal[
                                        ILT.toolData.fileSW, first + count];
                                   Put.Line[ILT.toolData.fileSW, ")"L];
                                   END;
                              duplicate =>
                                   Put.Line[
                                        ILT.toolData.fileSW,
                                        "duplicate page found"L];
                              orphan =>
                                   Put.Line[
                                        ILT.toolData.fileSW, "orphan page found"L];
                              ENDCASE =>
                                   Put.Line[
                                        ILT.toolData.fileSW, "unknown problem"L];
                         IF debug THEN
                              Process.Pause[Process.SecondsToTicks[5]];
                         problems ← TRUE;
                         ENDLOOP;
                    fileCount ← fileCount - 1;
                    ENDLOOP;

               IF ~problems THEN
                    Put.Line[ILT.toolData.fileSW, " No problems found"L];
               IF debug THEN Process.Pause[Process.SecondsToTicks[5]];
               END;  --DisplayScavLog


          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Enter ScavengeProc..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               Put.LongString[ILT.toolData.fileSW, vName];
               Put.CR[ILT.toolData.fileSW];
               };

          [volumeID, volumeOpen] ← ILT.GetVolumeID[vName];

          IF ~volumeOpen THEN RETURN;


          Put.Text[ILT.toolData.fileSW, " Scavenging..."L];
	  --Cursor.Set[hourGlass];
	  
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Volume.Close..."L];
               --Process.Pause[Process.SecondsToTicks[5]];
               };

          Volume.Close[volumeID ! ANY => CONTINUE];

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "LimitPermissions..."L];
               --Process.Pause[Process.SecondsToTicks[5]];
               };

          logFile ← File.LimitPermissions[
               Scavenger.Scavenge[volumeID, volumeID, TRUE], File.read];
          Put.Line[ILT.toolData.fileSW, "Done"L];
	  --Cursor.Set[textPointer];
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Volume.Open..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          Volume.Open[volumeID];
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "DisplayScavLog..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          DisplayScavLog[
               ! UNWIND => {Space.Unmap[scavLogSp]; Volume.Close[volumeID]}];
          --	DisplayScavLog[];

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Unmap..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          Space.Unmap[scavLogSp];
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Volume.Close..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          Volume.Close[volumeID];
          END;  --ScavengeProc

     END.....