--LTScavengeImpl.mesa
--Created by
--   JFung.PASA	  		29-Sep-83 16:16:16
--	Modified version from VolumeInitImplA.mesa
--last edited by JFung.PASA	 4-Sep-84 15:34:24


DIRECTORY
     Cursor,
     Environment,
     File,
     Format,
     LispToolOps,
     OthelloDefs,
     PhysicalVolume,
     Process,
     Put,
     Scavenger,
     Space,
     Volume;



LTScavengeImpl: PROGRAM
     IMPORTS
          Cursor, File, LispToolOps, OthelloDefs, Process, Put,
          Scavenger, Space, Volume

     EXPORTS LispToolOps

     SHARES File =

     --BEGIN OPEN ILT: LispToolOps, OthelloDefs, OthelloOps;
     BEGIN OPEN ILT: LispToolOps;

     debug: BOOLEAN ← FALSE;

     ScavengeProc: PUBLIC PROCEDURE [vName: LONG STRING] =
          BEGIN
          buffer: LONG POINTER TO ARRAY [0..Environment.wordsPerPage) OF
               UNSPECIFIED ← NIL;
          convert: BOOLEAN ← FALSE;
          logFile: File.File;
          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
                         [] ← Space.CopyIn[buffer, [logFile, logPage, 1]];
                         logPage ← logPage + 1;
                         logWd ← 0;
                         END;
                    p↑ ← buffer[logWd];
                    p ← p + 1;
                    c ← c - 1;
                    logWd ← logWd + 1;
                    ENDLOOP
               END;  -- GetWds



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

               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];


               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, volumeID]].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 debug THEN {
               Put.Line[ILT.toolData.fileSW, "volumeOpened..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          IF ~volumeOpen THEN RETURN;

          --MyNameIs[myNameIs: "Scavenge"L, myHelpIs: "Scavenge Logical Volume"L];

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

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

          Put.Text[ILT.toolData.fileSW, " Scavenging..."L];
          Cursor.Set[hourGlass];

          BEGIN
          ENABLE
               Scavenger.Error =>
                    IF error = needsConversion AND ~convert THEN
                         IF (convert ← OthelloDefs.Yes[
                                   "That volume is not in the current format. Do you want to convert it? "L])
                              THEN {OthelloDefs.Confirm[twice]; RETRY}
                         ELSE OthelloDefs.AbortingCommand["Volume cannot be scavenged"L];

          logFile ← Scavenger.Scavenge[volumeID, volumeID, safeRepair, convert];
          Put.Line[ILT.toolData.fileSW, "Done"L];
          
          END;
	  
	  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]];
               };
          buffer ← Space.ScratchMap[1];

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

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

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

     END.....