FingerLogImpl.mesa
Last Edited by: Donahue, August 14, 1985 1:05:03 pm PDT
Spreitzer, August 11, 1985 5:11:26 pm PDT
Gifford, July 26, 1985 12:02:15 pm PDT
DIRECTORY
Atom,
BasicTime USING [GMT],
Convert,
FingerLog,
FS USING[StreamOpen, Error],
IO,
Rope;
FingerLogImpl: CEDAR PROGRAM
IMPORTS Atom, Convert, FS, IO
EXPORTS FingerLog =
BEGIN
OPEN FingerLog;
fingerLogName: Rope.ROPE = "///Finger.Log";
fingerStream: IO.STREAM;
a stream always opened to the finger log file. Normally, the stream is opened for appending; when executing a ParseLog it is opened for reading and then closed
stateChangeAtom: ATOM = Atom.MakeAtom["StateChange"];
userPropChangeAtom: ATOM = Atom.MakeAtom["UserPropChange"];
machinePropChangeAtom: ATOM = Atom.MakeAtom["MachinePropChange"];
addMachinePropAtom: ATOM = Atom.MakeAtom["AddMachineProp"];
addUserPropAtom: ATOM = Atom.MakeAtom["AddUserProp"];
deleteMachinePropAtom: ATOM = Atom.MakeAtom["DeleteMachineProp"];
deleteUserPropAtom: ATOM = Atom.MakeAtom["DeleteUserProp"];
FlushLog: PUBLIC PROC[] ~ {
IF fingerStream # NIL THEN fingerStream.Close[];
fingerStream ← FS.StreamOpen[fingerLogName, $write];
fingerStream.SetLength[0];
fingerStream.Close[];
fingerStream ← NIL };
Log: PUBLIC PROC[ logEntry: LogEntry ] = TRUSTED {
Write the entry on the log file
IF fingerStream = NIL THEN fingerStream ← FS.StreamOpen[fingerLogName, $append];
WITH entry: logEntry SELECT FROM
StateChange => {
fingerStream.Put[IO.atom[stateChangeAtom], IO.rope[" "]];
fingerStream.Put[IO.atom[IF entry.event = login THEN $login ELSE $logout], IO.rope[" "]];
fingerStream.Put[IO.rope[entry.user], IO.rope[" "]];
fingerStream.Put[IO.time[entry.time], IO.rope["\n"]] };
UserPropChange => {
fingerStream.Put[IO.atom[userPropChangeAtom], IO.rope[" "]];
fingerStream.Put[IO.rope[Convert.RopeFromRope[entry.user]], IO.rope[" "]];
fingerStream.Put[IO.rope[Convert.RopeFromRope[entry.name]], IO.rope[" "]];
fingerStream.Put[IO.rope[Convert.RopeFromRope[entry.val]], IO.rope[" "]];
fingerStream.Put[IO.time[entry.time], IO.rope["\n"]] };
MachinePropChange => {
fingerStream.Put[IO.atom[machinePropChangeAtom], IO.rope[" "]];
fingerStream.Put[IO.rope[Convert.RopeFromRope[entry.machine]], IO.rope[" "]];
fingerStream.Put[IO.rope[Convert.RopeFromRope[entry.name]], IO.rope[" "]];
fingerStream.Put[IO.rope[Convert.RopeFromRope[entry.val]], IO.rope["\n"]] };
AddMachineProp => {
fingerStream.Put[IO.atom[addMachinePropAtom], IO.rope[" "]];
fingerStream.Put[IO.rope[Convert.RopeFromRope[entry.name]], IO.rope[" "]];
fingerStream.Put[IO.int[entry.version], IO.rope["\n"]] };
AddUserProp => {
fingerStream.Put[IO.atom[addUserPropAtom], IO.rope[" "]];
fingerStream.Put[IO.rope[Convert.RopeFromRope[entry.name]], IO.rope[" "]];
fingerStream.Put[IO.int[entry.version], IO.rope["\n"]] };
DeleteUserProp => {
fingerStream.Put[IO.atom[deleteUserPropAtom], IO.rope[" "]];
fingerStream.Put[IO.rope[Convert.RopeFromRope[entry.name]], IO.rope[" "]];
fingerStream.Put[IO.int[entry.version], IO.rope["\n"]] };
DeleteMachineProp => {
fingerStream.Put[IO.atom[deleteMachinePropAtom], IO.rope[" "]];
fingerStream.Put[IO.rope[Convert.RopeFromRope[entry.name]], IO.rope[" "]];
fingerStream.Put[IO.int[entry.version], IO.rope["\n"]]};
ENDCASE;
fingerStream.Flush[] };
ParseLog: PUBLIC PROC[] RETURNS[ stateLog: LIST OF LogEntry ] ~ {
ENABLE FS.Error => GOTO Quit;
IF fingerStream # NIL THEN fingerStream.Close[];
fingerStream ← FS.StreamOpen[fingerLogName, $read];
BEGIN
ENABLE IO.EndOfStream, IO.Error => CONTINUE;
op: ATOM;
nextEntry: LogEntry;
WHILE TRUE DO
op ← fingerStream.GetAtom[];
SELECT op FROM
stateChangeAtom => {
what: ATOM = fingerStream.GetAtom[];
name: Rope.ROPE = fingerStream.GetRopeLiteral[];
when: BasicTime.GMT = fingerStream.GetTime[];
nextEntry ← NEW[ StateChange LogEntryObject ← [StateChange[event: IF what = $login THEN login ELSE logout, user: name, time: when ]] ] };
userPropChangeAtom => {
user: Rope.ROPE = fingerStream.GetRopeLiteral[];
name: Rope.ROPE = fingerStream.GetRopeLiteral[];
val: Rope.ROPE = fingerStream.GetRopeLiteral[];
time: BasicTime.GMT = fingerStream.GetTime[];
nextEntry ← NEW[ UserPropChange LogEntryObject ← [UserPropChange[user: user, name: name, val: val, time: time ]] ] };
machinePropChangeAtom => {
machine: Rope.ROPE = fingerStream.GetRopeLiteral[];
name: Rope.ROPE = fingerStream.GetRopeLiteral[];
val: Rope.ROPE = fingerStream.GetRopeLiteral[];
nextEntry ← NEW[ MachinePropChange LogEntryObject ← [MachinePropChange[machine: machine, name: name, val: val]] ] };
addMachinePropAtom => {
name: Rope.ROPE = fingerStream.GetRopeLiteral[];
version: INT = fingerStream.GetInt[];
nextEntry ← NEW[ AddMachineProp LogEntryObject ← [AddMachineProp[name: name, version: version]] ] };
addUserPropAtom => {
name: Rope.ROPE = fingerStream.GetRopeLiteral[];
version: INT = fingerStream.GetInt[];
nextEntry ← NEW[ AddUserProp LogEntryObject ← [AddUserProp[name: name, version: version]] ] };
deleteUserPropAtom => {
name: Rope.ROPE = fingerStream.GetRopeLiteral[];
version: INT = fingerStream.GetInt[];
nextEntry ← NEW[ DeleteUserProp LogEntryObject ← [DeleteUserProp[name: name, version: version]] ] };
deleteMachinePropAtom => {
name: Rope.ROPE = fingerStream.GetRopeLiteral[];
version: INT = fingerStream.GetInt[];
nextEntry ← NEW[ DeleteMachineProp LogEntryObject ← [DeleteMachineProp[name: name, version: version]] ] };
ENDCASE;
IF stateLog = NIL THEN stateLog ← LIST[nextEntry]
ELSE {
log: LIST OF LogEntry ← stateLog;
WHILE log.rest # NIL DO log ← log.rest ENDLOOP;
log.rest ← LIST[nextEntry]
}
ENDLOOP
END;
fingerStream.Close[! IO.Error, FS.Error => CONTINUE];
fingerStream ← NIL
EXITS
Quit => {IF fingerStream # NIL THEN fingerStream.Close[! IO.Error, FS.Error => CONTINUE]; fingerStream ← NIL}
};
END.