1919module ScheduledMerges (
2020 -- * Main API
2121 LSM ,
22- Key , Value , Blob ,
22+ Key ( K ) , Value ( V ), resolveValue , Blob ( B ) ,
2323 new ,
2424 LookupResult (.. ),
2525 lookup , lookups ,
2626 Update (.. ),
2727 update , updates ,
2828 insert , inserts ,
2929 delete , deletes ,
30+ mupsert , mupserts ,
3031 supply ,
3132 duplicate ,
3233
@@ -52,8 +53,6 @@ import Control.Monad.ST
5253import Control.Tracer (Tracer , contramap , traceWith )
5354import GHC.Stack (HasCallStack , callStack )
5455
55- import Database.LSMTree.Normal (LookupResult (.. ), Update (.. ))
56-
5756
5857data LSM s = LSMHandle ! (STRef s Counter )
5958 ! (STRef s (LSMContent s ))
@@ -122,12 +121,20 @@ runSize = Map.size
122121bufferSize :: Buffer -> Int
123122bufferSize = Map. size
124123
125- type Op = Update Value Blob
124+ type Op = Update Value Blob
125+
126+ newtype Key = K Int
127+ deriving stock (Eq , Ord , Show )
128+ deriving newtype Enum
129+
130+ newtype Value = V Int
131+ deriving stock (Eq , Show )
126132
127- type Key = Int
128- type Value = Int
129- type Blob = Int
133+ resolveValue :: Value -> Value -> Value
134+ resolveValue (V x) (V y) = V (x + y)
130135
136+ newtype Blob = B Int
137+ deriving stock (Eq , Show )
131138
132139-- | The size of the 4 tiering runs at each level are allowed to be:
133140-- @4^(level-1) < size <= 4^level@
@@ -321,13 +328,23 @@ newMerge tr level mergepolicy mergelast rs = do
321328 MergeLastLevel -> lastLevelMerge (mergek rs)
322329
323330mergek :: [Run ] -> Run
324- mergek = Map. unions
331+ mergek = Map. unionsWith combine
332+
333+ combine :: Op -> Op -> Op
334+ combine x y = case x of
335+ Insert {} -> x
336+ Delete {} -> x
337+ Mupsert v -> case y of
338+ Insert v' mb -> Insert (resolveValue v v') mb
339+ Delete -> Insert v Nothing
340+ Mupsert v' -> Mupsert (resolveValue v v')
325341
326342lastLevelMerge :: Run -> Run
327- lastLevelMerge = Map. filter isInsert
343+ lastLevelMerge = Map. filter ( not . isDelete)
328344 where
329- isInsert Insert {} = True
330- isInsert Delete = False
345+ isDelete Delete = True
346+ isDelete Insert {} = False
347+ isDelete Mupsert {} = False
331348
332349expectCompletedMerge :: HasCallStack
333350 => Tracer (ST s ) EventDetail
@@ -421,18 +438,29 @@ new = do
421438 lsm <- newSTRef (LSMContent Map. empty [] )
422439 return (LSMHandle c lsm)
423440
441+ inserts :: Tracer (ST s ) Event -> LSM s -> [(Key , Value , Maybe Blob )] -> ST s ()
442+ inserts tr lsm kvbs = updates tr lsm [ (k, Insert v b) | (k, v, b) <- kvbs ]
424443
425- inserts :: Tracer (ST s ) Event -> LSM s -> [( Key , Value )] -> ST s ()
426- inserts tr lsm kvs = updates tr lsm [ (k, Insert v Nothing ) | (k,v) <- kvs ]
444+ insert :: Tracer (ST s ) Event -> LSM s -> Key -> Value -> Maybe Blob -> ST s ()
445+ insert tr lsm k v b = update tr lsm k ( Insert v b)
427446
428- insert :: Tracer (ST s ) Event -> LSM s -> Key -> Value -> ST s ()
429- insert tr lsm k v = update tr lsm k ( Insert v Nothing )
447+ deletes :: Tracer (ST s ) Event -> LSM s -> [ Key ] -> ST s ()
448+ deletes tr lsm ks = updates tr lsm [ (k, Delete ) | k <- ks ]
430449
431450delete :: Tracer (ST s ) Event -> LSM s -> Key -> ST s ()
432451delete tr lsm k = update tr lsm k Delete
433452
434- deletes :: Tracer (ST s ) Event -> LSM s -> [Key ] -> ST s ()
435- deletes tr lsm ks = updates tr lsm [ (k, Delete ) | k <- ks ]
453+ mupserts :: Tracer (ST s ) Event -> LSM s -> [(Key , Value )] -> ST s ()
454+ mupserts tr lsm kvbs = updates tr lsm [ (k, Mupsert v) | (k, v) <- kvbs ]
455+
456+ mupsert :: Tracer (ST s ) Event -> LSM s -> Key -> Value -> ST s ()
457+ mupsert tr lsm k v = update tr lsm k (Mupsert v)
458+
459+ data Update v b =
460+ Insert ! v ! (Maybe b )
461+ | Mupsert ! v
462+ | Delete
463+ deriving stock (Eq , Show )
436464
437465updates :: Tracer (ST s ) Event -> LSM s -> [(Key , Op )] -> ST s ()
438466updates tr lsm = mapM_ (uncurry (update tr lsm))
@@ -444,7 +472,7 @@ update tr (LSMHandle scr lsmr) k op = do
444472 modifySTRef' scr (+ 1 )
445473 supplyCredits 1 ls
446474 invariant ls
447- let wb' = Map. insert k op wb
475+ let wb' = Map. insertWith combine k op wb
448476 if bufferSize wb' >= maxBufferSize
449477 then do
450478 ls' <- increment tr sc (bufferToRun wb') ls
@@ -460,21 +488,32 @@ supply (LSMHandle scr lsmr) credits = do
460488 supplyCredits credits ls
461489 invariant ls
462490
491+ data LookupResult v b =
492+ NotFound
493+ | Found ! v ! (Maybe b )
494+ deriving stock (Eq , Show )
495+
463496lookups :: LSM s -> [Key ] -> ST s [(Key , LookupResult Value Blob )]
464- lookups lsm = mapM (\ k -> (k,) <$> lookup lsm k)
497+ lookups lsm ks = do
498+ runs <- concat <$> allLayers lsm
499+ return $ map (\ k -> (k, doLookup k runs)) ks
465500
466501lookup :: LSM s -> Key -> ST s (LookupResult Value Blob )
467502lookup lsm k = do
468- rss <- allLayers lsm
469- return $!
470- foldr (\ lookures continue ->
471- case lookures of
472- Nothing -> continue
473- Just (Insert v Nothing ) -> Found v
474- Just (Insert v (Just b)) -> FoundWithBlob v b
475- Just Delete -> NotFound )
476- NotFound
477- [ Map. lookup k r | rs <- rss, r <- rs ]
503+ runs <- concat <$> allLayers lsm
504+ return $ doLookup k runs
505+
506+ doLookup :: Key -> [Run ] -> LookupResult Value Blob
507+ doLookup k =
508+ foldr (\ run continue ->
509+ case Map. lookup k run of
510+ Nothing -> continue
511+ Just (Insert v mb) -> Found v mb
512+ Just Delete -> NotFound
513+ Just (Mupsert v) -> case continue of
514+ NotFound -> Found v Nothing
515+ Found v' mb -> Found (resolveValue v v') mb)
516+ NotFound
478517
479518bufferToRun :: Buffer -> Run
480519bufferToRun = id
@@ -615,7 +654,6 @@ duplicate (LSMHandle _scr lsmr) = do
615654 -- it's that simple here, because we share all the pure value and all the
616655 -- STRefs and there's no ref counting to be done
617656
618-
619657-------------------------------------------------------------------------------
620658-- Measurements
621659--
@@ -640,12 +678,13 @@ flattenIncomingRun (Merging (MergingRun _ _ mr)) = do
640678 CompletedMerge r -> return [r]
641679 OngoingMerge _ rs _ -> return rs
642680
643- logicalValue :: LSM s -> ST s (Map Key Value )
644- logicalValue = fmap (Map. mapMaybe justInsert . Map. unions . concat )
681+ logicalValue :: LSM s -> ST s (Map Key ( Value , Maybe Blob ) )
682+ logicalValue = fmap (Map. mapMaybe justInsert . Map. unionsWith combine . concat )
645683 . allLayers
646684 where
647- justInsert (Insert v _ ) = Just v
685+ justInsert (Insert v b ) = Just (v, b)
648686 justInsert Delete = Nothing
687+ justInsert (Mupsert v) = Just (v, Nothing )
649688
650689dumpRepresentation :: LSM s
651690 -> ST s [(Maybe (MergePolicy , MergeLastLevel , MergingRunState ), [Run ])]
0 commit comments