-- File DBStats.mesa
-- Last edited by:
--   MBrown on November 29, 1982 2:04 pm
--   Cattell on March 14, 1983 2:08 pm
--   Willie-Sue on June 24, 1982 12:00 pm

DIRECTORY IO, Rope;

DBStats: DEFINITIONS = BEGIN
  -- This is the interface to the Cedar database statistics gathering facility.

  -- There are two kinds of "events": counter and timer.

  -- Counter events are for logging the freqency with which a specific action or set of
  --actions is performed.  If e is a counter event, then Inc[e] causes e's counter to be
  --incremented by 1.  Inc[e] is very inexpensive to perform.

  -- Timer events are for logging the time required for a specific action or set of
  --actions.  If e is a timer event, then Starting[e] records the current time in a
  --variable associated with e.  Then when Stopping[e] is performed at some later time,
  --it notes the difference between the current time and the time recorded by the
  --previous Starting[e].  At a minimum, the average value of this time interval is
  --maintained; a more elaborate implementation may also be supplied (max value,
  --standard deviation, histogram, ...).  Starting[e] and Stopping[e] involve one
  --procedure call each and hence are more expensive than Inc[e] (but note that events
  --are statically typed so only one set of operations applies to an event in any case).

  -- When two calls to Starting[e] occur in succession with no intervening Stopping[e],
  --the first Starting[e] is ignored; when two calls to Stopping[e] occur consecutively,
  --the last is ignored.  Each of these situations counts as a "glitch", and the number
  --of glitches is reported for debugging purposes during Print, described below. 
  --Glitches may occur due to a failure to call Stopping[e] during the UNWIND of a
  --procedure activation that called Starting[e]; a glitch is not a fatal error because
  --we consider it cumbersome to provide a catch for UNWIND simply to avoid glitches.

  -- Any program using this package must initialize the stats implementation module by
  --calling DBStats.Initialize[] before calling Inc[e] or Starting[e].  The current
  --state of all active counters and timers is appended to the file "DBStats.log" by
  --DBStats.Print[]; this does not change the state of counters or timers, but resets
  --the count of glitches to 0.  ERROR is raised if Print is called before Initialize. 
  --Initialize should be called to reinitialize the stats module after printing if
  --independent statistics are desired.

  -- Inc[e], Starting[e], and Stopping[e] are all INLINE procedures, and calls to them
  --with compile-time constant parameters produce no code when the procedure bodies
  --below are made empty.  Hence calls to these procedures may be imbedded freely in a
  --system for testing, and then this defs module can be stubbed (all procs INLINE with
  --empty bodies) for the efficient "production" version.


  Initialize: PROC[];
    -- Initializes stats module.

  CounterEvent: TYPE = {
    -- DBCache--
    CacheReadOrWrite,
    CacheHTLookup,
    CacheHTConflictInLookup,
    CacheMiss,
    CacheWritePageBack,
    -- DBSegment--
    SegmentAllocPage,
    SegmentFreePage,
    -- DBStorage (Tuples)--
    StorageCreateTuple,
    StorageCreateSystemTuple,
    StorageDestroyTuple,
    StorageReadTupleset,
    StorageReadField,
    StorageWriteField,
    StorageInitVecPage,
    StorageCheckVecPage,
    StorageAllocVec,
    StorageFreeVec,
    StorageModifyVec,
    StorageModifyDifficultVec,
    StorageCompactPage,
    CloseDBGroupScansActive,
    CloseDBTuplesetScansActive,
    -- DBStorage (BTree)--
    DBIndexInsert,
    DBIndexDelete,
    DBIndexOpenScan,
    DBIndexNextScan,
    DBIndexBiggerKey,
    DBIndexEqualKey,
    BTreeSearchPage,
    BTreeSwapInPage,
    BTreeSwapOutPage,
    -- DBView--
    CreateEntity,
    CreateRelship,
    ReleaseRelshipSet,
    ReleaseEntitySet,
    SurrogateCreateRelship,
    SurrogateDestroyRelship,
    DomainOf,
    RelationOf,
    SystemGetF,
    DictionaryGetF,
    DictionarySetF,
    GetTupleInfo,
    GetTupleInfoMiss,
    GetRelationInfo,
    GetRelationInfoMiss,
    GetAttributeInfo,
    GetAttributeInfoMiss,
    GetDomainInfo,
    GetDomainInfoMiss,
    SystemGetAttributeInfo
  };

  Inc: PROC[event: CounterEvent] = INLINE { CounterArray[event] ← CounterArray[event] + 1 };
    -- Increments the counter associated with event.
    
  TimerEvent: TYPE = {
    -- DBFile--
    PilotFileCreateTransaction,
    PilotFileFinishTransaction,
    PilotFileOpen,
    PilotFileReadPage,
    PilotFileWritePage,
    PilotFileGetSize,
    PilotFileSetSize,
    AlpineFileCreateTransaction,
    AlpineFileFinishTransaction,
    AlpineFileOpen,
    AlpineFileReadPage,
    AlpineFileWritePage,
    AlpineFileGetSize,
    AlpineFileSetSize,
    -- DBModel--
    GetP,
    SetP,
    GetF,
    SetF,
    SurrogateGetF,
    SurrogateSetF,
    NameOf,
    ChangeName,
    DeclareEntity,
    DeclareRelship,
    DestroyEntity,
    DestroyRelship,
    RelationSubset,
    DomainSubset,
    NextRelship,
    PrevRelship,
    NextEntity,
    PrevEntity,
    GetDomainRefAttributes,
    OpenToClose
  };

  FileTimerEvent: TYPE = TimerEvent [PilotFileCreateTransaction .. AlpineFileSetSize]; 

  Starting: PROC[event: TimerEvent] = INLINE { StartTimer[event] };
    -- Glitch if an unmatched Starting[event]; older Starting[event] is superceded by
    --this one.

  Stopping: PROC[event: TimerEvent] = INLINE { StopTimer[event] };
    -- Logs time since previous Starting[event].
    -- Glitch if no unmatched Starting[event]; this Stopping call is ignored.

  Aborting: PROC[event: TimerEvent] = INLINE { AbortTimer[event] };
    -- Cancel count of event (same as Stopping, but doesn't count the time).

  Print: PROC[heading: Rope.ROPE ← NIL, out: IO.STREAM← NIL, verbose: BOOLEAN ← FALSE];
    -- Prints current state of stats module to outStream, then resets glitch count.
    -- If verbose then print all events, otherwise just print nonzero ones.


  -- Private implementation details

  CounterArray: PRIVATE ARRAY CounterEvent OF LONG CARDINAL;
  StartTimer: PRIVATE PROC[event: TimerEvent];
  StopTimer:  PRIVATE PROC[event: TimerEvent];
  AbortTimer: PRIVATE PROC[event: TimerEvent];


END.--DBStats


CHANGE LOG

Created by MBrown on September 18, 1980  11:12 PM

Changed by MBrown on September 21, 1980  2:50 PM
-- Document the fact that Print prints to file DBStats.log, not IODefs.WriteChar.

Changed by MBrown on September 21, 1980  9:59 PM
-- Introduce glitches (instead of raising ERROR), based on use of timer events in
--DBFileImpl.

Changed by Cattell on September 22, 1980  3:13 PM
-- Added some timer events.

Changed by MBrown on October 31, 1980  10:03 AM
-- Added header parm to Print; added new DBTuples timer events.

Changed by MBrown on November 10, 1980  3:35 PM
-- Flushed all DBTuples timer events.

Changed by MBrown on November 14, 1980  3:37 PM
-- Added BTree counter events.

Changed by MBrown on November 14, 1980  5:32 PM
-- Added Attribute cache counter events.

Changed by MBrown on December 8, 1980  5:41 PM
-- Added OpenToClose timer event, defined FileTimerEvent subrange.

Changed by MBrown on December 16, 1980  10:33 AM
-- Added FileAbortTransaction timer event.

Changed by MBrown on February 26, 1981  10:08 AM
-- Added putChar, cleanup, and verbose parms to Print.

Changed by MBrown on 17-Jun-81 12:05:42
-- Added CloseDBGroupScansActive, CloseDBTuplesetScansActive counters.

Changed by Cattell on 15-Dec-81 10:16:23
-- Modified to use IOStream.

Changed by Cattell on April 29, 1982 8:23 pm
-- Added DBView events.

Changed by Willie-Sue on June 24, 1982 12:00 pm
-- IOStream => IO

Changed by Cattell on October 11, 1982 3:25 pm
-- Added more DBView events, removed old DBTuples events.  Added Aborting.

Changed by MBrown on November 29, 1982 2:04 pm
-- New DBFile events