{-# LANGUAGE RecordWildCards #-}
{-# OPTIONS -Wall #-}
module Network.DFINITY.RadixTree.Memory
( loadHot
, loadCold
, storeHot
, storeCold
) where
import Codec.Serialise (deserialise, serialise)
import Control.Monad.IO.Class (MonadIO)
import Crypto.Hash.SHA256 (hash)
import Data.ByteString.Char8 as Byte (take)
import Data.ByteString.Lazy (fromStrict, toStrict)
import Data.ByteString.Short (fromShort, toShort)
import Data.LruCache as LRU (insert, lookup)
import Data.Map.Strict as Map (insert, lookup)
import Database.LevelDB (defaultReadOptions, defaultWriteOptions, get, put)
import Network.DFINITY.RadixTree.Types
loadHot
:: MonadIO m
=> RadixRoot
-> RadixBuffer
-> RadixCache
-> RadixDatabase
-> m (Maybe (RadixBranch, RadixCache))
loadHot root buffer cache database =
case Map.lookup root buffer of
Just branch -> pure $ Just (branch, cache)
Nothing -> loadCold root cache database
loadCold
:: MonadIO m
=> RadixRoot
-> RadixCache
-> RadixDatabase
-> m (Maybe (RadixBranch, RadixCache))
loadCold root cache database =
case LRU.lookup root cache of
Just (branch, cache') ->
seq cache' $ seq branch $ pure $ Just (branch, cache')
Nothing -> do
let key = fromShort root
result <- get database defaultReadOptions key
case result of
Just bytes -> do
let branch = deserialise $ fromStrict bytes
let cache' = LRU.insert root branch cache
seq cache' $ seq branch $ pure $ Just (branch, cache')
Nothing -> pure $ Nothing
storeHot
:: RadixRoot
-> RadixBranch
-> RadixBuffer
-> RadixBuffer
storeHot = Map.insert
storeCold
:: MonadIO m
=> RadixBranch
-> RadixCache
-> RadixDatabase
-> m (RadixRoot, RadixCache)
storeCold branch cache database = do
put database defaultWriteOptions key bytes
seq cache' $ pure (root, cache')
where
bytes = toStrict $ serialise branch
key = Byte.take 20 $ hash bytes
root = toShort key
cache' = LRU.insert root branch cache