11{-# LANGUAGE DataKinds #-}
22
3+ -- | The internal API here is defined in terms of untyped serialised keys,
4+ -- values and blobs. It makes no distinction between normal and monoidal tables,
5+ -- accepting both blobs and mupserts.
6+ --
7+ -- This module mainly deals with concurrency- and exception-safe opening and
8+ -- closing of resources. Any other non-trivial logic should live somewhere else.
9+ --
310module Database.LSMTree.Internal (
411 -- * Existentials
512 Session' (.. )
@@ -84,8 +91,8 @@ import Data.Word (Word64)
8491import Database.LSMTree.Internal.BlobRef (WeakBlobRef (.. ))
8592import qualified Database.LSMTree.Internal.BlobRef as BlobRef
8693import Database.LSMTree.Internal.Config
94+ import qualified Database.LSMTree.Internal.Cursor as Cursor
8795import Database.LSMTree.Internal.Entry (Entry )
88- import qualified Database.LSMTree.Internal.Entry as Entry
8996import Database.LSMTree.Internal.Lookup (ByteCountDiscrepancy ,
9097 ResolveSerialisedValue , lookupsIO )
9198import Database.LSMTree.Internal.MergeSchedule
@@ -96,14 +103,12 @@ import Database.LSMTree.Internal.Range (Range (..))
96103import qualified Database.LSMTree.Internal.RawBytes as RB
97104import Database.LSMTree.Internal.Run (Run )
98105import qualified Database.LSMTree.Internal.Run as Run
99- import qualified Database.LSMTree.Internal.RunReader as Reader
100106import Database.LSMTree.Internal.RunReaders (OffsetKey (.. ))
101107import qualified Database.LSMTree.Internal.RunReaders as Readers
102108import Database.LSMTree.Internal.Serialise (SerialisedBlob (.. ),
103109 SerialisedKey , SerialisedValue )
104110import Database.LSMTree.Internal.Snapshot
105111import Database.LSMTree.Internal.UniqCounter
106- import qualified Database.LSMTree.Internal.Vector as V
107112import qualified Database.LSMTree.Internal.WriteBuffer as WB
108113import qualified Database.LSMTree.Internal.WriteBufferBlobs as WBB
109114import qualified System.FS.API as FS
@@ -855,8 +860,6 @@ retrieveBlobs sesh wrefs =
855860 Cursors
856861-------------------------------------------------------------------------------}
857862
858- -- TODO: Move to a separate Cursors module
859-
860863-- | A read-only view into the table state at the time of cursor creation.
861864--
862865-- For more information, see 'Database.LSMTree.Normal.Cursor'.
@@ -1059,123 +1062,13 @@ readCursorWhile resolve keyIsWanted n Cursor {..} fromEntry = do
10591062 -- a drained cursor will just return an empty vector
10601063 return (state, V. empty)
10611064 Just readers -> do
1062- (vec, hasMore) <- readCursorEntriesWhile resolve keyIsWanted fromEntry readers n
1065+ (vec, hasMore) <- Cursor. readEntriesWhile resolve keyIsWanted fromEntry readers n
10631066 -- if we drained the readers, remove them from the state
10641067 let ! state' = case hasMore of
10651068 Readers. HasMore -> state
10661069 Readers. Drained -> CursorOpen (cursorEnv {cursorReaders = Nothing })
10671070 return (state', vec)
10681071
1069- {-# INLINE readCursorEntriesWhile #-}
1070- {-# SPECIALISE readCursorEntriesWhile :: forall h res.
1071- ResolveSerialisedValue
1072- -> (SerialisedKey -> Bool)
1073- -> (SerialisedKey -> SerialisedValue -> Maybe (WeakBlobRef IO (Handle h)) -> res)
1074- -> Readers.Readers IO h
1075- -> Int
1076- -> IO (V.Vector res, Readers.HasMore) #-}
1077- -- | General notes on the code below:
1078- -- * it is quite similar to the one in Internal.Merge, but different enough
1079- -- that it's probably easier to keep them separate
1080- -- * any function that doesn't take a 'hasMore' argument assumes that the
1081- -- readers have not been drained yet, so we must check before calling them
1082- -- * there is probably opportunity for optimisations
1083- readCursorEntriesWhile :: forall h m res .
1084- (MonadFix m , MonadMask m , MonadST m , MonadSTM m )
1085- => ResolveSerialisedValue
1086- -> (SerialisedKey -> Bool )
1087- -> (SerialisedKey -> SerialisedValue -> Maybe (WeakBlobRef m (Handle h )) -> res )
1088- -> Readers. Readers m h
1089- -> Int
1090- -> m (V. Vector res , Readers. HasMore )
1091- readCursorEntriesWhile resolve keyIsWanted fromEntry readers n =
1092- flip (V. unfoldrNM' n) Readers. HasMore $ \ case
1093- Readers. Drained -> return (Nothing , Readers. Drained )
1094- Readers. HasMore -> readEntryIfWanted
1095- where
1096- -- Produces a result unless the readers have been drained or 'keyIsWanted'
1097- -- returned False.
1098- readEntryIfWanted :: m (Maybe res , Readers. HasMore )
1099- readEntryIfWanted = do
1100- key <- Readers. peekKey readers
1101- if keyIsWanted key then readEntry
1102- else return (Nothing , Readers. HasMore )
1103-
1104- readEntry :: m (Maybe res , Readers. HasMore )
1105- readEntry = do
1106- (key, readerEntry, hasMore) <- Readers. pop readers
1107- let ! entry = Reader. toFullEntry readerEntry
1108- case hasMore of
1109- Readers. Drained -> do
1110- handleResolved key entry Readers. Drained
1111- Readers. HasMore -> do
1112- case entry of
1113- Entry. Mupdate v ->
1114- handleMupdate key v
1115- _ -> do
1116- -- Anything but Mupdate supersedes all previous entries of
1117- -- the same key, so we can simply drop them and are done.
1118- hasMore' <- dropRemaining key
1119- handleResolved key entry hasMore'
1120-
1121- dropRemaining :: SerialisedKey -> m Readers. HasMore
1122- dropRemaining key = do
1123- (_, hasMore) <- Readers. dropWhileKey readers key
1124- return hasMore
1125-
1126- -- Resolve a 'Mupsert' value with the other entries of the same key.
1127- handleMupdate :: SerialisedKey
1128- -> SerialisedValue
1129- -> m (Maybe res , Readers. HasMore )
1130- handleMupdate key v = do
1131- nextKey <- Readers. peekKey readers
1132- if nextKey /= key
1133- then
1134- -- No more entries for same key, done.
1135- handleResolved key (Entry. Mupdate v) Readers. HasMore
1136- else do
1137- (_, nextEntry, hasMore) <- Readers. pop readers
1138- let resolved = Entry. combine resolve (Entry. Mupdate v)
1139- (Reader. toFullEntry nextEntry)
1140- case hasMore of
1141- Readers. HasMore -> case resolved of
1142- Entry. Mupdate v' ->
1143- -- Still a mupsert, keep resolving!
1144- handleMupdate key v'
1145- _ -> do
1146- -- Done with this key, remaining entries are obsolete.
1147- hasMore' <- dropRemaining key
1148- handleResolved key resolved hasMore'
1149- Readers. Drained -> do
1150- handleResolved key resolved Readers. Drained
1151-
1152- -- Once we have a resolved entry, we still have to make sure it's not
1153- -- a 'Delete', since we only want to write values to the result vector.
1154- handleResolved :: SerialisedKey
1155- -> Entry SerialisedValue (BlobRef. BlobRef m (Handle h ))
1156- -> Readers. HasMore
1157- -> m (Maybe res , Readers. HasMore )
1158- handleResolved key entry hasMore =
1159- case toResult key entry of
1160- Just ! res ->
1161- -- Found one resolved value, done.
1162- return (Just res, hasMore)
1163- Nothing ->
1164- -- Resolved value was a Delete, which we don't want to include.
1165- -- So look for another one (unless there are no more entries!).
1166- case hasMore of
1167- Readers. HasMore -> readEntryIfWanted
1168- Readers. Drained -> return (Nothing , Readers. Drained )
1169-
1170- toResult :: SerialisedKey
1171- -> Entry SerialisedValue (BlobRef. BlobRef m (Handle h ))
1172- -> Maybe res
1173- toResult key = \ case
1174- Entry. Insert v -> Just $ fromEntry key v Nothing
1175- Entry. InsertWithBlob v b -> Just $ fromEntry key v (Just (WeakBlobRef b))
1176- Entry. Mupdate v -> Just $ fromEntry key v Nothing
1177- Entry. Delete -> Nothing
1178-
11791072{- ------------------------------------------------------------------------------
11801073 Snapshots
11811074-------------------------------------------------------------------------------}
0 commit comments