DIRECTORY AlpineEnvironment USING [LockOption], Atom USING [MakeAtom], CardTable USING[Create], DBCommon, DBFileAlpine, DBSegment, DBStorage, DBDefs, DB, DBModel, DBModelPrivate, FS, RefTab, Rope, SymTab; DBModelSegmentImpl: CEDAR PROGRAM IMPORTS Atom, CardTable, DBSegment, DBStorage, DB, DBModelPrivate, FS, RefTab, Rope, SymTab EXPORTS DBModel, DBModelPrivate = BEGIN OPEN DBCommon, DBDefs; initialized: PUBLIC BOOL _ FALSE; segmentTable: RefTab.Ref = RefTab.Create[]; Initialize: PUBLIC PROC[nCachePages: NAT, cacheFileName: ROPE] = { IF initialized THEN RETURN; initialized _ TRUE; IF cacheFileName=NIL THEN cacheFileName_ "DBSegment.VM"; DBStorage.Initialize[nCachePages, cacheFileName]; DBModelPrivate.InitializeDomainSchema[]; DBModelPrivate.InitializeRelationSchema[]; DBModelPrivate.InitializeIndexSchema[] }; SegmentToHandle: PUBLIC PROC [s: Segment] RETURNS [handle: SegmentHandle] ~ { found: BOOL; val: REF ANY; [found, val] _ RefTab.Fetch[segmentTable, s]; IF found THEN {handle _ NARROW[val]; RETURN}; handle _ NEW[SegmentObject _ [segment: s]]; [] _ RefTab.Insert[segmentTable, s, handle] }; CacheKey: PUBLIC PROC[segment: Segment] RETURNS[key: INT] = { key _ SegmentToHandle[segment].key }; OpenTransaction: PUBLIC PROC[segment: Segment, useTrans: TransactionHandle, eraseAfterOpen: BOOL _ FALSE] RETURNS[trans: TransactionHandle, schemaInvalid: BOOL] = { sh: SegmentHandle = SegmentToHandle[segment]; schemaInvalid _ FALSE; IF NOT initialized THEN ERROR DB.Error[DatabaseNotInitialized]; trans _ IF useTrans # NIL THEN useTrans ELSE NEW[TransactionObject _ [trans: DBStorage.MakeTransaction[server: sh.server]]]; DBStorage.OpenTransaction[segment, trans, eraseAfterOpen]; sh.indices _ DBStorage.RootIndicesFromSegment[segment]; BEGIN dbSchemaStamp: INT = DBSegment.GetVersionStamp[segment]; schemaInvalid _ eraseAfterOpen OR sh.cacheTrashed OR (sh.schemaVersionStamp # dbSchemaStamp); IF schemaInvalid THEN { sh.key _ sh.key + 1; sh.domainTable _ SymTab.Create[]; sh.relationTable _ SymTab.Create[]; sh.attributeTable _ CardTable.Create[]; sh.domainsByTID _ CardTable.Create[]; sh.cacheTrashed _ FALSE; -- The cache is empty but valid now sh.schemaVersionStamp _ dbSchemaStamp; sh.schemaUpdated _ FALSE } END; RETURN[trans, schemaInvalid] }; MarkTransaction: PUBLIC PROC[trans: TransactionHandle] = { FinishTransaction[trans: trans, continue: TRUE] }; FinishTransaction: PROC[trans: TransactionHandle, continue: BOOL] = { IF trans # NIL THEN { FOR segments: DBCommon.SegmentList _ trans.segments, segments.next UNTIL segments = NIL DO sh: SegmentHandle _ SegmentToHandle[segments.segment]; IF sh.schemaUpdated THEN { DBSegment.SetVersionStamp[segments.segment, sh.schemaVersionStamp + 1] }; ENDLOOP; DBStorage.FinishTransaction[handle: trans, abort: FALSE, continue: continue]; FOR segments: DBCommon.SegmentList _ trans.segments, segments.next UNTIL segments = NIL DO sh: SegmentHandle _ SegmentToHandle[segments.segment]; IF sh.schemaUpdated THEN { sh.schemaVersionStamp _ sh.schemaVersionStamp + 1; sh.schemaUpdated _ FALSE }; ENDLOOP } }; AbortTransaction: PUBLIC PROC[trans: TransactionHandle] = { IF trans#NIL THEN { DBStorage.FinishTransaction[trans, TRUE, FALSE]; FOR segments: DBCommon.SegmentList _ trans.segments, segments.next UNTIL segments = NIL DO sh: SegmentHandle _ SegmentToHandle[segments.segment]; IF sh.schemaUpdated THEN { sh.domainTable _ sh.relationTable _ NIL; sh.attributeTable _ sh.domainsByTID _ NIL; sh.schemaUpdated _ FALSE; sh.cacheTrashed _ TRUE } ENDLOOP; trans.segments _ NIL } }; CloseTransaction: PUBLIC PROC[trans: TransactionHandle] = { FinishTransaction[trans: trans, continue: FALSE]; trans.segments _ NIL }; DeclareSegment: PUBLIC PROC[filePath: ROPE, segment: Segment, number: DBCommon.SegmentIndex, lock: AlpineEnvironment.LockOption, readonly: BOOL, createIfNotFound: BOOL, nPagesInitial, nPagesPerExtent: INT] = { fileVersion: DBStorage.VersionOptions = IF readonly OR NOT createIfNotFound THEN OldFileOnly ELSE None; nameComponents: FS.ComponentPositions; server, baseName: Rope.ROPE; IF NOT initialized THEN ERROR DB.Error[DatabaseNotInitialized]; [fullFName ~ filePath, cp ~ nameComponents] _ FS.ExpandName[name: filePath, wDir: "///"]; server _ Rope.Substr[filePath, nameComponents.server.start, nameComponents.server.length]; baseName _ Rope.Substr[filePath, nameComponents.base.start, nameComponents.base.length]; IF Rope.Length[server] = 0 OR Rope.Length[baseName] = 0 THEN ERROR DB.Error[IllegalFileName]; IF segment = NIL THEN segment _ Atom.MakeAtom[baseName]; IF number= 0 THEN number _ MapSegmentToNumber[segment]; BEGIN handle: SegmentHandle _ SegmentToHandle[segment]; newAttachment: BOOL = DBStorage.AttachSegment[filePath, segment, number, lock, readonly, fileVersion, nPagesInitial, nPagesPerExtent]; IF NOT newAttachment THEN RETURN; handle.server _ server; handle.cacheTrashed _ TRUE; -- whatever is hanging around in the schema cache for the segment will become invalid when the next transaction is opened END }; EraseSegment: PUBLIC PROC[segment: Segment, useTrans: TransactionHandle] RETURNS [trans: TransactionHandle] = { RETURN[OpenTransaction[segment: segment, useTrans: useTrans, eraseAfterOpen: TRUE].trans] }; GetSegmentInfo: PUBLIC PROC[segment: Segment] RETURNS [filePath: ROPE, readOnly: BOOL] = { IF segment = NIL THEN ERROR DB.Error[NILArgument]; [filePath, readOnly] _ DBSegment.GetSegmentInfo[segment] }; MapSegmentToNumber: PROC [segment: Segment] RETURNS [NAT] = { FOR i: CARDINAL IN [0..builtinSegmentCount) DO IF segment = segmentArray[i].segment THEN RETURN[segmentArray[i].index]; ENDLOOP; RETURN WITH ERROR DB.Error[CannotDefaultSegment]; -- seg number not given & can't guess }; SegmentAndIndex: TYPE = RECORD[segment: Segment, index: SegmentIndex]; builtinSegmentCount: CARDINAL = 8; segmentArray: ARRAY [0..builtinSegmentCount) OF SegmentAndIndex = [ [$Icons, 140B], [$Walnut, 200B], [$Nuthatch, 250B], [$Finger, 260B], [$Test, 300B], [$Whiteboard, 310B], [$Tool, 320B], [$WalnutSortDef, 330B] ]; END. „File: DBModelSegmentImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last edited by: Donahue, April 15, 1986 3:43:33 pm PST This table contains the segment handles for each currently in use segment; these segment handles have all of the cached schema information. Initialization of database system Initializes database system Management of the schema caches for each segment Transaction operations Check the database version of the schema version stamp and flush the segment caches if the version stamps disagree The schema cache is invalid (ie., the key will change) iff either the database is being erased, the cache is currently empty (caused by an aborted transaction), or the stamps in the database and cache disagree Write the updated version stamps for segments that have a changed schema Commit the transaction (The fact that the schema was changed is still known at this point so that if the transaction aborts, the schema cache is flushed. In the case of an abort, we can't assume anything about the state of the cache relative to the database!) If the transaction successfully commits, update the cached version stamps of all segments that changed the schema as a result of the transaction Bad news. The only thing that can be done here is to flush all of the cached information about the schema and recompute it when a new transaction is opened Throw away away the segments for the transaction; it is now disconnected from everything Throw away away the segments for the transaction; it is now disconnected from everything Segment operations Save away the server name for future reference reserve [330B .. 350B) for Pasadena Κύ˜šœ™Jšœ Οmœ1™<—šœ™Icode™&J˜—šΟk ˜ Jšœžœ˜%Jšœžœ ˜Jšœ žœ ˜J˜ J˜ J˜ J˜ J˜Jšžœ˜J˜J˜J˜J˜J˜J˜J˜—šœžœž˜!Jšžœ(žœ*˜[Jšžœ˜!J˜—šžœžœ˜J˜Jšœ žœžœžœ˜!J˜šœ+˜+Jšœ‹™‹——head1šœ!™!š Οn œžœžœžœžœ˜BJšœ™Jšžœ žœžœ˜Jšœžœ˜Jšžœžœžœ˜8J˜1Jšœ(˜(Jšœ*˜*J˜&Jšœ˜——™0šŸœž œžœ˜MKšœžœ˜ Kšœžœžœ˜ K˜-Kšžœžœ žœžœ˜-Kšœ žœ˜+K˜+K˜—K˜šŸœž œžœžœ˜=Jšœ%˜%——šœ™šŸœžœžœ@žœžœžœ*žœ˜€Jšœ-˜-Jšœžœ˜Jš žœžœ žœžœžœ˜?šœžœ žœžœ ˜'JšžœžœL˜T—Jšœ:˜:Jšœ7˜7J™ršž˜Jšœžœ&˜8JšœΡ™ΡJšœžœžœ)˜]šžœžœ˜Jšœ˜Jšœ!˜!Jšœ#˜#J˜'J˜%JšœžœΟc#˜=Jšœ&˜&Jšœžœ˜—Jšžœ˜—šžœ˜J˜——šŸœžœžœ˜;Jšœ*žœ˜2J˜—šŸœžœ%žœ˜Ešžœ žœžœ˜šœH™Hšžœ@žœ žœž˜ZJšœ6˜6šžœžœ˜JšœI˜I—Jšžœ˜——Jšœ„™„Jšœ2žœ˜MJšœ™šžœ@žœ žœž˜ZJšœ6˜6šžœžœ˜Jšœ2˜2Jšœžœ˜—Jšžœ˜ ———J˜šŸœžœžœ˜;šžœžœžœ˜Jšœ#žœžœ˜0šžœ@žœ žœž˜ZJšœ6˜6šžœžœ˜Jšœœ™œJšœ$žœ˜(Jšœ&žœ˜*Jšœžœ˜Jšœžœ˜—Jšžœ˜—JšœX™XJšœžœ˜—J˜—J˜šŸœžœžœ˜;Jšœ*žœ˜1JšœX™XJšœžœ˜——šœ™šŸœžœžœ žœažœžœ"žœ˜ΡJš œ(žœ žœžœžœ žœ˜gJšœžœ˜&Jšœžœ˜Jš žœžœ žœžœžœ˜?Jšœ.žœ)˜YJšœZ˜ZJšœX˜XJš žœžœžœžœžœ˜]Jšžœ žœžœ#˜8Jšžœ žœ&˜7Jšœ.™.šž˜Jšœ1˜1Jšœžœs˜†Jšžœžœžœžœ˜!Jšœ˜Jšœžœ y˜•Jšžœ˜——J˜šŸ œžœžœ0žœ˜oJšžœGžœ ˜\J˜—š Ÿœžœžœžœ žœ žœ˜ZJšžœ žœžœžœ˜2Jšœ;˜;J˜—šŸœžœžœžœ˜=šžœžœžœž˜.Jšžœ#žœžœ˜HJšžœ˜—Jš žœžœžœžœ %˜WJ˜—J˜Jšœžœžœ(˜FJšœžœ˜"šœžœžœ˜AJšœ‘˜‘Jšœ#™#Jšœ˜——J˜Jšžœ˜J˜J˜J˜J˜—…—”%