MoreFileSetsImpl.Mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Last Edited by: Spreitzer, February 11, 1986 12:51:53 pm PST
DIRECTORY ArchivistBTreePublic, Basics, BasicTime, Convert, DFUtilities, FileSets, FileSetsPrivate, FS, IO, MoreFileSets, Process, RedBlackTree, Rope, Tempus, TextFind, TextReplace, TiogaOps, ViewerClasses, ViewerTools, WalnutWindow;
MoreFileSetsImpl: CEDAR PROGRAM
IMPORTS ArchivistBTreePublic, BasicTime, Convert, FileSets, FileSetsPrivate, FS, IO, Process, Rope, Tempus, TiogaOps, WalnutWindow
EXPORTS MoreFileSets
={OPEN FileSets, FileSetsPrivate, MoreFileSets;
Filters:
BTree: TYPE = REF BTreeRec;
BTreeRec: TYPE = RECORD [h: ArchivistBTreePublic.Handle];
IsArchived: PUBLIC PROC [--caches current BTree--] RETURNS [f: Filter] = {
f ← NEW [FilterRep ← [TestArchive, NEW [BTreeRec ← [ArchivistBTreePublic.OpenBTree[] ]] ]];
};
TestArchive: PROC [fn: FileNote, data: REF ANY] RETURNS [BOOL] = {
bt: BTree ← NARROW[data];
created: GMT ← GetCreated[fn];
cp: FS.ComponentPositions ← FS.ExpandName[fn.fsName].cp;
SELECT cp.ver.length FROM
=0 => {
fil: ArchivistBTreePublic.FileInfoList ← ArchivistBTreePublic.EnumerateRecord[bt.h, fn.fsName, created];
RETURN [fil # NIL];
};
#0 => RETURN [ArchivistBTreePublic.ReadFileInfo[bt.h, fn.fsName, created] # NIL];
ENDCASE => ERROR;
};
Primitive Enumerations:
FindByDate: PROC [date: GMT] RETURNS [v: Viewer] = {
list: LIST OF Viewer ← WalnutWindow.EnumWalnutViewers[keepSeparate: TRUE].msgList;
FOR list ← list, list.rest WHILE list # NIL DO {
root: TiogaOps.Ref ← TiogaOps.ViewerDoc[list.first];
curNode: TiogaOps.Ref ← root;
FOR curNode: TiogaOps.Ref ← TiogaOps.StepForward[root], TiogaOps.StepForward[curNode] WHILE curNode # NIL DO
from: STREAMIO.RIS[TiogaOps.GetRope[curNode].Cat["\n"]];
FOR i: INT ← from.SkipWhitespace[], from.SkipWhitespace[] WHILE NOT from.EndOf[] DO
keyword: ROPE ← from.GetTokenRope[MyBreak].token;
Process.CheckForAbort[];
IF keyword.Equal["Date:", FALSE] THEN {
restOfLine: ROPE ← from.GetLineRope[];
thisDate: GMT ← Tempus.Parse[restOfLine].time;
IF thisDate = date THEN RETURN [list.first] ELSE GOTO NotThisOne;
};
IF keyword.Fetch[keyword.Length[]-1] # ': THEN GOTO NotThisOne;
IF keyword.Equal["Archived:"] OR keyword.Equal["Archive:"] OR keyword.Equal["Retrieved:"] OR keyword.Equal["Retrieve:"] THEN GOTO NotThisOne;
[] ← from.GetLineRope[];
ENDLOOP;
ENDLOOP;
SIGNAL Warning[IO.PutFR["No date in Walnut message viewer named %g", IO.refAny[list.first.name]]];
EXITS
NotThisOne => NULL;
} ENDLOOP;
SIGNAL Warning[IO.PutFR["no message viewer on an archive message dated %g", IO.time[date]]];
v ← NIL;
};
FromArchiveMsg: PUBLIC PROC [date: GMT, which: ArchiveWhich, ids: IdentificationScheme ← []] RETURNS [fs: FileSet] = {
Add: PROC [fn: FileNote] --FileConsumer-- = {[] ← Insert[fs, fn]};
fs ← NewFileSet[ids];
EnumArchiveMsg[date, Add, which, ids];
fs.summary ← Convert.RopeFromInt[fs.Size[]];
};
ParseError: ERROR [message: ROPE] = CODE;
EnumArchiveMsg: PUBLIC PROC [date: GMT, to: FileConsumer, which: ArchiveWhich, ids: IdentificationScheme ← []] = {
heading: BOOLTRUE;
v: Viewer ← FindByDate[date];
root, curNode: TiogaOps.Ref;
IF v = NIL THEN RETURN;
root ← TiogaOps.ViewerDoc[v];
curNode ← root;
FOR curNode: TiogaOps.Ref ← TiogaOps.StepForward[root], TiogaOps.StepForward[curNode] WHILE curNode # NIL DO
from: STREAMIO.RIS[TiogaOps.GetRope[curNode].Cat["\n"]];
Skip: PROC [toke: ROPE] = {
got: ROPE ← from.GetTokenRope[MyBreak].token;
IF NOT got.Equal[toke] THEN ERROR ParseError[IO.PutFR["Got %g instead of %g in archive message of %g", IO.refAny[got], IO.refAny[toke], IO.time[date]]];
};
InsistEOL: PROC = {
c: CHAR ← from.GetChar[];
IF c # '\n THEN ERROR ParseError[IO.PutFR["Got %g instead of newline in archive message of %g", IO.char[c], IO.time[date]]];
};
FOR i: INT ← from.SkipWhitespace[], from.SkipWhitespace[] WHILE NOT from.EndOf[] DO
ENABLE ParseError => {SIGNAL Warning[message]; EXIT};
keyword: ROPE ← from.GetTokenRope[MyBreak].token;
Process.CheckForAbort[];
IF keyword.Equal["Archived:"] THEN {
fileName, pv, bv: ROPE;
gmt: GMT;
fn: FileNote;
heading ← FALSE;
fileName ← from.GetTokenRope[MyBreak].token;
Skip["of"];
gmt ← from.GetTime[];
Skip["on"];
pv ← from.GetTokenRope[MyBreak].token;
Skip["or"];
bv ← from.GetTokenRope[MyBreak].token;
InsistEOL[];
IF (fn ← CreateNote[fileName: fileName, created: gmt, ids: ids]) # NIL THEN {
fn.primaryVolume ← pv;
fn.backupVolume ← bv;
to[fn];
};
} ELSE
IF keyword.Equal["Retrieved:"] THEN {
fromName, toName: ROPE;
gmt: GMT;
fn: FileNote;
heading ← FALSE;
fromName ← from.GetTokenRope[MyBreak].token;
Skip["of"];
gmt ← from.GetTime[];
Skip["as"];
toName ← from.GetTokenRope[MyBreak].token;
InsistEOL[];
IF (fn ← CreateNote[fileName: SELECT which FROM archive => fromName, online => toName, ENDCASE => ERROR, created: gmt, ids: ids]) # NIL THEN to[fn];
} ELSE
IF keyword.Equal["Archive:"] THEN {
fileName: ROPE;
fn: FileNote;
heading ← FALSE;
fileName ← from.GetTokenRope[MyBreak].token;
InsistEOL[];
IF HasWildcards[fileName] THEN {
Consume: PROC [fullFName: ROPE] RETURNS [continue: BOOL] --FS.NameProc-- = {
IF (fn ← CreateNote[fullFName, noGMT, ids]) # NIL THEN to[fn];
continue ← TRUE};
FS.EnumerateForNames[fileName, Consume];
}
ELSE {
IF (fn ← CreateNote[fileName, noGMT, ids]) # NIL THEN to[fn];
};
} ELSE
IF keyword.Equal["Retrieve:"] THEN {
fileName, pv, bv: ROPE;
gmt: GMT;
fn: FileNote;
heading ← FALSE;
fileName ← from.GetTokenRope[MyBreak].token;
Skip["of"];
gmt ← from.GetTime[];
Skip["from"];
pv ← from.GetTokenRope[MyBreak].token;
Skip["or"];
bv ← from.GetTokenRope[MyBreak].token;
InsistEOL[];
IF (fn ← CreateNote[fileName, gmt, ids]) # NIL THEN {
fn.primaryVolume ← pv;
fn.backupVolume ← bv;
to[fn];
};
} ELSE
{
IF NOT heading THEN ERROR ParseError[IO.PutFR["Got non-archiving keyword %g among archiving keywords in archive message of %g", IO.rope[keyword], IO.time[date]]];
IF keyword.Length[] = 0 THEN ERROR;
IF keyword.Fetch[keyword.Length[]-1] # ': THEN ERROR ParseError[IO.PutFR["Found non-keyword %g in archive message of %g", IO.refAny[keyword], IO.time[date]]];
[] ← from.GetLineRope[];
};
ENDLOOP;
from.Close[];
ENDLOOP;
};
HasWildcards: PROC [fileName: ROPE] RETURNS [hasem: BOOL] =
{hasem ← fileName.Find["*"] >= 0};
MyBreak: PROC [char: CHAR] RETURNS [cc: IO.CharClass] --IO.BreakProc-- = {
cc ← IF char IN ['\000 .. ' ] THEN sepr ELSE other;
};
RefineTime: PROC [fileName: ROPE, date: DFUtilities.Date] RETURNS [gmt: GMT] = {
SELECT date.format FROM
explicit => RETURN [date.gmt];
omitted, greaterThan, notEqual => RETURN [GetGMT[fileName]];
ENDCASE => ERROR;
};
GetGMT: PROC [fileName: ROPE] RETURNS [created: GMT] = {
ok: BOOLTRUE;
[created: created] ← FS.FileInfo[name: fileName, remoteCheck: FALSE !FS.Error => {ok ← FALSE; CONTINUE}];
IF NOT ok THEN created ← noGMT;
};
FromArchivist: PUBLIC PROC [pattern: ROPE, created: GMT ← noGMT, ids: IdentificationScheme ← []] RETURNS [fs: FileSet] = {
Add: PROC [fn: FileNote] = {[] ← Insert[fs, fn]};
fs ← NewFileSet[ids];
EnumArchivist[pattern, Add, created, ids];
fs.summary ← Convert.RopeFromInt[fs.Size[]];
};
EnumArchivist: PUBLIC PROC [pattern: ROPE, to: FileConsumer, created: GMT ← noGMT, ids: IdentificationScheme ← []] = {
Enumerate: PROC [pattern: ROPE, Consume: Consumer] = {
h: ArchivistBTreePublic.Handle ← ArchivistBTreePublic.OpenBTree[];
fil: ArchivistBTreePublic.FileInfoList;
fil ← h.EnumerateRecord[pattern, created];
h.CloseBTree[];
FOR fil ← fil, fil.next WHILE fil # NIL DO
primaryVolume, backupVolume: ROPE;
vs: IO.STREAMIO.RIS[fil.volumes];
{ENABLE
IO.EndOfStream => IF stream = vs THEN {
SIGNAL Warning[IO.PutFR["Archivist thinks %g of %g has less than two volumes; tell Tim Diebert", IO.rope[fil.fileName], IO.time[fil.created]]];
CONTINUE};
primaryVolume ← vs.GetTokenRope[IO.IDProc].token;
backupVolume ← vs.GetTokenRope[IO.IDProc].token;
};
vs.Close[];
SELECT fil.state FROM
none, pending, backup => NULL;
complete => Consume[fil.fileName, fil.created, primaryVolume, backupVolume];
ENDCASE => ERROR;
ENDLOOP;
h ← h;
};
Consume: PROC [fullFName: ROPE, created: GMT, primaryVolume, backupVolume: ROPE] = {
fn: FileNote ← CreateNote[fullFName, created, ids];
IF fn # NIL THEN {
fn.primaryVolume ← primaryVolume;
fn.backupVolume ← backupVolume;
to[fn];
};
};
HashEnumerate[pattern, Enumerate, Consume];
};
}.