GVWatcher - get statistics from each server
Andrew Birrell, December 23, 1982 10:32 am
Michael Schroeder, December 27, 1983 10:20 am
Hal Murray, March 13, 1986 6:54:05 pm PST
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],
Pup USING [Address],
PupName USING [Error, NameLookup],
PupStream USING [ConsumeMark, Create, SendMark, StreamClosing, waitForever],
PupWKS USING [telnet],
ViewerIO USING [CreateViewerStreams];
GVWatcher: CEDAR PROGRAM
IMPORTS BasicTime, Commander, GVNames, IO, Process, PupName, PupStream, ViewerIO = {
MemberInfo: TYPE = GVNames.MemberInfo;
serverScript: Rope.ROPE = "dtdsdpdhq\n";
serverList: Rope.ROPE = "gv.gv";
DoConnection: PROC [out: IO.STREAM, serverName: Rope.ROPE] = {
addr: Pup.Address;
serverStream: IO.STREAMNIL;
setPageLength: [0..256) = 3;
timingMark: [0..256) = 5;
timingMarkReply: [0..256) = 6;
UserToServer: PROC = {
ENABLE ABORTED, PupStream.StreamClosing => CONTINUE;
IO.PutRope[serverStream, serverScript];
IO.Flush[serverStream];
};
AcceptFromServer: PROC [serverStream: IO.STREAM] = {
userToServer: PROCESS;
TRUSTED { userToServer ← FORK UserToServer[]; };
DO BEGIN
ENABLE
BEGIN
ABORTED, PupStream.StreamClosing => TRUSTED { Process.Abort[userToServer]; };
UNWIND => TRUSTED { JOIN userToServer; }; -- outside the Pup pkg monitor!
IO.EndOfStream => GOTO Mark;
END;
c: CHAR = IO.GetChar[serverStream];
IF c # IO.LF THEN IO.PutChar[out, c];
EXITS Mark =>
BEGIN
value: [0..256) = PupStream.ConsumeMark[serverStream];
IF value = timingMark THEN PupStream.SendMark[serverStream, timingMarkReply];
END;
END;
ENDLOOP;
};
IO.PutF[out, "\n\n----------\n\nConnecting to %g ... ", [rope[serverName]] ];
BEGIN
connect: Rope.ROPE;
info: GVNames.ConnectInfo;
[info, connect] ← GVNames.GetConnect[serverName];
SELECT info FROM
allDown => { IO.PutRope[out, "no R-Server available"]; GOTO Failed; };
notFound, group => { IO.PutRope[out, "not an individual"]; GOTO Failed; };
individual =>
NULL;
ENDCASE => ERROR;
IO.PutF[out, "%g ... ", [rope[connect]]];
addr ← PupName.NameLookup[connect, PupWKS.telnet ! PupName.Error =>
BEGIN
IO.PutF[out, "Can't find host name: %g.", [rope[text]]];
GOTO Failed;
END];
addr.socket ← PupWKS.telnet; -- force socket number
serverStream ← PupStream.Create[addr, PupStream.waitForever, PupStream.waitForever
! PupStream.StreamClosing =>
BEGIN
IO.PutF[out, "Can't connect to host: %g.", [rope[text]]];
GOTO Failed;
END];
IO.PutRope[out, "open."];
END;
AcceptFromServer[serverStream ! PupStream.StreamClosing =>
BEGIN
IO.PutF[out, "\nConnection closed by %g", [rope[serverName]] ];
IF text # NIL THEN out.PutF[": %g", [rope[text]] ];
CONTINUE
END ];
IO.Close[serverStream];
EXITS Failed => NULL;
};
main procedure
DoIt: Commander.CommandProc = {
[cmd: Handle] RETURNS [result: REFNIL, msg: Rope.ROPENIL]
TRUSTED { Process.Detach[FORK ReallyDoit[]]; };
};
ReallyDoit: PROC = {
out: IO.STREAM = ViewerIO.CreateViewerStreams["GV Statistics watcher"].out;
info: MemberInfo = GVNames.GetMembers[serverList];
IO.PutF[
out,
"\nGrapevine Statistics Watcher started at %g%l",
[time[BasicTime.Now[]]],
[rope["f"]] ];
SELECT info.type FROM
allDown => IO.PutRope[out, "\nCan't expand server-list"];
notFound => IO.PutRope[out, "\nIncorrect server-list"];
individual => IO.PutRope[out, "\nIncorrect server-list"];
group => {
group: group MemberInfo = NARROW[info, group MemberInfo];
FOR members: LIST OF Rope.ROPE ← group.members, members.rest UNTIL members = NIL DO
DoConnection[out, members.first];
ENDLOOP;
};
ENDCASE => ERROR;
IO.PutRope[out, "\n\n-----\n"];
};
Commander.Register[key: "GVWatcher", proc: DoIt, doc: "Get statistics from Grapevine servers"];
}.