WalnutStream.Mesa
Copyright Ó 1984, 1988, 1992 by Xerox Corporation. All rights reserved.
Willie-Sue, December 13, 1988 11:54:24 am PST
Contents: types and procedures which take an explicit stream parameter
DIRECTORY
IO USING [STREAM],
MailBasics USING [RName, Timestamp],
Rope USING [ROPE],
ViewerTools USING [TiogaContents],
WalnutKernelDefs USING [LogEntry, MsgLogEntry, LogEntryObject];
WalnutStream: CEDAR DEFINITIONS =
BEGIN
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
LogEntry: TYPE = WalnutKernelDefs.LogEntry;
LogEntryObject: TYPE = WalnutKernelDefs.LogEntryObject;
MsgLogEntry: TYPE = WalnutKernelDefs.MsgLogEntry;
Opening streams (log files are assumed to be on alpine servers, but that is enforced by the higher levels)
Open: PROC[name: ROPE, readOnly: BOOL ¬ FALSE, pages: INT ¬ 200,
  useOldIfFound: BOOL ¬ FALSE, exclusive: BOOL ¬ FALSE] RETURNS [strm: STREAM];
if exclusive then an file is opened in [$write, $fail] mode (not used by WalnutRoot)
Miscellaneous stream operations
Aborted: PROC [strm: STREAM] RETURNS [aborted: BOOL];
AbortStream: PROC [strm: STREAM];
FlushStream: PROC[strm: STREAM, setCreateDate: BOOL¬ FALSE];
flushes the stream and sets the create date to BasicTime.Now if requested
SetHighWaterMark: PROC[
 strm: STREAM, hwmBytes: INT, numPages: INT, setCreateDate: BOOL ¬ FALSE];
sets the high water mark and length for an alpine file; if the length of the file is more than numPages, then it is truncated to that length; if numPages = -1, don't change the page count
SetPosition: PROC[strm: STREAM, index: INT] RETURNS[ok: BOOL];
set the index on the stream, returns FALSE if index is beyond EndOfStream; if index = -1 then position to end
ReadRope: PROC[strm: STREAM, len: INT] RETURNS[ROPE];
reads a ROPE from strm, starting at the current position; returns NIL IF EndOfStream was encountered
Reading and writing log entries
FindNextEntry: PROC[strm: STREAM] RETURNS[startPos: INT];
find the next entry, starting at the current position of the stream, returns -1 if there are no more entries
ReadEntry: PROC[strm: STREAM, quick: BOOL ¬ FALSE]
RETURNS[le: LogEntry, length: INT];
returns NIL if there is not a valid entry at pos, and doesn't change the log position. The stream will be positioned just beyond the entry. If the entry contains a log position, logicalStart is added to it. If quick is TRUE, a message does not get its headers parsed; the length of the headers is returned instead.
PeekEntry: PROC[strm: STREAM, quick: BOOL]
RETURNS[ident: ATOM, msgID: ROPE, length: INT];
returns ident = NIL if there is not a valid entry at the current log position. The stream index is NOT advanced by this operation. The length is the length of the entire entry, not just that portion of it read in this operation.
Does not check if ident is for a legal log entry, allowing parsing of "illegal" logs
if quick then don't return msgID (so don't have to make a rope)
WriteEntry: PROC[strm: STREAM, le: LogEntry, pos: INT ¬ -1] RETURNS[startPos: INT];
startPos (of the entry just written) is needed by the code which reads messages from grapevine
WalnutStream provides a set of pre-allocated LogEntry records that can be filled in for use with WriteEntry
logInfoRef: LogInfoRef;
LogInfoRef: TYPE = REF LogInfoArray;
LogInfoArray: TYPE = RECORD[
logFileInfo: REF LogFileInfo LogEntryObject,
createMsg: REF CreateMsg LogEntryObject,
expungeMsgs: REF ExpungeMsgs LogEntryObject,
writeExpungeLog: REF WriteExpungeLog LogEntryObject,
createMsgSet: REF CreateMsgSet LogEntryObject,
emptyMsgSet: REF EmptyMsgSet LogEntryObject,
destroyMsgSet: REF DestroyMsgSet LogEntryObject,
addMsg: REF AddMsg LogEntryObject,
removeMsg: REF RemoveMsg LogEntryObject,
moveMsg: REF MoveMsg LogEntryObject,
hasbeenRead: REF HasBeenRead LogEntryObject,
recordNewMailInfo: REF RecordNewMailInfo LogEntryObject,
startCopyNewMail: REF StartCopyNewMail LogEntryObject,
endCopyNewMailInfo: REF EndCopyNewMailInfo LogEntryObject,
acceptNewMail: REF AcceptNewMail LogEntryObject,
startReadArchiveFile: REF StartReadArchiveFile LogEntryObject,
endReadArchiveFile: REF EndReadArchiveFile LogEntryObject,
startCopyReadArchive: REF StartCopyReadArchive LogEntryObject,
endCopyReadArchiveInfo: REF EndCopyReadArchiveInfo LogEntryObject,
endOfLog: REF EndOfLog LogEntryObject
];
WriteMsgBody: PROC[strm: STREAM, body: ViewerTools.TiogaContents];
writes body on at the end of strm, followed by a CR
Overwrite: PROC[to, from: STREAM, startPos: INT, fromPos: INT¬ -1];
if startPos is -1 then writing is done at the end of to, if fromPos is -1 then don't reposition from
CopyBytes: PROC[from, to: STREAM, num: INT];
copies num bytes from from to to
MsgEntryInfoFromStream: PROC[strm: STREAM, mle: MsgLogEntry];
parses the headers (that walnut is interested in) of a msg directly from stream
procedures for trafficking in the various possible representations of an entity name
IdOnFileWithSender: PROC[ts: MailBasics.Timestamp, sender: MailBasics.RName] RETURNS[idOnFile: ROPE];
MsgNameFromIdOnFile: PROC[strm: STREAM] RETURNS[msg: ROPE];
END.