-- File: DBStorageImplD.mesa
-- Last edited by:
--   MBrown on May 22, 1983 10:27 pm,
--   Cattell on November 4, 1983 2:28 am
--   Willie-Sue on February 3, 1983 11:13 am

  DIRECTORY
    DBCommon,
    DBSegment,
    DBIndex USING [InitializeIndex, CallAfterFinishTransaction],
    DBStorage USING[AddSystemField, CreateIndex, CreateSystemPageTuple, CreateSystemTupleset,
     FieldHandle, IndexHandle, IndexObjectSize, SystemTuplesetHandle, TupleHandle],
    DBStorageGroupScan USING [Init, CallAfterFinishTransaction],
    DBStorageTID USING[TID],
    DBStorageTuple USING[Init, ConsTupleObject, CallAfterFinishTransaction, TIDOfTuple],
    DBStorageTuplesetScan USING[Init, CallAfterFinishTransaction],
    Rope USING [ROPE];

DBStorageImplD: PROGRAM
  IMPORTS
    DBIndex,
    DBSegment,
    DBStorage,
    DBStorageGroupScan,
    DBStorageTuple,
    DBStorageTuplesetScan
  EXPORTS
    DBStorage
  = BEGIN
  
  FileSystem: TYPE = DBCommon.FileSystem;
  Segment: TYPE = DBCommon.Segment;
  SegmentIndex: TYPE = DBCommon.SegmentIndex;
  SegmentID: TYPE = DBCommon.SegmentID;
  VersionOptions: TYPE = DBCommon.VersionOptions;
  Trans: TYPE = DBCommon.Trans;
  TID: TYPE = DBStorageTID.TID;
  TupleHandle: TYPE = DBStorage.TupleHandle;
  ROPE: TYPE = Rope.ROPE;

  -- Initialization

  Initialize: PUBLIC PROC [nCachePages: NAT, nFreeTuples: NAT, cacheFileName: ROPE] = {
    DBSegment.Initialize[nCachePages, cacheFileName, CreateIndexes];
    DBStorageGroupScan.Init[];
    DBStorageTuplesetScan.Init[];
    DBStorageTuple.Init[nFreeTuples];
    DBIndex.InitializeIndex[];
    };

  CreateIndexes: PROC [s: Segment] RETURNS [TID, TID] = {
    -- Called from DBSegmentImpl for the initialization of a segment.
    indexTS: DBStorage.SystemTuplesetHandle ←
      DBStorage.CreateSystemTupleset[1];
    indexFH: DBStorage.FieldHandle ←
      DBStorage.AddSystemField[indexTS, [NWord[DBStorage.IndexObjectSize]]];
    indexHandle1: TupleHandle ←
      DBStorage.CreateSystemPageTuple[indexTS, NIL, s];
    indexHandle2: TupleHandle ←
      DBStorage.CreateSystemPageTuple[indexTS, indexHandle1, s];
    DBStorage.CreateIndex[indexHandle1];
    DBStorage.CreateIndex[indexHandle2];
    RETURN[
      DBStorageTuple.TIDOfTuple[indexHandle1],
      DBStorageTuple.TIDOfTuple[indexHandle2]];
    };


  --  Transaction interface

  OpenTransaction: PUBLIC PROC [s: Segment, useTrans: Trans, noLog: BOOL] = {
    DBSegment.OpenTransaction[s, useTrans, noLog];
    };

  FinishTransaction: PUBLIC PROC [t: Trans, abort: BOOL, continue: BOOL] = {
    IF abort OR NOT continue THEN {
      -- Yes, we call DBIndex.CallAfterFinishTransaction BEFORE calling
      --DBSegment.FinishTransaction!  This is a work-around: otherwise,
      --we try to "Unlock" a cache page that was already discarded by
      --DBSegment.FinishTransaction.)
      DBIndex.CallAfterFinishTransaction[];
      };
    DBSegment.FinishTransaction[t, abort, continue];
    IF abort OR NOT continue THEN {
      -- Any volatile state that references tuples in nonexistent segments must now
      --be discarded.  DBSegment.IsValidTID is useful in determining what to discard.
      DBStorageTuplesetScan.CallAfterFinishTransaction[];
      DBStorageGroupScan.CallAfterFinishTransaction[];
      -- Call tuple manager last, since others may release tuples.
      DBStorageTuple.CallAfterFinishTransaction[];
      };
    };

  --  Segment interface

  AttachSegment: PUBLIC PROC [
    fileName: ROPE, s: Segment, segmentIndex: SegmentIndex, readonly: BOOL,
    version: VersionOptions, initializeExistingFile: BOOL,
    nBytesInitial, nBytesPerExtent: INT] = {
    DBSegment.AttachSegment[fileName, s, segmentIndex, readonly, version,
      initializeExistingFile, nBytesInitial, nBytesPerExtent];
    };

  RootIndicesFromSegment: PUBLIC PROC [s: Segment]
    RETURNS [index1, index2: DBStorage.IndexHandle] = {
    indexTID1, indexTID2: TID;
    [indexTID1, indexTID2] ← DBSegment.RootIndicesFromSegment[s];
    RETURN [
      DBStorageTuple.ConsTupleObject[tid: indexTID1],
      DBStorageTuple.ConsTupleObject[tid: indexTID2]];
    };

  GetSegmentInfo: PUBLIC PROC [s: Segment] RETURNS [
    filePath: ROPE, number: NAT, trans: Trans,
    readOnly: BOOL, nBytesInitial, nBytesPerExtent: INT] = {
    [filePath, number, trans, readOnly, nBytesInitial, nBytesPerExtent]←
      DBSegment.GetSegmentInfo[s];
    };

  SegmentFromTuple: PUBLIC PROC [x: TupleHandle] RETURNS [s: Segment] = {
    RETURN [DBSegment.SegmentFromTID[DBStorageTuple.TIDOfTuple[x]]];
    };

  SegmentIDFromTuple: PUBLIC PROC [x: TupleHandle] RETURNS [segmentID: SegmentID] = {
    RETURN [DBSegment.SegmentIDFromDBPage[DBStorageTuple.TIDOfTuple[x]]];
    };

  EnumerateSegments: PUBLIC PROC [
    enumProc: PROC [s: Segment, segmentIndex: SegmentIndex] RETURNS [stop: BOOL]] = {
    DBSegment.EnumerateSegments[enumProc];
    };

END.--DBStorageImplD


CHANGE LOG

Created by MBrown on February 29, 1980  11:26 AM

Changed by MBrown on March 3, 1980  3:19 PM
-- Changed CreateDatabase and OpenDatabase to create and use real indexes.

Changed by MBrown on April 18, 1980  11:46 AM
-- Added calls to DBStorage.CreateIndex so that index is actually initialized (previously
--we were testing without the index implementation).

Changed by MBrown on  9-May-80 11:00
-- InitializeIndex is now called by CreateDatabase and OpenDatabase; FinalizeIndex
--is called by CloseDatabase.

Changed by MBrown on June 11, 1980  3:39 PM
-- Changes due to exported TupleObject and related cleanups.

Changed by MBrown on June 24, 1980  11:51 AM
-- Make CreateIndexes call FreeFieldObject to release field handle, and DeallocSystemTuplesetObject
--to release system tupleset handle.

Changed by MBrown on August 4, 1980  11:54 PM
-- CloseDatabase now cleans up storage level data structures: DBStorageTuple.ReInitialize,
--DBStorageTuplesetScan.NoticeCloseDatabase, DBStorageGroupScan.NoticeCloseDatabase.

Changed by MBrown on August 5, 1980  9:33 PM
-- Changed CloseDatabase and CloseCommunication to conform to changes in DBStorage (which was
--changed because the old scheme was fuzzy and unworkable).

Changed by MBrown on August 11, 1980  8:32 PM
-- Made CloseDatabase call DBStorageTuple.ReInitialize LAST, so evidence is still around
--of the TSID of an open scan.

Changed by MBrown on August 29, 1980  2:41 PM
-- OpenCommunication returns the welcome text result.

Changed by MBrown on September 12, 1980  1:34 PM
-- OpenDatabase and CreateDatabase now take nCachePages as a parameter (defaults in DBStorage).
--Added Finalize.

Changed by MBrown on December 8, 1980  3:50 PM
-- CreateSegment now takes nBytesInitial and nBytesPerExtent as parameters.

Changed by MBrown on December 11, 1980  3:07 PM
-- Filled in a "real" implementation for AbortTransaction (one that should allow an OpenDatabase
--to follow an abort).

Changed by MBrown on December 11, 1980  7:08 PM
-- Flushed RegisterUser, added parms to OpenCommunication.  Changed Commit to CommitTransaction.
--Flushed SetTransactionNotifyProcedure. 

Changed by MBrown on February 26, 1981  9:01 PM
-- Redefined OpenCommunication: server is used to decide what file system to use.
--Transaction is UNSPECIFIED.  newTrans parm added.

Changed by MBrown on February 27, 1981  5:21 PM
-- Pre-Pilot changes: use z.Free.

Changed by MBrown on 18-Jun-81 14:51:09
-- System tupleset is now collectible, no explicit FREE.

Changed by Cattell on May 4, 1982 12:59 pm
-- CloseCommunication no longer does CloseDatabase.

Changed by Willie-Sue on June 24, 1982 12:21 pm
-- Rope.Ref => Rope.ROPE

Changed by MBrown on November 30, 1982 9:44 pm
-- Changes for new segment scheme.

Changed by Willie-Sue on February 3, 1983
--  Added noLog arg to OpenTransaction

Changed by MBrown on May 22, 1983 10:23 pm
-- In FinishTransaction, work around bug in DBIndex.CallAfterFinishTransaction.