-- Copyright (C) 1983, 1985  by Xerox Corporation. All rights reserved. 
-- PupBootServerTool.mesa, HGM,  5-Sep-85 19:56:05
-- Please don't forget to update the herald...

DIRECTORY
  Format USING [],  -- Needed by Put.Date and such
  FormSW USING [
    ClientItemsProcType, ProcType, AllocateItemDescriptor, newLine, sameLine,
    Display, FindItem, CommandItem, BooleanItem, StringItem],
  Menu USING [Create, Handle, Instantiate, ItemObject, MCRType],
  MsgSW USING [Post],
  Process USING [Yield],
  Put USING [Char, CR, Date, Decimal, Line, LongNumber, Number, Text],
  Space USING [nullInterval],
  Time USING [Current],
  Tool USING [Create, MakeSWsProc, MakeMsgSW, MakeFileSW, MakeFormSW],
  ToolWindow USING [TransitionProcType],
  UserInput USING [GetDefaultWindow, UserAbort],
  Window USING [Handle, Place],

  Stats USING [StatGetCounter],
  BootServer USING [AppendBFN],
  BootServerDefs USING [
    PupBootServerOn, PupBootServerOff, StartProbingForBootFiles,
    StartLongRangeProbingForBootFiles, msg, slowBooteeHost, slosheeHost,
    slowBootFileName, slosheeFileName, running, slowBooting, probing, sloshing,
    statFileSent, statBootDir, statMicrocodeBooted, statFileSentSlow,
    statBootNew],
  BootServerFriends USING [BootFile, EnumerateBootTable, timeNotKnown];

PupBootServerTool: MONITOR
  IMPORTS
    Process, Time, FormSW, Menu, MsgSW, Put, Tool, UserInput, Stats,
    BootServer, BootServerDefs, BootServerFriends
  EXPORTS BootServerDefs =
  BEGIN

  form, log: PUBLIC Window.Handle ← NIL;

  Init: PROCEDURE =
    BEGIN
    herald: STRING = "Boot Server of  5-Sep-85 19:55:58"L;
    [] ← Tool.Create[
      name: herald, makeSWsProc: MakeSWs,
      clientTransition: ClientTransition, initialState: inactive];
    Menu.Instantiate[menu, UserInput.GetDefaultWindow[]];
    END;

  UpdatePicture: PUBLIC PROCEDURE =
    BEGIN
    IF form = NIL THEN RETURN;
    FormSW.FindItem[form, startIX].flags.invisible ← BootServerDefs.running;
    FormSW.FindItem[form, stopIX].flags.invisible ← ~BootServerDefs.running;
    FormSW.FindItem[form, probeIX].flags.invisible ← ~BootServerDefs.running;
    FormSW.FindItem[form, longIX].flags.invisible ← ~BootServerDefs.running;
    FormSW.FindItem[form, printIX].flags.invisible ← ~BootServerDefs.running;
    FormSW.Display[form];
    END;

  PrintBootInfo: PUBLIC PROCEDURE [wh: Window.Handle] =
    BEGIN
    PrintHeader[wh, "Boot Server Statistics:"L];
    PrintMaybe[
      wh, "Boot files sent"L, Stats.StatGetCounter[
      BootServerDefs.statFileSent]];
    PrintMaybe[
      wh, "Boot directory requests"L, Stats.StatGetCounter[
      BootServerDefs.statBootDir]];
    PrintMaybe[
      wh, "Microcode Boots requests"L, Stats.StatGetCounter[
      BootServerDefs.statMicrocodeBooted]];
    PrintMaybe[
      wh, "Slow boot files sent"L, Stats.StatGetCounter[
      BootServerDefs.statFileSentSlow]];
    PrintMaybe[
      wh, "New boot files retrieved"L, Stats.StatGetCounter[
      BootServerDefs.statBootNew]];
    END;

  PrintMaybe: PROCEDURE [wh: Window.Handle, s: STRING, n: LONG INTEGER] =
    BEGIN
    IF n = 0 THEN RETURN;
    Put.Text[wh, s];
    Put.Text[wh, ": "L];
    Put.LongNumber[wh, n, [10, FALSE, TRUE, 0]];
    Put.CR[wh];
    END;

  PrintBootFileTable: PROCEDURE [wh: Window.Handle] =
    BEGIN
    PrintOne: PROCEDURE [bf: BootServerFriends.BootFile] =
      BEGIN
      pages ← pages + bf.pages;
      IF bf.space # Space.nullInterval THEN pagesInVM ← pagesInVM + bf.pages;
      IF UserInput.UserAbort[wh] THEN RETURN;
      BEGIN
      temp: STRING = [30];
      BootServer.AppendBFN[temp, bf.code];
      FOR i: CARDINAL IN [temp.length..12) DO Put.Char[wh, ' ]; ENDLOOP;
      Put.Text[wh, temp];
      END;
      IF bf.space # Space.nullInterval THEN Put.Char[wh, '*] ELSE Put.Char[wh, ' ];
      Put.Number[wh, bf.pages, [10, FALSE, TRUE, 5]];
      Put.LongNumber[wh, bf.count, [10, FALSE, TRUE, 6]];
      IF bf.count = 0 THEN Put.Text[wh, "      "L]
      ELSE Put.LongNumber[wh, bf.ms/bf.count, [10, FALSE, TRUE, 6]];
      IF bf.inTransit THEN Put.Text[wh, "T "L] ELSE Put.Text[wh, "  "L];
      SELECT TRUE FROM
        bf.unknown => Put.Text[wh, "Not on this disk  "L];
        (bf.create = BootServerFriends.timeNotKnown) =>
          Put.Text[wh, "Unknown           "L];
        ENDCASE => Put.Date[wh, bf.create, dateTime];
      SELECT bf.machineType FROM
        alto => Put.Text[wh, " Alto    "L];
        d0 => Put.Text[wh, " D0      "L];
        dorado => Put.Text[wh, " Dorado  "L];
        dLion => Put.Text[wh, " DLion   "L];
        dLionTrident => Put.Text[wh, " DLionTri"L];
        dicentra => Put.Text[wh, " Dicentra"L];
        dove => Put.Text[wh, " Dove"L];
        other => Put.Text[wh, " Other"L];
        ENDCASE => Put.Text[wh, " ??      "L];
      SELECT bf.fileType FROM
        microcode => Put.Text[wh, " M"L];
        germ => Put.Text[wh, " G"L];
        boot => Put.Text[wh, " B"L];
        pup => Put.Text[wh, " P"L];
        ENDCASE => Put.Text[wh, " ?"L];
      Put.Text[wh, "  "L];
      Put.Text[wh, bf.fileName];
      Put.CR[wh];
      DoSomeYields[];
      END;
    pages, pagesInVM: CARDINAL ← 0;
    Put.CR[wh];
    PrintHeader[wh, "Boot File Table:"L];
    Put.Line[
      wh, "     Code      Pgs Count AvgMs      Create Time              FileName"L];
    BootServerFriends.EnumerateBootTable[PrintOne];
    IF pagesInVM # 0 THEN
      BEGIN
      Put.Decimal[wh, pagesInVM];
      Put.Text[wh, " out of "L];
      Put.Decimal[wh, pages];
      Put.Line[wh, " pages are mapped into VM."L];
      END;
    END;

  PrintHeader: PROCEDURE [wh: Window.Handle, s: STRING] =
    BEGIN
    Put.CR[wh];
    Put.Date[wh, Time.Current[], dateTime];
    Put.Text[wh, "  "L];
    Put.Line[wh, s];
    END;

  DoSomeYields: PROCEDURE =
    BEGIN THROUGH [0..100) DO Process.Yield[]; ENDLOOP; END;

  Start: FormSW.ProcType = BEGIN BootServerDefs.PupBootServerOn[]; END;

  Stop: FormSW.ProcType = BEGIN BootServerDefs.PupBootServerOff[]; END;

  ProbeCommand: FormSW.ProcType =
    BEGIN OPEN BootServerDefs;
    IF msg # NIL THEN
      SELECT TRUE FROM
        probing => MsgSW.Post[msg, "Already probing for new Boot files."L];
        sloshing => MsgSW.Post[msg, "Currently sloshing a new Boot file."L];
        ENDCASE => MsgSW.Post[msg, "Probing for new Boot files."L];
    StartProbingForBootFiles[];
    END;

  LongRangeProbeCommand: FormSW.ProcType =
    BEGIN OPEN BootServerDefs;
    IF msg # NIL THEN
      SELECT TRUE FROM
        probing => MsgSW.Post[msg, "Already probing for new Boot files."L];
        sloshing => MsgSW.Post[msg, "Currently sloshing a new Boot file."L];
        ENDCASE => MsgSW.Post[msg, "Probing for new Boot files."L];
    StartLongRangeProbingForBootFiles[];
    END;

  PrintInfo: FormSW.ProcType = BEGIN PrintBootInfo[log]; END;

  PrintTable: FormSW.ProcType = BEGIN PrintBootFileTable[log]; END;

  MakeSWs: Tool.MakeSWsProc =
    BEGIN
    BootServerDefs.msg ← Tool.MakeMsgSW[window: window, lines: 5];
    form ← Tool.MakeFormSW[window: window, formProc: MakeForm];
    log ← Tool.MakeFileSW[window: window, name: "BootServer.log$"L, allowTypeIn: FALSE];
    Menu.Instantiate[menu, log];
    END;

  menu: Menu.Handle = Menu.Create[DESCRIPTOR[items], "Booter", TRUE];
  items: ARRAY [0..1] OF Menu.ItemObject ← [["Info", DoMenu], ["Table", DoMenu]];

  infoMx: CARDINAL = 0;
  tableMx: CARDINAL = 1;

  DoMenu: Menu.MCRType =
    BEGIN
    IF window # log THEN window ← NIL;  -- Great window in the sky
    SELECT index FROM
      infoMx => PrintBootInfo[window];
      tableMx => PrintBootFileTable[window];
      ENDCASE => ERROR;
    END;

  startIX: CARDINAL = 0;
  stopIX: CARDINAL = 1;
  probeIX: CARDINAL = 2;
  longIX: CARDINAL = 3;
  printIX: CARDINAL = 6;
  MakeForm: FormSW.ClientItemsProcType =
    BEGIN OPEN BootServerDefs;
    booteePlace: Window.Place = [7*15, FormSW.sameLine];
    bootFilePlace: Window.Place = [7*35, FormSW.sameLine];
    nParams: CARDINAL = 13;
    items ← FormSW.AllocateItemDescriptor[nParams];
    items[0] ← FormSW.CommandItem[
      tag: "Start"L, proc: Start, place: FormSW.newLine, invisible: running];
    items[1] ← FormSW.CommandItem[
      tag: "Stop"L, proc: Stop, place: FormSW.newLine, invisible: ~running];
    items[2] ← FormSW.CommandItem[
      tag: "Probe"L, proc: ProbeCommand, invisible: ~running];
    items[3] ← FormSW.CommandItem[
      tag: "LongRangeProbe"L, proc: LongRangeProbeCommand, invisible: ~running];
    items[4] ← FormSW.BooleanItem[
      tag: "Probing"L, switch: @probing, readOnly: TRUE];
    items[5] ← FormSW.CommandItem[
      tag: "PrintInfo"L, proc: PrintInfo, place: FormSW.newLine];
    items[6] ← FormSW.CommandItem[
      tag: "PrintTable"L, proc: PrintTable, invisible: ~running];
    items[7] ← FormSW.BooleanItem[
      tag: "SlowBooting"L, switch: @slowBooting, place: FormSW.newLine,
      readOnly: TRUE];
    items[8] ← FormSW.StringItem[
      tag: "SlowBootee"L, string: @slowBooteeHost, place: booteePlace,
      readOnly: TRUE];
    items[9] ← FormSW.StringItem[
      tag: "SlowFile"L, string: @slowBootFileName, place: bootFilePlace,
      readOnly: TRUE];
    items[10] ← FormSW.BooleanItem[
      tag: "Sloshing"L, switch: @sloshing, place: FormSW.newLine, readOnly: TRUE];
    items[11] ← FormSW.StringItem[
      tag: "Sloshee"L, string: @slosheeHost, place: booteePlace, readOnly: TRUE];
    items[12] ← FormSW.StringItem[
      tag: "SloshFile"L, string: @slosheeFileName, place: bootFilePlace,
      readOnly: TRUE];
    RETURN[items, TRUE];
    END;

  ClientTransition: ToolWindow.TransitionProcType =
    BEGIN IF new = inactive THEN BootServerDefs.msg ← form ← log ← NIL; END;

  -- initialization

  Init[];
  END.