@@ -66,6 +66,7 @@ module Database.LSMTree.Internal (
6666 , duplicate
6767 ) where
6868
69+ import Codec.CBOR.Read
6970import Control.Concurrent.Class.MonadMVar.Strict
7071import Control.Concurrent.Class.MonadSTM (MonadSTM (.. ))
7172import Control.Concurrent.Class.MonadSTM.RWVar (RWVar )
@@ -79,7 +80,6 @@ import Control.Monad.Primitive
7980import Control.TempRegistry
8081import Control.Tracer
8182import Data.Arena (ArenaManager , newArenaManager )
82- import qualified Data.ByteString.Char8 as BSC
8383import Data.Char (isNumber )
8484import Data.Foldable
8585import Data.Functor.Compose (Compose (.. ))
@@ -119,7 +119,6 @@ import qualified System.FS.API as FS
119119import System.FS.API (FsError , FsErrorPath (.. ), FsPath , Handle ,
120120 HasFS )
121121import qualified System.FS.API.Lazy as FS
122- import qualified System.FS.API.Strict as FS
123122import qualified System.FS.BlockIO.API as FS
124123import System.FS.BlockIO.API (HasBlockIO )
125124
@@ -166,6 +165,9 @@ instance NFData (MonoidalCursor m k v) where
166165-------------------------------------------------------------------------------}
167166
168167-- TODO: give this a nicer Show instance.
168+ --
169+ -- TODO: the snapshot-related errors could be put in a separate type, since each
170+ -- gets a SnapshotName.
169171data LSMTreeError =
170172 SessionDirDoesNotExist FsErrorPath
171173 -- | The session directory is already locked
@@ -186,7 +188,15 @@ data LSMTreeError =
186188 | ErrCursorClosed
187189 | ErrSnapshotExists SnapshotName
188190 | ErrSnapshotNotExists SnapshotName
189- | ErrSnapshotWrongType SnapshotName
191+ | ErrSnapshotDeserialiseFailure DeserialiseFailure SnapshotName
192+ | ErrSnapshotWrongTableType
193+ SnapshotName
194+ SnapshotTableType -- ^ Expected type
195+ SnapshotTableType -- ^ Actual type
196+ | ErrSnapshotWrongLabel
197+ SnapshotName
198+ SnapshotLabel -- ^ Expected label
199+ SnapshotLabel -- ^ Actual label
190200 -- | Something went wrong during batch lookups.
191201 | ErrLookup ByteCountDiscrepancy
192202 -- | A 'BlobRef' used with 'retrieveBlobs' was invalid.
@@ -1081,6 +1091,7 @@ readCursorWhile resolve keyIsWanted n Cursor {..} fromEntry = do
10811091 ResolveSerialisedValue
10821092 -> SnapshotName
10831093 -> SnapshotLabel
1094+ -> SnapshotTableType
10841095 -> Table IO h
10851096 -> IO Int #-}
10861097-- | See 'Database.LSMTree.Normal.snapshot''.
@@ -1089,9 +1100,10 @@ snapshot ::
10891100 => ResolveSerialisedValue
10901101 -> SnapshotName
10911102 -> SnapshotLabel
1103+ -> SnapshotTableType
10921104 -> Table m h
10931105 -> m Int
1094- snapshot resolve snap label t = do
1106+ snapshot resolve snap label tableType t = do
10951107 traceWith (tableTracer t) $ TraceSnapshot snap
10961108 let conf = tableConfig t
10971109 withOpenTable t $ \ thEnv -> do
@@ -1129,19 +1141,20 @@ snapshot resolve snap label t = do
11291141 -- consistent.
11301142
11311143 snappedLevels <- snapLevels (tableLevels content)
1132- let snapContents = BSC. pack $ show ( label, snappedLevels, tableConfig t)
1144+ let snapContents = encodeSnapshotMetaData ( SnapshotMetaData label tableType ( tableConfig t) snappedLevels )
11331145
11341146 FS. withFile
11351147 (tableHasFS thEnv)
11361148 snapPath
11371149 (FS. WriteMode FS. MustBeNew ) $ \ h ->
1138- void $ FS. hPutAllStrict (tableHasFS thEnv) h snapContents
1150+ void $ FS. hPutAll (tableHasFS thEnv) h snapContents
11391151
11401152 pure $! numSnapRuns snappedLevels
11411153
11421154{-# SPECIALISE open ::
11431155 Session IO h
11441156 -> SnapshotLabel
1157+ -> SnapshotTableType
11451158 -> TableConfigOverride
11461159 -> SnapshotName
11471160 -> ResolveSerialisedValue
@@ -1151,11 +1164,12 @@ open ::
11511164 (MonadFix m , MonadMask m , MonadMVar m , MonadST m , MonadSTM m )
11521165 => Session m h
11531166 -> SnapshotLabel -- ^ Expected label
1167+ -> SnapshotTableType -- ^ Expected table type
11541168 -> TableConfigOverride -- ^ Optional config override
11551169 -> SnapshotName
11561170 -> ResolveSerialisedValue
11571171 -> m (Table m h )
1158- open sesh label override snap resolve = do
1172+ open sesh label tableType override snap resolve = do
11591173 traceWith (sessionTracer sesh) $ TraceOpenSnapshot snap override
11601174 withOpenSession sesh $ \ seshEnv -> do
11611175 withTempRegistry $ \ reg -> do
@@ -1169,8 +1183,18 @@ open sesh label override snap resolve = do
11691183 snapPath
11701184 FS. ReadMode $ \ h ->
11711185 FS. hGetAll (sessionHasFS seshEnv) h
1172- let (label', snappedLevels, conf) = read $ BSC. unpack $ BSC. toStrict $ bs
1173- unless (label == label') $ throwIO (ErrSnapshotWrongType snap)
1186+
1187+ snapMetaData <- case decodeSnapshotMetaData bs of
1188+ Left e -> throwIO (ErrSnapshotDeserialiseFailure e snap)
1189+ Right x -> pure x
1190+ let SnapshotMetaData label' tableType' conf snappedLevels = snapMetaData
1191+
1192+ unless (tableType == tableType') $
1193+ throwIO (ErrSnapshotWrongTableType snap tableType tableType')
1194+
1195+ unless (label == label') $
1196+ throwIO (ErrSnapshotWrongLabel snap label label')
1197+
11741198 let conf' = applyOverride override conf
11751199 am <- newArenaManager
11761200 blobpath <- Paths. tableBlobPath (sessionRoot seshEnv) <$>
0 commit comments