{-# LANGUAGE RankNTypes #-}
module Singular.Registry.Trie.PureManager
(
mkPureTrieManager
, mkPureTrieManagerFrom
, dumpPureTries
) where
import Control.Exception (evaluate)
import Control.Monad.State.Strict (State, get, runState)
import Data.IORef
( IORef
, modifyIORef'
, newIORef
, readIORef
)
import Data.Map.Strict (Map)
import Data.Map.Strict qualified as Map
import Data.Set (Set)
import Data.Set qualified as Set
import MPF.Backend.Pure
( MPFInMemoryDB
, emptyMPFInMemoryDB
)
import Singular.Registry.Ledger (TokenId)
import Singular.Registry.Trie (Trie (..), TrieManager (..))
import Singular.Registry.Trie.Pure
( mkPureTrieFromRef
, stateTrie
)
mkPureTrieManager :: IO (TrieManager IO)
mkPureTrieManager :: IO (TrieManager IO)
mkPureTrieManager = (TrieManager IO, IO (Map TokenId MPFInMemoryDB)) -> TrieManager IO
forall a b. (a, b) -> a
fst ((TrieManager IO, IO (Map TokenId MPFInMemoryDB))
-> TrieManager IO)
-> IO (TrieManager IO, IO (Map TokenId MPFInMemoryDB))
-> IO (TrieManager IO)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Map TokenId MPFInMemoryDB
-> IO (TrieManager IO, IO (Map TokenId MPFInMemoryDB))
mkPureTrieManagerFrom Map TokenId MPFInMemoryDB
forall k a. Map k a
Map.empty
mkPureTrieManagerFrom
:: Map TokenId MPFInMemoryDB
-> IO (TrieManager IO, IO (Map TokenId MPFInMemoryDB))
mkPureTrieManagerFrom :: Map TokenId MPFInMemoryDB
-> IO (TrieManager IO, IO (Map TokenId MPFInMemoryDB))
mkPureTrieManagerFrom Map TokenId MPFInMemoryDB
initial = do
seeded <- (MPFInMemoryDB -> IO (IORef MPFInMemoryDB))
-> Map TokenId MPFInMemoryDB
-> IO (Map TokenId (IORef MPFInMemoryDB))
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Map TokenId a -> f (Map TokenId b)
traverse MPFInMemoryDB -> IO (IORef MPFInMemoryDB)
forall a. a -> IO (IORef a)
newIORef Map TokenId MPFInMemoryDB
initial
ref <- newIORef seeded
hiddenRef <-
newIORef (Set.empty :: Set TokenId)
pure
( TrieManager
{ withTrie =
pureWithTrie ref hiddenRef
, withSpeculativeTrie =
pureWithSpeculativeTrie
ref
hiddenRef
, createTrie = pureCreateTrie ref
, deleteTrie = pureDeleteTrie ref
, hideTrie = pureHideTrie hiddenRef
, unhideTrie =
pureUnhideTrie hiddenRef
}
, dumpPureTries ref
)
dumpPureTries
:: IORef (Map TokenId (IORef MPFInMemoryDB))
-> IO (Map TokenId MPFInMemoryDB)
dumpPureTries :: IORef (Map TokenId (IORef MPFInMemoryDB))
-> IO (Map TokenId MPFInMemoryDB)
dumpPureTries IORef (Map TokenId (IORef MPFInMemoryDB))
ref = IORef (Map TokenId (IORef MPFInMemoryDB))
-> IO (Map TokenId (IORef MPFInMemoryDB))
forall a. IORef a -> IO a
readIORef IORef (Map TokenId (IORef MPFInMemoryDB))
ref IO (Map TokenId (IORef MPFInMemoryDB))
-> (Map TokenId (IORef MPFInMemoryDB)
-> IO (Map TokenId MPFInMemoryDB))
-> IO (Map TokenId MPFInMemoryDB)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (IORef MPFInMemoryDB -> IO MPFInMemoryDB)
-> Map TokenId (IORef MPFInMemoryDB)
-> IO (Map TokenId MPFInMemoryDB)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Map TokenId a -> f (Map TokenId b)
traverse IORef MPFInMemoryDB -> IO MPFInMemoryDB
forall a. IORef a -> IO a
readIORef
pureWithTrie
:: IORef (Map TokenId (IORef MPFInMemoryDB))
-> IORef (Set TokenId)
-> TokenId
-> (Trie IO -> IO a)
-> IO a
pureWithTrie :: forall a.
IORef (Map TokenId (IORef MPFInMemoryDB))
-> IORef (Set TokenId) -> TokenId -> (Trie IO -> IO a) -> IO a
pureWithTrie IORef (Map TokenId (IORef MPFInMemoryDB))
ref IORef (Set TokenId)
hiddenRef TokenId
tid Trie IO -> IO a
action = do
hidden <- IORef (Set TokenId) -> IO (Set TokenId)
forall a. IORef a -> IO a
readIORef IORef (Set TokenId)
hiddenRef
if Set.member tid hidden
then
error $
"Trie is hidden: " ++ show tid
else do
tries <- readIORef ref
case Map.lookup tid tries of
Maybe (IORef MPFInMemoryDB)
Nothing ->
[Char] -> IO a
forall a. HasCallStack => [Char] -> a
error ([Char] -> IO a) -> [Char] -> IO a
forall a b. (a -> b) -> a -> b
$
[Char]
"Trie not found: "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ TokenId -> [Char]
forall a. Show a => a -> [Char]
show TokenId
tid
Just IORef MPFInMemoryDB
dbRef ->
Trie IO -> IO a
action
(IORef MPFInMemoryDB -> Trie IO
mkPureTrieFromRef IORef MPFInMemoryDB
dbRef)
pureWithSpeculativeTrie
:: IORef (Map TokenId (IORef MPFInMemoryDB))
-> IORef (Set TokenId)
-> TokenId
-> (forall n. (Monad n) => Trie n -> n a)
-> IO a
pureWithSpeculativeTrie :: forall a.
IORef (Map TokenId (IORef MPFInMemoryDB))
-> IORef (Set TokenId)
-> TokenId
-> (forall (n :: * -> *). Monad n => Trie n -> n a)
-> IO a
pureWithSpeculativeTrie
IORef (Map TokenId (IORef MPFInMemoryDB))
ref
IORef (Set TokenId)
hiddenRef
TokenId
tid
forall (n :: * -> *). Monad n => Trie n -> n a
action = do
hidden <- IORef (Set TokenId) -> IO (Set TokenId)
forall a. IORef a -> IO a
readIORef IORef (Set TokenId)
hiddenRef
if Set.member tid hidden
then
error $
"Trie is hidden: "
++ show tid
else do
tries <- readIORef ref
case Map.lookup tid tries of
Maybe (IORef MPFInMemoryDB)
Nothing ->
[Char] -> IO a
forall a. HasCallStack => [Char] -> a
error ([Char] -> IO a) -> [Char] -> IO a
forall a b. (a -> b) -> a -> b
$
[Char]
"Trie not found: "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ TokenId -> [Char]
forall a. Show a => a -> [Char]
show TokenId
tid
Just IORef MPFInMemoryDB
dbRef -> do
db <- IORef MPFInMemoryDB -> IO MPFInMemoryDB
forall a. IORef a -> IO a
readIORef IORef MPFInMemoryDB
dbRef
(answer, _) <- evaluate (runState (action speculativeTrie) db)
pure answer
speculativeTrie :: Trie (State MPFInMemoryDB)
speculativeTrie :: Trie (State MPFInMemoryDB)
speculativeTrie =
Trie (State MPFInMemoryDB)
stateTrie
{ insert = \ByteString
key ByteString
value -> State MPFInMemoryDB Root -> State MPFInMemoryDB Root
forall {m :: * -> *} {a} {b}. MonadState a m => m b -> m b
strictMutation (Trie (State MPFInMemoryDB)
-> ByteString -> ByteString -> State MPFInMemoryDB Root
forall (m :: * -> *). Trie m -> ByteString -> ByteString -> m Root
insert Trie (State MPFInMemoryDB)
stateTrie ByteString
key ByteString
value)
, delete = strictMutation . delete stateTrie
}
where
strictMutation :: m b -> m b
strictMutation m b
action = do
answer <- m b
action
changed <- get
changed `seq` pure answer
pureCreateTrie
:: IORef (Map TokenId (IORef MPFInMemoryDB))
-> TokenId
-> IO ()
pureCreateTrie :: IORef (Map TokenId (IORef MPFInMemoryDB)) -> TokenId -> IO ()
pureCreateTrie IORef (Map TokenId (IORef MPFInMemoryDB))
ref TokenId
tid = do
dbRef <- MPFInMemoryDB -> IO (IORef MPFInMemoryDB)
forall a. a -> IO (IORef a)
newIORef MPFInMemoryDB
emptyMPFInMemoryDB
modifyIORef' ref (Map.insert tid dbRef)
pureDeleteTrie
:: IORef (Map TokenId (IORef MPFInMemoryDB))
-> TokenId
-> IO ()
pureDeleteTrie :: IORef (Map TokenId (IORef MPFInMemoryDB)) -> TokenId -> IO ()
pureDeleteTrie IORef (Map TokenId (IORef MPFInMemoryDB))
ref =
IORef (Map TokenId (IORef MPFInMemoryDB))
-> (Map TokenId (IORef MPFInMemoryDB)
-> Map TokenId (IORef MPFInMemoryDB))
-> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' IORef (Map TokenId (IORef MPFInMemoryDB))
ref ((Map TokenId (IORef MPFInMemoryDB)
-> Map TokenId (IORef MPFInMemoryDB))
-> IO ())
-> (TokenId
-> Map TokenId (IORef MPFInMemoryDB)
-> Map TokenId (IORef MPFInMemoryDB))
-> TokenId
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TokenId
-> Map TokenId (IORef MPFInMemoryDB)
-> Map TokenId (IORef MPFInMemoryDB)
forall k a. Ord k => k -> Map k a -> Map k a
Map.delete
pureHideTrie
:: IORef (Set TokenId) -> TokenId -> IO ()
pureHideTrie :: IORef (Set TokenId) -> TokenId -> IO ()
pureHideTrie IORef (Set TokenId)
hiddenRef TokenId
tid =
IORef (Set TokenId) -> (Set TokenId -> Set TokenId) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' IORef (Set TokenId)
hiddenRef (TokenId -> Set TokenId -> Set TokenId
forall a. Ord a => a -> Set a -> Set a
Set.insert TokenId
tid)
pureUnhideTrie
:: IORef (Set TokenId) -> TokenId -> IO ()
pureUnhideTrie :: IORef (Set TokenId) -> TokenId -> IO ()
pureUnhideTrie IORef (Set TokenId)
hiddenRef TokenId
tid =
IORef (Set TokenId) -> (Set TokenId -> Set TokenId) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' IORef (Set TokenId)
hiddenRef (TokenId -> Set TokenId -> Set TokenId
forall a. Ord a => a -> Set a -> Set a
Set.delete TokenId
tid)