File: DBStorageFieldImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Last edited by MBrown on 18-Jun-81 14:40:28
Last Edited by: Willie-Sue, February 15, 1985 12:35:06 pm PST
Last Edited by: Cattell, January 18, 1984 11:13 am
Last Edited by: Widom, July 19, 1985 2:25:29 pm PDT
Donahue, December 31, 1985 2:41:08 pm PST
DIRECTORY
DB,
DBCommon USING[CacheHandle, DBPage, NullDBPage, WordsPerPage],
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],
Rope USING [ROPE];
DBStorageFieldImpl:
CEDAR
PROGRAM
IMPORTS
DB,
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 DB.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 DB.InternalError; -- [Unknown];
RETURN[fh.groupID];
};--GroupIDOfField
Procs exported to DBStorage
CreateTupleset:
PUBLIC
PROC[x: DBStorage.TuplesetHandle] =
TRUSTED {
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: DBCommon.CacheHandle;
dbPage: DBPage;
[dbPage,] ← DecomposeTID[DBStorageTuple.TIDOfTuple[x]];
[tsObjPtr, cacheHint] ← DBStoragePrivate.GetNWordBase[x, TuplesetFieldHandle[]];
DBSegment.WriteLockedPage[cacheHint];
tsObjPtr^ ← [
wordsForTupleFields: 0,
nVarFields: 0,
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 DB.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 ← [typeDependent: group[]]]]};
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] =
TRUSTED {
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← [typeDependent: group[]]];
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 DB.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 DB.Failure[$tupleTooLong, "can't make tuple this big"];
RETURN[fh, wordsForTupleFields + fieldInfo.length];
};--MakeFieldHandle
AddField:
PUBLIC
PROC[x: DBStorage.TuplesetHandle, y: DBStorage.FieldDescriptor]
RETURNS[FieldHandle] =
TRUSTED {
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: DBCommon.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 DB.Error[NotImplemented]; -- Adding field to existing relation!
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 DB.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
Changed by Willie-Sue February 15, 1985
made Cedar, added tioga formatting