RoundTripDriver.mesa
Copyright Ó 1992 by Xerox Corporation. All rights reserved.
Last tweaked by Mike Spreitzer on October 31, 1990 11:22 am PST
Willie-s, April 22, 1992 11:10 am PDT
DIRECTORY BasicTime, Commander, CommanderOps, Convert, Histograms, HistogramsOut, HistogramsViewing, IO, NetworkName, NetworkStream, Process, Rope;
RoundTripDriver: CEDAR PROGRAM
IMPORTS BasicTime, Commander, CommanderOps, Convert, Histograms, HistogramsOut, HistogramsViewing, IO, NetworkName, NetworkStream, Process
=
BEGIN
Time: TYPE ~ RECORD [s, us: INT];
minTime: REAL ¬ -3.0;
maxTime: REAL ¬ 30.0;
dTime: REAL ¬ 0.05;
dataTimeout: INT ¬ 10D3;
unixOrg: BasicTime.GMT ~ BasicTime.Pack[[year: 1970, month: January, day: 1, hour: 0, minute: 0, second: 0, zone: 0, dst: no]];
Probe: Commander.CommandProc ~ {
argv: CommanderOps.ArgumentVector ~ CommanderOps.Parse[cmd];
nTests: INT ¬ 50;
msPause: INT ¬ 500;
toHost, fromHost: IO.STREAM ¬ NIL;
rn: REF INT ¬ NEW [INT ¬ 0];
doer: PROCESS ¬ NIL;
PutCard: PROC [c: CARD] ~ {PutShort[c/10000H]; PutShort[c MOD 10000H]};
PutShort: PROC [c: CARDINAL] ~ {
toHost.PutChar[VAL[c/100H]];
toHost.PutChar[VAL[c MOD 100H]]};
IF argv.argc<1 OR argv.argc>4 THEN RETURN [$Failure, "Usage: RoundTripDriver <arpa host name or address> [<number of tests> [<ms between tests>]]"];
IF argv.argc > 2 THEN nTests ¬ Convert.IntFromRope[argv[2]];
IF argv.argc > 3 THEN msPause ¬ Convert.IntFromRope[argv[3]];
cmd.out.PutF["Probing %g %g times, %g milliseconds between probes.\n", [rope[argv[1]]], [integer[nTests]], [integer[msPause]] ];
{ENABLE {
NetworkStream.Error => CommanderOps.Failed[IO.PutFR["NetworkStream.Error[LIST[%g, ..], %g]", [atom[codes.first]], [rope[msg]] ]];
NetworkName.Error => CommanderOps.Failed[IO.PutFR["NetworkName.Error[LIST[%g, ..], %g]", [atom[codes.first]], [rope[msg]] ]];
IO.Error => CommanderOps.Failed["IO.Error"];
NetworkStream.Timeout => CommanderOps.Failed[IO.PutFR1["No response within %g milliseconds", [integer[dataTimeout]] ]];
};
[fromHost, toHost] ¬ NetworkStream.CreateStreams[$ARPA, NetworkName.AddressFromName[$ARPA, argv[1], "58801"].addr, $basicStream, dataTimeout];
{ENABLE UNWIND => {
toHost.Close[TRUE !IO.Error => CONTINUE];
fromHost.Close[TRUE !IO.Error => CONTINUE]};
doer ¬ FORK Receive[fromHost, rn, cmd];
THROUGH [1..nTests] DO
start: Time ~ GetNow[];
PutCard[start.s];
PutCard[start.us];
NetworkStream.SendSoon[toHost, 0];
Process.PauseMsec[msPause];
ENDLOOP;
};
toHost.Close[!IO.Error => CONTINUE];
Process.PauseMsec[1000];
fromHost.Close[TRUE !IO.Error => CONTINUE];
TRUSTED {JOIN doer};
RETURN}};
Receive: PROC [fromHost: IO.STREAM, rn: REF INT, cmd: Commander.Handle] ~ {
GetShort: PROC RETURNS [CARDINAL] ~ {
hi: BYTE ~ fromHost.GetChar[].ORD;
RETURN [hi*100H + fromHost.GetChar[].ORD]};
GetCard: PROC RETURNS [CARD] ~ {
hi: CARDINAL ~ GetShort[]; RETURN [hi*10000H + GetShort[]]};
GetTime: PROC RETURNS [Time] ~ {
s: CARD ~ GetCard[];
us: CARD ~ GetCard[];
RETURN [[s, us]]};
upTime: Histograms.Histogram ~ Histograms.Create1D[factor: dTime, offset: minTime];
downTime: Histograms.Histogram ~ Histograms.Create1D[factor: dTime, offset: minTime];
roundTime: Histograms.Histogram ~ Histograms.Create1D[factor: dTime, offset: -1.0];
roundAvg, roundStd: REAL;
[] ¬ HistogramsViewing.Show[h: upTime, format: "%5.2f", width: 5, viewerInit: [name: "rtd: Term -> host seconds"], base: 2.0, updatePeriod: 5];
[] ¬ HistogramsViewing.Show[h: downTime, format: "%5.2f", width: 5, viewerInit: [name: "rtd: host -> Term seconds"], base: 2.0, updatePeriod: 5];
[] ¬ HistogramsViewing.Show[h: roundTime, format: "%5.2f", width: 5, viewerInit: [name: "rtd: Term -> host -> Term seconds"], base: 2.0, updatePeriod: 5];
DO ENABLE IO.Error, IO.EndOfStream => EXIT;
IF fromHost.EndOf[] THEN EXIT;
{start: Time ~ GetTime[];
mid: Time ~ GetTime[];
end: Time ~ GetNow[];
dUp: INT ~ Diff[mid, start];
dDn: INT ~ Diff[end, mid];
dRound: INT ~ dUp+dDn;
rn­ ¬ rn­+1;
cmd.out.PutChar['.];
upTime.IncrementTransformed[minTime, maxTime, dUp/1.0E6];
downTime.IncrementTransformed[minTime, maxTime, dDn/1.0E6];
roundTime.IncrementTransformed[-1.0, maxTime, dRound/1.0E6];
}ENDLOOP;
cmd.out.PutF1[" %g round trips done.\n", [integer[rn­]] ];
[avg: roundAvg, stdDev: roundStd] ¬ HistogramsOut.Stats1D[roundTime];
cmd.out.PutF["Round trip time: %g +- %g s.\n", [real[roundAvg]], [real[roundStd]] ];
RETURN};
GetNow: PROC RETURNS [Time] ~ {
egmt: BasicTime.ExtendedGMT ~ BasicTime.ExtendedNow[];
RETURN [[BasicTime.Period[from: unixOrg, to: egmt.gmt], egmt.usecs]]};
Diff: PROC [a, b: Time] RETURNS [d: INT] ~ {
d ¬ (a.s-b.s)*1D6 + (a.us-b.us);
RETURN};
Commander.Register["RoundTripDriver", Probe, "<arpa host address> [<number of tests> [<ms between tests>]]"];
END.