@@ -73,6 +73,7 @@ import Control.Concurrent.STM.TBQueue (newTBQueueIO)
7373import qualified Data.ByteString.Base16 as Base16
7474import qualified Data.ByteString.Char8 as BS
7575import qualified Data.ByteString.Short as SBS
76+ import qualified Data.List as List
7677import qualified Data.Map.Strict as Map
7778import qualified Data.Set as Set
7879import qualified Data.Strict.Maybe as Strict
@@ -421,11 +422,11 @@ hashToAnnotation = Base16.encode . BS.take 5
421422loadLedgerAtPoint :: HasLedgerEnv -> CardanoPoint -> IO (Either [DiskSnapshot ] CardanoLedgerState )
422423loadLedgerAtPoint hasLedgerEnv point = do
423424 mLedgerDB <- atomically $ readTVar $ leStateVar hasLedgerEnv
424- -- First try to find the ledger in memory
425- let mStates = rollbackLedger mLedgerDB
425+ let (mStates, dropped) = rollbackLedger mLedgerDB
426426 case mStates of
427427 Nothing -> do
428428 writeLedgerState hasLedgerEnv Strict. Nothing
429+ closeDroppedHandles dropped
429430 performMajorGC
430431 mst <- findStateFromSnapshot hasLedgerEnv point
431432 case mst of
@@ -440,18 +441,31 @@ loadLedgerAtPoint hasLedgerEnv point = do
440441 let sr = ledgerDbCurrent ledgerDB'
441442 deleteNewerSnapshots hasLedgerEnv point
442443 writeLedgerState hasLedgerEnv $ Strict. Just ledgerDB'
444+ closeDroppedHandles dropped
443445 pure $ Right (srState sr)
444446 where
447+ -- | Returns (kept states or Nothing, dropped states to close)
445448 rollbackLedger ::
446449 Strict. Maybe LedgerDB ->
447- Maybe (StrictSeq DbSyncStateRef )
450+ ( Maybe (StrictSeq DbSyncStateRef ), [ DbSyncStateRef ] )
448451 rollbackLedger mLedgerDB = case mLedgerDB of
449- Strict. Nothing -> Nothing
452+ Strict. Nothing -> ( Nothing , [] )
450453 Strict. Just ledgerDB ->
451- let kept = SSeq. fromList $ dropWhile
454+ let allEntries = toList $ ledgerDbCheckpoints ledgerDB
455+ (newer, older) = List. span
452456 (\ sr -> Consensus. getTipSlot (clsState (srState sr)) > pointSlot point)
453- (toList $ ledgerDbCheckpoints ledgerDB)
454- in if SSeq. null kept then Nothing else Just kept
457+ allEntries
458+ kept = SSeq. fromList older
459+ in if SSeq. null kept
460+ then (Nothing , allEntries)
461+ else (Just kept, newer)
462+
463+ -- | Close handles from dropped states.
464+ -- Waits for the snapshot writer to finish if any handle is still being used.
465+ closeDroppedHandles :: [DbSyncStateRef ] -> IO ()
466+ closeDroppedHandles refs = forM_ refs $ \ sr -> do
467+ atomically $ readTVar (srCanClose sr) >>= check
468+ close (srTables sr)
455469
456470
457471writeLedgerState :: HasLedgerEnv -> Strict. Maybe LedgerDB -> IO ()
0 commit comments