-- 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, January 16, 1983 11:41 am
DIRECTORY
DBCache USING[CacheHandle],
DBCommon USING[DBPage, NullDBPage, WordsPerPage],
DBEnvironment USING[InternalError, Fatal],
DBHeapStorage USING[Node --GetTheMDSZone--],
DBSegment USING[SegmentIDFromDBPage, UnlockPage, WriteLockedPage],
DBStorage USING[FieldDescriptor, FieldHandle, TuplesetHandle,
FieldObjectSize, TuplesetObjectSize, IndexObjectSize,
SystemTupleID, MaxSystemTupleID],
DBStorageConcrete USING[SystemTuplesetObject, FieldObject, FieldType],
DBStorageExtTuple USING[SizeOfNullTuple],
DBStorageField USING[],
DBStoragePrivate USING[GetNWordBase],
DBStorageTID USING[TID, DecomposeTID],
DBStorageTupleset USING[TuplesetObject],
DBStorageTuple USING[TIDOfTuple],
SafeStorage USING [GetSystemZone];
DBStorageFieldImpl: PROGRAM
IMPORTS
DBEnvironment,
DBHeapStorage,
DBSegment,
DBStoragePrivate,
DBStorageTID,
DBStorageTuple,
SafeStorage
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 = POINTER TO FieldObject;
ListofFieldHandle: TYPE = DESCRIPTOR FOR ARRAY OF FieldHandle;
SystemTuplesetObject: PUBLIC TYPE = DBStorageConcrete.SystemTuplesetObject;
SystemTuplesetHandle: TYPE = REF SystemTuplesetObject;
-- z: MDSZone = DBHeapStorage.GetTheMDSZone[];
systemTuplesetObjectZone: ZONE = SafeStorage.GetSystemZone[];
-- Procs exported to DBStorageField
CopyFieldObject: PUBLIC PROC[fh: FieldHandle] RETURNS[FieldHandle] = {
result: FieldHandle ← Alloc[];
result↑ ← fh↑;
RETURN[result];
};--CopyFieldObject
FreeFieldObject: PUBLIC PROC[fh: FieldHandle] = {
IF fh # NIL THEN Free[fh];
};--FreeFieldObject
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
-- grubby details of FieldObject storage management. LOOPHOLEs below assume that a FieldObject
--is large enough to hold a FieldHandle.
freeFieldObjectList: FieldHandle ← NIL;
Alloc: PROC[] RETURNS[FieldHandle] = --INLINE-- {
result: FieldHandle;
IF freeFieldObjectList#NIL THEN BEGIN
result ← freeFieldObjectList;
freeFieldObjectList ← LOOPHOLE[freeFieldObjectList,POINTER TO FieldHandle]↑;
RETURN[result]; END
ELSE
-- RETURN[z.NEW[FieldObject]];
RETURN[DBHeapStorage.Node[SIZE[FieldObject]]];
};--Alloc
Free: PROC[f: FieldHandle] = INLINE {
LOOPHOLE[f,POINTER TO FieldHandle]↑ ← freeFieldObjectList; freeFieldObjectList ← f;
};--Free
-- 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[systemTuplesetObjectZone.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
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 ← Alloc[];
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.Fatal[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.