17
17
module Ouroboros.Consensus.Storage.LedgerDB.V2 (mkInitDb ) where
18
18
19
19
import Control.Arrow ((>>>) )
20
- import qualified Control.Monad as Monad (void , (>=>) )
20
+ import qualified Control.Monad as Monad (join , void )
21
21
import Control.Monad.Except
22
22
import Control.RAWLock
23
23
import qualified Control.RAWLock as RAWLock
24
24
import Control.ResourceRegistry
25
25
import Control.Tracer
26
- import Data.Foldable (traverse_ )
27
26
import qualified Data.Foldable as Foldable
28
27
import Data.Functor.Contravariant ((>$<) )
29
28
import Data.Kind (Type )
@@ -197,7 +196,7 @@ mkInternals bss h =
197
196
let selectWhereTo = case whereTo of
198
197
TakeAtImmutableTip -> anchorHandle
199
198
TakeAtVolatileTip -> currentHandle
200
- withStateRef env (MkSolo . selectWhereTo) $ \ (MkSolo st ) ->
199
+ withStateRef env (MkSolo . selectWhereTo) $ \ (MkSolo (st, _) ) ->
201
200
Monad. void $
202
201
takeSnapshot
203
202
(configCodec . getExtLedgerCfg . ledgerDbCfg $ ldbCfg env)
@@ -367,7 +366,7 @@ implTryTakeSnapshot ::
367
366
implTryTakeSnapshot bss env mTime nrBlocks =
368
367
if onDiskShouldTakeSnapshot (ldbSnapshotPolicy env) (uncurry (flip diffTime) <$> mTime) nrBlocks
369
368
then do
370
- withStateRef env (MkSolo . anchorHandle) $ \ (MkSolo st ) ->
369
+ withStateRef env (MkSolo . anchorHandle) $ \ (MkSolo (st, _) ) ->
371
370
Monad. void $
372
371
takeSnapshot
373
372
(configCodec . getExtLedgerCfg . ledgerDbCfg $ ldbCfg env)
@@ -565,33 +564,35 @@ getEnvSTM (LDBHandle varState) f =
565
564
566
565
-- | Get a 'StateRef' from the 'LedgerSeq' in the 'LedgerDBEnv', with the
567
566
-- '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.
569
569
--
570
570
-- For more flexibility, an arbitrary 'Traversable' of the 'StateRef' can be
571
571
-- returned; for the simple use case of getting a single 'StateRef', use @t ~
572
572
-- 'Solo'@.
573
573
getStateRef ::
574
574
(IOLike m , Traversable t ) =>
575
575
LedgerDBEnv m l blk ->
576
+ ResourceRegistry m ->
576
577
(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 =
579
580
RAWLock. withReadAccess (ldbOpenHandlesLock ldbEnv) $ \ () -> do
580
581
tst <- project <$> readTVarIO (ldbSeq ldbEnv)
581
582
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)
584
585
585
586
-- | Like 'StateRef', but takes care of closing the handle when the given action
586
587
-- returns or errors.
587
588
withStateRef ::
588
589
(IOLike m , Traversable t ) =>
589
590
LedgerDBEnv m l blk ->
590
591
(LedgerSeq m l -> t (StateRef m l )) ->
591
- (t (StateRef m l ) -> m a ) ->
592
+ (t (StateRef m l , ResourceKey m ) -> m a ) ->
592
593
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
595
596
596
597
acquireAtTarget ::
597
598
( HeaderHash l ~ HeaderHash blk
@@ -602,9 +603,10 @@ acquireAtTarget ::
602
603
) =>
603
604
LedgerDBEnv m l blk ->
604
605
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
608
610
Right VolatileTip -> pure $ currentHandle l
609
611
Right ImmutableTip -> pure $ anchorHandle l
610
612
Right (SpecificPoint pt) -> do
@@ -638,7 +640,7 @@ newForkerAtTarget ::
638
640
Target (Point blk ) ->
639
641
m (Either GetForkerError (Forker m l blk ))
640
642
newForkerAtTarget 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)
642
644
643
645
newForkerByRollback ::
644
646
( HeaderHash l ~ HeaderHash blk
@@ -653,14 +655,14 @@ newForkerByRollback ::
653
655
Word64 ->
654
656
m (Either GetForkerError (Forker m l blk ))
655
657
newForkerByRollback 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)
657
659
658
660
closeForkerEnv ::
659
661
IOLike m => ForkerEnv m l blk -> m ()
660
662
closeForkerEnv ForkerEnv {foeResourcesToRelease = (lock, key, toRelease)} =
661
663
RAWLock. withWriteAccess lock $
662
664
const $ do
663
- id =<< atomically (swapTVar toRelease (pure () ))
665
+ Monad. join $ atomically (swapTVar toRelease (pure () ))
664
666
_ <- release key
665
667
pure (() , () )
666
668
@@ -750,14 +752,19 @@ newForker ::
750
752
LedgerDBHandle m l blk ->
751
753
LedgerDBEnv m l blk ->
752
754
ResourceRegistry m ->
753
- StateRef m l ->
755
+ ( StateRef m l , ResourceKey m ) ->
754
756
m (Forker m l blk )
755
- newForker h ldbEnv rr st = do
757
+ newForker h ldbEnv rr (st, rk) = do
756
758
forkerKey <- atomically $ stateTVar (ldbNextForkerKey ldbEnv) $ \ r -> (r, r + 1 )
757
759
let tr = LedgerDBForkerEvent . TraceForkerEventWithKey forkerKey >$< ldbTracer ldbEnv
758
760
traceWith tr ForkerOpen
759
761
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)
761
768
let forkerEnv =
762
769
ForkerEnv
763
770
{ foeLedgerSeq = lseqVar
0 commit comments