-- File: DBStorageFieldImpl.mesa -- Last edited by MBrown on 18-Jun-81 14:40:28 -- Last Edited by: Willie-Sue, January 10, 1983 2:50 pm -- Last Edited by: Cattell, September 14, 1983 4:17 pm DIRECTORY DBCache USING[CacheHandle], DBCommon USING[DBPage, NullDBPage, WordsPerPage], DBEnvironment USING[InternalError, Failure], DBSegment USING[SegmentIDFromDBPage, UnlockPage, WriteLockedPage], DBStorage, DBStorageConcrete USING[SystemTuplesetObject, FieldObject, FieldType], DBStorageExtTuple USING[SizeOfNullTuple], DBStorageField USING[], DBStoragePrivate USING[GetNWordBase], DBStorageTID USING[TID, DecomposeTID], DBStorageTupleset USING[TuplesetObject], DBStorageTuple USING[TIDOfTuple]; DBStorageFieldImpl: PROGRAM IMPORTS DBEnvironment, DBSegment, DBStoragePrivate, DBStorageTID, DBStorageTuple EXPORTS DBStorage, DBStorageField = BEGIN OPEN DBCommon, DBStorageTID; -- This module exports the following procedures of DBStorage: -- CreateTupleset, CreateSystemTupleset, DestroyTupleset, AddField, AddSystemField, DeleteField. -- This module exports all of DBStorageField. -- PROBLEMS, THINGS YET TO BE DONE: -- postponed: DestroyTupleset, DeleteField. -- AddField will only work on an empty tupleset; otherwise it SIGNALs BadOperation. -- Types exported to DBStorage FieldObject: PUBLIC TYPE = DBStorageConcrete.FieldObject; FieldHandle: TYPE = REF FieldObject; ListofFieldHandle: TYPE = LIST OF FieldHandle; SystemTuplesetObject: PUBLIC TYPE = DBStorageConcrete.SystemTuplesetObject; SystemTuplesetHandle: TYPE = REF SystemTuplesetObject; -- Procs exported to DBStorageField tuplesetFieldHandle: FieldHandle; indexFieldHandle: FieldHandle; TuplesetFieldHandle: PUBLIC PROC RETURNS[FieldHandle] = { RETURN[tuplesetFieldHandle] };--TuplesetFieldHandle IndexFieldHandle: PUBLIC PROC RETURNS[FieldHandle] = { RETURN[indexFieldHandle] };--IndexFieldHandle CheckFieldHandleType: PUBLIC PROC[fh: FieldHandle, t: DBStorageConcrete.FieldType] = { -- Generates an ERROR if fh's fieldType is not t. IF fh.fieldType # t THEN ERROR DBEnvironment.InternalError; -- [Unknown]; };--CheckFieldHandleType FieldOffset: PUBLIC PROC[fh: FieldHandle] RETURNS[CARDINAL] = { RETURN[fh.offset]; };--FieldOffset NWordsInField: PUBLIC PROC[fh: FieldHandle] RETURNS[CARDINAL] = { RETURN[fh.nWords]; };--NWordsInField GroupIDOfField: PUBLIC PROC[fh: FieldHandle] RETURNS[TID] = { IF fh.fieldType # Group THEN ERROR DBEnvironment.InternalError; -- [Unknown]; RETURN[fh.groupID]; };--GroupIDOfField -- Procs exported to DBStorage CreateTupleset: PUBLIC PROC[x: DBStorage.TuplesetHandle, expectedNGroups: CARDINAL] = { -- Creates a new tupleset whose tuples have no fields. The parameter x is an -- existing tuple whose first-created field is an NWord field, TuplesetObjectLength -- words long. Information describing the new tupleset is placed in this field, and -- tuples in the new tupleset are placed in the same segment as tuple x . Tuple x is -- returned by a ReadTuplesetID call on any tuple in this tupleset. -- Note that the TuplesetHandle is used primarily by CreateTuple, but is also -- modified by AddField/DeleteField. tsObjPtr: LONG POINTER TO DBStorageTupleset.TuplesetObject; cacheHint: DBCache.CacheHandle; dbPage: DBPage; [dbPage,] ← DecomposeTID[DBStorageTuple.TIDOfTuple[x]]; [tsObjPtr, cacheHint] ← DBStoragePrivate.GetNWordBase[x, TuplesetFieldHandle[]]; DBSegment.WriteLockedPage[cacheHint]; tsObjPtr↑ ← [ wordsForTupleFields: 0, nVarFields: 0, expectedNGroups: expectedNGroups, searchList: [tuplesetID: DBStorageTuple.TIDOfTuple[x], next: NullDBPage, prev: NullDBPage], pageAllocator: [segmentID: DBSegment.SegmentIDFromDBPage[dbPage]] ]; DBSegment.UnlockPage[cacheHint]; };--CreateTupleset CreateSystemTupleset: PUBLIC PROC[x: DBStorage.SystemTupleID] RETURNS[SystemTuplesetHandle] = { -- Creates a new system tupleset (system tuplesets do not live in a single segment -- and the pages containing their tuples are not chained together by the storage -- level). IF x NOT IN [1..DBStorage.MaxSystemTupleID] THEN ERROR DBEnvironment.InternalError; -- [Unknown]; RETURN[NEW[SystemTuplesetObject ← [tuplesetID: x, wordsForTupleFields: 0]]]; };--CreateSystemTupleset DestroyTupleset: PUBLIC PROC[x: DBStorage.TuplesetHandle] = { -- In effect this procedure performs DestroyTuple on every tuple of the set -- described by x, and undoes whatever was done by the CreateTupleset call that -- created the tupleset. Any further user of TuplesetHandle x is an error. -- (DestroyTupleset has no effect on system tuplesets). ERROR; };--DestroyTupleset CreateFieldHandle: PUBLIC PROC RETURNS [FieldHandle] = -- Since the FieldObject type is opaque, this procedure is needed to allocate a FieldHandle, -- to be passed to ReadNWord when retrieving a FieldHandle stored in the data schema. {RETURN[NEW[DBStorageConcrete.FieldObject]]}; MaxWordsPerTuple: CARDINAL = 3*(DBCommon.WordsPerPage/4); -- If AddField would make a tuple type with more than this many words per tuple, BadOperation is --raised. MakeFieldHandle: PROC[y: DBStorage.FieldDescriptor, wordsForTupleFields: CARDINAL] RETURNS[--fh-- FieldHandle, --newWordsInTuple-- CARDINAL] = { -- Creates a new field handle, for a tupleset whose tuples contain wordsInTuple words, in fh -- based on the description of the field in y. Returns the new number of words in a tuple. -- If this number of words is uncomfortably large (see MaxWordsPerTuple above), raise -- BadOperation. -- Called from: AddField, AddSystemField, module init code. fh: FieldHandle ← NEW[DBStorageConcrete.FieldObject]; fieldInfo: RECORD[code: DBStorageConcrete.FieldType, length: CARDINAL] ← WITH fd: y SELECT FROM OneWord => [OneWord, 1], TwoWord => [TwoWord, 2], NWord => [NWord, fd.length], VarWord => [VarWord, 1 + fd.lengthHint], VarByte => [VarByte, 1 + (fd.lengthHint+1)/2], Group => [Group, 3*SIZE[TID]], ENDCASE => ERROR DBEnvironment.InternalError; -- [Unknown]; fh.fieldType ← fieldInfo.code; fh.offset ← DBStorageExtTuple.SizeOfNullTuple + wordsForTupleFields; fh.nWords ← fieldInfo.length; WITH fd: y SELECT FROM Group => fh.groupID ← DBStorageTuple.TIDOfTuple[fd.groupID]; ENDCASE => fh.fill1 ← 0; IF wordsForTupleFields + fieldInfo.length > MaxWordsPerTuple THEN ERROR DBEnvironment.Failure[$tupleTooLong]; RETURN[fh, wordsForTupleFields + fieldInfo.length]; };--MakeFieldHandle AddField: PUBLIC PROC[x: DBStorage.TuplesetHandle, y: DBStorage.FieldDescriptor] RETURNS[FieldHandle] = { -- In effect this procedure modifies each tuple of set x, adding a new field of -- type y. It returns a FieldHandle for the new field. fh: FieldHandle; tsObjPtr: LONG POINTER TO DBStorageTupleset.TuplesetObject; cacheHint: DBCache.CacheHandle; [tsObjPtr, cacheHint] ← DBStoragePrivate.GetNWordBase[x, TuplesetFieldHandle[]]; -- For now, die if user tries to add a field after a tuple has been created. IF tsObjPtr.allocList#NullDBPage OR tsObjPtr.searchList.next#NullDBPage THEN ERROR DBEnvironment.InternalError; -- [AddFieldToExistingTupleset]; DBSegment.WriteLockedPage[cacheHint]; [fh, tsObjPtr.wordsForTupleFields] ← MakeFieldHandle[y, tsObjPtr.wordsForTupleFields]; SELECT fh.fieldType FROM VarWord, VarByte => {tsObjPtr.nVarFields ← tsObjPtr.nVarFields + 1; }; ENDCASE => {}; DBSegment.UnlockPage[cacheHint]; RETURN[fh]; };--AddField AddSystemField: PUBLIC PROC[x: SystemTuplesetHandle, y: DBStorage.FieldDescriptor] RETURNS[FieldHandle] = { -- This procedure adds to x the length of y. It returns a FieldHandle for the new -- field. fh: FieldHandle; [fh, x.wordsForTupleFields] ← MakeFieldHandle[y, x.wordsForTupleFields]; RETURN[fh]; };--AddSystemField DeleteField: PUBLIC PROC [x: DBStorage.TuplesetHandle, z: ListofFieldHandle, i: INTEGER] RETURNS[ListofFieldHandle] = { -- In effect this procedure modifies each tuple of set x, deleting the i-th field -- in list z. Parameter z describes all of the fields of tuples in x, and the result -- gives new handles for the undeleted fields, in the same order (handles will change -- due to deletion). -- Note: will the field handles be presented in order of creation? this would -- avoid a sort. (This procedure will NOT be implemented in the first system). ERROR; };--DeleteField -- Mainline code (start trap on first TuplesetFieldHandle[] or IndexFieldHandle[] will do this -- required initialization) IF DBStorage.FieldObjectSize < SIZE[DBStorageConcrete.FieldObject] OR DBStorage.TuplesetObjectSize < SIZE[DBStorageTupleset.TuplesetObject] THEN ERROR DBEnvironment.InternalError; -- [Unknown]; [tuplesetFieldHandle,] ← MakeFieldHandle[[NWord[DBStorage.TuplesetObjectSize]], 0]; [indexFieldHandle,] ← MakeFieldHandle[[NWord[DBStorage.IndexObjectSize]], 0]; END.--DBStorageFieldImpl CHANGE LOG Created by MBrown on 2-Feb-80 16:07 -- AllocVec, CompactPage, and related inlines {~1 to paper-sketch AllocVec, 3:15 to --code, :10 to compile}. Changed by MBrown on February 3, 1980 3:07 PM -- CreateTupleset, CreateSystemTupleset, AddField, AddSystemField, FreeTupleHandle. Changed by MBrown on February 10, 1980 11:41 PM -- Read1Word, Read2Word, ReadNWord (except overflow page reads). Changed by MBrown on February 16, 1980 12:15 AM -- Major restructuring of storage impl. Moved everything but tupleset creation/field --creation out of this module. Changed by MBrown on February 16, 1980 9:11 PM -- Moved heap storage allocation to DBStorageHeap. Changed by MBrown on February 16, 1980 11:04 PM -- Invented MakeFieldHandle to reduce some duplication. Changed by MBrown on 17-Feb-80 13:59 -- Eliminated use of @ from CreateTupleset. Added checks for inconsistent sizes of --objects, making the "true" size be the one in DBStorage. (This can be larger than --the actual size with no ill effect, but smaller is a no-no). Changed length to --wordsPerTuple in SystemTuplesetObject. Changed by MBrown on February 25, 1980 7:45 PM -- Added procs exported to DBStoragePrivateA (TuplesetFieldHandle, IndexFieldHandle). --Made tupleset creation and field creation consistent with DBStoragePrivateB's TupleBody --structure. Changed by MBrown on April 9, 1980 10:11 AM -- Made CreateTupleset convert the TSID to a DBPage before converting THAT to a segmentID. Changed by MBrown on April 17, 1980 11:02 PM -- Changed SystemTuplesetID to SystemTupleID. Changed by MBrown on June 8, 1980 9:25 PM -- Scattered minor changes in introducing FieldObject as an opaque type. The module now contains --only 2 LOOPHOLEs. Changed MakeFieldHandle to do storage allocation for the field handle it --produces. Changed by MBrown on June 8, 1980 10:19 PM -- Compiler insists on an exported version of DBStorage.ListofFieldHandle. Changed by MBrown on June 10, 1980 8:39 PM -- Renamed to be StorageFieldImpl from StorageImplA. Changed by MBrown on June 24, 1980 11:26 AM -- Made SystemTuplesetObject be opaque in DBStorage. Changed by MBrown on July 31, 1980 3:11 PM -- Added expectedNGroups to CreateTupleset. Changed by MBrown on August 13, 1980 11:59 AM -- DBStoragePrivateB.SizeOfNullTuple became DBStorageExtTuple.SizeOfNullTuple. Changed by MBrown on August 25, 1980 1:37 PM -- Added nVarFields to TuplesetObject. Changed by MBrown on September 26, 1980 12:28 PM -- Converted to new DBException. Changed by MBrown on February 27, 1981 3:58 PM -- Use zone for storage allocation. Changed by MBrown on 18-Jun-81 14:47:11 -- Use counted zone for allocation of system tupleset objects. Changed by Cattell on November 4, 1983 2:21 am -- Removed tuple object zone, just do vanilla NEWs for Cedar 5.0