@@ -49,7 +49,7 @@ import Data.STRef
4949import Control.Exception (assert )
5050import Control.Monad.ST
5151import Control.Tracer (Tracer , contramap , traceWith )
52- import GHC.Stack (HasCallStack )
52+ import GHC.Stack (HasCallStack , callStack )
5353
5454import Database.LSMTree.Normal (LookupResult (.. ), Update (.. ))
5555
@@ -159,101 +159,103 @@ mergeLastForLevel _ = MergeMidLevel
159159-- | Note that the invariants rely on the fact that levelling is only used on
160160-- the last level.
161161--
162- invariant :: forall s . Levels s -> ST s Bool
162+ invariant :: forall s . Levels s -> ST s ()
163163invariant = go 1
164164 where
165- go :: Int -> [Level s ] -> ST s Bool
166- go ! _ [] = return True
165+ go :: Int -> [Level s ] -> ST s ()
166+ go ! _ [] = return ()
167167
168168 go ! ln (Level mr rs : ls) = do
169169
170170 mrs <- case mr of
171171 SingleRun r -> return (CompletedMerge r)
172172 MergingRun _ _ ref -> readSTRef ref
173173
174- assert (case mr of
175- SingleRun {} -> True
176- MergingRun mp ml _ -> mergePolicyForLevel ln ls == mp
177- && mergeLastForLevel ls == ml)
178- assert (length rs <= 3 ) $
179- assert (expectedRunLengths ln rs ls) $
180- assert (expectedMergingRunLengths ln mr mrs ls) $
181- return ()
174+ assertST $ case mr of
175+ SingleRun {} -> True
176+ MergingRun mp ml _ -> mergePolicyForLevel ln ls == mp
177+ && mergeLastForLevel ls == ml
178+ assertST $ length rs <= 3
179+ expectedRunLengths ln rs ls
180+ expectedMergingRunLengths ln mr mrs ls
182181
183182 go (ln+ 1 ) ls
184183
185184 -- All runs within a level "proper" (as opposed to the incoming runs
186185 -- being merged) should be of the correct size for the level.
187- expectedRunLengths :: Int -> [Run ] -> [Level s ] -> Bool
186+ expectedRunLengths :: Int -> [Run ] -> [Level s ] -> ST s ()
188187 expectedRunLengths ln rs ls =
189188 case mergePolicyForLevel ln ls of
190189 -- Levels using levelling have only one run, and that single run is
191190 -- (almost) always involved in an ongoing merge. Thus there are no
192191 -- other "normal" runs. The exception is when a levelling run becomes
193192 -- too large and is promoted, in that case initially there's no merge,
194193 -- but it is still represented as a 'MergingRun', using 'SingleRun'.
195- MergePolicyLevelling -> null rs
196- MergePolicyTiering -> all (\ r -> tieringRunSizeToLevel r == ln) rs
194+ MergePolicyLevelling -> assertST $ null rs
195+ MergePolicyTiering -> assertST $ all (\ r -> tieringRunSizeToLevel r == ln) rs
197196
198197 -- Incoming runs being merged also need to be of the right size, but the
199198 -- conditions are more complicated.
200199 expectedMergingRunLengths :: Int -> MergingRun s -> MergingRunState
201- -> [Level s ] -> Bool
200+ -> [Level s ] -> ST s ()
202201 expectedMergingRunLengths ln mr mrs ls =
203202 case mergePolicyForLevel ln ls of
204203 MergePolicyLevelling ->
205204 case (mr, mrs) of
206205 -- A single incoming run (which thus didn't need merging) must be
207206 -- of the expected size range already
208207 (SingleRun r, CompletedMerge {}) ->
209- assert ( levellingRunSizeToLevel r == ln) True
208+ assertST $ levellingRunSizeToLevel r == ln
210209
211210 -- A completed merge for levelling can be of almost any size at all!
212211 -- It can be smaller, due to deletions in the last level. But it
213212 -- can't be bigger than would fit into the next level.
214213 (_, CompletedMerge r) ->
215- assert ( levellingRunSizeToLevel r <= ln+ 1 ) True
214+ assertST $ levellingRunSizeToLevel r <= ln+ 1
216215
217216 -- An ongoing merge for levelling should have 4 incoming runs of
218217 -- the right size for the level below, and 1 run from this level,
219218 -- but the run from this level can be of almost any size for the
220219 -- same reasons as above. Although if this is the first merge for
221220 -- a new level, it'll have only 4 runs.
222- (_, OngoingMerge _ rs _) ->
223- assert ( length rs == 4 || length rs == 5 ) True
224- && assert ( all (\ r -> tieringRunSizeToLevel r == ln- 1 ) (take 4 rs)) True
225- && assert ( all (\ r -> levellingRunSizeToLevel r <= ln+ 1 ) (drop 4 rs)) True
221+ (_, OngoingMerge _ rs _) -> do
222+ assertST $ length rs == 4 || length rs == 5
223+ assertST $ all (\ r -> tieringRunSizeToLevel r == ln- 1 ) (take 4 rs)
224+ assertST $ all (\ r -> levellingRunSizeToLevel r <= ln+ 1 ) (drop 4 rs)
226225
227226 MergePolicyTiering ->
228227 case (mr, mrs, mergeLastForLevel ls) of
229228 -- A single incoming run (which thus didn't need merging) must be
230229 -- of the expected size already
231230 (SingleRun r, CompletedMerge {}, _) ->
232- tieringRunSizeToLevel r == ln
231+ assertST $ tieringRunSizeToLevel r == ln
233232
234233 -- A completed last level run can be of almost any smaller size due
235234 -- to deletions, but it can't be bigger than the next level down.
236235 -- Note that tiering on the last level only occurs when there is
237236 -- a single level only.
238- (_, CompletedMerge r, MergeLastLevel ) ->
239- ln == 1
240- && tieringRunSizeToLevel r <= ln+ 1
237+ (_, CompletedMerge r, MergeLastLevel ) -> do
238+ assertST $ ln == 1
239+ assertST $ tieringRunSizeToLevel r <= ln+ 1
241240
242241 -- A completed mid level run is usually of the size for the
243242 -- level it is entering, but can also be one smaller (in which case
244243 -- it'll be held back and merged again).
245244 (_, CompletedMerge r, MergeMidLevel ) ->
246- rln == ln || rln == ln+ 1
247- where
248- rln = tieringRunSizeToLevel r
245+ assertST $ tieringRunSizeToLevel r `elem` [ln, ln+ 1 ]
249246
250247 -- An ongoing merge for tiering should have 4 incoming runs of
251248 -- the right size for the level below, and at most 1 run held back
252249 -- due to being too small (which would thus also be of the size of
253250 -- the level below).
254- (_, OngoingMerge _ rs _, _) ->
255- (length rs == 4 || length rs == 5 )
256- && all (\ r -> tieringRunSizeToLevel r == ln- 1 ) rs
251+ (_, OngoingMerge _ rs _, _) -> do
252+ assertST $ length rs == 4 || length rs == 5
253+ assertST $ all (\ r -> tieringRunSizeToLevel r == ln- 1 ) rs
254+
255+ -- 'callStack' just ensures that the 'HasCallStack' constraint is not redundant
256+ -- when compiling with debug assertions disabled.
257+ assertST :: HasCallStack => Bool -> ST s ()
258+ assertST p = assert p $ return (const () callStack)
257259
258260
259261-------------------------------------------------------------------------------
@@ -423,8 +425,7 @@ supply (LSMHandle scr lsmr) credits = do
423425 LSMContent _ ls <- readSTRef lsmr
424426 modifySTRef' scr (+ 1 )
425427 supplyCredits credits ls
426- ok <- invariant ls
427- assert ok $ return ()
428+ invariant ls
428429
429430lookups :: LSM s -> [Key ] -> ST s [(Key , LookupResult Value Blob )]
430431lookups lsm = mapM (\ k -> (k,) <$> lookup lsm k)
@@ -494,8 +495,8 @@ increment :: forall s. Tracer (ST s) Event
494495 -> Counter -> Run -> Levels s -> ST s (Levels s )
495496increment tr sc = \ r ls -> do
496497 ls' <- go 1 [r] ls
497- ok <- invariant ls'
498- assert ok ( return ls')
498+ invariant ls'
499+ return ls'
499500 where
500501 go :: Int -> [Run ] -> Levels s -> ST s (Levels s )
501502 go ! ln incoming [] = do
0 commit comments