-- 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.