-- 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