<<>> <> <> <> <> <> <> <<>> <> <> <<>> DIRECTORY Atom USING [PutProp], BasicTime USING [GMT, nullGMT, OutOfRange], Convert USING [TimeFromRope], IO, LoganBerry, LoganBerryEntry, Rope USING [ROPE, Cat], WalnutDefs USING [LogInfo, SchemaMismatch, WalnutOpsHandle], WalnutOpsInternal USING [], WalnutRoot USING [CommitAndContinue, RootHandle, RootHandleRec], WalnutSchema; WalnutOpsMiscImpl: CEDAR PROGRAM IMPORTS Atom, BasicTime, Convert, IO, LoganBerry, LoganBerryEntry, Rope, WalnutDefs, WalnutRoot EXPORTS WalnutSchema, WalnutDefs = BEGIN OPEN WalnutSchema; <<>> <> GMT: TYPE = BasicTime.GMT; ROPE: TYPE = Rope.ROPE; LogInfo: TYPE = WalnutDefs.LogInfo; WalnutOpsHandle: TYPE = WalnutDefs.WalnutOpsHandle; RootHandle: TYPE = WalnutRoot.RootHandle; RootHandleRec: PUBLIC TYPE = WalnutRoot.RootHandleRec; SchemaHandle: TYPE = WalnutSchema.SchemaHandle; SchemaHandleRec: PUBLIC TYPE = WalnutSchema.SchemaHandleRec; <<>> <> <<>> SchemaMismatch: PUBLIC SIGNAL[explanation: ROPE ¬ NIL] = CODE; VersionMismatch: PUBLIC SIGNAL[explanation: ROPE ¬ NIL] = CODE; Error: PUBLIC SIGNAL [who, code: ATOM, explanation: ROPE ¬ NIL] = CODE; <> <<>> completeSchemaVersionDate: GMT = Convert.TimeFromRope["June 29, 1988 12:20:00 pm PDT"]; simpleSchemaVersionDate: GMT = Convert.TimeFromRope["June 29, 1988 4:54:19 pm PDT"]; schemaDateField: ATOM = $SchemaDate; gSchemaDateInfoName: ROPE = "SchemaDInfo"; <> Initialize: PUBLIC PROC [opsH: WalnutOpsHandle] RETURNS[ok: BOOL] = { <> sH: SchemaHandle; schemaDate: BasicTime.GMT = ( IF opsH.completeSchema THEN completeSchemaVersionDate ELSE simpleSchemaVersionDate ); BEGIN schemaRelship: LoganBerry.Entry ¬ LoganBerry.ReadEntry[db: opsH.db, key: $Key, value: gSchemaDateInfoName].entry; IF schemaRelship = NIL THEN { schemaRelship ¬ LIST[[$Key, gSchemaDateInfoName], [schemaDateField, LoganBerryEntry.T2V[schemaDate]]]; LoganBerry.WriteEntry[db: opsH.db, entry: schemaRelship]; } ELSE { date: BasicTime.GMT = LoganBerryEntry.V2T[LoganBerryEntry.GetAttr[schemaRelship, schemaDateField]]; IF date # schemaDate THEN ERROR WalnutDefs.SchemaMismatch[TimesToRope[date, schemaDate]] }; opsH.schemaHandle ¬ sH ¬ NEW[SchemaHandleRec]; <<>> END; <> <> Atom.PutProp[$WalnutLB, $WalnutSchemaHandle, sH]; <> <<>> sH.gRootInfo ¬ "RootInfo"; sH.gRootFileStamp ¬ $RootFileStamp; -- rootFile create date for this db (gmt) sH.gRootFileKey ¬ $RootFileKey; -- key from rootFile for this db (rope) sH.gMailFor ¬ $MailFor; -- RName (rope) sH.gLogInfo ¬ "LogInfo"; sH.gLogFileID ¬ $LogFileID; -- int sH.gOpInProgressPos ¬ $OpInProgressPos; -- int - long running operation Pos sH.gFirstDestroyedMsgPos ¬ $FirstDestroyedMsgPos; -- int sH.gBytesInDestroyedMsgs ¬ $BytesInDestroyedMsgs; -- int sH.gTimeOfLastScavenge ¬ $TimeOfLastScavenge; -- gmt sH.gParseLogInfo ¬ "ParseLogInfo"; sH.gParseLogInProgress ¬ $ParseLogInProgress; -- bool sH.gParseLogPos ¬ $ParseLogPos; -- int sH.gExpungeInfo ¬ "ExpungeInfo"; sH.gLogExpungePhase ¬ $LogExpungePhase; -- int sH.gExpungeFileID ¬ $ExpungeFileID; -- int sH.gCurrentLogPos ¬ $CurrentLogPos; -- int sH.gExpungeLogPos ¬ $ExpungeLogPos; -- int sH.gTimeOfLastExpunge ¬ $TimeOfLastExpunge; -- gmt sH.gNewMailInfo ¬ "NewMailInfo"; sH.gNewMailLogLength ¬ $NewMailLogLength; -- int sH.gCopyNewMailLogPos ¬ $CopyNewMailLogPos; -- int sH.gAcceptNewMailLogPos ¬ $AcceptNewMailLogPos; -- int sH.gAddingServerMsgs ¬ $AddingServerMsgs; -- bool sH.gLastNewMailTimeStamp ¬ $LastNewMailTimeStamp; -- time sH.gReadArchiveInfo ¬ "ReadArchiveInfo"; sH.gReadArchiveLogPos ¬ $ReadArchiveLogPos; -- int sH.gCopyReadArchiveLogPos ¬ $CopyReadArchiveLogPos; -- int sH.gVersionInfo ¬ "VersionInfo"; sH.gMsgCount ¬ $MsgCount; -- int (number of msgs) sH.gMsgSetCount ¬ $MsgSetCount; -- int (number of msgSets) sH.gMsgSetsVersion ¬ $MsgSetsVersion; -- int (version number for msgSets) sH.sBasicInfo ¬ "Server-"; -- One per Server sH.sBIOf ¬ $ServerName; -- Server sH.sBINum ¬ $Num; -- int (number of msgs) sH.msBasicInfo ¬ "MsgSet-"; -- One per MsgSet sH.msBIOf ¬ $PrintNameIs; -- MsgSet sH.msBICount ¬ $Count; -- int (number of member msgs) sH.msBIVersion ¬ $Version; -- int sH.msPrintNameIs ¬ $PrintNameIs; -- rope sH.mMsgInfo ¬ "Msg-"; -- One per Msg sH.mMIOf ¬ $MsgID; -- Msg sH.mMIHerald ¬ $Herald; -- rope sH.mMIShortNameLen ¬ $ShortNameLen; -- int (for icon label, etc) sH.mMIEntryStart ¬ $EntryStart; -- int (start of entry in log) sH.mMITextOffset ¬ $TextOffset; -- int (offset for text) sH.mMITextLen ¬ $TextLen; -- int (length of text) sH.mMIFormatLen ¬ $FormatLen; -- int (length of formatting) sH.mMIDate ¬ $Date; -- time sH.mMISubject ¬ $Subject; -- Subject (truncated to 20 chars) sH.mMISubjectText ¬ $SubjectText; -- rope (up to 99 chars) sH.mMIIsInReplyTo ¬ $IsInReplyTo; -- bool sH.mMISender ¬ $Sender; -- Address (only one allowed) sH.mDisplayInfo ¬ "MsgDisplay-"; -- One per Msg sH.mDIOf ¬ $MsgID; -- Msg sH.mDITOCHeadEntry ¬ $TOCHeadEntry; -- rope sH.mDIHasBeenRead ¬ $HasBeenRead; -- bool sH.mInfo ¬ "MsgShow-"; -- One per Msg sH.mInfoOf ¬ $InfoOf; -- Msg sH.mDateIs ¬ $DateIs; -- time sH.mShowIs ¬ $ShowIs; -- Unaccepted sH.cdRelation ¬ "MsgCd-"; -- One per Msg sH.cdMsg ¬ $Msg; -- Msg sH.cdMsgSet ¬ $MsgSet; -- MsgSet (multiple allowed) sH.cdDate ¬ $DateIs; -- time (of the Msg) sH.toRelation ¬ "MsgTo-"; -- One per Msg sH.toMsg ¬ $Msg; -- Msg sH.toAddress ¬ $Address; -- Address (multiple allowed) sH.toDate ¬ $DateIs; -- time (of the Msg) sH.ccRelation ¬ "MsgCc-"; -- One per Msg sH.ccMsg ¬ $Msg; -- Msg sH.ccAddress ¬ $Address; -- Address (multiple allowed) sH.ccDate ¬ $DateIs; -- time (of the Msg) sH.fromRelation ¬ "MsgFrom-"; -- One per Msg sH.fromMsg ¬ $Msg; -- Msg sH.fromAddress ¬ $Address; -- Address (multiple allowed) sH.fromDate ¬ $DateIs; -- time (of the Msg) <<>> <> <<>> BEGIN gr: LoganBerry.Entry ¬ LoganBerry.ReadEntry[db: opsH.db, key: $Key, value: sH.gRootInfo].entry; IF gr = NIL THEN { init: LoganBerry.Entry ¬ LIST[ [$Key, sH.gRootInfo], [sH.gRootFileStamp, LoganBerryEntry.T2V[BasicTime.nullGMT]], [sH.gRootFileKey, NIL], [sH.gMailFor, NIL] ]; LoganBerry.WriteEntry[db: opsH.db, entry: init]; init ¬ LIST[ [$Key, sH.gLogInfo], [sH.gLogFileID, LoganBerryEntry.I2V[0]], [sH.gOpInProgressPos, LoganBerryEntry.I2V[0]], [sH.gFirstDestroyedMsgPos, LoganBerryEntry.I2V[0]], [sH.gBytesInDestroyedMsgs, LoganBerryEntry.I2V[0]], [sH.gTimeOfLastScavenge, LoganBerryEntry.T2V[BasicTime.nullGMT]] ]; LoganBerry.WriteEntry[db: opsH.db, entry: init]; init ¬ LIST[ [$Key, sH.gParseLogInfo], [sH.gParseLogInProgress, LoganBerryEntry.B2V[FALSE]], [sH.gParseLogPos, LoganBerryEntry.I2V[0]] ]; LoganBerry.WriteEntry[db: opsH.db, entry: init]; init ¬ LIST[ [$Key, sH.gExpungeInfo], [sH.gLogExpungePhase, LoganBerryEntry.I2V[0]], [sH.gExpungeFileID, LoganBerryEntry.I2V[0]], [sH.gCurrentLogPos, LoganBerryEntry.I2V[0]], [sH.gExpungeLogPos, LoganBerryEntry.I2V[0]], [sH.gTimeOfLastExpunge, LoganBerryEntry.T2V[BasicTime.nullGMT]] ]; LoganBerry.WriteEntry[db: opsH.db, entry: init]; init ¬ LIST[ [$Key, sH.gNewMailInfo], [sH.gNewMailLogLength, LoganBerryEntry.I2V[0]], [sH.gCopyNewMailLogPos, LoganBerryEntry.I2V[0]], [sH.gAcceptNewMailLogPos, LoganBerryEntry.I2V[0]], [sH.gAddingServerMsgs, LoganBerryEntry.B2V[FALSE]], [sH.gLastNewMailTimeStamp, LoganBerryEntry.T2V[BasicTime.nullGMT]] ]; LoganBerry.WriteEntry[db: opsH.db, entry: init]; init ¬ LIST[ [$Key, sH.gReadArchiveInfo], [sH.gReadArchiveLogPos, LoganBerryEntry.I2V[0]], [sH.gCopyReadArchiveLogPos, LoganBerryEntry.I2V[0]] ]; LoganBerry.WriteEntry[db: opsH.db, entry: init]; <> init ¬ LIST[ [$Key, sH.gVersionInfo], [sH.gMsgCount, LoganBerryEntry.I2V[0]], [sH.gMsgSetCount, LoganBerryEntry.I2V[2]], [sH.gMsgSetsVersion, LoganBerryEntry.I2V[1]] ]; LoganBerry.WriteEntry[db: opsH.db, entry: init]; }; END; <> WalnutRoot.CommitAndContinue[opsH]; RETURN[TRUE]; }; SetSchemaVersion: PUBLIC PROC[opsH: WalnutOpsHandle] = { <> schemaDate: BasicTime.GMT = ( IF opsH.completeSchema THEN completeSchemaVersionDate ELSE simpleSchemaVersionDate ); schemaRelship: LoganBerry.Entry ¬ LoganBerry.ReadEntry[db: opsH.db, key: $Key, value: gSchemaDateInfoName].entry; IF schemaRelship # NIL THEN { LoganBerryEntry.SetAttr[schemaRelship, schemaDateField, LoganBerryEntry.T2V[schemaDate]]; LoganBerry.WriteEntry[db: opsH.db, entry: schemaRelship, replace: TRUE]; } ELSE { schemaRelship ¬ LIST[[$Key, gSchemaDateInfoName], [schemaDateField, LoganBerryEntry.T2V[schemaDate]]]; LoganBerry.WriteEntry[db: opsH.db, entry: schemaRelship]; }; <> }; GetSchemaVersion: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[actual, shouldBe: BasicTime.GMT] = { <> schemaRelship: LoganBerry.Entry ¬ LoganBerry.ReadEntry[db: opsH.db, key: $Key, value: gSchemaDateInfoName].entry; shouldBe ¬ ( IF opsH.completeSchema THEN completeSchemaVersionDate ELSE simpleSchemaVersionDate ); actual ¬ IF schemaRelship # NIL THEN LoganBerryEntry.V2T[LoganBerryEntry.GetAttr[schemaRelship, schemaDateField]] ELSE BasicTime.nullGMT; }; TimesToRope: PROC[is, shouldBe: BasicTime.GMT] RETURNS[ROPE] = { isR, shouldR: ROPE; isR ¬ IO.PutFR1[NIL, [time[is]] ! BasicTime.OutOfRange => { isR ¬ IF is = BasicTime.nullGMT THEN "nullGMT" ELSE "OutOfRange"; CONTINUE }]; shouldR ¬ IO.PutFR1[NIL, [time[shouldBe]] ! BasicTime.OutOfRange => { shouldR ¬ IF shouldBe = BasicTime.nullGMT THEN "nullGMT" ELSE "OutOfRange"; CONTINUE }]; RETURN[Rope.Cat["\nSchema is of: ", isR, " but should be of: ", shouldR]]; }; END.