-- File: LineUse.mesa, Last Edit: HGM January 30, 1981 3:37 PM
DIRECTORY
Event USING [Item, Reason, AddNotifier],
Format USING [], -- Needed by Put.Number
FormSW USING [
ClientItemsProcType, ProcType, AllocateItemDescriptor, newLine, CommandItem,
StringItem, NumberItem],
Inline USING [LowHalf, HighHalf],
MsgSW USING [Post],
Process USING [Detach, MsecToTicks, SetTimeout, Yield],
Put USING [Char, CR, Date, Line, Number, Text],
String USING [AppendLongNumber, AppendString],
System USING [GreenwichMeanTime, GetGreenwichMeanTime, AdjustGreenwichMeanTime],
Time USING [AppendCurrent, Current],
Tool USING [
Create, MakeSWsProc, UnusedLogName, MakeMsgSW, MakeFormSW, MakeFileSW,
AddThisSW],
ToolWindow USING [TransitionProcType, DisplayProcType, CreateSubwindow],
Window USING [Handle, Box, DisplayData, DisplayInvert, DisplayWhite],
AltoSlaDefs,
GateControlDefs USING [gateControlExamine, gateControlStatsAck],
PupDefs USING [
AppendPupAddress, PupPackageMake, PupPackageDestroy, PupBuffer,
GetFreePupBuffer, ReturnFreePupBuffer, PupAddress, GetPupAddress,
PupNameTrouble, GetPupContentsBytes, SetPupContentsWords, PupSocket,
PupSocketDestroy, PupSocketMake, MsToTocks],
PupTypes USING [fillInSocketID],
CommUtilDefs USING [magicMemoryLocation],
DriverDefs;
LineUse: MONITOR
IMPORTS
Event, Inline, FormSW, MsgSW, Process, Put, String, System, Time, Tool,
ToolWindow, Window, PupDefs
SHARES DriverDefs =
BEGIN OPEN PupDefs;
tool, msg, form, boxes, log: Window.Handle;
eventItem: Event.Item ← [eventMask: 177777B, eventProc: Broom];
running: BOOLEAN ← FALSE;
pleaseStop: BOOLEAN ← FALSE;
indicator: {left, right, off} ← off;
seconds: CARDINAL ← 60;
target: STRING ← [30];
where: PupAddress ← [[0], [0], [31415, 9265]];
soc: PupSocket ← NIL;
giantVector: DriverDefs.GiantVector;
giantVectorLoc: POINTER TO DriverDefs.GiantVector;
Go: FormSW.ProcType =
BEGIN
IF running THEN
BEGIN MsgSW.Post[msg, "Somebody is already running..."L]; RETURN; END;
Put.CR[log];
Put.Date[log, Time.Current[], dateTime];
Put.Text[log, " Watching SLA lines on "L];
IF ~FindPath[] THEN RETURN;
running ← TRUE;
Process.Detach[FORK Watch[]];
END;
Stop: FormSW.ProcType = BEGIN Off[]; END;
Off: PROCEDURE =
BEGIN
IF ~running THEN RETURN;
pleaseStop ← TRUE;
WHILE running DO Process.Yield[]; ENDLOOP;
pleaseStop ← FALSE;
END;
FindPath: PROCEDURE RETURNS [BOOLEAN] =
BEGIN
Put.Text[log, target];
Put.Char[log, '=];
GetPupAddress[
@where, target !
PupNameTrouble =>
BEGIN MsgSW.Post[msg, e]; Put.Line[log, e]; GOTO Trouble; END];
PrintPupAddress[where];
Put.Line[log, "."L];
RETURN[TRUE];
EXITS Trouble => RETURN[FALSE];
END;
Watch: ENTRY PROCEDURE =
BEGIN
time: System.GreenwichMeanTime ← System.GetGreenwichMeanTime[];
pause: CONDITION;
MakeConnection[];
SetupBoxes[];
Process.SetTimeout[@pause, Process.MsecToTicks[500]];
GetInfo[];
oldLineInfo ← newLineInfo;
FOR line: AltoSlaDefs.Line IN [0..activeLines) DO
oldDest[line] ← 177777B; oldLineInfo[line].state ← missing; ENDLOOP;
CheckLineState[];
oldLineInfo ← newLineInfo;
Put.CR[log];
PrintHeader[];
UNTIL pleaseStop DO
UNTIL pleaseStop OR (System.GetGreenwichMeanTime[] - time) >= seconds DO
WAIT pause; ENDLOOP;
time ← System.AdjustGreenwichMeanTime[time, seconds];
GetInfo[];
PrintTime[];
Put.CR[log];
PrintInfo[];
CheckLineState[];
oldLineInfo ← newLineInfo;
ENDLOOP;
SetDownBoxes[];
KillConnection[];
running ← FALSE;
END;
activeLines: CARDINAL;
hisLineInfo: LONG POINTER TO ARRAY AltoSlaDefs.Line OF
AltoSlaDefs.LineInfoBlock;
hisSlaRouting: LONG POINTER TO ARRAY AltoSlaDefs.SlaHost OF
AltoSlaDefs.RoutingTableEntry;
oldLineInfo, newLineInfo: ARRAY AltoSlaDefs.Line OF AltoSlaDefs.LineInfoBlock;
newSlaRoutingTable: ARRAY AltoSlaDefs.SlaHost OF AltoSlaDefs.RoutingTableEntry;
oldDest: ARRAY AltoSlaDefs.Line OF CARDINAL;
GetInfo: PROCEDURE =
BEGIN OPEN AltoSlaDefs;
GetBig[
to: @newLineInfo, from: hisLineInfo, size: activeLines*SIZE[LineInfoBlock]];
GetBig[
to: @newSlaRoutingTable, from: hisSlaRouting,
size: maxSlaHost*SIZE[RoutingTableEntry]];
END;
PrintHeader: PROCEDURE =
BEGIN OPEN AltoSlaDefs;
Put.Line[
log,
"
Q Rej Packets Bytes Bits/Sec Delay Ms
L H L C H S Hi Sent Recv Sent Recv Sent Recv Hi Send
"L];
END;
PrintInfo: PROCEDURE =
BEGIN
FOR line: AltoSlaDefs.Line IN [0..activeLines) DO
lib: AltoSlaDefs.LineInfoBlock;
temp: LONG INTEGER;
O1[line];
D3[newLineInfo[line].hiPriQueue.length];
D2[newLineInfo[line].lowPriQueue.length];
lib.connRejections ←
newLineInfo[line].connRejections - oldLineInfo[line].connRejections;
lib.hiRejections ←
newLineInfo[line].hiRejections - oldLineInfo[line].hiRejections;
lib.rejections ←
newLineInfo[line].rejections - oldLineInfo[line].rejections;
LD3[lib.connRejections];
LD3[lib.hiRejections];
LD3[lib.rejections];
lib.packetsSent ←
newLineInfo[line].packetsSent - oldLineInfo[line].packetsSent;
lib.packetsRecv ←
newLineInfo[line].packetsRecv - oldLineInfo[line].packetsRecv;
lib.bytesSent ← newLineInfo[line].bytesSent - oldLineInfo[line].bytesSent;
lib.bytesRecv ← newLineInfo[line].bytesRecv - oldLineInfo[line].bytesRecv;
lib.queueDelay ←
newLineInfo[line].queueDelay - oldLineInfo[line].queueDelay;
lib.hiPacketsSent ←
newLineInfo[line].hiPacketsSent - oldLineInfo[line].hiPacketsSent;
lib.hiBytesSent ←
newLineInfo[line].hiBytesSent - oldLineInfo[line].hiBytesSent;
lib.hiQueueDelay ←
newLineInfo[line].hiQueueDelay - oldLineInfo[line].hiQueueDelay;
LD7[lib.hiPacketsSent];
LD7[lib.packetsSent];
LD7[lib.packetsRecv];
LD7[lib.bytesSent];
LD7[lib.bytesRecv];
temp ← lib.bytesSent + AltoSlaDefs.overheadPerPacket*lib.packetsSent;
LD7[temp*8/seconds];
temp ← lib.bytesRecv + AltoSlaDefs.overheadPerPacket*lib.packetsRecv;
LD7[temp*8/seconds];
LD7[(lib.hiQueueDelay*39)/lib.hiPacketsSent];
LD7[(lib.queueDelay*39)/lib.packetsSent];
Put.CR[log];
ENDLOOP;
END;
CheckLineState: PROCEDURE =
BEGIN
changed: BOOLEAN;
FOR line: AltoSlaDefs.Line IN [0..activeLines) DO
changed ← FALSE;
-- find out who this line is connected to
FOR host: AltoSlaDefs.SlaHost IN AltoSlaDefs.SlaHost DO
rte: POINTER TO AltoSlaDefs.RoutingTableEntry;
rte ← @newSlaRoutingTable[host];
IF rte.line = line AND rte.hops = 1 THEN
BEGIN
IF oldDest[line] # host THEN changed ← TRUE;
oldDest[line] ← host;
EXIT;
END;
ENDLOOP;
IF oldLineInfo[line].state # newLineInfo[line].state THEN changed ← TRUE;
IF ~changed THEN LOOP;
PrintTime[];
Put.Text[log, " Line "];
O[line];
Put.Text[log, " is "];
SELECT newLineInfo[line].state FROM
up => BEGIN Put.Text[log, "up to host "]; O[oldDest[line]]; END;
down => Put.Text[log, "down"L];
loopedBack => Put.Text[log, "looped back"L];
ENDCASE => Put.Line[log, "??"L];
Put.Char[log, '.];
Put.CR[log];
ENDLOOP;
END;
Read: PROCEDURE [p: LONG POINTER] RETURNS [x: UNSPECIFIED] =
BEGIN Get[to: @x, from: p, size: 1]; END;
GetBig: PROCEDURE [to: POINTER, from: LONG POINTER, size: CARDINAL] =
BEGIN
end: CARDINAL ← 0;
hunk: CARDINAL;
UNTIL end = size DO
hunk ← MIN[250, size - end];
Get[to + end, from + end, hunk];
end ← end + hunk;
ENDLOOP;
END;
-- get a block of info from the "right" address space
thisID: CARDINAL ← 0;
Get: PROCEDURE [to: POINTER, from: LONG POINTER, size: CARDINAL] =
BEGIN
b: PupBuffer;
i: CARDINAL;
IF size > 250 THEN ERROR;
IF Inline.HighHalf[from] # 0 THEN ERROR;
thisID ← thisID + 1;
DO
-- until we get the answer
b ← GetFreePupBuffer[];
b.pupID ← [27182, thisID];
b.pupWords[0] ← LOOPHOLE[Inline.LowHalf[from]];
b.pupWords[1] ← size;
b.pupType ← GateControlDefs.gateControlExamine;
SetPupContentsWords[b, 2];
soc.put[b];
-- The loop structure here is not very nice.....
FlipBoxes[];
b ← soc.get[];
IF b = NIL THEN LOOP;
IF b.pupType = error OR b.pupID.b # thisID THEN
BEGIN ReturnFreePupBuffer[b]; LOOP; END;
IF b.pupType = GateControlDefs.gateControlStatsAck AND GetPupContentsBytes[
b] = 2*(2 + size) THEN EXIT;
ERROR;
ENDLOOP;
FlipBoxes[];
FOR i IN [0..size) DO (to + i)↑ ← b.pupWords[2 + i]; ENDLOOP;
ReturnFreePupBuffer[b];
END;
PrintTime: PROCEDURE =
BEGIN text: STRING = [20]; Time.AppendCurrent[text]; Put.Text[log, text]; END;
PrintPupAddress: PROCEDURE [a: PupAddress] =
BEGIN
text: STRING = [20];
AppendPupAddress[text, a];
Put.Text[log, text];
END;
O: PROCEDURE [n: CARDINAL] = BEGIN Put.Number[log, n, [8, FALSE, TRUE, 0]]; END;
O1: PROCEDURE [n: CARDINAL] =
BEGIN Put.Number[log, n, [8, FALSE, TRUE, 1]]; END;
O3: PROCEDURE [n: CARDINAL] =
BEGIN Put.Number[log, n, [8, FALSE, TRUE, 3]]; END;
D: PROCEDURE [n: CARDINAL] =
BEGIN Put.Number[log, n, [10, FALSE, TRUE, 0]]; END;
D2: PROCEDURE [n: CARDINAL] =
BEGIN Put.Number[log, n, [10, FALSE, TRUE, 2]]; END;
D3: PROCEDURE [n: CARDINAL] =
BEGIN Put.Number[log, n, [10, FALSE, TRUE, 3]]; END;
D4: PROCEDURE [n: CARDINAL] =
BEGIN Put.Number[log, n, [10, FALSE, TRUE, 4]]; END;
LD2: PROCEDURE [num: LONG INTEGER] =
BEGIN
s: STRING = [20];
String.AppendLongNumber[s, num, 10];
THROUGH [s.length..2) DO Put.Char[log, ' ]; ENDLOOP;
Put.Text[log, s];
END;
LD3: PROCEDURE [num: LONG INTEGER] =
BEGIN
s: STRING = [20];
String.AppendLongNumber[s, num, 10];
THROUGH [s.length..3) DO Put.Char[log, ' ]; ENDLOOP;
Put.Text[log, s];
END;
LD7: PROCEDURE [num: LONG INTEGER] =
BEGIN
s: STRING = [20];
String.AppendLongNumber[s, num, 10];
THROUGH [s.length..7) DO Put.Char[log, ' ]; ENDLOOP;
Put.Text[log, s];
END;
MakeConnection: PROCEDURE =
BEGIN
soc ← PupSocketMake[PupTypes.fillInSocketID, where, MsToTocks[1000]];
giantVectorLoc ← Read[CommUtilDefs.magicMemoryLocation];
Get[
to: @giantVector, from: giantVectorLoc, size: SIZE[DriverDefs.GiantVector]];
BEGIN OPEN AltoSlaDefs;
p: LONG POINTER ← giantVector.slaThings;
IF p = NIL THEN ERROR;
p ← p + maxByte; -- skip CRC Table
activeLines ← Read[p];
p ← 8 + p + maxLine*SIZE[LineTableEntry];
hisSlaRouting ← p;
p ← p + maxSlaHost*SIZE[RoutingTableEntry];
hisLineInfo ← p;
IF activeLines > maxLine THEN ERROR;
END;
END;
KillConnection: PROCEDURE = BEGIN PupSocketDestroy[soc]; soc ← NIL; END;
indicatorBox: Window.Box = [[25, 10], [16, 16]];
DisplayBoxes: ToolWindow.DisplayProcType =
BEGIN
pattern: ARRAY [0..1] OF ARRAY [0..8) OF WORD;
left: WORD = 177400B;
right: WORD = 000377B;
SELECT indicator FROM
left => pattern ← [ALL[left], ALL[right]];
right => pattern ← [ALL[right], ALL[left]];
off => pattern ← [ALL[0], ALL[0]];
ENDCASE;
Window.DisplayData[window, indicatorBox, @pattern, 1]
END;
SetupBoxes: PROCEDURE = BEGIN indicator ← left; DisplayBoxes[boxes]; END;
FlipBoxes: PROCEDURE =
BEGIN
SELECT indicator FROM
left => indicator ← right;
off, right => indicator ← left;
ENDCASE;
Window.DisplayInvert[boxes, indicatorBox];
END;
SetDownBoxes: PROCEDURE =
BEGIN indicator ← off; Window.DisplayWhite[boxes, indicatorBox]; END;
MakeBoxesSW: PROCEDURE [window: Window.Handle] =
BEGIN
boxes ← ToolWindow.CreateSubwindow[parent: window, display: DisplayBoxes];
boxes.box.dims.h ← 36;
Tool.AddThisSW[window: window, sw: boxes, swType: vanilla];
END;
MakeSWs: Tool.MakeSWsProc =
BEGIN
logFileName: STRING = [40];
msg ← Tool.MakeMsgSW[window: window, lines: 5];
form ← Tool.MakeFormSW[window: window, formProc: MakeForm];
MakeBoxesSW[window];
Tool.UnusedLogName[logFileName, "LineUse.log$"L];
log ← Tool.MakeFileSW[window: window, name: logFileName];
END;
MakeForm: FormSW.ClientItemsProcType =
BEGIN
nParams: CARDINAL = 4;
items ← FormSW.AllocateItemDescriptor[nParams];
items[0] ← FormSW.CommandItem[
tag: "Stop"L, proc: Stop, place: FormSW.newLine];
items[1] ← FormSW.CommandItem[tag: "Go"L, proc: Go];
items[2] ← FormSW.NumberItem[tag: "Seconds"L, value: @seconds, default: 60];
items[3] ← FormSW.StringItem[tag: "Target"L, string: @target];
RETURN[items, TRUE];
END;
ClientTransition: ToolWindow.TransitionProcType =
BEGIN
SELECT TRUE FROM
old = inactive =>
BEGIN String.AppendString[target, "ME"L]; PupDefs.PupPackageMake[]; END;
new = inactive =>
BEGIN IF running THEN Off[]; PupDefs.PupPackageDestroy[]; END;
ENDCASE;
END;
Broom: PROCEDURE [why: Event.Reason] =
BEGIN
SELECT why FROM
makeImage, makeCheck =>
BEGIN IF running THEN Off[]; PupDefs.PupPackageDestroy[]; END;
startImage, restartCheck, continueCheck =>
BEGIN PupDefs.PupPackageMake[]; END;
ENDCASE => NULL;
END;
Init: PROCEDURE =
BEGIN
herald: STRING = "Line Use of January 30, 1981"L;
tool ← Tool.Create[
name: herald, makeSWsProc: MakeSWs, clientTransition: ClientTransition];
END;
-- Main Body
Event.AddNotifier[@eventItem];
END.