File DBSegment.mesa
Copyright c 1985 by Xerox Corporation. All rights reserved.
Last edited by
MBrown on December 16, 1982 2:37 pm
Willie-Sue on March 25, 1985 9:15:02 am PST
Cattell, July 15, 1983 2:48 pm
Widom, September 3, 1985 3:24:30 pm PDT
Donahue, May 22, 1986 11:10:53 am PDT
DIRECTORY
AlpineEnvironment USING [LockOption],
DBCommon,
Rope USING [ROPE];
DBSegment: CEDAR DEFINITIONS = BEGIN
ROPE: TYPE = Rope.ROPE;
Trans: TYPE = DBCommon.Transaction;
Segment: TYPE = DBCommon.Segment;
SegmentID: TYPE = DBCommon.SegmentID;
SegmentIndex: TYPE = DBCommon.SegmentIndex;
VersionOptions: TYPE = DBCommon.VersionOptions;
DBPage: TYPE = DBCommon.DBPage;
CacheHandle: TYPE = DBCommon.CacheHandle;
TID: TYPE = DBCommon.TID;
This is the interface to databases at the level of segments. A database has a uniform address space, but within this space live "segments" which are the repositories of database pages. Thus it is possible to allocate a page from a segment, or free a previously allocated page.
Initialization
Initialize: PROC [nCachePages: NAT, useCacheFile: ROPE,
segmentInitProc: PROC [s: Segment] RETURNS [ARRAY[0..DBCommon.systemIndexCount) OF TID]];
Initializes the database system at the segment level. Use nCachePages pages for cache size. Call segmentInitProc when creating a new segment.
Segment interface
AttachSegment: PROC [fileName: ROPE, s: Segment, segmentIndex: SegmentIndex, lock: AlpineEnvironment.LockOption, readonly: BOOL, version: VersionOptions, nPagesInitial, nPagesPerExtent: NAT] RETURNS[newAttachement: BOOL];
This may only be done for segments that are closed (a segment is closed when a FlushCache is performed on the segment) or have not been previously opened. This procedure returns TRUE iff the fileName supplied was not that of the previous AttachSegment for the same segment
EnumerateSegments: PROC [enumProc: PROC [s: Segment, segmentIndex: SegmentIndex] RETURNS [stop: BOOL]];
OpenSegment: PROC [s: Segment, trans: Trans, eraseAfterOpening: BOOL];
Open the segment using the given transaction. The transaction is used to open the file that was named by the prior AttachSegment
CloseSegment: PROC [s: Segment];
GetSegmentInfo: PROC [s: Segment] RETURNS [filePath: ROPE, readOnly: BOOL];
WriteOutCache: PROC[s: Segment];
Force out all dirty cached pages for the segment
FlushCache: PROC[s: Segment];
Throw away all cached (dirty or not) pages for the segment. This also closes the open file for the segment.
Operations on the head page of a segment
GetVersionStamp: PROC [segment: Segment] RETURNS[schemaVersion: INT];
Returns the current schema version stamp for the given segment. This also sets a read lock on the schema version stamp, which will be held until the transaction for the segment is aborted or closed
SetVersionStamp: PROC [segment: Segment, to: INT];
Called when the schema for the given segment is changed; updates the schema version stamp.
RootIndicesFromSegment: PROC [s: Segment] RETURNS [indexTIDs: ARRAY[0..DBCommon.systemIndexCount) OF TID];
SegmentFromTID: PROC [tid: TID] RETURNS [s: Segment];
"tid" is a tuple ID in an attached segment. Returns the name of the segment.
IsValidTID: PROC [tid: TID] RETURNS [valid: BOOL];
"tid" is a tuple ID in an attached segment. Returns TRUE iff the segment is open.
SegmentIDFromDBPage: PROC [p: DBPage] RETURNS [SegmentID];
"p" is a page in an open segment. Returns the first page in the segment.
SegmentIDFromSegment: PROC [s: Segment] RETURNS [SegmentID];
s is an attached segment. Returns the first page in the segment.
Page allocation
AllocPage: PROC [s: SegmentID] RETURNS [p: DBPage, pValidHint: CacheHandle, cachePage: LONG POINTER];
PARAMETERS: s is a SegmentID (a pointer to the head page of a segment).
RESULTS: p is a previously unused page within segment s, with pValidHint a cache hint and cachePage a cache pointer for it. pValidHint ha a lock count of 1.
ERRORS: if s does not identify a segment, if the file representing s is full, or if the database address space is full.
NOTES: AllocPage does NOT necessarily read the page p from Juniper.
FreePage: PROC [s: SegmentID, freePg: DBPage, freeHint: CacheHandle];
PARAMETERS: s is a SegmentID (result of SegmentIDFromDBPage or SegmentIDFromFile), and freePg is a page within that segment (with freeHint a cache hint for it). The lock count of freeHint is 1.
EFFECTS: FreePage makes freePg unused, and freeHint becomes meaningless.
ERRORS: if s is not a SegmentID, or if freePg is not in s.
NOTES: If references to freePg still exist, they become "dangling". Errors of this kind may go undetected, since freed pages are reused.
Page access
Definition: A "valid" cache hint for a DBPage p is a DBCache.CacheHandle for p, with a positive lock count. Note that when a cache hint becomes invalid (lock count reaches zero), it is an error to use any core location derived from the hint.
ReadPage: PROC [p: DBPage, pHint: CacheHandle] RETURNS [pValidHint: CacheHandle, coreLoc: LONG POINTER];
PARAMETERS: p is a page address in the current database, and pHint is a cache hint for it.
RESULTS: pValidHint is a valid cache hint for p, and coreLoc is a pointer to the data contained on page p. The caller may read data from the page using this
pointer, for as long as pValidHint has a positive lock count.
EFFECTS: the lock count of pValidHint is increased by 1 (the count is implicitly zero before the first reference to the page).
ERRORS: DBException.Fatal[AllCachePagesLocked] if it is necessary to read p into core, and there are no unlocked pages in the cache to read p into.
WritePage: PROC [p: DBPage, pHint: CacheHandle] RETURNS [pValidHint: CacheHandle, coreLoc: LONG POINTER];
The same as ReadPage, except that the caller may also write the data pointed to by coreLoc (i.e. it sets the write-dirty bit in pValidHint).
ERRORS: DBException.Fatal[AccessDenied] if this page cannot be written back to
the file system.
UnlockPage: PROC [pValidHint: CacheHandle];
EFFECTS: Decrements pValidHint's lock count by one.
ERRORS: DBException.InternalBug[AlreadyUnlocked] if the count was already zero.
WriteLockedPage: PROC [pValidHint: CacheHandle];
PARAMETERS: pValidHint is a CacheHandle with a positive lock count.
EFFECTS: the write-dirty bit of pValidHint is set.
ERRORS: If pValidHint's lock count is 0 then DBException.InternalBug is raised. If the page is protected from writing (cannot be written back to the file system) then DBException.Fatal[AccessDenied] is raised.
NOTES: The effect of WriteLockedPage is the same as WritePage; UnlockPage, except that the page must be locked beforehand. The effect of WritePage is identical to [pValidHint, coreLoc] ← ReadPage[p, pHint]; WriteLockedPage[pValidHint].
LockCount: PROC [p: DBPage, pValidHint: CacheHandle] RETURNS [lockCount: CARDINAL];
PARAMETERS: p is a page address in the current database, and pValidHint is a
valid cache hint for it.
RESULTS: the lock count of page p.
ERRORS: DBException.BadOperaton[??] is raised if pHint is not a valid cache handle for page p. This includes pHint having a lock count of 0.
NOTES: This routine is intended for use in debugging only, especially for checking assertions like "p now has lock count 1, so calling UnlockPage will release it." Programs should not intentionally lose track of the lock count of a page and then use this procedure to release the page.
ObtainCoreLoc: PROC [p: DBPage, pValidHint: CacheHandle] RETURNS [coreLoc: LONG POINTER];
PARAMETERS: p is a page address in the current database, and pValidHint is a valid cache hint for it.
RETURNS: The core location of the page p.
ERRORS: DBException.BadOperaton[??] is raised if pHint is not a valid cache handle for page p. This includes pHint having a lock count of 0.
NOTES: The parameter pHint is for efficiency, to avoid a hashed lookup when the hint is known to be valid. When the validity of the hint is uncertain, ReadPage should be used instead of ObtainCoreLoc.
Debugging
CheckState: PROC [doPrinting, printOnlyLockedPages: BOOL];
Checks internal consistency of segment implementation, optionally prints to the debug stream.
END. -- DBSegment
CHANGE LOG
Created by MBrown on January 4, 1980 3:31 PM
Changed by MBrown on January 14, 1980 2:29 PM
Changed module name to conform to Cedar standard.
Changed by MBrown on February 4, 1980 3:44 PM
Changed name of GetSegmentID to FileIDToSegmentID; added DBPageToSegmentID.
Changed by MBrown on February 21, 1980 10:20 AM
Added procedures ReadPage, WritePage, ... ObtainFile. The intention is to make
segments a true "level", i.e. the storage level will no longer communicate directly
with the cache level.
Also changed definition of AllocPage to return a locked page.
Changed by MBrown on February 21, 1980 1:38 PM
Made AllocPage return the LONG POINTER to the locked page. Added LockCountOfPage.
Changed by MBrown on February 29, 1980 10:33 AM
Added OpenDatabase, etc, to complete the isolation between the segment and storage
levels.
Changed by MBrown on March 3, 1980 1:36 PM
Changed CreateDatabase and OpenDatabase to allow root indexes to be created.
Changed by MBrown on April 16, 1980 4:42 PM
Changed LockCountOfPage to LockCount, added ObtainCoreLoc.
Changed by MBrown on April 18, 1980 11:34 AM
Worked on comments.
Changed by MBrown on June 10, 1980 8:46 PM
TID now comes from DBCommon.
Changed by MBrown on August 5, 1980 8:49 PM
Clarified the specifications of CloseDatabase and CloseCommunication. Responsibility
for performing the former immediately before the latter is now delegated to the
client.
Changed by MBrown on August 29, 1980 3:34 PM
Added server parm and welcomeText result to OpenCommunication.
Changed by MBrown on September 12, 1980 11:07 AM
Added Finalize, added comments about sequencing of Segment interface calls.
Changed by MBrown on December 8, 1980 3:46 PM
Added nBytesInitial and nBytesPerExtent parms to CreateSegment.
Changed by MBrown on December 11, 1980 6:54 PM
Flushed RegisterUser, added parms to OpenCommunication. Changed Commit to CommitTransaction.
Flushed SetTransactionNotifyProcedure.
Changed by MBrown on February 26, 1981 9:11 PM
Redefined OpenCommunication: server is used to decide what file system to use. Transaction is
UNSPECIFIED. newTrans parm added.
Changed by MBrown on 19-Jun-81 8:51:33
STRING -> Rope.Ref.
Changed by Willie-Sue on June 24, 1982 12:12 pm
Rope.Ref => Rope.ROPE
Changed by MBrown on November 24, 1982 4:18 pm
Changes to enable independent segments.
Changed by Cattell on January 16, 1983 12:41 pm
Added useCacheFile arg to Initialize.
Changed by Willie-Sue on February 3, 1983 10:38 am
Added noLog arg to OpenTransaction.
Changed by Willie-Sue on February 15, 1985
nBytes => nPages; added Tioga formatting, made Cedar
Changed by Donahue on October 23, 1985
Moved transaction management out of the interface and into DBStorage. Added WriteOutCache and FlushCache to interface (that's the only part of DBSegment that is needed to manage transactions.)