packages feed

lsm-tree-1.0.0.0: src-extras/Database/LSMTree/Extras/Index.hs

{-|
    Provides additional support for working with fence pointer indexes and their
    accumulators.
-}
module Database.LSMTree.Extras.Index
(
    Append (AppendSinglePage, AppendMultiPage),
    appendToCompact,
    appendToOrdinary,
    append
)
where

import           Control.DeepSeq (NFData (rnf))
import           Control.Monad.ST.Strict (ST)
import           Data.Foldable (toList)
import           Data.Word (Word32)
import           Database.LSMTree.Internal.Chunk (Chunk)
import           Database.LSMTree.Internal.Index (IndexAcc)
import qualified Database.LSMTree.Internal.Index as Index (appendMulti,
                     appendSingle)
import           Database.LSMTree.Internal.Index.CompactAcc (IndexCompactAcc)
import qualified Database.LSMTree.Internal.Index.CompactAcc as IndexCompact
                     (appendMulti, appendSingle)
import           Database.LSMTree.Internal.Index.OrdinaryAcc (IndexOrdinaryAcc)
import qualified Database.LSMTree.Internal.Index.OrdinaryAcc as IndexOrdinary
                     (appendMulti, appendSingle)
import           Database.LSMTree.Internal.Serialise (SerialisedKey)

-- | Instruction for appending pages, to be used in conjunction with indexes.
data Append
    = {-|
          Append a single page that fully comprises one or more key–value pairs.
      -}
      AppendSinglePage
          SerialisedKey -- ^ Minimum key
          SerialisedKey -- ^ Maximum key
    | {-|
          Append multiple pages that together comprise a single key–value pair.
      -}
      AppendMultiPage
          SerialisedKey -- ^ Sole key
          Word32        -- ^ Number of overflow pages

instance NFData Append where

    rnf (AppendSinglePage minKey maxKey)
        = rnf minKey `seq` rnf maxKey
    rnf (AppendMultiPage key overflowPageCount)
        = rnf key `seq` rnf overflowPageCount

{-|
    Adds information about appended pages to an index and outputs newly
    available chunks, using primitives specific to the type of the index.

    See the documentation of the 'IndexAcc' type for constraints to adhere to.
-}
appendWith :: ((SerialisedKey, SerialisedKey) -> j s -> ST s (Maybe Chunk))
           -> ((SerialisedKey, Word32)        -> j s -> ST s [Chunk])
           -> Append
           -> j s
           -> ST s [Chunk]
appendWith appendSingle appendMulti instruction indexAcc = case instruction of
    AppendSinglePage minKey maxKey
        -> toList <$> appendSingle (minKey, maxKey) indexAcc
    AppendMultiPage key overflowPageCount
        -> appendMulti (key, overflowPageCount) indexAcc
{-# INLINABLE appendWith #-}

{-|
    Adds information about appended pages to a compact index and outputs newly
    available chunks.

    See the documentation of the 'IndexAcc' type for constraints to adhere to.
-}
appendToCompact :: Append -> IndexCompactAcc s -> ST s [Chunk]
appendToCompact = appendWith IndexCompact.appendSingle
                             IndexCompact.appendMulti
{-# INLINE appendToCompact #-}

{-|
    Adds information about appended pages to an ordinary index and outputs newly
    available chunks.

    See the documentation of the 'IndexAcc' type for constraints to adhere to.
-}
appendToOrdinary :: Append -> IndexOrdinaryAcc s -> ST s [Chunk]
appendToOrdinary = appendWith IndexOrdinary.appendSingle
                              IndexOrdinary.appendMulti
{-# INLINE appendToOrdinary #-}

{-|
    Adds information about appended pages to an index and outputs newly
    available chunks.

    See the documentation of the 'IndexAcc' type for constraints to adhere to.
-}
append :: Append -> IndexAcc s -> ST s [Chunk]
append = appendWith Index.appendSingle
                    Index.appendMulti
{-# INLINE append #-}