-- Copyright (C) 1983  by Xerox Corporation. All rights reserved. 
-- NameServerInfo.mesa, HGM, 23-Sep-83  0:17:40

DIRECTORY
  Ascii USING [CR],
  Format USING [LongNumber, Number],
  Process USING [Yield],
  Put USING [Line, Text],
  String USING [AppendChar, AppendDecimal, AppendLongDecimal, AppendString],
  Time USING [AppendCurrent],
  Window USING [Handle],

  NameServerDefs USING [
    CacheEntry, EnumerateCache,
    statVers, statSend, statName, statAddress, statConst, statBusy, statHits,
    statMisses, statNone, statFile, statMsScanningFile],
  PupDefs USING [AppendPupAddress],
  Stats USING [StatGetCounter],
  
  OthelloDefs USING [CommandProcessor, IndexTooLarge, MyNameIs, RegisterCommandProc];

NameServerInfo: PROGRAM
  IMPORTS
    Format, Process, Time, Put, String,
    NameServerDefs, PupDefs, Stats,
    OthelloDefs =
  BEGIN

  PrintNameInfo: PUBLIC PROCEDURE [wh: Window.Handle] =
    BEGIN OPEN NameServerDefs, Stats;
    PrintHeader[wh, "Name Server Statistics:"L];
    PrintMaybe[wh, "Directory Version requests"L, StatGetCounter[statVers]];
    PrintMaybe[wh, "Directories sent"L, StatGetCounter[statSend]];
    PrintMaybe[wh, "Name Lookup requests"L, StatGetCounter[statName]];
    PrintMaybe[wh, "Address Lookup requests"L, StatGetCounter[statAddress]];
    PrintMaybe[wh, "Name Lookup constants"L, StatGetCounter[statConst]];
    PrintMaybe[
      wh, "Requests while Name/Address Lookup server was Busy"L, StatGetCounter[
      statBusy]];
    PrintMaybe[wh, "Hits in Name Lookup cache"L, StatGetCounter[statHits]];
    PrintMaybe[
      wh, "Misses found in Name Lookup cache"L, StatGetCounter[statMisses]];
    PrintMaybe[wh, "Name Lookup cache misses"L, StatGetCounter[statNone]];
    PrintMaybe[wh, "Name Lookup file searches"L, StatGetCounter[statFile]];
    IF StatGetCounter[statFile] # 0 THEN
      PrintMaybe[
        wh, "Average time (ms) to search file"L,
        StatGetCounter[statMsScanningFile]/StatGetCounter[statFile]];
    END;

  PrintMaybe: PROCEDURE [wh: Window.Handle, s: STRING, n: LONG INTEGER] =
    BEGIN
    temp: STRING = [200];
    IF n = 0 THEN RETURN;
    String.AppendString[temp, s];
    String.AppendString[temp, ": "L];
    String.AppendLongDecimal[temp, n];
    String.AppendChar[temp, Ascii.CR];
    Put.Text[wh, temp];
    END;

  PrintNameServerCache: PROCEDURE [wh: Window.Handle] =
    BEGIN
    size: CARDINAL ← 0;
    PrintOne: PROCEDURE [ce: NameServerDefs.CacheEntry] =
      BEGIN
      Append: PROCEDURE [s: LONG STRING, clientData: LONG POINTER] =
        BEGIN String.AppendString[temp, s]; END;
      temp: STRING = [400];  -- GrapevineRServer is > 200
      size ← size + ce.size;
      Format.LongNumber[Append, ce.count, [10, FALSE, TRUE, 6]];
      Format.Number[Append, ce.sequence, [10, FALSE, TRUE, 5]];
      Format.Number[Append, ce.size, [10, FALSE, TRUE, 5]];
      String.AppendString[temp, "  "L];
      IF LENGTH[ce.names] = 0 THEN String.AppendChar[temp, '?]
      ELSE
        FOR i: CARDINAL IN [0..LENGTH[ce.names]) DO
          IF i # 0 THEN String.AppendString[temp, ", "L];
	  String.AppendString[temp, ce.names[i]];
	  ENDLOOP;
      String.AppendString[temp, " <=> "L];
      IF LENGTH[ce.addrs] = 0 THEN String.AppendChar[temp, '?]
      ELSE
        FOR i: CARDINAL IN [0..LENGTH[ce.addrs]) DO
          IF i # 0 THEN String.AppendString[temp, ", "L];
          PupDefs.AppendPupAddress[temp, ce.addrs[i]];
          ENDLOOP;
      String.AppendChar[temp, Ascii.CR];
      Put.Text[wh, temp];
      DoSomeYields[];
      END;
    PrintHeader[wh, "Cache for Name Lookup Server:"L];
    Put.Line[wh, " Count  Seq  size Name(s) <=> Address(es)"L];
    NameServerDefs.EnumerateCache[PrintOne];
    IF size = 0 THEN Put.Line[wh, "The cache is empty."L]
    ELSE
      BEGIN
      temp: STRING = [200];
      String.AppendString[temp, "There are "L];
      String.AppendDecimal[temp, size];
      String.AppendString[temp, " words in use by the cache."L];
      String.AppendChar[temp, Ascii.CR];
      Put.Text[wh, temp];
      END;
    END;

  PrintHeader: PROCEDURE [wh: Window.Handle, s: STRING] =
    BEGIN
    temp: STRING = [200];
    Time.AppendCurrent[temp];
    String.AppendString[temp, "  "L];
    String.AppendString[temp, s];
    String.AppendChar[temp, Ascii.CR];
    Put.Text[wh, temp];
    END;

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


  Commands: PROC [index: CARDINAL] =
    BEGIN
    SELECT index FROM
      0 =>
        BEGIN
        OthelloDefs.MyNameIs[
	  myNameIs: "Cache Info"L,
	  myHelpIs: "Print Summary Info of Pup Name Lookup Cache"L];
	PrintNameInfo[NIL];
	END;
      1 =>
        BEGIN
        OthelloDefs.MyNameIs[
	  myNameIs: "Cache Contents"L,
	  myHelpIs: "Print Contents of Pup Name Lookup Cache"L];
	PrintNameServerCache[NIL];
	END;
      ENDCASE => OthelloDefs.IndexTooLarge;
    END;
   
  commandProcessor: OthelloDefs.CommandProcessor ← [Commands];
  OthelloDefs.RegisterCommandProc[@commandProcessor];
  END.