CinderSysOpsImpl.mesa
Copyright Ó 1987, 1989, 1991 by Xerox Corporation. All rights reserved.
Russ Atkinson (RRA) November 20, 1987 4:45:58 pm PST
Andy Litman February 16, 1988 11:39:36 pm PST
JKF July 22, 1989 3:58:35 pm PDT
DIRECTORY
BasicTime USING [GMT, nullGMT],
CinderSysOps USING [Interceptor, OpenKind],
FS USING [Delete, Error, GetInfo, GetName, OpenFile, OpenFileFromStream, StreamOpen],
IO USING [Close, Error, STREAM],
Rope USING [ROPE];
CinderSysOpsImpl: CEDAR MONITOR
IMPORTS FS, IO
EXPORTS CinderSysOps
= BEGIN
GMT: TYPE = BasicTime.GMT;
nullGMT: GMT = BasicTime.nullGMT;
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
currentInterceptor: CinderSysOps.Interceptor ¬ NIL;
openList: OpenStreamList ¬ NIL;
OpenStreamList: TYPE = LIST OF OpenStreamEntry;
OpenStreamEntry: TYPE = RECORD [stream: STREAM, kind: CinderSysOps.OpenKind];
Intercept: PUBLIC ENTRY PROC [interceptor: CinderSysOps.Interceptor] RETURNS [old: CinderSysOps.Interceptor] = {
old ¬ currentInterceptor;
currentInterceptor ¬ interceptor;
};
Open: PUBLIC PROC [name: ROPE, kind: CinderSysOps.OpenKind]
RETURNS [stream: STREAM ¬ NIL, err: ROPE ¬ NIL, time: GMT ¬ nullGMT] = {
interceptor: CinderSysOps.Interceptor ¬ currentInterceptor;
IF interceptor # NIL AND interceptor.open # NIL
THEN
[stream, err, time] ¬ interceptor.open[interceptor, name, kind]
ELSE {
FS supplies the default operation
ENABLE FS.Error => {err ¬ error.explanation; GO TO oops};
st: STREAM ¬ FS.StreamOpen[
fileName: name,
accessOptions: IF kind = read THEN $read ELSE $create];
time ¬ FS.GetInfo[FS.OpenFileFromStream[st]].created;
stream ¬ st;
};
IF err = NIL THEN AddToList[stream, kind];
EXITS oops => {};
};
Close: PUBLIC PROC [stream: STREAM, abortAndDelete: BOOL] RETURNS [err: ROPE] = {
interceptor: CinderSysOps.Interceptor ¬ currentInterceptor;
kind: CinderSysOps.OpenKind;
[stream, kind] ¬ RemFromList[stream];
IF stream = NIL THEN RETURN;
IF interceptor # NIL AND interceptor.close # NIL
THEN
err ¬ interceptor.close[interceptor, stream, abortAndDelete]
ELSE {
FS supplies the default operation
ENABLE {
FS.Error => {err ¬ error.explanation; GO TO exit};
IO.Error => GO TO exit;
};
file: FS.OpenFile ¬ FS.OpenFileFromStream[stream];
name: ROPE ¬ FS.GetName[file].fullFName;
time: BasicTime.GMT ¬ FS.GetInfo[file].created;
SELECT kind FROM
read, writeLog => IO.Close[stream];
ENDCASE => {
IO.Close[stream, abortAndDelete];
IF abortAndDelete THEN FS.Delete[name, time];
};
};
EXITS exit => {};
};
Delete: PUBLIC PROC [name: ROPE] RETURNS [err: ROPE] = {
interceptor: CinderSysOps.Interceptor ¬ currentInterceptor;
IF interceptor # NIL AND interceptor.delete # NIL
THEN err ¬ interceptor.delete[interceptor, name]
ELSE FS.Delete[name ! FS.Error => {err ¬ error.explanation; CONTINUE}];
};
Cleanup: PUBLIC PROC [abortAndDelete: BOOL] = {
DO
sample: OpenStreamList ¬ openList;
IF sample = NIL THEN EXIT;
[] ¬ Close[sample.first.stream, abortAndDelete];
ENDLOOP;
};
RemFromList: ENTRY PROC [stream: STREAM]
RETURNS [st: STREAM ¬ NIL, kind: CinderSysOps.OpenKind ¬ read] = {
lag: OpenStreamList ¬ openList;
IF lag # NIL THEN {
IF lag.first.stream = stream THEN {
st ¬ stream;
kind ¬ lag.first.kind;
openList ¬ lag.rest;
RETURN;
};
DO
next: OpenStreamList ¬ lag.rest;
IF next = NIL THEN EXIT;
IF next.first.stream = stream THEN {
st ¬ stream;
kind ¬ next.first.kind;
lag.rest ¬ next.rest;
RETURN;
};
lag ¬ next;
ENDLOOP;
};
};
AddToList: ENTRY PROC [stream: STREAM, kind: CinderSysOps.OpenKind] = {
openList ¬ CONS[ [stream, kind], openList];
};
END.