-- File DBSegment.mesa -- Last edited by -- MBrown on December 16, 1982 2:37 pm -- Willie-Sue on February 3, 1983 10:38 am -- Cattell, July 15, 1983 2:48 pm DIRECTORY DBCommon, DBCache USING [CacheHandle], DBStorageTID USING [TID], Rope USING [ROPE]; DBSegment: DEFINITIONS = BEGIN ROPE: TYPE = Rope.ROPE; Trans: TYPE = DBCommon.Trans; Segment: TYPE = DBCommon.Segment; SegmentID: TYPE = DBCommon.SegmentID; SegmentIndex: TYPE = DBCommon.SegmentIndex; VersionOptions: TYPE = DBCommon.VersionOptions; DBPage: TYPE = DBCommon.DBPage; CacheHandle: TYPE = DBCache.CacheHandle; TID: TYPE = DBStorageTID.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. -- To preserve the hierarchical character of the system, this in the only major --lower-level interface used in the storage level implementation, and is the only --interface exported by the segment level implementation. -- Initialization Initialize: PROC [ nCachePages: NAT, useCacheFile: ROPE, segmentInitProc: PROC [s: Segment] RETURNS [TID, TID]]; -- Initializes the database system at the segment level and below. -- Use nCachePages pages for cache size. Call segmentInitProc when creating -- a new segment. -- Segment/Transaction interface (closely parallel to DBStorage) AttachSegment: PROC [ fileName: ROPE, s: Segment, segmentIndex: SegmentIndex, readonly: BOOL, version: VersionOptions, initializeExistingFile: BOOL, nBytesInitial, nBytesPerExtent: INT]; EnumerateSegments: PROC [ enumProc: PROC [s: Segment, segmentIndex: SegmentIndex] RETURNS [stop: BOOL]]; OpenTransaction: PROC [ s: Segment, useTrans: Trans, noLog: BOOL] RETURNS [fileChanged: BOOL]; -- Returns TRUE if the file changed since the last time we opened a transaction -- on that file from client's machine. (Always returns TRUE first time). GetSegmentInfo: PROC [s: Segment] RETURNS [ filePath: ROPE, number: NAT, trans: Trans, readOnly: BOOL, nBytesInitial, nBytesPerExtent: INT]; FinishTransaction: PROC [t: Trans, abort: BOOL, continue: BOOL]; RootIndicesFromSegment: PROC [s: Segment] RETURNS [index1, index2: 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 a transaction is open --for that segment. 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 interface 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 interface -- 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-- DBCache.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-- DBCache.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 interface 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 DBStorageTID. 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.