<<>> <> <> <> <> <> <> <> <> <<>> <> <> DIRECTORY Atom USING [GetProp], BasicTime USING [GMT, nullGMT], LoganBerry, LoganBerryEntry, RefTab USING [Ref], Rope, WalnutDB, WalnutDefs USING [MsgSet, ServerInfo, WalnutOpsHandle], WalnutKernelDefs USING [LogExpungePhase], WalnutRoot USING [CommitAndContinue, RootHandle], WalnutSchema; WalnutDBOpsImpl: CEDAR PROGRAM IMPORTS Atom, LoganBerry, LoganBerryEntry, Rope, WalnutRoot, WalnutSchema EXPORTS WalnutDB, WalnutDefs = BEGIN OPEN WalnutSchema; <<>> <> GMT: TYPE = BasicTime.GMT; ROPE: TYPE = Rope.ROPE; MsgSet: TYPE = WalnutDefs.MsgSet; Value: TYPE = LoganBerry.AttributeValue; Relship: TYPE = LoganBerry.Entry; ServerInfo: TYPE = WalnutDefs.ServerInfo; RootHandle: TYPE = WalnutRoot.RootHandle; SchemaHandle: TYPE = WalnutSchema.SchemaHandle; SchemaHandleRec: PUBLIC TYPE = WalnutSchema.SchemaHandleRec; <<>> <> printActive: ROPE = "Active"; canonicalActive: ROPE = "active"; printDeleted: ROPE = "Deleted"; canonicalDeleted: ROPE = "deleted"; debugging: BOOL ¬ FALSE; DBErrorSeen: SIGNAL = CODE; serverLcn: LIST OF ROPE ¬ NIL; <> DeclareDB: PUBLIC PROC[opsH: WalnutOpsHandle, schemaInvalid: BOOL] RETURNS[ok: BOOL] = { sH: SchemaHandle ¬ NARROW[Atom.GetProp[$WalnutLB, $WalnutSchemaHandle]]; IF ( schemaInvalid ) OR ( sH = NIL ) OR ( sH.activeEntity = NIL ) THEN { opsH.schemaHandle ¬ NIL; [] ¬ InitSchema[opsH, schemaInvalid] } ELSE { opsH.schemaHandle ¬ sH; sH.msgSetsTable ¬ NIL; }; RETURN[opsH.schemaHandle # NIL]; }; InitSchema: PUBLIC PROC[opsH: WalnutOpsHandle, schemaInvalid: BOOL ¬ TRUE] RETURNS[ok: BOOL] = { sH: SchemaHandle; init: LoganBerry.Entry; fullNeeded: BOOL; IF schemaInvalid THEN { WalnutSchema.SetSchemaVersion[opsH]; WalnutRoot.CommitAndContinue[opsH]; }; [] ¬ WalnutSchema.Initialize[opsH]; sH ¬ opsH.schemaHandle; fullNeeded ¬ (ReadEntry[db: opsH.db, key: $Key, value: Rope.Concat[sH.msBasicInfo, canonicalActive]].entry = NIL); BEGIN sH.activeEntity ¬ canonicalActive; sH.deletedEntity ¬ canonicalDeleted; END; sH.unacceptedEntity ¬ "TRUE"; IF fullNeeded THEN { -- create active and deleted message sets init ¬ LIST [ [$Key, Rope.Concat[sH.msBasicInfo, canonicalActive]], [sH.msBICount, "0"], [sH.msBIVersion, "1"], [sH.msPrintNameIs, printActive] ]; WriteEntry[db: opsH.db, entry: init]; init ¬ LIST [ [$Key, Rope.Concat[sH.msBasicInfo, canonicalDeleted]], [sH.msBICount, "0"], [sH.msBIVersion, "1"], [sH.msPrintNameIs, printDeleted] ]; WriteEntry[db: opsH.db, entry: init]; }; RETURN[TRUE]; }; <<>> <> GetRootInfo: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[dbRootCreateDate: GMT, dbFileKey, dbMailFor: ROPE] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rRootInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gRootInfo].entry; dbRootCreateDate ¬ LoganBerryEntry.V2T[LoganBerryEntry.GetAttr[rRootInfo, sH.gRootFileStamp]]; dbFileKey ¬ LoganBerryEntry.V2S[LoganBerryEntry.GetAttr[rRootInfo, sH.gRootFileKey]]; dbMailFor ¬ LoganBerryEntry.V2S[LoganBerryEntry.GetAttr[rRootInfo, sH.gMailFor]]; }; SetRootInfo: PUBLIC PROC[opsH: WalnutOpsHandle, dbRootCreateDate: GMT, dbFileKey, dbMailFor: ROPE] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rRootInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gRootInfo].entry; LoganBerryEntry.SetAttr[rRootInfo, sH.gRootFileStamp, LoganBerryEntry.T2V[dbRootCreateDate]]; LoganBerryEntry.SetAttr[rRootInfo, sH.gRootFileKey, LoganBerryEntry.S2V[dbFileKey]]; LoganBerryEntry.SetAttr[rRootInfo, sH.gMailFor, LoganBerryEntry.S2V[dbMailFor]]; WriteEntry[db: opsH.db, entry: rRootInfo, replace: TRUE]; }; GetRootFileVersion: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[rootFileStamp: GMT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rRootInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gRootInfo].entry; rootFileStamp ¬ LoganBerryEntry.V2T[LoganBerryEntry.GetAttr[rRootInfo, sH.gRootFileStamp]]; }; SetRootFileVersion: PUBLIC PROC[opsH: WalnutOpsHandle, rootFileStamp: GMT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rRootInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gRootInfo].entry; LoganBerryEntry.SetAttr[rRootInfo, sH.gRootFileStamp, LoganBerryEntry.T2V[rootFileStamp]]; WriteEntry[db: opsH.db, entry: rRootInfo, replace: TRUE]; }; GetOpInProgressPos: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[inProgressPos: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rLogInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gLogInfo].entry; inProgressPos¬ LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rLogInfo, sH.gOpInProgressPos]] }; SetOpInProgressPos: PUBLIC PROC[opsH: WalnutOpsHandle, inProgressPos: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rLogInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gLogInfo].entry; LoganBerryEntry.SetAttr[rLogInfo, sH.gOpInProgressPos, LoganBerryEntry.I2V[inProgressPos]]; WriteEntry[db: opsH.db, entry: rLogInfo, replace: TRUE]; }; GetParseLogInProgress: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[inProgress: BOOL] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rParseLogInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gParseLogInfo].entry; inProgress¬ LoganBerryEntry.V2B[LoganBerryEntry.GetAttr[rParseLogInfo, sH.gParseLogInProgress]] }; SetParseLogInProgress: PUBLIC PROC[opsH: WalnutOpsHandle, inProgress: BOOL] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rParseLogInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gParseLogInfo].entry; LoganBerryEntry.SetAttr[rParseLogInfo, sH.gParseLogInProgress, LoganBerryEntry.B2V[inProgress]]; WriteEntry[db: opsH.db, entry: rParseLogInfo, replace: TRUE]; IF inProgress THEN LoganBerry.StartTransaction[db: opsH.db] ELSE [] ¬ LoganBerry.EndTransaction[db: opsH.db]; }; GetParseLogPos: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[pos: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rParseLogInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gParseLogInfo].entry; pos ¬ LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rParseLogInfo, sH.gParseLogPos]] }; SetParseLogPos: PUBLIC PROC[opsH: WalnutOpsHandle, pos: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rParseLogInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gParseLogInfo].entry; LoganBerryEntry.SetAttr[rParseLogInfo, sH.gParseLogPos, LoganBerryEntry.I2V[pos]]; WriteEntry[db: opsH.db, entry: rParseLogInfo, replace: TRUE]; }; GetMsgDisplayInfo: PUBLIC PROC[opsH: WalnutOpsHandle, m: ROPE] RETURNS[hasBeenRead: BOOL, tocEntry: ROPE, startOfSubject: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rel: Relship = ReadEntry[db: opsH.db, key: $Key, value: Rope.Concat[sH.mDisplayInfo, m]].entry; miRel: Relship = ReadEntry[db: opsH.db, key: $Key, value: Rope.Concat[sH.mMsgInfo, m]].entry; tocHead: ROPE = LoganBerryEntry.V2S[LoganBerryEntry.GetAttr[rel, sH.mDITOCHeadEntry]]; hasBeenRead ¬ LoganBerryEntry.V2B[LoganBerryEntry.GetAttr[rel, sH.mDIHasBeenRead]]; tocEntry ¬ tocHead.Concat[LoganBerryEntry.V2S[LoganBerryEntry.GetAttr[miRel, sH.mMISubjectText]] ]; startOfSubject ¬ tocHead.Length[]; }; ChangeCountInMsgSet: PUBLIC PROC[opsH: WalnutOpsHandle, ms: ROPE, inc: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rel: Relship = ReadEntry[db: opsH.db, key: $Key, value: Rope.Concat[sH.msBasicInfo, ms]].entry; new: INT ¬ LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rel, sH.msBICount]] + inc; IF new < 0 THEN new ¬ 0; -- empty didn't used to change the count LoganBerryEntry.SetAttr[rel, sH.msBICount, LoganBerryEntry.I2V[new]]; new ¬ LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rel, sH.msBIVersion]] + 1; LoganBerryEntry.SetAttr[rel, sH.msBIVersion, LoganBerryEntry.I2V[new]]; }; ChangeCountOfMsgs: PUBLIC PROC[opsH: WalnutOpsHandle, delta: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rVersionInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gVersionInfo].entry; numNow: INT = LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rVersionInfo, sH.gMsgCount]]; LoganBerryEntry.SetAttr[rVersionInfo, sH.gMsgCount, LoganBerryEntry.I2V[numNow + delta]]; WriteEntry[db: opsH.db, entry: rVersionInfo, replace: TRUE]; }; <<>> <> GetExpungeFileID: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[expungeFileID: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rExpungeInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gExpungeInfo].entry; expungeFileID ¬ LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rExpungeInfo, sH.gExpungeFileID]] }; SetExpungeFileID: PUBLIC PROC[opsH: WalnutOpsHandle, expungeFileID: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rExpungeInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gExpungeInfo].entry; LoganBerryEntry.SetAttr[rExpungeInfo, sH.gExpungeFileID, LoganBerryEntry.I2V[expungeFileID]]; WriteEntry[db: opsH.db, entry: rExpungeInfo, replace: TRUE]; }; GetExpungeInfo: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[firstDestroyedMsgPos, bytesInDestroyedMsgs: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rLogInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gLogInfo].entry; firstDestroyedMsgPos ¬ LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rLogInfo, sH.gFirstDestroyedMsgPos]]; bytesInDestroyedMsgs ¬ LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rLogInfo, sH.gBytesInDestroyedMsgs]] }; SetExpungeInfo: PUBLIC PROC[opsH: WalnutOpsHandle, firstDestroyedMsgPos, bytesInDestroyedMsgs: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rLogInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gLogInfo].entry; LoganBerryEntry.SetAttr[rLogInfo, sH.gFirstDestroyedMsgPos, LoganBerryEntry.I2V[firstDestroyedMsgPos]]; LoganBerryEntry.SetAttr[rLogInfo, sH.gBytesInDestroyedMsgs, LoganBerryEntry.I2V[bytesInDestroyedMsgs]]; WriteEntry[db: opsH.db, entry: rLogInfo, replace: TRUE]; }; GetLogExpungePhase: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[exp: WalnutKernelDefs.LogExpungePhase] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rExpungeInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gExpungeInfo].entry; ph: INT ¬ LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rExpungeInfo, sH.gLogExpungePhase]]; pSmall: CARDINAL ¬ ph; exp ¬ VAL[pSmall]; }; SetLogExpungePhase: PUBLIC PROC[opsH: WalnutOpsHandle, expungePhase: WalnutKernelDefs.LogExpungePhase] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rExpungeInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gExpungeInfo].entry; LoganBerryEntry.SetAttr[rExpungeInfo, sH.gLogExpungePhase, LoganBerryEntry.I2V[ORD[expungePhase]]]; WriteEntry[db: opsH.db, entry: rExpungeInfo, replace: TRUE]; }; GetExpungeProgressInfo: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[currentLogPos, expungeLogPos: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rExpungeInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gExpungeInfo].entry; currentLogPos ¬ LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rExpungeInfo, sH.gCurrentLogPos]]; expungeLogPos ¬ LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rExpungeInfo, sH.gExpungeLogPos]]; }; SetExpungeProgressInfo: PUBLIC PROC[opsH: WalnutOpsHandle, currentLogPos, expungeLogPos: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rExpungeInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gExpungeInfo].entry; LoganBerryEntry.SetAttr[rExpungeInfo, sH.gCurrentLogPos, LoganBerryEntry.I2V[currentLogPos]]; LoganBerryEntry.SetAttr[rExpungeInfo, sH.gExpungeLogPos, LoganBerryEntry.I2V[expungeLogPos]]; WriteEntry[db: opsH.db, entry: rExpungeInfo, replace: TRUE]; }; GetTimeOfLastExpunge: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[when: GMT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rExpungeInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gExpungeInfo].entry; when ¬ LoganBerryEntry.V2T[LoganBerryEntry.GetAttr[rExpungeInfo, sH.gTimeOfLastExpunge]] }; SetTimeOfLastExpunge: PUBLIC PROC[opsH: WalnutOpsHandle, when: GMT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rExpungeInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gLogInfo].entry; LoganBerryEntry.SetAttr[rExpungeInfo, sH.gTimeOfLastExpunge, LoganBerryEntry.T2V[when]]; WriteEntry[db: opsH.db, entry: rExpungeInfo, replace: TRUE]; }; GetTimeOfLastScavenge: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[when: GMT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rLogInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gLogInfo].entry; when ¬ LoganBerryEntry.V2T[LoganBerryEntry.GetAttr[rLogInfo, sH.gTimeOfLastScavenge]] }; SetTimeOfLastScavenge: PUBLIC PROC[opsH: WalnutOpsHandle, when: GMT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rLogInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gLogInfo].entry; LoganBerryEntry.SetAttr[rLogInfo, sH.gTimeOfLastScavenge, LoganBerryEntry.T2V[when]]; WriteEntry[db: opsH.db, entry: rLogInfo, replace: TRUE]; }; SetAcceptNewMailPos: PUBLIC PROC[opsH: WalnutOpsHandle, pos: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rNewMailInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gNewMailInfo].entry; LoganBerryEntry.SetAttr[rNewMailInfo, sH.gAcceptNewMailLogPos, LoganBerryEntry.I2V[pos]]; WriteEntry[db: opsH.db, entry: rNewMailInfo, replace: TRUE]; }; GetAcceptNewMailPos: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[pos: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rNewMailInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gNewMailInfo].entry; pos ¬ LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rNewMailInfo, sH.gAcceptNewMailLogPos]] }; SetAddingServerMsgs: PUBLIC PROC[opsH: WalnutOpsHandle, addingServerMsgs: BOOL] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rNewMailInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gNewMailInfo].entry; LoganBerryEntry.SetAttr[rNewMailInfo, sH.gAddingServerMsgs, LoganBerryEntry.B2V[addingServerMsgs]]; WriteEntry[db: opsH.db, entry: rNewMailInfo, replace: TRUE]; }; GetAddingServerMsgs: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[addingServerMsgs: BOOL] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rNewMailInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gNewMailInfo].entry; addingServerMsgs ¬ LoganBerryEntry.V2B[LoganBerryEntry.GetAttr[rNewMailInfo, sH.gAddingServerMsgs]]; }; EnumerateServers: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[serverList: LIST OF ServerInfo] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; enum: LoganBerry.Cursor ¬ LoganBerry.GenerateEntries[db: opsH.db, key: $Key, start: Rope.Concat[sH.sBasicInfo, "\000"], end: Rope.Concat[sH.sBasicInfo, "\177"]]; se: LoganBerry.Entry; FOR se ¬ LoganBerry.NextEntry[cursor: enum], LoganBerry.NextEntry[cursor: enum] UNTIL se = NIL DO rel: Relship = se; si: ServerInfo; si.server ¬ LoganBerryEntry.GetAttr[rel, sH.sBIOf]; si.num ¬ LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rel, sH.sBINum]]; serverList ¬ CONS[si, serverList]; ENDLOOP; LoganBerry.EndGenerate[cursor: enum]; }; GetServerInfo: PUBLIC PROC[opsH: WalnutOpsHandle, server: ROPE] RETURNS[num: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; se: LoganBerry.Entry = ReadEntry[db: opsH.db, key: $Key, value: Rope.Concat[sH.sBasicInfo, server]].entry; IF se # NIL THEN { rel: Relship = se; num ¬ LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rel, sH.sBINum]] } ELSE num ¬ 0; }; SetNewMailInfo: PUBLIC PROC[opsH: WalnutOpsHandle, logLen: INT, when: GMT, server: ROPE, num: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rNewMailInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gNewMailInfo].entry; IF server # NIL THEN { lcn: ROPE = server; se: LoganBerry.Entry ¬ ReadEntry[db: opsH.db, key: $Key, value: Rope.Concat[sH.sBasicInfo, lcn]].entry; IF se = NIL THEN { -- create this entity init: LoganBerry.Entry = LIST[ [$Key, Rope.Concat[sH.sBasicInfo, lcn]], [sH.sBIOf, lcn], [sH.sBINum, LoganBerryEntry.I2V[num]] ]; WriteEntry[db: opsH.db, entry: init]; } ELSE { rel: Relship = se; LoganBerryEntry.SetAttr[rel, sH.sBINum, LoganBerryEntry.I2V[num]]; WriteEntry[db: opsH.db, entry: rel, replace: TRUE]; }; }; LoganBerryEntry.SetAttr[rNewMailInfo, sH.gNewMailLogLength, LoganBerryEntry.I2V[logLen]]; IF when # BasicTime.nullGMT THEN LoganBerryEntry.SetAttr[rNewMailInfo, sH.gLastNewMailTimeStamp, LoganBerryEntry.T2V[when]]; WriteEntry[db: opsH.db, entry: rNewMailInfo, replace: TRUE]; }; SetNewMailLogLength: PUBLIC PROC[opsH: WalnutOpsHandle, logLen: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rNewMailInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gNewMailInfo].entry; LoganBerryEntry.SetAttr[rNewMailInfo, sH.gNewMailLogLength, LoganBerryEntry.I2V[logLen]]; WriteEntry[db: opsH.db, entry: rNewMailInfo, replace: TRUE]; }; GetNewMailLogLength: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[logLen: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rNewMailInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gNewMailInfo].entry; logLen ¬ LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rNewMailInfo, sH.gNewMailLogLength]] }; GetLastNewMailTimeStamp: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[when: GMT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rNewMailInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gNewMailInfo].entry; when ¬ LoganBerryEntry.V2T[LoganBerryEntry.GetAttr[rNewMailInfo, sH.gLastNewMailTimeStamp]] }; SetCopyMailLogPos: PUBLIC PROC[opsH: WalnutOpsHandle, pos: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rNewMailInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gNewMailInfo].entry; LoganBerryEntry.SetAttr[rNewMailInfo, sH.gCopyNewMailLogPos, LoganBerryEntry.I2V[pos]]; WriteEntry[db: opsH.db, entry: rNewMailInfo, replace: TRUE]; }; GetCopyMailLogPos: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[pos: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rNewMailInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gNewMailInfo].entry; pos ¬ LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rNewMailInfo, sH.gCopyNewMailLogPos]] }; SetReadArchivePos: PUBLIC PROC[opsH: WalnutOpsHandle, pos: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rReadArchiveInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gReadArchiveInfo].entry; LoganBerryEntry.SetAttr[rReadArchiveInfo, sH.gReadArchiveLogPos, LoganBerryEntry.I2V[pos]]; WriteEntry[db: opsH.db, entry: rReadArchiveInfo, replace: TRUE]; }; GetReadArchivePos: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[pos: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rReadArchiveInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gReadArchiveInfo].entry; pos ¬ LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rReadArchiveInfo, sH.gReadArchiveLogPos]] }; SetCopyReadArchivePos: PUBLIC PROC[opsH: WalnutOpsHandle, pos: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rReadArchiveInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gReadArchiveInfo].entry; LoganBerryEntry.SetAttr[rReadArchiveInfo, sH.gCopyReadArchiveLogPos, LoganBerryEntry.I2V[pos]]; WriteEntry[db: opsH.db, entry: rReadArchiveInfo, replace: TRUE]; }; GetCopyReadArchivePos: PUBLIC PROC[opsH: WalnutOpsHandle] RETURNS[pos: INT] = { sH: WalnutSchema.SchemaHandle = opsH.schemaHandle; rReadArchiveInfo: Relship = ReadEntry[db: opsH.db, key: $Key, value: sH.gReadArchiveInfo].entry; pos ¬ LoganBerryEntry.V2I[LoganBerryEntry.GetAttr[rReadArchiveInfo, sH.gCopyReadArchiveLogPos]] }; <> <<>> ReadEntry: PROC[conv: LoganBerry.Conv¬NIL, db: LoganBerry.OpenDB, key: LoganBerry.AttributeType, value: LoganBerry.AttributeValue] RETURNS [entry: LoganBerry.Entry, others: BOOLEAN¬FALSE -- !unused?--] ~ { [entry, others] ¬ LoganBerry.ReadEntry[conv, db, key, value]; }; WriteEntry: PROC[conv: LoganBerry.Conv¬NIL, db: LoganBerry.OpenDB, entry: LoganBerry.Entry, log: LoganBerry.LogID ¬ LoganBerry.activityLog, replace: BOOLEAN ¬ FALSE]~{ LoganBerry.WriteEntry[conv, db, entry, log, replace]; }; END.