DIRECTORY
Basics USING [BITAND],
BasicTime USING [GMT, nullGMT, Unpacked, Unpack, Now],
Commander USING [Register, CommandProc],
FS USING [Error, StreamOpen],
IO,
Process USING [Detach, Pause, SecondsToTicks],
PupName USING [NameLookup, Error],
PupStream USING [Create, StreamClosing, Timeout, waitForever],
Pup USING [Address],
Rope USING [Find, ROPE, Substr],
RefText USING [TrustTextAsRope]
;
DLSMonitor:
CEDAR MONITOR
IMPORTS Basics, BasicTime, Commander, FS, IO, Process, PupName, PupStream, RefText, Rope
EXPORTS
~ BEGIN
STREAM: TYPE ~ IO.STREAM;
ROPE: TYPE ~ Rope.ROPE;
running: BOOL ← FALSE;
timeOut: CARDINAL ← 0;
timerForked: BOOL ← FALSE;
server: ROPE ~ "DLS+100000";
fileName: ROPE ~ "DLSLog.txt";
Restart: ERROR = CODE;
DLSMonitorProc:
PROC [] =
BEGIN
ForkIt:
ENTRY
PROC [] =
TRUSTED
{timerForked ← TRUE; Process.Detach[FORK TimerProcess[]]};
dlsStream: STREAM;
fileStream: STREAM ← NIL;
c: CHAR;
txt: REF TEXT ← NEW [TEXT[1000]];
l: CARDINAL ← 0;
ClearTimeout[];
IF ~ timerForked THEN ForkIt[];
SetRunning[TRUE];
fileStream ←
FS.StreamOpen[fileName: fileName, accessOptions: append, keep: 10 !
FS.Error =>
IF error.group = lock
THEN
{fileStream ← FS.StreamOpen[fileName: fileName, accessOptions: create, keep: 10];
CONTINUE}];
dlsStream ← GetConnection[];
IO.PutF[fileStream, "%g $ Starting\n", IO.rope[RFC822Date[]]];
IO.Flush[fileStream];
DO
ENABLE
{PupStream.StreamClosing,
IO.Error =>
BEGIN
IO.PutF[fileStream, "%g $ DLS Not responding\n", IO.rope[RFC822Date[]]];
IO.Flush[fileStream];
dlsStream ← GetConnection[];
CONTINUE;
END; -- of PupStream.StreamClosing
Restart =>
BEGIN
IO.PutF[fileStream, "%g $ Restarting\n", IO.rope[RFC822Date[]]];
IO.Flush[fileStream];
dlsStream ← GetConnection[];
CONTINUE;
END;}; -- of ENABLE
IF dlsStream = NIL THEN {IO.Close[fileStream]; ForceTimeout[]; RETURN};
BEGIN
DO
i: INT ← IO.CharsAvail[dlsStream];
IF i > 0 THEN EXIT;
IF ~ GetRunning[]
THEN
{IO.Close[fileStream]; IO.Close[dlsStream]; ForceTimeout[]; RETURN};
Process.Pause[Process.SecondsToTicks[10]];
IF Timeout[] THEN {ClearTimeout[]; IO.Close[dlsStream]; ERROR Restart};
ENDLOOP;
c ←
IO.GetChar[dlsStream !
PupStream.Timeout => IF ~ GetRunning[] THEN EXIT ELSE RESUME;
IO.EndOfStream => IF ~ GetRunning[] THEN EXIT ELSE LOOP];
c ← LOOPHOLE[Basics.BITAND[LOOPHOLE[c, CARDINAL], 177B], CHAR];
IF c =
IO.
CR
THEN
BEGIN
IO.PutF[fileStream, "%g $ %g\n",
IO.rope[RFC822Date[]], IO.rope[RefText.TrustTextAsRope[txt]]];
IO.Flush[fileStream];
txt.length ← 0;
END
ELSE IF c = '\000 THEN LOOP
ELSE IF c = IO.LF THEN LOOP
ELSE
BEGIN
txt[txt.length] ← c; txt.length ← txt.length + 1;
IF txt.length >= txt.maxLength THEN txt.length ← 0;
END;
END;
ENDLOOP;
ForceTimeout[];
IO.Close[fileStream];
IO.Close[dlsStream];
END;
GetConnection:
PROC []
RETURNS [dlsStream:
STREAM] =
BEGIN
dlsStream ← NIL;
DO
dlsStream ← EstablishConnection[server];
IF dlsStream # NIL THEN EXIT;
IF ~ GetRunning[] THEN EXIT;
Process.Pause[Process.SecondsToTicks[10]];
ENDLOOP;
RETURN [dlsStream];
END;
EstablishConnection:
PROC [serverName:
ROPE]
RETURNS [
STREAM] =
BEGIN
ENABLE { PupStream.StreamClosing => GOTO Exit; UNWIND => NULL; };
commPortAddress: Pup.Address ← PupName.NameLookup[serverName, [0, 0, 0, 1]
! PupName.Error => GOTO Exit];
s: STREAM ← PupStream.Create[commPortAddress, PupStream.waitForever, PupStream.waitForever];
IO.PutChar[s, 'c];
IO.Flush[s];
RETURN [s];
EXITS Exit => RETURN [NIL];
END;
Timeout: ENTRY PROC [] RETURNS [BOOL] = {RETURN[timeOut > 6]};
ClearTimeout: ENTRY PROC [] = {timeOut ← 0};
IncTimeout: ENTRY PROC [] = {timeOut ← timeOut + 1};
ForceTimeout: ENTRY PROC [] = {timeOut ← 9999};
TimerProcess:
PROC [] =
BEGIN
DO
Process.Pause[Process.SecondsToTicks[30*60]];
IncTimeout[];
IF ~ GetRunning[] THEN RETURN;
ENDLOOP;
END;
SetRunning: ENTRY PROC [val: BOOL] = {running ← val};
GetRunning: ENTRY PROC [] RETURNS [BOOL] = {RETURN [running]};
RFC822Date:
PUBLIC
PROC[gmt: BasicTime.
GMT← BasicTime.nullGMT]
RETURNS[date:
ROPE] =
-- generates arpa standard time, dd mmm yy hh:mm:ss zzz
BEGIN OPEN IO;
upt: BasicTime.Unpacked ←
BasicTime.Unpack[IF gmt = BasicTime.nullGMT THEN BasicTime.Now[] ELSE gmt];
zone: ROPE;
month, tyme, year: ROPE;
timeFormat: ROPE = "%02g:%02g:%02g %g"; -- "hh:mm:ss zzz"
dateFormat: ROPE = "%2g %g %g %g"; -- "dd mmm yy timeFormat"
arpaNeg: BOOL← upt.zone > 0;
aZone: INT← ABS[upt.zone];
zDif: INT← aZone / 60;
zMul: INT← zDif * 60;
IF (zMul = aZone)
AND arpaNeg
THEN
BEGIN
IF upt.dst = yes
THEN
SELECT zDif
FROM
0 => zone← "UT";
4 => zone← "EDT";
5 => zone← "CDT";
6 => zone← "MDT";
8 => zone← "PDT";
ENDCASE
ELSE
SELECT zDif
FROM
0 => zone← "UT";
5 => zone← "EST";
6 => zone← "CST";
7 => zone← "MST";
8 => zone← "PST";
ENDCASE;
END;
IF zone =
NIL
THEN BEGIN
mm: INT← aZone - zMul;
zone← PutFR[IF arpaNeg THEN "-%02g%02g" ELSE "+%02g%02g", int[zDif], int[mm]];
END;
SELECT upt.month
FROM
January => month← "Jan";
February => month← "Feb";
March => month← "Mar";
April => month← "Apr";
May => month← "May";
June => month← "Jun";
July => month← "Jul";
August => month← "Aug";
September => month← "Sep";
October => month← "Oct";
November => month← "Nov";
December => month← "Dec";
unspecified => ERROR;
ENDCASE => ERROR;
year← Rope.Substr[PutFR[NIL, int[upt.year]], 2];
tyme← PutFR[timeFormat, int[upt.hour], int[upt.minute], int[upt.second], rope[zone]];
date← PutFR[dateFormat, int[upt.day], rope[month], rope[year], rope[tyme]];
END;
DLSMonitorCommand: Commander.CommandProc ~
BEGIN
op: {start, stop};
IF Rope.Find[cmd.commandLine, "start", 0, FALSE] >= 0 THEN op ← start
ELSE IF Rope.Find[cmd.commandLine, "stop", 0, FALSE] >= 0 THEN op ← stop
ELSE IF NOT GetRunning[] THEN op ← start
ELSE op ← stop;
IF op = start
THEN
BEGIN
TRUSTED { Process.Detach[FORK DLSMonitorProc[]]};
cmd.out.PutRope["DLS Monitor Started\n"];
END
ELSE
BEGIN
SetRunning[FALSE];
cmd.out.PutRope["DLS Monitor Stopped\n"];
END;
END;
Commander.Register["DLSMonitor", DLSMonitorCommand, "DLSMonitor [ start | stop ]\n"];
END...