-- Copyright (C) 1983, 1985 by Xerox Corporation. All rights reserved. -- BSPTestTool.mesa, HGM, 25-Jun-85 3:14:48 -- Please don't forget to update the herald.... DIRECTORY FormSW USING [ ClientItemsProcType, ProcType, AllocateItemDescriptor, newLine, Display, FindItem, CommandItem, BooleanItem, StringItem, NumberItem], Heap USING [systemZone], MsgSW USING [Post], Process USING [Detach, Yield], Put USING [Char, CR, Text, Line, LongDecimal], String USING [AppendString], System USING [Pulses, GetClockPulses, PulsesToMicroseconds], Time USING [AppendCurrent, Current], Tool USING [Create, MakeSWsProc, MakeMsgSW, MakeFormSW, MakeFileSW], ToolWindow USING [TransitionProcType], Window USING [Handle], Stream USING [Handle, PutWord, PutBlock, SendNow, Delete], PupDefs USING [ AppendPupAddress, GetPupAddress, PupNameTrouble, PupPackageMake, PupPackageDestroy, SecondsToTocks], PupStream USING [PupByteStreamCreate, StreamClosing, CloseReason], PupTypes USING [PupAddress, bspTestSoc]; BSPTestTool: PROGRAM IMPORTS FormSW, Heap, MsgSW, Process, Put, String, System, Time, Tool, Stream, PupDefs, PupStream = BEGIN OPEN PupStream, PupTypes; z: UNCOUNTED ZONE = Heap.systemZone; defualtClumpLength: CARDINAL = 1000; -- words defualtNumberOfClumps: CARDINAL = 1000; -- 1 mega word msg, form, log: Window.Handle; -- Be sure to initialize it when it is allocated!!!! data: LONG POINTER TO Data ← NIL; -- NIL when we are inactive Data: TYPE = RECORD [ where: PupAddress ← [[0], [0], PupTypes.bspTestSoc], clumpLength: CARDINAL ← defualtClumpLength, numberOfClumps: CARDINAL ← defualtNumberOfClumps, pleaseStop: BOOLEAN ← FALSE, alignTheFink0: WORD ← NULL, running: BOOLEAN ← FALSE, alignTheFink1: WORD ← NULL, verbose: BOOLEAN ← FALSE, alignTheFink2: WORD ← NULL, sendForever: BOOLEAN ← FALSE, alignTheFink3: WORD ← NULL, forceOutClumps: BOOLEAN ← FALSE, alignTheFink4: WORD ← NULL, sendFirstWord: BOOLEAN ← FALSE, target: LONG STRING ← NULL]; Init: PROCEDURE = BEGIN herald: STRING = "BSP Tester of 25-Jun-85 3:14:43"L; [] ← Tool.Create[ name: herald, makeSWsProc: MakeSWs, clientTransition: ClientTransition]; END; BSPTestOn: PROCEDURE = BEGIN WriteCR[]; IF data.clumpLength ~IN [2..10000) THEN BEGIN MsgSW.Post[msg, "ClumpLength should be between 2 and 10000."L]; RETURN; END; WriteCurrentDateAndTime[]; WriteString[" Sending to "L]; IF ~FindPath[] THEN RETURN; data.running ← TRUE; UpdatePicture[]; Process.Detach[FORK Push[]]; END; BSPTestOff: PROCEDURE = BEGIN data.pleaseStop ← TRUE; WHILE data.running DO Process.Yield[]; ENDLOOP; data.pleaseStop ← FALSE; UpdatePicture[]; END; Finished: PROCEDURE = BEGIN data.running ← FALSE; IF ~data.pleaseStop THEN UpdatePicture[]; END; UpdatePicture: PROCEDURE = BEGIN FormSW.FindItem[form, startIX].flags.invisible ← data.running; FormSW.FindItem[form, stopIX].flags.invisible ← ~data.running; FormSW.FindItem[form, clumpIX].flags.readOnly ← data.running; FormSW.Display[form]; END; FindPath: PROCEDURE RETURNS [BOOLEAN] = BEGIN OPEN data; WriteString[target]; WriteChar['=]; PupDefs.GetPupAddress[ @where, target ! PupDefs.PupNameTrouble => BEGIN MsgSW.Post[msg, e]; WriteLine[e]; GOTO Trouble; END]; PrintPupAddress[where]; WriteLine["."L]; RETURN[TRUE]; EXITS Trouble => RETURN[FALSE]; END; Push: PROCEDURE = BEGIN OPEN data; sh: Stream.Handle; start, stop: LONG CARDINAL; words: LONG CARDINAL ← 0; recent: System.Pulses; startOpen, endOpen, startFirstSend, endFirstSend, startClose, endClose: System.Pulses; Buffer: TYPE = RECORD [SEQUENCE COMPUTED CARDINAL OF CARDINAL]; buffer: LONG POINTER; hits: CARDINAL ← 0; info: ARRAY CloseReason OF STRING = [ localClose: "Closed locally"L, localAbort: "Local Abort"L, remoteClose: "Remote close"L, noRouteToNetwork: "No route to that network"L, transmissionTimeout: "Transmission timeout"L, remoteReject: "Remote reject"L]; WriteString["Clump size is "L]; WriteLongDecimal[clumpLength]; WriteLine[" words."L]; start ← Time.Current[]; startOpen ← System.GetClockPulses[]; sh ← PupByteStreamCreate[ where, PupDefs.SecondsToTocks[10] ! StreamClosing => BEGIN WriteString["Connection failed: "L]; IF text # NIL THEN BEGIN WriteChar['(]; WriteString[text]; WriteString[") "L]; END; WriteLine[info[why]]; GOTO Failed; END]; endOpen ← System.GetClockPulses[]; IF sendFirstWord THEN BEGIN ENABLE StreamClosing => CONTINUE; startFirstSend ← System.GetClockPulses[]; Stream.PutWord[sh, 0]; words ← words + 1; endFirstSend ← System.GetClockPulses[]; END; recent ← System.GetClockPulses[]; buffer ← z.NEW[Buffer[clumpLength]]; FOR clumps: CARDINAL ← 0, clumps + 1 UNTIL pleaseStop OR (~sendForever AND clumps >= data.numberOfClumps) DO Stream.PutBlock[ sh, [buffer, 0, 2*clumpLength], forceOutClumps ! StreamClosing => BEGIN WriteString["Push Stream closed: "L]; IF text # NIL THEN BEGIN WriteChar['(]; WriteString[text]; WriteString[") "L]; END; WriteLine[info[why]]; GOTO Closed; END]; words ← words + clumpLength; IF verbose THEN BEGIN WriteChar['!]; IF ((hits ← hits + 1) MOD 50) = 0 THEN BEGIN ms: LONG CARDINAL; -- Oh shit. This overflows at a clumpLength of 20000 wrods. fudge: LONG CARDINAL = 100*LONG[16*50]; ms ← System.PulsesToMicroseconds[[System.GetClockPulses[] - recent]]/10000; WriteString[" "L]; WriteLongDecimal[(fudge*clumpLength)/ms]; WriteLine[" bits/sec"L]; recent ← System.GetClockPulses[]; END; END; REPEAT Closed => NULL; ENDLOOP; startClose ← System.GetClockPulses[]; Stream.SendNow[sh ! StreamClosing => CONTINUE]; Stream.Delete[sh]; endClose ← System.GetClockPulses[]; stop ← Time.Current[]; z.FREE[@buffer]; WriteCR[]; WriteLongDecimal[words]; WriteLine[" words sent."L]; IF stop - start > 100 OR words > 100000 THEN BEGIN WriteLongDecimal[16*words/(stop - start)]; END ELSE BEGIN t: System.Pulses ← [endClose - startOpen]; WriteLongDecimal[16*words*1000/(System.PulsesToMicroseconds[t]/1000)]; END; WriteLine[" data bits per second."L]; PrintTiming["Open"L, endOpen, startOpen]; IF sendFirstWord THEN PrintTiming["First Ack"L, endFirstSend, startFirstSend]; PrintTiming["Close"L, endClose, startClose]; IF words < 5000000 THEN PrintTiming["Total"L, endClose, startOpen]; WriteCR[]; Finished[]; EXITS Failed => Finished[]; END; -- IO things WriteChar: PROCEDURE [c: CHARACTER] = BEGIN Put.Char[log, c]; END; WriteCR: PROCEDURE = BEGIN Put.CR[log]; END; WriteString: PROCEDURE [s: LONG STRING] = BEGIN Put.Text[log, s]; END; WriteLine: PROCEDURE [s: LONG STRING] = BEGIN Put.Line[log, s]; END; WriteLongDecimal: PROCEDURE [n: LONG CARDINAL] = BEGIN Put.LongDecimal[log, n]; END; WriteCurrentDateAndTime: PROCEDURE = BEGIN time: STRING = [20]; Time.AppendCurrent[time]; WriteString[time]; END; PrintPupAddress: PROCEDURE [a: PupAddress] = BEGIN temp: STRING = [40]; PupDefs.AppendPupAddress[temp, a]; WriteString[temp]; END; PrintTiming: PROCEDURE [s: LONG STRING, end, start: System.Pulses] = BEGIN t: System.Pulses ← [end - start]; WriteString[s]; WriteString[" took "L]; WriteLongDecimal[System.PulsesToMicroseconds[t]/1000]; WriteLine[" ms."L]; END; Start: FormSW.ProcType = BEGIN BSPTestOn[]; END; Stop: FormSW.ProcType = BEGIN BSPTestOff[]; END; MakeSWs: Tool.MakeSWsProc = BEGIN msg ← Tool.MakeMsgSW[window: window, lines: 5]; form ← Tool.MakeFormSW[window: window, formProc: MakeForm]; log ← Tool.MakeFileSW[window: window, name: "BSPTest.log$"L, allowTypeIn: FALSE]; END; startIX: CARDINAL = 0; stopIX: CARDINAL = 1; clumpIX: CARDINAL = 4; MakeForm: FormSW.ClientItemsProcType = BEGIN nParams: CARDINAL = 10; items ← FormSW.AllocateItemDescriptor[nParams]; items[0] ← FormSW.CommandItem[ tag: "Start"L, proc: Start, place: FormSW.newLine]; items[1] ← FormSW.CommandItem[ tag: "Stop"L, proc: Stop, place: FormSW.newLine, invisible: TRUE]; items[2] ← FormSW.BooleanItem[ tag: "Running"L, switch: @data.running, readOnly: TRUE]; items[3] ← FormSW.BooleanItem[tag: "Verbose"L, switch: @data.verbose]; items[4] ← FormSW.BooleanItem[tag: "SendForever"L, switch: @data.sendForever]; items[5] ← FormSW.BooleanItem[ tag: "SendFirstWord"L, switch: @data.sendFirstWord]; items[6] ← FormSW.BooleanItem[ tag: "ForceOutClumps"L, switch: @data.forceOutClumps]; items[7] ← FormSW.NumberItem[ tag: "ClumpLength"L, value: @data.clumpLength, place: FormSW.newLine]; items[8] ← FormSW.NumberItem[ tag: "NumberOfClumps"L, value: @data.numberOfClumps, place: FormSW.newLine]; items[9] ← FormSW.StringItem[ tag: "Target"L, string: @data.target, place: FormSW.newLine, inHeap: TRUE]; RETURN[items, TRUE]; END; AlreadyActive: ERROR = CODE; NotActive: ERROR = CODE; ClientTransition: ToolWindow.TransitionProcType = BEGIN SELECT TRUE FROM old = inactive => BEGIN IF data # NIL THEN ERROR AlreadyActive; data ← z.NEW[Data]; data↑ ← []; data.target ← z.NEW[StringBody[20]]; String.AppendString[data.target, "ME"L]; [] ← PupDefs.PupPackageMake[]; END; new = inactive => BEGIN IF data = NIL THEN ERROR NotActive; IF data.running THEN BSPTestOff[]; PupDefs.PupPackageDestroy[]; z.FREE[@data.target]; z.FREE[@data]; END; ENDCASE; END; -- Main Body Init[]; END.