Skip to content

Commit 3b99563

Browse files
committed
Make Ref ownership handling more consistent in incoming run handling
This follows our standard pattern that we avoid transferring ownership of references. Callees make their own referenes and callers retain or release their own.
1 parent 46adedc commit 3b99563

File tree

2 files changed

+60
-66
lines changed

2 files changed

+60
-66
lines changed

src/Database/LSMTree/Internal/MergeSchedule.hs

Lines changed: 35 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ module Database.LSMTree.Internal.MergeSchedule (
2828
, newIncomingSingleRun
2929
, newIncomingCompletedMergingRun
3030
, newIncomingMergingRun
31+
, releaseIncomingRun
3132
, supplyCreditsIncomingRun
3233
, snapshotIncomingRun
3334
-- * Union level
@@ -349,7 +350,7 @@ releaseLevels ::
349350
-> m ()
350351
releaseLevels reg levels =
351352
V.forM_ levels $ \Level {incomingRun, residentRuns} -> do
352-
releaseIncomingRun reg incomingRun
353+
delayedCommit reg (releaseIncomingRun incomingRun)
353354
V.mapM_ (delayedCommit reg . releaseRef) residentRuns
354355

355356
{-# SPECIALISE iforLevelM_ :: Levels IO h -> (LevelNo -> Level IO h -> IO ()) -> IO () #-}
@@ -406,34 +407,33 @@ duplicateIncomingRun reg (Merging mp md mcv mr) =
406407
Merging mp md <$> (newPrimVar =<< readPrimVar mcv)
407408
<*> withRollback reg (dupRef mr) releaseRef
408409

409-
{-# SPECIALISE releaseIncomingRun :: ActionRegistry IO -> IncomingRun IO h -> IO () #-}
410+
{-# SPECIALISE releaseIncomingRun :: IncomingRun IO h -> IO () #-}
410411
releaseIncomingRun ::
411412
(PrimMonad m, MonadMask m)
412-
=> ActionRegistry m
413-
-> IncomingRun m h -> m ()
414-
releaseIncomingRun reg (Single r) = delayedCommit reg (releaseRef r)
415-
releaseIncomingRun reg (Merging _ _ _ mr) = delayedCommit reg (releaseRef mr)
413+
=> IncomingRun m h -> m ()
414+
releaseIncomingRun (Single r) = releaseRef r
415+
releaseIncomingRun (Merging _ _ _ mr) = releaseRef mr
416416

417417
{-# SPECIALISE newIncomingSingleRun ::
418418
Tracer IO (AtLevel MergeTrace)
419419
-> LevelNo
420420
-> Ref (Run IO h)
421421
-> IO (IncomingRun IO h) #-}
422422
newIncomingSingleRun ::
423-
Monad m
423+
PrimMonad m
424424
=> Tracer m (AtLevel MergeTrace)
425425
-> LevelNo
426426
-> Ref (Run m h)
427427
-> m (IncomingRun m h)
428428
newIncomingSingleRun tr ln r = do
429+
r' <- dupRef r
429430
traceWith tr $ AtLevel ln $
430-
TraceNewMergeSingleRun (Run.size r) (Run.runFsPathsNumber r)
431-
return (Single r)
431+
TraceNewMergeSingleRun (Run.size r') (Run.runFsPathsNumber r')
432+
return (Single r')
432433

433434
{-# SPECIALISE newIncomingCompletedMergingRun ::
434435
Tracer IO (AtLevel MergeTrace)
435436
-> TableConfig
436-
-> ActionRegistry IO
437437
-> LevelNo
438438
-> MergePolicyForLevel
439439
-> NumRuns
@@ -444,17 +444,16 @@ newIncomingCompletedMergingRun ::
444444
(MonadMask m, MonadMVar m, MonadSTM m, MonadST m)
445445
=> Tracer m (AtLevel MergeTrace)
446446
-> TableConfig
447-
-> ActionRegistry m
448447
-> LevelNo
449448
-> MergePolicyForLevel
450449
-> NumRuns
451450
-> MergeDebt
452451
-> Ref (Run m h)
453452
-> m (IncomingRun m h)
454-
newIncomingCompletedMergingRun tr conf reg ln mergePolicy nr mergeDebt r = do
453+
newIncomingCompletedMergingRun tr conf ln mergePolicy nr mergeDebt r = do
455454
traceWith tr $ AtLevel ln $
456455
TraceNewMergeCompletedRun (Run.size r) (Run.runFsPathsNumber r)
457-
mr <- withRollback reg (MR.newCompleted nr mergeDebt r) releaseRef
456+
mr <- MR.newCompleted nr mergeDebt r
458457
let nominalDebt = nominalDebtForLevel conf ln
459458
nominalCredits = nominalDebtAsCredits nominalDebt
460459
nominalCreditsVar <- newPrimVar nominalCredits
@@ -468,7 +467,6 @@ newIncomingCompletedMergingRun tr conf reg ln mergePolicy nr mergeDebt r = do
468467
-> UniqCounter IO
469468
-> TableConfig
470469
-> ResolveSerialisedValue
471-
-> ActionRegistry IO
472470
-> MergePolicyForLevel
473471
-> MR.LevelMergeType
474472
-> LevelNo
@@ -483,7 +481,6 @@ newIncomingMergingRun ::
483481
-> UniqCounter m
484482
-> TableConfig
485483
-> ResolveSerialisedValue
486-
-> ActionRegistry m
487484
-> MergePolicyForLevel
488485
-> MR.LevelMergeType
489486
-> LevelNo
@@ -494,8 +491,7 @@ newIncomingMergingRun tr hfs hbio activeDir uc
494491
confDiskCachePolicy,
495492
confFencePointerIndex
496493
}
497-
resolve reg
498-
mergePolicy mergeType ln rs = do
494+
resolve mergePolicy mergeType ln rs = do
499495
!rn <- uniqueToRunNumber <$> incrUniqCounter uc
500496
let !caching = diskCachePolicyForLevel confDiskCachePolicy ln
501497
!alloc = bloomFilterAllocForLevel conf ln
@@ -504,11 +500,9 @@ newIncomingMergingRun tr hfs hbio activeDir uc
504500
traceWith tr $ AtLevel ln $
505501
TraceNewMerge (V.map Run.size rs) (runNumber runPaths)
506502
caching alloc mergePolicy mergeType
507-
mr <- withRollback reg
508-
(MR.new hfs hbio resolve caching
509-
alloc indexType mergeType
510-
runPaths rs)
511-
releaseRef
503+
mr <- MR.new hfs hbio resolve caching
504+
alloc indexType mergeType
505+
runPaths rs
512506
let nominalDebt = nominalDebtForLevel conf ln
513507
nominalCredits = NominalCredits 0
514508
nominalCreditsVar <- newPrimVar nominalCredits
@@ -1061,33 +1055,30 @@ addRunToLevels tr conf@TableConfig{..} resolve hfs hbio root uc r0 reg levels ul
10611055
TraceExpectCompletedMerge (Run.runFsPathsNumber r)
10621056
pure r
10631057

1064-
-- Releases the runs.
1058+
-- Consumes and releases the runs.
10651059
newMerge :: MergePolicyForLevel
10661060
-> MR.LevelMergeType
10671061
-> LevelNo
10681062
-> V.Vector (Ref (Run m h))
10691063
-> m (IncomingRun m h)
1070-
newMerge mergePolicy mergeType ln rs
1071-
| Just (r, rest) <- V.uncons rs
1072-
, V.null rest = do
1073-
-- We create a fresh reference and release the original one.
1074-
-- This will also make it easier to trace back where it was allocated.
1075-
r' <- withRollback reg (dupRef r) releaseRef
1076-
ir <- newIncomingSingleRun tr ln r'
1077-
delayedCommit reg (releaseRef r)
1078-
pure ir
1079-
1080-
| otherwise = assert (let l = V.length rs in l >= 2 && l <= 5) $ do
1081-
ir <- newIncomingMergingRun tr hfs hbio (Paths.activeDir root) uc
1082-
conf resolve reg
1083-
mergePolicy mergeType ln rs
1084-
-- The runs will end up inside the merging run, with fresh references.
1085-
-- The original references can be released (but only on the happy path).
1086-
V.forM_ rs $ \r -> delayedCommit reg (releaseRef r)
1087-
case confMergeSchedule of
1088-
Incremental -> pure ()
1089-
OneShot -> immediatelyCompleteIncomingRun tr conf ln ir
1090-
return ir
1064+
newMerge mergePolicy mergeType ln rs = do
1065+
ir <- withRollback reg
1066+
(case V.uncons rs of
1067+
Just (r, rest) | V.null rest
1068+
-> newIncomingSingleRun tr ln r
1069+
_ -> newIncomingMergingRun tr hfs hbio
1070+
(Paths.activeDir root) uc
1071+
conf resolve mergePolicy mergeType
1072+
ln rs)
1073+
releaseIncomingRun
1074+
-- The runs will end up inside the incoming/merging run, with fresh
1075+
-- references (since newIncoming* will make duplicates).
1076+
-- The original references must be released (but only on the happy path).
1077+
V.forM_ rs $ \r -> delayedCommit reg (releaseRef r)
1078+
case confMergeSchedule of
1079+
Incremental -> pure ()
1080+
OneShot -> immediatelyCompleteIncomingRun tr conf ln ir
1081+
return ir
10911082

10921083
-- | We use levelling on the last level, unless that is also the first level.
10931084
mergePolicyForLevel ::

src/Database/LSMTree/Internal/Snapshot.hs

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import Control.Concurrent.Class.MonadSTM (MonadSTM)
2929
import Control.DeepSeq (NFData (..))
3030
import Control.Monad (void)
3131
import Control.Monad.Class.MonadST (MonadST)
32-
import Control.Monad.Class.MonadThrow (MonadMask)
32+
import Control.Monad.Class.MonadThrow (MonadMask, bracketOnError)
3333
import Control.Monad.Primitive (PrimMonad)
3434
import Control.RefCount
3535
import Control.Tracer (Tracer, nullTracer)
@@ -471,34 +471,37 @@ fromSnapLevels reg hfs hbio conf uc resolve dir (SnapLevels levels) =
471471
tr = nullTracer
472472

473473
fromSnapLevel :: LevelNo -> SnapLevel (Ref (Run m h)) -> m (Level m h)
474-
fromSnapLevel ln SnapLevel{..} = do
475-
incomingRun <- fromSnapIncomingRun ln snapIncoming
476-
residentRuns <- V.mapM dupRun snapResidentRuns
474+
fromSnapLevel ln SnapLevel{snapIncoming, snapResidentRuns} = do
475+
incomingRun <- withRollback reg
476+
(fromSnapIncomingRun ln snapIncoming)
477+
releaseIncomingRun
478+
residentRuns <- V.forM snapResidentRuns $ \r ->
479+
withRollback reg
480+
(dupRef r)
481+
releaseRef
477482
pure Level {incomingRun , residentRuns}
478483

479484
fromSnapIncomingRun ::
480485
LevelNo
481486
-> SnapIncomingRun (Ref (Run m h))
482487
-> m (IncomingRun m h)
483488
fromSnapIncomingRun ln (SnapSingleRun run) =
484-
newIncomingSingleRun tr ln =<< dupRun run
485-
486-
fromSnapIncomingRun ln (SnapMergingRun mpfl nr md nc smrs) = do
487-
case smrs of
488-
SnapCompletedMerge r ->
489-
newIncomingCompletedMergingRun tr conf reg ln mpfl nr md r
490-
491-
SnapOngoingMerge rs mt -> do
492-
ir <- newIncomingMergingRun tr hfs hbio dir uc
493-
conf resolve reg
494-
mpfl mt ln rs
495-
-- When a snapshot is created, merge progress is lost, so we have to
496-
-- redo merging work here. The MergeCredits in SnapMergingRun tracks
497-
-- how many credits were supplied before the snapshot was taken.
498-
supplyCreditsIncomingRun conf ln ir nc
499-
return ir
500-
501-
dupRun r = withRollback reg (dupRef r) releaseRef
489+
newIncomingSingleRun tr ln run
490+
491+
fromSnapIncomingRun ln (SnapMergingRun mpfl nr md _nc
492+
(SnapCompletedMerge r)) =
493+
newIncomingCompletedMergingRun tr conf ln mpfl nr md r
494+
495+
fromSnapIncomingRun ln (SnapMergingRun mpfl _nr _md nc
496+
(SnapOngoingMerge rs mt)) = do
497+
bracketOnError (newIncomingMergingRun tr hfs hbio dir uc
498+
conf resolve
499+
mpfl mt ln rs) releaseIncomingRun $ \ir -> do
500+
-- When a snapshot is created, merge progress is lost, so we have to
501+
-- redo merging work here. The MergeCredits in SnapMergingRun tracks
502+
-- how many credits were supplied before the snapshot was taken.
503+
supplyCreditsIncomingRun conf ln ir nc
504+
return ir
502505

503506
{-------------------------------------------------------------------------------
504507
Hard links

0 commit comments

Comments
 (0)