lsm-tree-1.0.0.0: src-core/Database/LSMTree/Internal/Entry.hs
{-# OPTIONS_HADDOCK not-home #-}
module Database.LSMTree.Internal.Entry (
Entry (..)
, hasBlob
, onValue
, onBlobRef
, NumEntries (..)
, unNumEntries
-- * Value resolution/merging
, combine
, combineUnion
, combineMaybe
) where
import Control.DeepSeq (NFData (..))
import Data.Bifoldable (Bifoldable (..))
import Data.Bifunctor (Bifunctor (..))
data Entry v b
= Insert !v
| InsertWithBlob !v !b
| Upsert !v
| Delete
deriving stock (Eq, Show, Functor, Foldable, Traversable)
hasBlob :: Entry v b -> Bool
hasBlob Insert{} = False
hasBlob InsertWithBlob{} = True
hasBlob Upsert{} = False
hasBlob Delete{} = False
instance (NFData v, NFData b) => NFData (Entry v b) where
rnf (Insert v) = rnf v
rnf (InsertWithBlob v br) = rnf v `seq` rnf br
rnf (Upsert v) = rnf v
rnf Delete = ()
onValue :: v' -> (v -> v') -> Entry v b -> v'
onValue def f = \case
Insert v -> f v
InsertWithBlob v _ -> f v
Upsert v -> f v
Delete -> def
onBlobRef :: b' -> (b -> b') -> Entry v b -> b'
onBlobRef def g = \case
Insert{} -> def
InsertWithBlob _ br -> g br
Upsert{} -> def
Delete -> def
instance Bifunctor Entry where
first f = \case
Insert v -> Insert (f v)
InsertWithBlob v br -> InsertWithBlob (f v) br
Upsert v -> Upsert (f v)
Delete -> Delete
second g = \case
Insert v -> Insert v
InsertWithBlob v br -> InsertWithBlob v (g br)
Upsert v -> Upsert v
Delete -> Delete
instance Bifoldable Entry where
bifoldMap f g = \case
Insert v -> f v
InsertWithBlob v br -> f v <> g br
Upsert v -> f v
Delete -> mempty
-- | A count of entries, for example the number of entries in a run.
--
-- This number is limited by the machine's word size. On 32-bit systems, the
-- maximum number we can represent is @2^31@ which is roughly 2 billion. This
-- should be a sufficiently large limit that we never reach it in practice. By
-- extension for 64-bit and higher-bit systems this limit is also sufficiently
-- large.
newtype NumEntries = NumEntries Int
deriving stock (Eq, Ord, Show)
deriving newtype NFData
instance Semigroup NumEntries where
NumEntries a <> NumEntries b = NumEntries (a + b)
instance Monoid NumEntries where
mempty = NumEntries 0
unNumEntries :: NumEntries -> Int
unNumEntries (NumEntries x) = x
{-------------------------------------------------------------------------------
Value resolution/merging
-------------------------------------------------------------------------------}
-- | Given a value-merge function, combine entries. Only take a blob from the
-- left entry.
--
-- Note: 'Entry' is a semigroup with 'combine' if the @(v -> v -> v)@ argument
-- is associative.
combine :: (v -> v -> v) -> Entry v b -> Entry v b -> Entry v b
combine _ e@Delete _ = e
combine _ e@Insert {} _ = e
combine _ e@InsertWithBlob {} _ = e
combine _ (Upsert u) Delete = Insert u
combine f (Upsert u) (Insert v) = Insert (f u v)
combine f (Upsert u) (InsertWithBlob v _) = Insert (f u v)
combine f (Upsert u) (Upsert v) = Upsert (f u v)
-- | Combine two entries of runs that have been 'union'ed together. If any one
-- has a value, the result should have a value (represented by 'Insert'). If
-- both have a value, these values get combined monoidally. Only take a blob
-- from the left entry.
--
-- Note: 'Entry' is a semigroup with 'combineUnion' if the @(v -> v -> v)@
-- argument is associative.
combineUnion :: (v -> v -> v) -> Entry v b -> Entry v b -> Entry v b
combineUnion f = go
where
go Delete (Upsert v) = Insert v
go Delete e = e
go (Upsert u) Delete = Insert u
go e Delete = e
go (Insert u) (Insert v) = Insert (f u v)
go (Insert u) (InsertWithBlob v _) = Insert (f u v)
go (Insert u) (Upsert v) = Insert (f u v)
go (InsertWithBlob u b) (Insert v) = InsertWithBlob (f u v) b
go (InsertWithBlob u b) (InsertWithBlob v _) = InsertWithBlob (f u v) b
go (InsertWithBlob u b) (Upsert v) = InsertWithBlob (f u v) b
go (Upsert u) (Insert v) = Insert (f u v)
go (Upsert u) (InsertWithBlob v _) = Insert (f u v)
go (Upsert u) (Upsert v) = Insert (f u v)
combineMaybe :: (v -> v -> v) -> Maybe (Entry v b) -> Maybe (Entry v b) -> Maybe (Entry v b)
combineMaybe _ e1 Nothing = e1
combineMaybe _ Nothing e2 = e2
combineMaybe f (Just e1) (Just e2) = Just $! combine f e1 e2