-- File: StatsPrint.mesa, Last Edit by JGS on February 7, 1980 10:48 AM

-- Copyright Xerox Corporation 1979, 1980

DIRECTORY
IODefs: FROM "IODefs" USING [CR, WriteChar, WriteLine, WriteString],
StringDefs: FROM "StringDefs" USING [AppendLongNumber],
StatsDefs: FROM "StatsDefs" USING [StatCounterIndex],
StatsPrivateDefs: FROM "StatsPrivateDefs" USING [statText];

StatsPrint: MONITOR
IMPORTS IODefs, StringDefs, StatsPrivateDefs
EXPORTS StatsPrivateDefs =
BEGIN OPEN StatsDefs;

statText: POINTER TO ARRAY StatCounterIndex OF STRING ← @StatsPrivateDefs.sta
tText;

-- print
out nonZero slots in table
StatPrintCounters: PUBLIC PROCEDURE [
num: POINTER TO ARRAY StatCounterIndex OF LONG CARDINAL] =
BEGIN
i: StatCounterIndex;
t: LONG CARDINAL;
FOR i IN StatCounterIndex DO
t ← num↑[i];
IF t#0 THEN StatPrintLine[t,statText[i]];
ENDLOOP;
StatP
rintGoodies[num];
END;

-- print one line
StatPrintLine: PROCEDURE [num: LONG CARDINAL, text: STRING] =
BEGIN OPEN IODefs;
s: STRING ← [20];
StringDefs.AppendLongNumber[s,num,10];
THROUGH [s.length..10) DO WriteChar[’ ]; ENDLOOP;
WriteString[s];
WriteChar[’ ];
IF text#NIL THEN WriteLine[text] ELSE WriteChar[CR];
END;
-- print out various things that arn’t counted directly - like bits/sec
-- watch out for overflow - 16 bits, or even 32 is just not enough


StatPrintGoodies: PROCEDURE [
num: POINTER TO ARRAY StatCounterIndex OF LONG CARDINAL] =
BEGIN
temp: LONG CARDINAL;
ms: LONG CARDINAL = num[statTime];
sec: LONG CARDINAL = num[statSeconds];

IF ms=0 AND sec=0 THEN RETURN; -- divide by zero

-- Ethernet Bandwidth
IF (temp←num[statEtherWordsLocal])#0 THEN
StatPrintLine[WordsPerSecond[temp,ms,sec],"Ether Bits/Sec Locally"L];
IF (temp←num[statEtherWordsReceived])#0 THEN
StatPrintLine[WordsPerSecond[temp,ms,sec],"Ether Bits/Sec In"L];
IF (temp←num[statEtherWordsSent])#0 THEN
StatPrintLine[WordsPerSecond[temp,ms,sec],"Ether Bits/Sec Out"L];

-- Data Bandwidth
IF (temp←num[statDataBytesReceived])#0 THEN
StatPrintLine[BytesPerSecond[temp,ms,sec],"Data Bits/Sec In"L];
IF (temp←num[statDataBytesSent])#0 THEN
StatPrintLine[BytesPerSecond[temp,ms,sec],"Data Bits/Sec Out"L];

-- Retransmission rate
IF num[statDataPacketsRetransmitted]#0 THEN
BEGIN
temp ← Yetch[num[statDataPacketsRetransmitted],num[statDataPacketsSent]];
StatPrintLine[temp,"Retransmissions per 1000"L];
END;
IF num[statDataPacketsReceivedAgain]#0 THEN
BEGIN
temp ← Yetch[num[statDataPacketsReceivedAgain],num[statDataPacketsReceived]];
StatPrintLine[temp,"Duplicates per 1000"L];
END;

-- Packets/Ack
IF num[statAcksReceived]#0 AND num[statDataPacketsSent]#0 THEN
BEGIN
temp ← Yetch[num[statDataPacketsSent],num[statAcksReceived]];
StatPrintLine[temp,"Packets sent per 1000 Acks received"L];
END;
IF num[statAcksSent]#0 AND num[statDataPacketsReceived]#0 THEN
BEGIN
temp ← Yetch[num[statDataPacketsReceived],num[statAcksSent]];
StatPrintLine[temp,"Packets received per 1000 Acks sent"L];
END;

-- Time/Packet
temp ← num[statDataPacketsSent]+num[statDataPacketsReceived];
IF temp#0 THEN
BEGIN
temp ← MicroSecPerPacket[ms,sec,temp];
StatPrintLine[temp,"MicroSec/DataPacket"L];
END;
temp ← num[statPupReceived];
IF temp#0 THEN
BEGIN
temp ← MicroSecPerPacket[ms,sec,temp];
StatPrintLine[temp,"MicroSec/Pup Received"L];
END;
temp ← num[statPupSent]+num[statPupBroadcast];
IF temp#0 THEN
BEGIN
temp ← MicroSecPerPacket[ms,sec,temp];
StatPrintLine[temp,"MicroSec/Pup Sent"L];
END;

END;

-- 32 bits of miliseconds is almost 50 (49.71) days or almost 1200 (1193) hours

WordsPerSecond: PROCEDURE [words, ms, sec: LONG CARDINAL] RETURNS [result: LONG CARDINAL] =
BEGIN
IF words>bigestNum/16 THEN result ← BitsPerSecond[words,ms/16,sec/16]
ELSE result ← BitsPerSecond[words*16,ms,sec];
END;

BytesPerSecond: PROCEDURE [bytes, ms, sec: LONG CARDINAL] RETURNS [result: LONG CARDINAL] =
BEGIN
IF bytes>bigestNum/8 THEN result ← BitsPerSecond[bytes,ms/8,sec/8]
ELSE result ← BitsPerSecond[bytes*8,ms,sec];
END;

BitsPerSecond: PROCEDURE [bits, ms, sec: LONG CARDINAL] RETURNS [result: LONG CARDINAL] =
BEGIN
IF sec>bigestNum/1000 THEN result ← bits/sec
ELSE result ← Yetch[bits,ms];
END;

MicroSecPerPacket: PROCEDURE [ms, sec, packets: LONG CARDINAL] RETURNS [result: LONG CARDINAL] =
BEGIN
IF sec>bigestNum/1000 THEN result ← Yetch[sec,packets/1000]
ELSE result ← Yetch[ms,packets];
END;

-- Do right thing to avoid overflow, 32 bits is not enough
-- RETURN[a*1000/b]
Yetch: PROCEDURE [a, b: LONG CARDINAL] RETURNS [t: LONG CARDINAL] =
BEGIN
-- 26411 from Compiler
IF a<x32 THEN t ← (a*1000)/b ELSE
IF a<x320 THEN t ← (a*100)/(b/10) ELSE
IF a<x3200 THEN t ← (a*10)/(b/100) ELSE
t ← a/(b/1000);
IF FALSE THEN
SELECT a FROM -- 2↑31 is about 2,000,000,000
<x32 => t ← (a*1000)/b;
<x320 => t ← (a*100)/(b/10);
<x3200 => t ← (a*10)/(b/100);
ENDCASE => t ← a/(b/1000);
END;

bigestNum: LONG CARDINAL = 2000000000; -- about 31 bits

x32: LONG CARDINAL = 2048000; -- 32*64000
x320: LONG CARDINAL = 20480000; -- 320*64000
x3200: LONG CARDINAL = 204800000; -- 3200*64000


-- initialization
END.