Grapevine Tool - get statistics from each server --
GVWatcher.mesa (derived from Chat.mesa)
Andrew Birrell, December 23, 1982 10:32 am
Michael Schroeder, December 27, 1983 10:20 am
DIRECTORY
BasicTime USING [Now],
Commander USING [CommandProc, Register],
GVBasics USING [RName],
GVNames USING [ConnectInfo, GetConnect, GetMembers, MemberInfo],
IO USING[Close, EndOfStream, Flush, GetChar, LF, PutChar, PutF, PutRope, STREAM],
Process USING[ Abort, Detach ],
Rope USING [ROPE],
PupStream,
PupTypes USING[ telnetSoc ],
ViewerIO USING[ CreateViewerStreams ];
GVWatcher: MONITOR
IMPORTS BasicTime, Commander, GVNames, IO, Process, PupStream, ViewerIO =
BEGIN
serverScript: Rope.ROPE = "dtdsdpdhq\n";
serverList: Rope.ROPE = "gv.gv";
DoConnection: PROCEDURE[out: IO.STREAM, serverName: Rope.ROPE] =
BEGIN
addr: PupStream.PupAddress;
serverStream: IO.STREAMNIL;
setPageLength: [0..256) = 3;
timingMark: [0..256) = 5;
timingMarkReply: [0..256) = 6;
UserToServer: PROCEDURE =
BEGIN
ENABLE ABORTED, PupStream.StreamClosing => GOTO return;
serverStream.PutRope[serverScript]; serverStream.Flush[];
EXITS return => NULL;
END;
AcceptFromServer: PROC[serverStream: IO.STREAM] =
BEGIN
userToServer: PROCESS = FORK UserToServer[];
DO BEGIN
ENABLE
BEGIN
ABORTED, PupStream.StreamClosing =>
{ Process.Abort[userToServer] };
UNWIND => JOIN userToServer-- outside the Pup pkg monitor! --;
IO.EndOfStream => GOTO mark;
END;
c: CHAR = serverStream.GetChar[];
IF c # IO.LF THEN out.PutChar[c];
EXITS mark =>
BEGIN
value: [0..256) = PupStream.ConsumeMark[serverStream];
IF value = timingMark THEN PupStream.SendMark[serverStream, timingMarkReply];
END;
END;
ENDLOOP;
END;
out.PutF["\n\n----------\n\nConnecting to %g ... ", [rope[serverName]] ];
BEGIN
connect: Rope.ROPE;
info: GVNames.ConnectInfo;
[info, connect] ← GVNames.GetConnect[serverName];
SELECT info FROM
allDown =>
{ out.PutRope["no R-Server available"]; GOTO failed };
notFound, group =>
{ out.PutRope["not an individual"]; GOTO failed };
individual =>
NULL;
ENDCASE => ERROR;
out.PutF["%g ... ", [rope[connect]]];
addr ← PupStream.GetPupAddress[PupTypes.telnetSoc, connect ! PupStream.PupNameTrouble =>
BEGIN
out.PutF["Can't find host name: %g.", [rope[e]]];
GOTO failed;
END];
addr.socket ← PupTypes.telnetSoc; -- force socket number --
serverStream ← PupStream.PupByteStreamCreate
[addr, PupStream.veryLongWait ! PupStream.StreamClosing =>
BEGIN
out.PutF["Can't connect to host: %g.", [rope[text]]];
GOTO failed;
END];
out.PutRope["open."];
END;
AcceptFromServer[serverStream ! PupStream.StreamClosing =>
BEGIN
out.PutF["\nConnection closed by %g", [rope[serverName]] ];
IF text # NIL THEN out.PutF[": %g", [rope[text]] ];
CONTINUE
END ];
serverStream.Close[];
EXITS failed => NULL;
END--DoConnection--;
main procedure
DoIt: Commander.CommandProc = TRUSTED
[cmd: Handle] RETURNS [result: REFNIL, msg: Rope.ROPENIL]
{ Process.Detach[FORK ReallyDoit[]] };
ReallyDoit: PROC =
BEGIN
out: IO.STREAM = ViewerIO.CreateViewerStreams["GV Statistics watcher"].out;
info: GVNames.MemberInfo = GVNames.GetMembers[serverList];
out.PutF["\nGrapevine Statistics Watcher started at %g%l", [time[BasicTime.Now[]]], [rope["f"]] ];
WITH i: info SELECT FROM
allDown => out.PutRope["\nCan't expand server-list"];
notFound, individual => out.PutRope["\nIncorrect server-list"];
group =>
FOR l: LIST OF Rope.ROPE ← i.members, l.rest UNTIL l = NIL DO
DoConnection[out, l.first];
ENDLOOP;
ENDCASE => ERROR;
out.PutRope["\n\n-----\n"];
END;
Commander.Register[key: "GVWatcher", proc: DoIt, doc: "Get statistics from Grapevine servers"];
END.