WalnutDB.mesa
Copyright Ó 1984, 1987, 1988, 1992 by Xerox Corporation. All rights reserved.
Willie-Sue, November 14, 1988 12:52:34 pm PST
Donahue, May 12, 1986 1:43:10 pm PDT
Jack Kent, May 29, 1987 10:51:02 pm PDT
Doug Terry, November 7, 1989 2:37:04 pm PST
Contents: types and procedures dealing with the Walnut message database
Initiated by Donahue, 19 April 1983
(Changed ShiftMsgPosition to SetMsgEntryPosition to reflect change in dealing with absolute log positions)
(Added operations to set and get new mail and read archive log information -- used on restart)
DIRECTORY
BasicTime USING [GMT],
LoganBerry USING [Cursor],
Rope USING [ROPE, Equal],
ViewerTools USING [TiogaContents],
WalnutDefs USING [CheckReportProc, dontCareDomainVersion, dontCareMsgSetVersion, MsgSet, SeFromToCcSuDaMid, ServerInfo, WalnutOpsHandle],
WalnutKernelDefs USING [LogExpungePhase, MsgLogEntry];
WalnutDB: CEDAR DEFINITIONS
IMPORTS Rope =
BEGIN
Types
ROPE: TYPE = Rope.ROPE;
GMT: TYPE = BasicTime.GMT;
TiogaContents: TYPE = ViewerTools.TiogaContents;
MsgSet: TYPE = WalnutDefs.MsgSet;  -- [ROPE, INT]
WalnutOpsHandle: TYPE = WalnutDefs.WalnutOpsHandle;
CheckReportProc: TYPE = WalnutDefs.CheckReportProc;
dontCareDomainVersion: INT = WalnutDefs.dontCareDomainVersion;
dontCareMsgSetVersion: INT = WalnutDefs.dontCareMsgSetVersion;
LogExpungePhase: TYPE = WalnutKernelDefs.LogExpungePhase;
ServerInfo: TYPE = WalnutDefs.ServerInfo;
LazyEnumerator: TYPE = REF LazyEnumeratorRec;
LazyEnumeratorRec: TYPE;
GeneralEnumerator: TYPE = REF GeneralEnumeratorRec;
GeneralEnumeratorRec: PUBLIC TYPE = RECORD[
opsH: WalnutOpsHandle,
cursor: LoganBerry.Cursor
];
SeFromToCcSuDaMid: TYPE = WalnutDefs.SeFromToCcSuDaMid;
EntryRef: TYPE = REF EntryObject;
EntryObject: TYPE = RECORD [seFromToCcSuDaMid: SeFromToCcSuDaMid, msgSetName: ROPE];
Operations on Messages
MsgExists: PROC[opsH: WalnutOpsHandle, msg: ROPE] RETURNS [existed: BOOL];
Does a message with this name exist in the database.
DestroyMsg is not allowed; this is ONLY done by the Expunge operation
GetIsInReplyTo: PROC [opsH: WalnutOpsHandle, msg: ROPE] RETURNS[isInReplyTo: BOOL];
returns TRUE if the subject field of this message started with "Re: "
GetHasBeenRead: PROC[opsH: WalnutOpsHandle, msg: ROPE] RETURNS[BOOL];
returns TRUE if the mHasBeenReadIs attribute for msg is TRUE
SetHasBeenRead: PROC[opsH: WalnutOpsHandle, msg: ROPE];
sets the mHasBeenReadIs attribute for msg to TRUE (no check on old value)
AddNewMsg: PROC[opsH: WalnutOpsHandle, msg: WalnutKernelDefs.MsgLogEntry] RETURNS[mExisted: BOOL];
takes a parsed message from the log & puts it in the database -- if the message already existed in the database, then return TRUE. Note: this guy takes the LogEntry given and has the responsibility for constructing the TOCEntry and herald for the message
GetMsgEntryPosition: PROC[opsH: WalnutOpsHandle, msg: ROPE] RETURNS[pos: INT];
returns the log position for the entry for this message (-1 if the message doesn't exist); used by the lazy evaluator
SetMsgEntryPosition: PROC[opsH: WalnutOpsHandle, to: INT];
Change the message position from what it previously was to the new position; uses a one-entry cache, set by MsgExists, which MUST be called just before SetMsgEntryPosition - this is used by the Expunge code
GetMsgDate: PROC[opsH: WalnutOpsHandle, msg: ROPE] RETURNS[date: GMT];
returns the date by which the message is indexed in the database
GetMsgTextInfo: PROC[opsH: WalnutOpsHandle, msg: ROPE]
RETURNS[textStart, textLen, formatLen: INT];
returns information needed to get the tioga text for msg from log
GetMsgText: PROC[opsH: WalnutOpsHandle, msg: ROPE] RETURNS[textStart, textLen, formatLen: INT, herald: ROPE, shortNameLen: INT];
returns information needed to get the tioga text for msg from log (also produces the herald to be used if displaying it in a viewer
GetDisplayProps: PROC[opsH: WalnutOpsHandle, msg: ROPE] RETURNS [hasBeenRead: BOOL, tocEntry: ROPE, startOfSubject: INT];
Return the display properties of a message (the hasbeenread flag and the table of contents entry, and where in TOCentry the subject field begins.
GetCategories: PROC[opsH: WalnutOpsHandle, msg: ROPE] RETURNS [ms: LIST OF ROPE];
Return the display properties of a message (the hasbeenread flag and the table of contents entry.
EqMsg: PROC[msg1, msg2: ROPE] RETURNS [BOOL] =
INLINE{ RETURN[Rope.Equal[msg1, msg2, FALSE]] };
SizeOfDatabase: PROC[opsH: WalnutOpsHandle] RETURNS[messages, msgSets: INT];
returns the number of messages in the database
Operations on Message Sets
MsgSetExists: PROC[opsH: WalnutOpsHandle, name: ROPE, msDomainVersion: INT]
RETURNS [existed: BOOL, msVersion: INT];
Does this message set already exist in the database.
CreateMsgSet: PROC[opsH: WalnutOpsHandle, name: ROPE, msDomainVersion: INT]
RETURNS [existed: BOOL, msVersion: INT];
NumInMsgSet: PROC[opsH: WalnutOpsHandle, name: ROPE] RETURNS[num: INT, msVersion: INT];
EmptyMsgSet: PROC[opsH: WalnutOpsHandle, msgSet: MsgSet, report: CheckReportProc]
RETURNS[someInDeleted: BOOL];
Removes any messages from msgSet. Commits periodically.
DestroyMsgSet: PROC[opsH: WalnutOpsHandle, msgSet: MsgSet, msDomainVersion: INT, report: CheckReportProc]
RETURNS[someInDeleted: BOOL];
Destroys the given msgSet, removing any messages from it first. If the message set is "Deleted" then does nothing. Commits periodically.
VerifyMsgSet: PROC[opsH: WalnutOpsHandle, msgSet: MsgSet] RETURNS[exists: BOOL];
Raises VersionMismatch if the version number is wrong.
VerifyDomainVersion: PROC[opsH: WalnutOpsHandle, msDomainVersion: INT];
Raises VersionMismatch if the msgSetDomain version number is wrong.
ExpungeMsgs: PROC[opsH: WalnutOpsHandle, deletedVersion: INT, report: CheckReportProc];
Destroys messages in the Deleted message set. Commits periodically.
MsgsEnumeration: PROC[opsH: WalnutOpsHandle, alphaOrder: BOOL¬ TRUE]
RETURNS[mL: LIST OF ROPE];
MsgSetsNames: PROC[opsH: WalnutOpsHandle, alphaOrder: BOOL¬ TRUE]
RETURNS[msL: LIST OF ROPE, msDomainVersion: INT];
MsgsInSetEnumeration: PROC[opsH: WalnutOpsHandle, name: ROPE, fromStart: BOOL¬ TRUE]
RETURNS [mL: LIST OF ROPE, msVersion: INT];
If msgSet is "Active", only the "accepted" messages are returned
EnumerateMsgSets: PROC [opsH: WalnutOpsHandle, alphaOrder: BOOL ¬ TRUE, proc: PROC[msgSet: MsgSet] RETURNS[continue: BOOL] ]
RETURNS [msDomainVersion: INT];
EnumerateMsgsInSet: PROC [
opsH: WalnutOpsHandle,
name: ROPE,
fromStart: BOOL ¬ TRUE,
proc: PROC[msg, tocEntry: ROPE, hasBeenRead: BOOL, startOfSubject: INT] RETURNS[continue: BOOL] ]
RETURNS [msVersion: INT];
for each msg in msgSet, will call proc with the indicated information about the msg;
raises WalnutDefs.Error if the enumeration fails
If msgSet is "Active", then only the "accepted" messages are enumerated
GenerateEntriesPlusDate: PROC [
opsH: WalnutOpsHandle,
attr: ATOM,
start: ROPE ¬ NIL,
end: ROPE ¬ NIL,
dateStart: ROPE ¬ NIL,
dateEnd: ROPE ¬ NIL ]
RETURNS [genEnum: GeneralEnumerator];
a lot like EnumerateMsgsInMsgSet, but more general...
NextEntry: PROC[genEnum: GeneralEnumerator] RETURNS[entry: EntryRef];
if msgID is NIL and valid is true, then the enumeration is finished; if valid is false, the msgSet version numbers don't match
EnumerateMsgsInMsgSet: PROC[opsH: WalnutOpsHandle, msgSet: MsgSet] RETURNS [lazyEnum: LazyEnumerator];
a lazy enumerator for the messages in the msgSet name, at the time of the call. The enumerator is valid until the next time the msgSet's version changes (by adding or deleting msgs); its use after that will cause a WalnutDefs.Error with code $InvalidEnumerator. See NextMsgInMsgSet for details. valid will be false if the msgSet versions don't match
NextMsgInMsgSet: PROC[lazyEnum: LazyEnumerator] RETURNS[msgID: ROPE, valid: BOOL];
if msgID is NIL and valid is true, then the enumeration is finished; if valid is false, the msgSet version numbers don't match
EnumerateUnacceptedMsgs: PROC[ opsH: WalnutOpsHandle, activeVersion: INT, proc: PROC[msg, tocEntry: ROPE, startOfSubject: INT] ];
for each unaccepted msg, will call proc with the indicated information about the msg;
raises WalnutDefs.Error if the enumeration fails
EqMsgSets: PROC[msgSet1, msgSet2: ROPE] RETURNS [BOOL] =
INLINE{ RETURN[Rope.Equal[msgSet1, msgSet2, FALSE]] };
MsgSetsInfo: PROC[opsH: WalnutOpsHandle] RETURNS[version, num: INT];
changes when msgSets are created or destroyed
Operations to Move Messages Among Message Sets
AddMsg: PROC[opsH: WalnutOpsHandle, msg: ROPE, from, to: MsgSet]
RETURNS[exists: BOOL];
Adds Msg to MsgSet, if it's not already in it. IF msgSet=deletedMsgSet, does nothing and returns existed=FALSE
RemoveMsg: PROC[opsH: WalnutOpsHandle, msg: ROPE, from: MsgSet, deletedVersion: INT]
RETURNS[deleted: BOOL];
IF removing msg from msgSet would leave it in no MsgSet, then msg gets added to the distinguished MsgSet Deleted, and returns deleted = TRUE
MoveMsg: PROC[opsH: WalnutOpsHandle, msg: ROPE, from, to: MsgSet] RETURNS [exists: BOOL];
Move the message. Note that the result of a move may be that a message becomes deleted (if to was the Deleted message set) or undeleted (if from is the Deleted message set)
AcceptNewMail: PROC[opsH: WalnutOpsHandle, pos: INT, activeVersion: INT];
makes new messages visible to the outside world. Commits periodically.
Other operations
DeclareDB: PROC[opsH: WalnutOpsHandle, schemaInvalid: BOOL] RETURNS[ok: BOOL];
This procedure need only be called once. Of course, if the readOnly status changes DeclareDB[] will have to be called again to establish the new values.
InitSchema: PROC[opsH: WalnutOpsHandle, schemaInvalid: BOOL ¬ TRUE] RETURNS[ok: BOOL];
must be called after doing an erase
GetRootInfo: PROC[opsH: WalnutOpsHandle] RETURNS[dbRootCreateDate: GMT, dbFileKey, dbMailFor: ROPE];
SetRootInfo: PROC[opsH: WalnutOpsHandle, dbRootCreateDate: GMT, dbFileKey, dbMailFor: ROPE];
GetRootFileVersion: PROC[opsH: WalnutOpsHandle] RETURNS[rootFileStamp: GMT];
rootFileVersion is needed more often
SetRootFileVersion: PROC[opsH: WalnutOpsHandle, rootFileStamp: GMT];
GetOpInProgressPos: PROC[opsH: WalnutOpsHandle] RETURNS[inProgressPos: INT];
SetOpInProgressPos: PROC[opsH: WalnutOpsHandle, inProgressPos: INT];
GetParseLogInProgress: PROC[opsH: WalnutOpsHandle] RETURNS[inProgress: BOOL];
SetParseLogInProgress: PROC[opsH: WalnutOpsHandle, inProgress: BOOL];
GetParseLogPos: PROC[opsH: WalnutOpsHandle] RETURNS[pos: INT];
SetParseLogPos: PROC[opsH: WalnutOpsHandle, pos: INT];
GetTimeOfLastScavenge: PROC[opsH: WalnutOpsHandle] RETURNS[when: GMT];
SetTimeOfLastScavenge: PROC[opsH: WalnutOpsHandle, when: GMT];
Operations used during Expunge, NewMail and reading Archive files
GetExpungeFileID: PROC[opsH: WalnutOpsHandle] RETURNS[expungeFileID: INT];
SetExpungeFileID: PROC[opsH: WalnutOpsHandle, expungeFileID: INT];
GetExpungeInfo: PROC[opsH: WalnutOpsHandle]
RETURNS[firstDestroyedMsgPos, bytesInDestroyedMsgs: INT];
SetExpungeInfo: PROC[opsH: WalnutOpsHandle, firstDestroyedMsgPos, bytesInDestroyedMsgs: INT];
GetLogExpungePhase: PROC[opsH: WalnutOpsHandle] RETURNS[expungePhase: LogExpungePhase];
SetLogExpungePhase: PROC[opsH: WalnutOpsHandle, expungePhase: LogExpungePhase];  -- commits
GetExpungeProgressInfo: PROC[opsH: WalnutOpsHandle]
RETURNS[currentLogPos, expungeLogPos: INT];
SetExpungeProgressInfo: PROC[opsH: WalnutOpsHandle, currentLogPos, expungeLogPos: INT];  -- commits
SetTimeOfLastExpunge: PROC[opsH: WalnutOpsHandle, when: GMT];
GetTimeOfLastExpunge: PROC[opsH: WalnutOpsHandle] RETURNS[when: GMT];
SetAcceptNewMailPos: PROC[opsH: WalnutOpsHandle, pos: INT];
GetAcceptNewMailPos: PROC[opsH: WalnutOpsHandle] RETURNS[pos: INT];
SetAddingServerMsgs: PROC[opsH: WalnutOpsHandle, addingServerMsgs: BOOL];
GetAddingServerMsgs: PROC[opsH: WalnutOpsHandle] RETURNS[addingServerMsgs: BOOL];
GetServerInfo: PROC[opsH: WalnutOpsHandle, server: ROPE] RETURNS[num: INT];
returns 0 if server doesn't exist
EnumerateServers: PROC[opsH: WalnutOpsHandle] RETURNS[serverList: LIST OF ServerInfo];
SetNewMailInfo: PROC[
opsH: WalnutOpsHandle, logLen: INT, when: GMT, server: ROPE, num: INT];
sets newMailLog length to logLen; if server doesn't exist, it will be created
SetNewMailLogLength: PROC[opsH: WalnutOpsHandle, logLen: INT];
GetNewMailLogLength: PROC[opsH: WalnutOpsHandle] RETURNS[logLen: INT];
GetLastNewMailTimeStamp: PROC[opsH: WalnutOpsHandle] RETURNS[when: GMT];
SetCopyMailLogPos: PROC[opsH: WalnutOpsHandle, pos: INT];
GetCopyMailLogPos: PROC[opsH: WalnutOpsHandle] RETURNS[pos: INT];
SetReadArchivePos: PROC[opsH: WalnutOpsHandle, pos: INT];
GetReadArchivePos: PROC[opsH: WalnutOpsHandle] RETURNS[pos: INT];
SetCopyReadArchivePos: PROC[opsH: WalnutOpsHandle, pos: INT];
GetCopyReadArchivePos: PROC[opsH: WalnutOpsHandle] RETURNS[pos: INT];
Local Procedures
ChangeCountInMsgSet: PROC[opsH: WalnutOpsHandle, ms: ROPE, inc: INT];
ChangeCountOfMsgs: PROC[opsH: WalnutOpsHandle, delta: INT];
GetMsgDisplayInfo: PROC[opsH: WalnutOpsHandle, m: ROPE]
 RETURNS[hasBeenRead: BOOL, tocEntry: ROPE, startOfSubject: INT];
CanonicalName: PROC[name: ROPE] RETURNS[aName: ATOM];
changes name to all lower case, to get canonical names
END.