DIRECTORY BasicTime USING [GMT, nullGMT, OutOfRange], Convert USING [TimeFromRope], DB USING [Boolean, CreateRelship, Error, FieldSpec, FirstRelship, DeclareDomain, DeclareIndex, DeclareProperty, DeclareRelation, GetF, Integer, L2F, L2FS, L2VS, SetF, String, T2V, Time, TypeForDomain, TypeSpec, V2T, Domain, FieldSequence, Index, Relation, Relship, TypeCode, ValueSequence], IO, Rope USING [ROPE, Cat], WalnutDefs USING [Error, SchemaMismatch, Segment], WalnutRoot USING [CommitAndContinue], WalnutSchema; WalnutSchemaImpl: CEDAR PROGRAM IMPORTS Convert, DB, IO, Rope, WalnutDefs, WalnutRoot EXPORTS WalnutSchema, WalnutDefs = BEGIN OPEN WalnutSchema; GMT: TYPE = BasicTime.GMT; ROPE: TYPE = Rope.ROPE; SchemaMismatch: PUBLIC SIGNAL[explanation: ROPE _ NIL] = CODE; VersionMismatch: PUBLIC SIGNAL[explanation: ROPE _ NIL] = CODE; Error: PUBLIC SIGNAL [who, code: ATOM, explanation: ROPE _ NIL] = CODE; schemaVersionDate: GMT = Convert.TimeFromRope["April 15, 1986 2:14:01 pm PST"]; gRootInfo: PUBLIC DB.Relation; gRootInfoFields: DB.FieldSpec = DB.L2FS[LIST[ [name: "RootFileStamp", type: DB.Time], [name: "gRootFileKey", type: DB.String, lengthHint: 20], [name: "MailFor", type: DB.String, lengthHint: 20] ]]; gLogInfo: PUBLIC DB.Relation; gLogInfoFields: DB.FieldSpec = DB.L2FS[LIST[ [name: "LogFileID", type: DB.Integer], [name: "OpInProgressPos", type: DB.Integer], [name: "FirstDestroyedMsgPos", type: DB.Integer], [name: "BytesInDestroyedMsgs", type: DB.Integer], [name: "TimeOfLastScavenge", type: DB.Time] ]]; gParseLogInfo: PUBLIC DB.Relation; gParseLogInfoFields: DB.FieldSpec = DB.L2FS[LIST[ [name: "ParseLogInProgress", type: DB.Boolean], [name: "ParseLogPos", type: DB.Integer] ]]; gExpungeInfo: PUBLIC DB.Relation; gExpungeLogInfoFields: DB.FieldSpec = DB.L2FS[LIST[ [name: "LogExpungePhase", type: DB.Integer], [name: "gExpungeFileID", type: DB.Integer], [name: "CurrentLogPos", type: DB.Integer], [name: "TempLogPos", type: DB.Integer], [name: "TimeOfLastExpunge", type: DB.Time] ]]; gNewMailInfo: PUBLIC DB.Relation; gNewMailInfoFields: DB.FieldSpec = DB.L2FS[LIST[ [name: "NewMailLogLength", type: DB.Integer], [name: "CopyNewMailLogPos", type: DB.Integer], [name: "AcceptNewMailLogPos", type: DB.Integer], [name: "AddingServerMsgs", type: DB.Boolean], [name: "LastNewMailTimeStamp", type: DB.Time] ]]; gReadArchiveInfo: PUBLIC DB.Relation; gReadArchiveInfoFields: DB.FieldSpec = DB.L2FS[LIST[ [name: "ReadArchiveLogPos", type: DB.Integer], [name: "CopyReadArchiveLogPos", type: DB.Integer] ]]; gVersionInfo: PUBLIC DB.Relation; gVersionInfoFields: DB.FieldSpec = DB.L2FS[LIST[ [name: "MsgCount", type: DB.Integer], [name: "MsgSetCount", type: DB.Integer], [name: "MsgSetsVersion", type: DB.Integer] ]]; MsgDomain: PUBLIC DB.Domain; MsgTypeProc: PROC[] RETURNS[DB.TypeCode] = { RETURN[DB.TypeForDomain[MsgDomain]] }; MsgType: DB.TypeSpec = [indirect[MsgTypeProc]]; MsgSetDomain: PUBLIC DB.Domain; MsgSetTypeProc: PROC[] RETURNS[DB.TypeCode] = { RETURN[DB.TypeForDomain[MsgSetDomain]] }; MsgSetType: DB.TypeSpec = [indirect[MsgSetTypeProc]]; ServerDomain: PUBLIC DB.Domain; ServerTypeProc: PROC[] RETURNS[DB.TypeCode] = { RETURN[DB.TypeForDomain[ServerDomain]] }; ServerType: DB.TypeSpec = [indirect[ServerTypeProc]]; UnacceptedDomain: PUBLIC DB.Domain; UnacceptedTypeProc: PROC[] RETURNS[DB.TypeCode] = { RETURN[DB.TypeForDomain[UnacceptedDomain]] }; UnacceptedType: DB.TypeSpec = [indirect[UnacceptedTypeProc]]; sBasicInfo: PUBLIC DB.Relation; -- One per Server sBasicType: DB.FieldSpec = DB.L2FS[LIST[ [name: "of", type: ServerType], [name: "messages", type: DB.Integer] ]]; msBasicInfo: PUBLIC DB.Relation; -- One per MsgSet msBasicType: DB.FieldSpec = DB.L2FS[LIST[ [name: "of", type: MsgSetType], [name: "count", type: DB.Integer], [name: "version", type: DB.Integer], [name: "printName", type: DB.String] ]]; mTextInfo: PUBLIC DB.Relation; -- One per Msg mTextType: DB.FieldSpec = DB.L2FS[LIST[ [name: "of", type: MsgType], [name: "herald", type: DB.String, lengthHint: 60], [name: "shortNameLen", type: DB.Integer], [name: "entryStart", type: DB.Integer], [name: "textOffset", type: DB.Integer], [name: "textLen", type: DB.Integer], [name: "formatLen", type: DB.Integer] ]]; mDisplayInfo: PUBLIC DB.Relation; -- One per Msg mDisplayType: DB.FieldSpec = DB.L2FS[LIST[ [name: "of", type: MsgType], [name: "tocEntry", type: DB.String, lengthHint: 70], [name: "startOfSubject", type: DB.Integer], [name: "hasBeenRead", type: DB.Boolean] ]]; mInfo: PUBLIC DB.Relation; -- One per Msg mInfoType: DB.FieldSpec = DB.L2FS[LIST[ [name: "of", type: MsgType], [name: "date", type: DB.Time], [name: "show", type: UnacceptedType] ]]; cdRelation: PUBLIC DB.Relation; -- One per Msg / MsgSet pair cdRelationType: DB.FieldSpec = DB.L2FS[LIST[ [name: "of", type: MsgType], [name: "msgSet", type: MsgSetType], [name: "date", type: DB.Time] ]]; cdIndex: PUBLIC DB.Index; cdIndexFieldSequence: DB.FieldSequence = DB.L2F[LIST[WalnutSchema.cdMsgSet, WalnutSchema.cdDate]]; schemaDateField: DB.FieldSpec = DB.L2FS[LIST[[name: "schemaDate", type: DB.Time]]]; gSchemaDateInfoName: ROPE = "gSchemaDateInfo"; Initialize: PUBLIC PROC [segment: WalnutDefs.Segment] = { DO BEGIN ENABLE DB.Error => IF code = ProtectionViolation THEN GOTO readOnly ELSE GOTO badSchema; gSchemaDateInfo: DB.Relation = DB.DeclareRelation[gSchemaDateInfoName, segment, schemaDateField]; schemaRelship: DB.Relship _ DB.FirstRelship[gSchemaDateInfo]; IF schemaRelship = NIL THEN schemaRelship _ DB.CreateRelship[gSchemaDateInfo, DB.L2VS[LIST[DB.T2V[schemaVersionDate]]]] ELSE { date: BasicTime.GMT = DB.V2T[DB.GetF[schemaRelship, 0]]; IF date = schemaVersionDate THEN EXIT; ERROR WalnutDefs.SchemaMismatch[TimesToRope[date, schemaVersionDate]] }; EXITS badSchema => ERROR WalnutDefs.SchemaMismatch[ TimesToRope[BasicTime.nullGMT, schemaVersionDate]]; readOnly => ERROR WalnutDefs.Error[ $db, $readOnly, "You only have read permission for this database"]; END; ENDLOOP; gRootInfo _ DB.DeclareRelation["RootInfo", segment, gRootInfoFields]; gLogInfo _ DB.DeclareRelation["LogInfo", segment, gLogInfoFields]; gParseLogInfo _ DB.DeclareRelation["ParseLogInfo", segment, gParseLogInfoFields]; gExpungeInfo _ DB.DeclareRelation["ExpungeInfo", segment, gExpungeLogInfoFields]; gNewMailInfo _ DB.DeclareRelation["NewMailInfo", segment, gNewMailInfoFields]; gReadArchiveInfo _ DB.DeclareRelation["ReadArchiveInfo", segment, gReadArchiveInfoFields]; gVersionInfo _ DB.DeclareRelation["VersionInfo", segment, gVersionInfoFields]; MsgDomain _ DB.DeclareDomain["Msg", segment]; MsgSetDomain _ DB.DeclareDomain["MsgSet", segment]; ServerDomain _ DB.DeclareDomain["Server", segment]; UnacceptedDomain _ DB.DeclareDomain["Unaccepted", segment]; sBasicInfo _ DB.DeclareProperty["sBasicInfo", segment, sBasicType]; msBasicInfo _ DB.DeclareProperty["msBasicInfo", segment, msBasicType]; mTextInfo _ DB.DeclareProperty["mTextInfo", segment, mTextType]; mDisplayInfo _ DB.DeclareProperty["mDisplayInfo", segment, mDisplayType]; mInfo _ DB.DeclareProperty["mInfo", segment, mInfoType]; cdRelation _ DB.DeclareRelation["cdRelation", segment, cdRelationType]; cdIndex _ DB.DeclareIndex[cdRelation, cdIndexFieldSequence]; BEGIN gr: DB.Relship _ DB.FirstRelship[gRootInfo]; IF gr = NIL THEN { init: DB.ValueSequence _ DB.L2VS[ LIST[ [time[BasicTime.nullGMT]], [rope[NIL]], [rope[NIL]] ] ]; [] _ DB.CreateRelship[gRootInfo, init]; init _ DB.L2VS[ LIST[ [integer[0]], [integer[0]], [integer[0]], [integer[0]], [time[BasicTime.nullGMT]] ] ]; [] _ DB.CreateRelship[gLogInfo, init]; init _ DB.L2VS[ LIST[ [boolean[FALSE]], [integer[0]] ] ]; [] _ DB.CreateRelship[gParseLogInfo, init]; init _ DB.L2VS[ LIST[ [integer[0]], [integer[0]], [integer[0]], [integer[0]], [time[BasicTime.nullGMT]] ] ]; [] _ DB.CreateRelship[gExpungeInfo, init]; init _ DB.L2VS[LIST[ [integer[0]], [integer[0]], [integer[0]], [boolean[FALSE]], [time[BasicTime.nullGMT]] ] ]; [] _ DB.CreateRelship[gNewMailInfo, init]; init _ DB.L2VS[ LIST[ [integer[0]], [integer[0]] ] ]; [] _ DB.CreateRelship[gReadArchiveInfo, init]; init _ DB.L2VS[ LIST[ [integer[0]], [integer[2]], [integer[1]] ] ]; [] _ DB.CreateRelship[gVersionInfo, init]; }; END; WalnutRoot.CommitAndContinue[]; }; SetSchemaVersion: PUBLIC PROC[segment: WalnutDefs.Segment] = { gSchemaDateInfo: DB.Relation = DB.DeclareRelation[gSchemaDateInfoName, segment, schemaDateField]; schemaRelship: DB.Relship _ DB.FirstRelship[gSchemaDateInfo]; IF schemaRelship # NIL THEN DB.SetF[schemaRelship, 0, DB.T2V[schemaVersionDate]] ELSE schemaRelship _ DB.CreateRelship[gSchemaDateInfo, DB.L2VS[LIST[DB.T2V[schemaVersionDate]]]]; }; TimesToRope: PROC[is, shouldBe: BasicTime.GMT] RETURNS[ROPE] = { isR, shouldR: ROPE; isR _ IO.PutFR[NIL, IO.time[is ! BasicTime.OutOfRange => isR _ "OutOfRange"]]; shouldR _ IO.PutFR[NIL, IO.time[shouldBe ! BasicTime.OutOfRange => shouldR _ "OutOfRange"]]; RETURN[Rope.Cat["\nSchema is of: ", isR, " but should be of: ", shouldR]]; }; END. ~WalnutSchemaImpl.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. Willie-Sue, May 22, 1986 4:59:34 pm PDT Donahue, April 10, 1986 2:49:04 pm PST Types and entities in the Walnut message database Last Edited by: Willie-Sue, January 4, 1985 9:05:15 am PST Last Edited by: Wert, August 31, 1984 7:38:03 pm PDT Last Edited by: Donahue, February 2, 1985 9:37:11 am PST (Added NewMail and Archive log position info for restart) (Changed to be consistent with new WalnutSchema) Types Signals and Errors Variables Global Relations - one each per database Global Domains Global Relations - one each per database Server entity Relation MsgSet entity Relation Msg displaying Relation Msg in MsgSet displayer relation Msg Date/Show relation Category/Date Relation Procedures This procedure initializes the database schema, and commits it to the database. -- Define the Global Relations -- Define the Global Domains -- Define the indicies check for relships MsgCount: 0, MsgSetCount: 2, MsgSetsVersion: 1 -- Commit what we've done this doesn't commit, so it can be used by NewWalnutUser WalnutRoot.CommitAndContinue[]; Κ υ˜šΠbc™Jšœ Οmœ1™J˜Jš œ œ œ œ œ œ˜?J˜Jš œ œ œ  œ œ œ œ˜G—J˜š’ ™ J™Jšœ œ9˜OJ˜—šŸ(™(J™Jšœ  œ œ ˜šœ œ ˜š œ œ˜ Jšœ œ˜'Jšœ œ˜8Jšœ œ˜2Jšœ˜—J˜—Jšœ  œ œ ˜šœ œ ˜š œ œ˜ Jšœ œ ˜&Jšœ  œ ˜,Jšœ% œ ˜1Jšœ% œ ˜1Jšœ# œ˜+Jšœ˜—J˜—Jšœ œ œ ˜"šœ œ ˜#š œ œ˜ Jšœ# œ ˜/Jšœ œ ˜'Jšœ˜—J˜—Jšœ œ œ ˜!šœ œ ˜%š œ œ˜ Jšœ  œ ˜,Jšœ œ ˜+Jšœ œ ˜*Jšœ œ ˜'Jšœ" œ˜*Jšœ˜—J˜—Jšœ œ œ ˜!šœ œ ˜"š œ œ˜ Jšœ! œ ˜-Jšœ" œ ˜.Jšœ$ œ ˜0Jšœ! œ ˜-Jšœ% œ˜-Jšœ˜—J˜—Jšœ œ œ ˜%šœ œ ˜&š œ œ˜ Jšœ" œ ˜.Jšœ& œ ˜1Jšœ˜—J˜—Jšœ œ œ ˜!šœ œ ˜"š œ œ˜ Jšœ œ ˜%Jšœ œ ˜(Jšœ*˜*Jšœ˜——J˜—šŸ™J˜Jš‘ œ œ œ˜J˜š‘ œ œ œ œ ˜*Jšœ œ œ˜(—J˜Jš‘œ œ$˜/J˜Jš‘ œ œ œ˜J˜š‘œ œ œ œ ˜-Jšœ œ œ ˜+—J˜Jš‘ œ œ'˜5J˜Jš‘ œ œ œ˜J˜š‘œ œ œ œ ˜-Jšœ œ œ ˜+—J˜Jš‘ œ œ'˜5J˜Jš‘œ œ œ˜#J˜š‘œ œ œ œ ˜1Jšœ œ œ$˜/—J˜Jš‘œ œ+˜=J˜šŸ(™(J™—™J™Jšœ  œ œŸ˜4šœ  œ ˜š œ œ˜ Jšœ˜Jšœ œ ˜$Jšœ˜———J™šŸœŸœ™J˜Jšœ  œ œŸ˜5šœ  œ ˜š œ œ˜ Jšœ˜Jšœ œ ˜"Jšœ œ ˜$Jšœ œ˜$Jšœ˜———J˜šŸœ Ÿœ™J˜Jšœ  œ œ Ÿ˜/šœ  œ ˜š œ œ˜ Jšœ˜Jšœ œ˜2Jšœ œ ˜)Jšœ œ ˜'Jšœ œ ˜'Jšœ œ ˜$Jšœ œ ˜%Jšœ˜———J™šŸœŸœ™ J˜Jšœ œ œ Ÿ˜2šœ œ ˜š œ œ˜ Jšœ˜Jšœ œ˜4Jšœ œ ˜+Jšœ œ ˜'Jšœ˜———J™šŸœ Ÿœ™J˜Jšœ œ œŸ˜,šœ  œ ˜š œ œ˜ Jšœ˜Jšœ œ˜Jšœ$˜$Jšœ˜———J˜šœ™J˜Jšœ  œ œŸ˜?šœ œ ˜š œ œ˜ Jšœ˜Jšœ#˜#Jšœ œ˜Jšœ˜——J˜Jšœ  œ œ˜šœ œ˜(Jš œ œ.˜9—J˜Jš œ œ  œ œ œ ˜SJšœ œ˜.J˜—J˜—š’ ™ J˜š‘ œ œ œ"˜9J˜J˜JšœO™OJ˜—š ˜š œ œ œ ˜Jš  œ œ œ  œ œ ˜EJ˜šœ œ ˜Jš œ@˜B—Jšœ œ  œ˜=š œ œ ˜Jš œ œ  œ œ œ˜[—š œ˜Jšœ œ œ œ˜8Jš œ œ œ˜&Jš œC˜H—š ˜šœ ˜ š œ˜ Jšœ3˜3——šœ ˜ š œ˜JšœC˜C———Jš œ˜—Jš œ˜J˜Jšœ™™Jšœ  œ7˜EJšœ  œ5˜BJšœ œ?˜QJšœ œ@˜QJšœ œ=˜Nšœ˜Jš œE˜G—Jšœ œ=˜N—J˜šœ™J˜Jšœ  œ˜-Jšœ œ"˜3Jšœ œ"˜3Jšœ œ&˜;—˜Jšœ  œ4˜CJšœ œ6˜FJ˜Jšœ  œ2˜@Jšœ œ8˜IJšœ œ.˜8J˜Jšœ  œ8˜GJ™—™J˜Jšœ  œ0˜<—J˜šœ™J™š ˜Jšœ œ  œ˜,š œ œ œ˜šœ œ œ œ˜'Jšœ! œ  œ˜8—Jšœ œ ˜'J˜šœ œ œ˜Jšœ7˜7Jšœ˜—Jšœ œ˜&J˜Jšœ œ œ  œ˜9Jšœ œ$˜+J˜šœ œ œ˜Jšœ7˜7Jšœ˜Jšœ˜—Jšœ œ#˜*J˜šœ œ œ˜Jšœ)˜)Jšœ  œ˜+Jšœ˜—Jšœ œ#˜*J˜Jšœ œ œ!˜5Jšœ œ'˜.J˜Jšœ.™.Jšœ œ œ/˜CJšœ œ#˜*J˜J˜—Jš œ˜—J™—J˜™J™J˜J™—Jšœ˜—J˜š‘œ œ œ!˜>J™7šœ œ ˜Jš œ@˜B—Jšœ œ  œ˜=š œ œ ˜Jš œ œ˜4š œ˜Jš œ  œ œ œ˜L——J™J˜—J˜š ‘ œ œ œ œ œ˜@Jšœ œ˜Jšœ œ œ œ8˜Nšœ  œ œ œ(˜BJšœ˜—Jš œD˜JJšœ˜——J˜Jš œ˜—J˜—…—#64©