-- File DBStorage.mesa -- Last edited by: -- MBrown on December 16, 1982 2:46 pm -- Cattell on June 6, 1983 3:16 pm -- Willie-Sue on February 3, 1983 10:59 am DIRECTORY DBCommon, DBEnvironment USING [TupleObject, FirstLast], IO USING [Handle], Rope USING [ROPE]; DBStorage: DEFINITIONS = BEGIN ROPE: TYPE = Rope.ROPE; Trans: TYPE = DBCommon.Trans; Segment: TYPE = DBCommon.Segment; SegmentIndex: TYPE = DBCommon.SegmentIndex; SegmentID: TYPE = DBCommon.SegmentID; VersionOptions: TYPE = DBCommon.VersionOptions; -- This interface contains all procedures defined by the storage level and used by the --tuple level. At last count there were 51 procedures in the interface. -- CONSTANTS and TYPES TuplesetObjectSize: CARDINAL = 20; IndexObjectSize: CARDINAL = 20; FieldObjectSize: CARDINAL = 5; -- Sizes of data structures that are shared between storage and tuple levels: --tupleset, index, and field "objects". Apart from this size information, these --objects are opaque above the storage level. FieldObjects do not change unless --DeleteField is done, so these may be cached by the tuple level; FieldObjects are --stored in the database, but pointers to in-core copies are always passed to the --storage level. Tupleset and Index objects may change due to tuple creation, index --insertion, etc; these are stored in the database and accessed directly by the --storage level, using the convention that the first-created field in a tuple --containing a Tupleset or Index object must contain the object, and have the --agreed-upon size. -- These sizes are used by both levels, even though the storage level knows the true --space requirement. If the actual record requires less space, it is padded to the --full size. TupleHandle: TYPE = REF TupleObject; TupleObject: TYPE = DBEnvironment.TupleObject; -- Concrete type defined in DBTuplesConcrete. TuplesetHandle: TYPE = TupleHandle; -- The first-created field of this tuple is an NWord field of length --TuplesetObjectSize, which is used to store the tupleset object (containing --information about the tupleset such as the size of a tuple and the list of pages --that contain tuples from this tupleset). A tupleset object is never copied, it is --always updated in place. SystemTuplesetHandle: TYPE = REF SystemTuplesetObject; SystemTuplesetObject: TYPE; -- Defined in DBStorageConcrete. SystemTupleID: TYPE = LONG CARDINAL; --really [1..MaxSystemTupleID] MaxSystemTupleID: CARDINAL = 128; -- Supplied as an argument to CreateSystemTupleset. CreateSystemPageTuple assigns this --number as tupleset ID, and whenever a tupleset ID is turned into a tuple, it is --range-checked to see if it is a system tupleset. FieldDescriptor: TYPE = RECORD[ variantPart: SELECT basicType: FieldClass FROM OneWord,TwoWord => NULL, NWord => [length: CARDINAL], -- Number of words in the field VarWord,VarByte => [lengthHint: CARDINAL], -- Number of words/bytes that can be stored inline in the field Group => [groupID: GroupID], -- A GroupID is a TupleHandle. The TID contained therein is considered to be --the unique ID of the Group field. Normally this is the TID of a dictionary --tuple that describes this attribute. In the case of the attributes of the --dictionary tuples themselves, a SystemTupleID is used; this points to no real --tuple. ENDCASE ];--FieldDescriptor -- A FieldDescriptor is used only as a parameter to AddField. FieldClass: TYPE = {OneWord, TwoWord, NWord, VarWord, VarByte, Group}; FieldHandle: TYPE = POINTER TO FieldObject; FieldObject: TYPE; ListOfFieldHandle: TYPE = DESCRIPTOR FOR ARRAY OF FieldHandle; -- The FieldObject pointed to has length FieldObjectSize, and its long-term storage is --the responsibility of the Tuple level. -- The FieldHandle is used to do field read/writes. The interface implies that a --field handle actually contains the FieldDescriptor that was used to create it, as --well as other stuff such as the offset within the tuple, etc. TuplesetScanHandle: TYPE = REF TuplesetScanObject; TuplesetScanObject: TYPE; -- Defined in DBStorageConcrete. GroupID: TYPE = TupleHandle; GroupScanHandle: TYPE = REF GroupScanObject; GroupScanObject: TYPE; -- Defined in DBStorageConcrete. IndexHandle: TYPE = TupleHandle; -- The first-created field of this tuple is an NWord field of length IndexObjectSize, --which is used to store the index object (information about the index such as the --location of the root page). An index object is never copied, it is always updated --in place. IndexScanHandle: TYPE = REF IndexScanObject; IndexScanObject: TYPE; -- Defined in DBStorageConcrete. Selection: TYPE = RECORD[lowerBound, upperBound: Rope.ROPE, includeLowerBound, includeUpperBound: BOOLEAN, lowerBoundInfinity, upperBoundInfinity: BOOLEAN _ FALSE]; -- Notes on allocation of storage for interface objects -- FieldDescriptor, Selection: Alloc/Dealloc by tuple level. -- FieldHandle: Created by storage level, copied to database by tuple level, then --deallocated by tuple level (who thus must know correct pool). Copied from database, --then alloc/dealloc by tuple level. -- Initialization Initialize: PROC [nCachePages: NAT, nFreeTuples: NAT, cacheFileName: ROPE]; -- Initializes the database system. Use nCachePages pages for cache size. --Allocate a free tuple list of the indicated size. -- Segment/Transaction interface AttachSegment: PROC [fileName: ROPE, s: Segment, segmentIndex: SegmentIndex, readonly: BOOL, version: VersionOptions, initializeExistingFile: BOOL, nBytesInitial, nBytesPerExtent: INT]; -- This operation "attaches" given segment to a given section of the database system's -- internal address space. At most one segment may be attached to a particular section. -- When a transaction is opened on this segment, using OpenTransaction (below), the -- following actions occur. The file with full path name fileName is looked up -- on the appropriate server. If the file is not there and version = OldFileOnly, ERRORs -- DBException.BadOperation[FileNotFound]; if it is there and version = NewFileOnly, -- ERRORs DBException.BadOperation[FileAlreadyExists]. -- Otherwise, creates a new segment or returns an existing one with the given name, -- as appropriate. In creating a new segment, at least nBytesInitial bytes are -- allocated, and nBytesPerExtent bytes will be allocated whenever the newly-created -- segment is extended. If initializeExistingFile then creates an empty segment from -- the file even if the file already existed. If readonly, then any subsequent request to -- write into the segment will raise an ERROR. -- Things are organized in this peculiar way so that an application may attach segments -- just once, even though it may execute many transactions (some of which may abort) -- on the segments. Note the lack of a "DetachSegment" proc. EnumerateSegments: PROC [ enumProc: PROC [s: Segment, segmentIndex: SegmentIndex] RETURNS [stop: BOOL]]; -- Enumerates all attached segments. OpenTransaction: PROC [s: Segment, useTrans: Trans, noLog: BOOL]; -- Allows access to the specified segment through a transaction, as described under -- AttachSegment. -- If useTrans = NIL, OpenTransaction begins a transaction and uses it -- for the coming sequence of database operations; otherwise it uses useTrans. -- if noLog = TRUE, then Alpine will not keep a log for this transaction GetSegmentInfo: PROC [ s: Segment] RETURNS [filePath: ROPE, number: NAT, trans: Trans]; -- Returns information about segment s. If s is undefined, returns NIL filePath. -- If s has a transaction open, returns the transaction; otherwise returns NIL. FinishTransaction: PROC [t: Trans, abort: BOOL, continue: BOOL]; -- If NOT abort AND continue, then all segments using the indicated transaction continue -- to have a transaction, but updates to these segments have been committed. RootIndicesFromSegment: PROC [s: Segment] RETURNS [index1, index2: IndexHandle]; -- Returns the two "root" indices for the segment s. -- ERROR if TransactionFromSegment[s] = NIL. SegmentFromTuple: PROC [x: TupleHandle] RETURNS [s: Segment]; -- Returns the segment in which the given TupleHandle is defined. SegmentIDFromTuple: PROC [x: TupleHandle] RETURNS [segmentID: SegmentID]; -- Returns the first DBPage of the segment in which the given TupleHandle is defined. -- Tupleset interface -- The procedures in this group deal with the definition and manipulation of the --entire set of tuples of a given type. Some involve either implicit or explicit --sequencing through a tuple set; the search order is system-defined. -- 1) Definition. CreateTupleset: PROC [x: TuplesetHandle, expectedNGroups: CARDINAL]; -- Creates a new tupleset, whose tuples have no fields, in the same segment as x. -- 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. Tuple x is returned by a ReadTupleset call (see next page) --on any tuple created in this tupleset. -- expectedNGroups is a hint giving the expected number of groups that a tuple of --this type will be head of. -- Note that the TuplesetHandle is used primarily by CreateTuple, but is also --modified by AddField/DeleteField. CreateSystemTupleset: PROC [x: SystemTupleID] RETURNS [SystemTuplesetHandle]; -- Creates a new system tupleset (system tuplesets do not live in a single segment --and pages containing their tuples are not chained together at storage level). SetSystemTupleTable: PROC [REF ARRAY [1..MaxSystemTupleID] OF TupleHandle]; -- The system tuple table defines TupleHandles that represent the system tuples. --There are two cases in which a storage level operation needs to return a system --tuple. These are ReadTupleset and GetGroupIDs, applied to a dictionary tuple. In --these cases the storage level is careful to check for a TID in the range --[1..MaxSystemTupleID], and when one is encountered the corresponding entry from --the system tuple table is returned. DestroyTupleset: PROC [x: 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). AddField: PROC [x: TuplesetHandle, y: 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. AddSystemField: PROC [x: SystemTuplesetHandle, y: FieldDescriptor] RETURNS [FieldHandle]; -- This procedure adds to x the length of y. Returns a FieldHandle for the new field. DeleteField: PROC [x: 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 avoids a sort. (DeleteField NOT be implemented in the first system). -- 2) Navigation. -- We provide a collection of functions to scan through a tupleset and return all of --the tuples that satisfy a predicate called a selection. Informally, a selection is --a disjunction of comparisons (equality, inequality, or range) on some subset of fields. FirstLast: TYPE = DBEnvironment.FirstLast; OpenScanTupleset: PROC [--x-- TuplesetHandle, --start-- FirstLast] RETURNS [TuplesetScanHandle]; -- Initializes for a sequential search through all tuples in set x. Starts scan --either before first tuple or after last, according to start parameter. NextScanTupleset: PROC [--x-- TuplesetScanHandle] RETURNS [TupleHandle]; -- Returns the next tuple in the scan, or NIL when the scan is empty. The --TuplesetScanHandle is modified as a side-effect of the Next call. PrevScanTupleset: PROC [--x-- TuplesetScanHandle] RETURNS [TupleHandle]; -- Returns the previous tuple in the scan, or NIL when the scan is empty. The --TuplesetScanHandle is modified as a side-effect of the Prev call. CloseScanTupleset: PROC [--x-- TuplesetScanHandle]; -- Destroys the TuplesetScanHandle x. -- Tuple interface: The procedures in this group deal with individual tuples. -- 1) Creation and destruction. CreateTuple: PROC [x: TuplesetHandle, y: TupleHandle _ NIL] RETURNS [newTuple: TupleHandle]; -- Attempts to create a new tuple of type x "near" existing tuple y. (If y=NIL then --this creates a new tuple of type x, according to the default algorithm for --tupleset x.). Returns with newTuple=NIL iff this is not possible; in this case no --tuple has been created. CreateSystemPageTuple: PROC [x: SystemTuplesetHandle, y: TupleHandle, s: Segment _ NIL] RETURNS [newTuple: TupleHandle]; -- Attempts to create a new system tuple of type x on the same page as existing --system tuple y. If this is not possible, the new tuple placed on an otherwise --empty page in the same segment as tuple y. If y = NIL then the new tuple is --placed on an otherwise empty page in segment s. Note that s is completely ignored --when y # NIL, and that unlike CreateTuple, this procedure ALWAYS creates a tuple. DestroyTuple: PROC [x: TupleHandle]; -- Destroys tuple x, then performs FreeTupleHandle[x] (see below). FreeTupleHandle: PROC [x: TupleHandle]; -- Logical no-op and not necessary, though may free some storage structures. ConsSystemTupleObject: PROC [type: TupleObjectType] RETURNS [TupleHandle]; -- Allocates a new TupleObject of given variant, with no particular contents. TupleObjectType: TYPE = {stored, system, tupleSet, attribute, entity, surrogate}; -- 2) Field access. -- We provide individual routines for each value type. Two parameters are common to --most of the routines in this section: x, the tuple to be accessed, and f, a FieldHandle --describing the position within tuple x containing the value to be read or written. -- The storage for values returned from ReadNWord and ReadVarWord is --acquired from a single internal heap allocator; this allocator may someday appear in --the interface. Pointers to cached pages are NOT given out as values; database values --are alwaye copied. ReadTupleset: PROC [x: TupleHandle] RETURNS [TuplesetHandle]; -- Returns a tuple handle for the tuple representing x's tupleset. Read1Word: PROC [x: TupleHandle, f: FieldHandle] RETURNS [CARDINAL]; Read2Word: PROC [x: TupleHandle, f: FieldHandle] RETURNS [LONG CARDINAL]; ReadNWord: PROC [x: TupleHandle, f: FieldHandle] RETURNS [POINTER TO UNSPECIFIED]; -- Result points to an n-word record, where n is encoded in f. ReadVarByte: PROC [x: TupleHandle, f: FieldHandle] RETURNS [Rope.ROPE]; ReadVarByteViaStream: PROC [x: TupleHandle, f: FieldHandle] RETURNS [IO.Handle]; -- The result stream can to GetChar, GetBlock, EndOf, etc. ReadVarWord: PROC [x: TupleHandle, f: FieldHandle] RETURNS [DESCRIPTOR FOR ARRAY OF CARDINAL]; Write1Word: PROC [x: TupleHandle, f: FieldHandle, val: CARDINAL]; Write2Word: PROC [x: TupleHandle, f: FieldHandle, val: LONG CARDINAL]; WriteNWord: PROC [x: TupleHandle, f: FieldHandle, val: POINTER TO UNSPECIFIED]; -- Last parm points to an n-word record, where n is encoded in f. WriteVarByte: PROC [x: TupleHandle, f: FieldHandle, val: Rope.ROPE]; WriteVarByteViaStream: PROC [x: TupleHandle, f: FieldHandle, val: IO.Handle]; -- The val stream must do GetChar, GetBlock, EndOf, etc. WriteVarWord: PROC [x: TupleHandle, f: FieldHandle, val: DESCRIPTOR FOR ARRAY OF CARDINAL]; -- Group interface -- A group is an ordered list of tuples, used in representing one-many relationships. --The relationship is between the group's head, which is a single tuple, and the group --itself. The relationship is named; we say that "x belongs to a g-group" if x has a --TID field with groupID g, and this field has a non-null value z; z is the head of --the group. The groupID g is bound into the field handle f of a TID field when it is --created. Thus it also makes sense to call a group an f-group when f is a TID field --handle. One tuple may be head of an unlimited number of groups, but only one --g-group for any groupID g. -- A GroupScanHandle is a handle on a group. It specifies a position that is either --before the first tuple, between two consecutive tuples, or after the last tuple. It --is used both for scanning through a group and for specifying a position to insert a --new tuple in a group. -- The tuple level is responsible for using the storage level primitives in ways that --preserve stronger invariants. Note also that the storage level does not implement a --set structure for groups. Thus it is not possible for the storage level to sequence --through all of the groups of a given type, as it can do for tuples. ReadTID: PROC [--x-- TupleHandle, --f-- FieldHandle] RETURNS [--z-- TupleHandle]; -- If x belongs to an f-group, ReadTID returns the head of the group; otherwise it --returns NIL. GetGroupIDs: PROC [--z-- TupleHandle] RETURNS [LIST OF GroupID]; -- Returns a list containing all GroupIDs g such that z is the head of a g-group. --The Tuple level is responsible for mapping from GroupIDs to FieldHandles, so that --the next procedure can be called when necessary. OpenScanGroup: PROC [--z-- TupleHandle, --f-- FieldHandle, --start-- FirstLast] RETURNS [--r-- GroupScanHandle]; -- Returns a GroupScanHandle positioned before the first (or after the last) tuple --of the f-group that has tuple z as head (first or last depending upon the value of --start). Returns a non-NIL GroupScanHandle even if there is no group. WriteTID: PROC [--x-- TupleHandle, --r-- GroupScanHandle]; -- Makes tuple x join the group specified by r at r's current position (i.e. between --the tuple just read and the next tuple that would be read by NextInGroup). A --NextInGroup following WriteTID returns the tuple following x; a PrevInGroup --returns x itself. -- Note that: (1) if x's field y had a non-NIL value before the WriteTID call, then --WriteTID has the effect of deleting x from some group (using WriteTIDNIL below), --(2) WriteTID cannot delete a tuple from one group without inserting it into --another, so WriteTIDNil below is necessary for that case, and (3) inserting or --deleting a tuple from a group requires the storage level to check all outstanding --GroupScanHandles to assure that they stay consistent with the deletion. WriteTIDNil: PROC [--x-- TupleHandle, --f-- FieldHandle]; -- Makes x's TID field point to the null tuple, i.e. removes x from whatever f-group --it currently belongs. NextInGroup: PROC [--r-- GroupScanHandle] RETURNS [--x-- TupleHandle]; -- Returns the tuple x immediately following the position r in a group, and moves r --one position forwards. Returns NIL if r was already positioned after the last --tuple in the group. PrevInGroup: PROC [--r-- GroupScanHandle] RETURNS [--x-- TupleHandle]; -- Returns the tuple x immediately preceding the position r in a group, and moves r --one position backwards. Returns NIL if r was already positioned before the first --tuple in the group. CloseScanGroup: PROC [--r-- GroupScanHandle]; -- The group interface may be expanded in the future to allow searches by value within --a group, especially if we choose to support ordered groups. -- Index interface -- 1) Definition. An index implements a map from byte string keys to doubleword --values. The byte strings are ordered in the obvious way, and the index allows --efficient range queries on key values. -- Note that the tuple level is responsible for mapping tuple field values into keys --that can be compared using the simple-minded routine in the storage level, and for --ensuring that all of and only the tuples of a single type are actually entered into --an index. CreateIndex: PROC [x: IndexHandle]; -- Creates a new index. x is a tuple whose first-created field is an NWord field, --IndexObjectSize words long. Information about the index is stored in this field. --Pages for the index are obtained from the segment containing tuple x. DestroyIndex: PROC [x: IndexHandle]; -- Destroys the index x. -- 2) Maintainance. These routines allow insertion and deletion of associations in --an index. InsertIntoIndex: PROC [x: IndexHandle, k: Rope.ROPE, v: TupleHandle]; -- Associates value v with key k . DeleteFromIndex: PROC [x: IndexHandle, k: Rope.ROPE, v: TupleHandle]; -- Deletes the given association from the index (v is necessary since multiple --values may be present for the same key). ERRORs DBException.InternalBug[...] if --the association is not present in the index x. -- 3) Navigation. These routines perform the same function as the corresponding --routines in the tuple set group, but have potentially greater efficiency because --they use an index. OpenScanIndex: PROC [x: IndexHandle, y: Selection, startPosition: FirstLast] RETURNS [IndexScanHandle]; NextScanIndex: PROC [x: IndexScanHandle] RETURNS [TupleHandle]; PrevScanIndex: PROC [x: IndexScanHandle] RETURNS [TupleHandle]; CloseScanIndex: PROC [x: IndexScanHandle]; END.--DBStorage -- Module History Created by MBrown on 27-Nov-79 11:18 -- Compiled with stubbed DBCommonPrivateDefs and DBCacheDefs Changed by MBrown on December 3, 1979 2:54 PM -- Added lengthHint to field descriptor for VarByte fields. The idea is to allow inline --storage of strings in the case that a good guess of the length is available. --Eliminated DBPrivateCommonDefs by placing DBPage into DBCacheDefs. Changed by MBrown on December 9, 1979 10:17 PM -- Changes to reflect the existence of DBCommonDefs and DBSignalDefs. Changed by MBrown on December 14, 1979 5:25 PM -- Changes to reflect modifications to DBCommonDefs, and add Login procedure, per --meeting of 14 December. Also changed the names of some segment interface procedures, --and added CloseDatabase. Changed by MBrown on January 6, 1980 7:47 PM -- Changes: VersionOptions moves here, DBCommon.LongJFHandle is FileID. Changed by MBrown on January 14, 1980 2:48 PM -- Changed module name to conform to Cedar standard; also eliminated wordcount parm from --ReadNWord (it will be encoded in the FiledHandle). Changed by MBrown on January 18, 1980 12:15 PM -- Changed IndexHandle and IndexValue types; also changed the result of ReadNWord and --last parm to WriteNWord to POINTER TO UNSPECIFIED. Changed by MBrown on February 3, 1980 3:01 PM -- Changed TuplesetHandle to be simply a TupleHandle. The convention observed by the --tuple level is that the first field holds the tuple object. (This is convenient for --the storage level, too, since it must in effect stash backpointers to tuple objects in --the tupleset lists). Changed by MBrown on February 4, 1980 3:35 PM -- Eliminated the Tupleset parm to DestroyTuple. Added lengthHint to VarWord variant of --FieldDescriptor. Changed by MBrown on February 10, 1980 9:09 PM -- Eliminated type TuplesetID, which is a TID and hence invisible at this interface. --Renamed ReadTuplesetID to be ReadTupleset. Made IndexHandle = TupleHandle in a manner --analogous to TuplesetHandle. This required creating IndexObjectSize, and changing --CreateIndex (returns no result, segment is implicit in the IndexHandle passed in). --Eliminated IndexValue, which is really just TupleHandle (what else?) Changed by MBrown on February 21, 1980 11:11 AM -- Moved VersionOptions back to DBCommon due to change in DBSegment. Changed CloseScan --to CloseScanIndex, and added CloseScanGroup. (These may go away when collectable --storage comes). Changed by MBrown on February 25, 1980 6:33 PM -- Changed field names in SystemTuplesetHandle to match corresponding fields in regular --tupleset handles. Changed definition of parameters to DeleteField. Changed by MBrown on 28-Feb-80 21:13 -- Added MaxSystemTuplesetID and SetSystemTuplesetTable. Changed by MBrown on February 29, 1980 10:16 AM -- Parm to SetSystemTuplesetTable is ARRAY [1..MaxSystemTuplesetID) OF TupleHandle (not --0-origin). Changed by MBrown on 29-Feb-80 15:24 -- It SHOULD have been [1..MaxSystemTuplesetID] (blush!) Changed by MBrown on 3-Mar-80 15:35 -- Changed CreateDatabase and OpenDatabase to return two Indexhandles, not one. Changed by MBrown on March 6, 1980 9:41 AM -- Changed spec of WriteTID, added WriteTIDNIL. Changed by MBrown on March 21, 1980 3:39 PM -- Changed order of last two components of a Selection. Changed by MBrown on April 15, 1980 10:43 AM -- Added defaulting to the segmentID parameter of CreateSystemPageTuple, and clarified --the specification of this proc. Added the "start" parm to OpenScanGroup (scans used --to start only before the first group tuple). Added comment about possible ERROR from --DeleteFromIndex. Changed by MBrown on April 17, 1980 3:04 PM -- Eliminated "set" from SystemTuplesetID, MaxSystemTuplesetID, SetSystemTuplesetTable. --Made MaxSystemTupleID = 20. This is in response to the observation that GetGroupIDs, --applied to a Tupleset tuple (say), wants to return a TupleHandle representing a system --attribute tuple, just as ReadTupleset on such a tuple wants to return a TupleHandle --representing a system tupleset tuple. Changed by MBrown on June 8, 1980 6:04 PM -- Introduced FieldObject, an exported type. Changed by MBrown on June 10, 1980 9:24 PM -- Introduced TupleObject, an exported type. Changed by MBrown on June 14, 1980 11:36 AM -- Ditto for TuplesetScanObject, GroupScanObject. Changed by MBrown on June 24, 1980 11:12 AM -- Ditto for SystemTuplesetObject. Changed by MBrown on July 23, 1980 9:54 PM -- Added start parm to OpenScanTupleset, and added PrevScanTupleset procedure. Changed --FirstLast to {first, last} (not {First, Last}; Cedar convention). Changed by Cattell on July 31, 1980 1:32 PM -- Increased MaxSystemTuplesetID. Changed by MBrown on July 31, 1980 3:05 PM -- Integrated Rick's change into my private version. Added expectedNGroups parm to --CreateTupleset. Changed by MBrown on August 5, 1980 1:03 AM -- Made Listof -> ListOf. Changed by MBrown on August 5, 1980 8:33 PM -- Clarified specs of CloseDatabase and CloseCommunication. There is more work to be --done in this area, e.g. what does AbortTransaction really do? How does a client --proceed after an abort, spontaneous or otherwise? Changed by MBrown on August 29, 1980 2:44 PM -- OpenCommunication takes a server parameter, returns the welcome text from Juniper if a login --is done. Changed by MBrown on September 12, 1980 1:41 PM -- OpenDatabase and CreateDatabase now take nCachePages as a parameter (defaultable). Added --Finalize. Changed by Suzuki on September 28, 1980 11:31 AM -- Added fields in Selection for Infinity. -- Added a parameter in OpenScanIndex; position: FirstLast to indicate the starting position Changed by MBrown on December 8, 1980 3:54 PM -- Added parms to CreateSegment: nBytesInitial, nBytesPerExtent. Changed by MBrown on December 11, 1980 7:11 PM -- Flushed RegisterUser, added parms to OpenCommunication. Changed Commit to CommitTransaction. --Flushed SetTransactionNotifyProcedure. Changed by MBrown on February 26, 1981 8:58 PM -- Redefined OpenCommunication: server is used to decide what file system to use. Transaction is --UNSPECIFIED. newTrans parm added. Changed by MBrown on 8-Jun-81 16:05:48 -- Start of conversion to use collectable storage. FieldHandle is still a POINTER, but everything --else changed to REF. (FieldHandle is a mess anyway, which is a symptom of the poor division --of function between storage and tuple levels.) Added procedures for access to VarByte fields --via FileByteStreams. Changed by Cattell on 16-Jun-81 14:14:34 -- Changed strings to ropes. Changed by MBrown on 19-Jun-81 9:24:21 -- TupleObject is defined opaquely in DBTuplesOpaque, not both here and in DBTuples. --SystemTupleTable is a REF to an ARRAY, not a POINTER. Changed by MBrown on 19-Jun-81 20:35:05 -- Merge in Rick's change of 19-Jun-81 17:09:31: index routines take Rope.Ref, not --STRING, as key. Changed by Cattell on 13-Aug-81 14:23:57 -- Incorporated change to DBTuplesConcrete in anticipation of View version: --changed ConsSystemTupleObject to take parameter giving variant desired. Changed by Cattell on 23-Feb-82 10:34:33 -- Uses IOStreams instead of FileByteStreams for fns Mark added 8-Jun-81 16:05:48. Changed by Willie-Sue on June 24, 1982 12:03 pm -- IOStream => IO, Rope.Ref => Rope.ROPE Changed by Cattell on October 25, 1982 3:04 pm -- First proposal for changes for new independent-segment databases. Don't forget to call FinalizeHeap in implementation of DBStorage.CloseDatabase, formerly called by View level. The old OpenCommunication procedure changed to OpenTransaction, OpenDatabase changed to just initialize the system, OpenTupleset changed to take segment as argument, and OpenSegment and CreateSystemPageTuple changed to use new segment scheme. Also added new operation SegmentForTuple. Changed by Cattell on October 25, 1982 3:04 pm -- Increased MaxSystemTupleID to 128 for good measure, to allow for future expansion. Changed by Willie-Sue on February 3, 1983 -- added noLog arg to OpenTransaction Changed by Cattell on March 15, 1983 10:16 am -- Put FirstLast type in DBEnvironment so can use same throughout Cypress. Ę.˜Jšœ¯=Īkœ œ’ą˜Ōî—…—wTwˆ