1717module Ouroboros.Consensus.Storage.LedgerDB.V2 (mkInitDb ) where
1818
1919import Control.Arrow ((>>>) )
20- import qualified Control.Monad as Monad (void , (>=>) )
20+ import qualified Control.Monad as Monad (join , void )
2121import Control.Monad.Except
2222import Control.RAWLock
2323import qualified Control.RAWLock as RAWLock
2424import Control.ResourceRegistry
2525import Control.Tracer
26- import Data.Foldable (traverse_ )
2726import qualified Data.Foldable as Foldable
2827import Data.Functor.Contravariant ((>$<) )
2928import Data.Kind (Type )
@@ -197,7 +196,7 @@ mkInternals bss h =
197196 let selectWhereTo = case whereTo of
198197 TakeAtImmutableTip -> anchorHandle
199198 TakeAtVolatileTip -> currentHandle
200- withStateRef env (MkSolo . selectWhereTo) $ \ (MkSolo st ) ->
199+ withStateRef env (MkSolo . selectWhereTo) $ \ (MkSolo (st, _) ) ->
201200 Monad. void $
202201 takeSnapshot
203202 (configCodec . getExtLedgerCfg . ledgerDbCfg $ ldbCfg env)
@@ -367,7 +366,7 @@ implTryTakeSnapshot ::
367366implTryTakeSnapshot bss env mTime nrBlocks =
368367 if onDiskShouldTakeSnapshot (ldbSnapshotPolicy env) (uncurry (flip diffTime) <$> mTime) nrBlocks
369368 then do
370- withStateRef env (MkSolo . anchorHandle) $ \ (MkSolo st ) ->
369+ withStateRef env (MkSolo . anchorHandle) $ \ (MkSolo (st, _) ) ->
371370 Monad. void $
372371 takeSnapshot
373372 (configCodec . getExtLedgerCfg . ledgerDbCfg $ ldbCfg env)
@@ -565,33 +564,35 @@ getEnvSTM (LDBHandle varState) f =
565564
566565-- | Get a 'StateRef' from the 'LedgerSeq' in the 'LedgerDBEnv', with the
567566-- 'LedgerTablesHandle' having been duplicated (such that the original can be
568- -- closed). The caller is responsible for closing the handle.
567+ -- closed). The caller should close the handle using the returned @ResourceKey@,
568+ -- although closing the registry will also release the handle.
569569--
570570-- For more flexibility, an arbitrary 'Traversable' of the 'StateRef' can be
571571-- returned; for the simple use case of getting a single 'StateRef', use @t ~
572572-- 'Solo'@.
573573getStateRef ::
574574 (IOLike m , Traversable t ) =>
575575 LedgerDBEnv m l blk ->
576+ ResourceRegistry m ->
576577 (LedgerSeq m l -> t (StateRef m l )) ->
577- m (t (StateRef m l ))
578- getStateRef ldbEnv project =
578+ m (t (StateRef m l , ResourceKey m ))
579+ getStateRef ldbEnv reg project =
579580 RAWLock. withReadAccess (ldbOpenHandlesLock ldbEnv) $ \ () -> do
580581 tst <- project <$> readTVarIO (ldbSeq ldbEnv)
581582 for tst $ \ st -> do
582- tables' <- duplicate $ tables st
583- pure st{tables = tables'}
583+ (resKey, tables') <- allocate reg ( \ _ -> duplicate $ tables st) close
584+ pure ( st{tables = tables'}, resKey)
584585
585586-- | Like 'StateRef', but takes care of closing the handle when the given action
586587-- returns or errors.
587588withStateRef ::
588589 (IOLike m , Traversable t ) =>
589590 LedgerDBEnv m l blk ->
590591 (LedgerSeq m l -> t (StateRef m l )) ->
591- (t (StateRef m l ) -> m a ) ->
592+ (t (StateRef m l , ResourceKey m ) -> m a ) ->
592593 m a
593- withStateRef ldbEnv project =
594- bracket ( getStateRef ldbEnv project) (traverse_ (close . tables))
594+ withStateRef ldbEnv project f =
595+ withRegistry $ \ reg -> getStateRef ldbEnv reg project >>= f
595596
596597acquireAtTarget ::
597598 ( HeaderHash l ~ HeaderHash blk
@@ -602,9 +603,10 @@ acquireAtTarget ::
602603 ) =>
603604 LedgerDBEnv m l blk ->
604605 Either Word64 (Target (Point blk )) ->
605- m (Either GetForkerError (StateRef m l ))
606- acquireAtTarget ldbEnv target =
607- getStateRef ldbEnv $ \ l -> case target of
606+ ResourceRegistry m ->
607+ m (Either GetForkerError (StateRef m l , ResourceKey m ))
608+ acquireAtTarget ldbEnv target reg =
609+ getStateRef ldbEnv reg $ \ l -> case target of
608610 Right VolatileTip -> pure $ currentHandle l
609611 Right ImmutableTip -> pure $ anchorHandle l
610612 Right (SpecificPoint pt) -> do
@@ -638,7 +640,7 @@ newForkerAtTarget ::
638640 Target (Point blk ) ->
639641 m (Either GetForkerError (Forker m l blk ))
640642newForkerAtTarget h rr pt = getEnv h $ \ ldbEnv ->
641- acquireAtTarget ldbEnv (Right pt) >>= traverse (newForker h ldbEnv rr)
643+ acquireAtTarget ldbEnv (Right pt) rr >>= traverse (newForker h ldbEnv rr)
642644
643645newForkerByRollback ::
644646 ( HeaderHash l ~ HeaderHash blk
@@ -653,14 +655,14 @@ newForkerByRollback ::
653655 Word64 ->
654656 m (Either GetForkerError (Forker m l blk ))
655657newForkerByRollback h rr n = getEnv h $ \ ldbEnv ->
656- acquireAtTarget ldbEnv (Left n) >>= traverse (newForker h ldbEnv rr)
658+ acquireAtTarget ldbEnv (Left n) rr >>= traverse (newForker h ldbEnv rr)
657659
658660closeForkerEnv ::
659661 IOLike m => ForkerEnv m l blk -> m ()
660662closeForkerEnv ForkerEnv {foeResourcesToRelease = (lock, key, toRelease)} =
661663 RAWLock. withWriteAccess lock $
662664 const $ do
663- id =<< atomically (swapTVar toRelease (pure () ))
665+ Monad. join $ atomically (swapTVar toRelease (pure () ))
664666 _ <- release key
665667 pure (() , () )
666668
@@ -750,14 +752,19 @@ newForker ::
750752 LedgerDBHandle m l blk ->
751753 LedgerDBEnv m l blk ->
752754 ResourceRegistry m ->
753- StateRef m l ->
755+ ( StateRef m l , ResourceKey m ) ->
754756 m (Forker m l blk )
755- newForker h ldbEnv rr st = do
757+ newForker h ldbEnv rr (st, rk) = do
756758 forkerKey <- atomically $ stateTVar (ldbNextForkerKey ldbEnv) $ \ r -> (r, r + 1 )
757759 let tr = LedgerDBForkerEvent . TraceForkerEventWithKey forkerKey >$< ldbTracer ldbEnv
758760 traceWith tr ForkerOpen
759761 lseqVar <- newTVarIO . LedgerSeq . AS. Empty $ st
760- (k, toRelease) <- allocate rr (\ _ -> newTVarIO (pure () )) (readTVarIO Monad. >=> id )
762+ -- The closing action that we allocate in the TVar from the start is not
763+ -- strictly necessary if the caller uses a short-lived registry like the ones
764+ -- in Chain selection or the forging loop. Just in case the user passes a
765+ -- long-lived registry, we store such closing action to make sure the handle
766+ -- is closed even under @forkerClose@ if the registry outlives the forker.
767+ (k, toRelease) <- allocate rr (\ _ -> newTVarIO (Monad. void (release rk))) (Monad. join . readTVarIO)
761768 let forkerEnv =
762769 ForkerEnv
763770 { foeLedgerSeq = lseqVar
0 commit comments