@@ -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
@@ -186,7 +185,15 @@ data LSMTreeError =
186185 | ErrCursorClosed
187186 | ErrSnapshotExists SnapshotName
188187 | ErrSnapshotNotExists SnapshotName
189- | ErrSnapshotWrongType SnapshotName
188+ | ErrSnapshotDeserialiseFailure DeserialiseFailure SnapshotName
189+ | ErrSnapshotWrongTableType
190+ SnapshotName
191+ SnapshotTableType -- ^ Expected type
192+ SnapshotTableType -- ^ Actual type
193+ | ErrSnapshotWrongLabel
194+ SnapshotName
195+ SnapshotLabel -- ^ Expected label
196+ SnapshotLabel -- ^ Actual label
190197 -- | Something went wrong during batch lookups.
191198 | ErrLookup ByteCountDiscrepancy
192199 -- | A 'BlobRef' used with 'retrieveBlobs' was invalid.
@@ -1081,6 +1088,7 @@ readCursorWhile resolve keyIsWanted n Cursor {..} fromEntry = do
10811088 ResolveSerialisedValue
10821089 -> SnapshotName
10831090 -> SnapshotLabel
1091+ -> SnapshotTableType
10841092 -> Table IO h
10851093 -> IO Int #-}
10861094-- | See 'Database.LSMTree.Normal.snapshot''.
@@ -1089,9 +1097,10 @@ snapshot ::
10891097 => ResolveSerialisedValue
10901098 -> SnapshotName
10911099 -> SnapshotLabel
1100+ -> SnapshotTableType
10921101 -> Table m h
10931102 -> m Int
1094- snapshot resolve snap label t = do
1103+ snapshot resolve snap label tableType t = do
10951104 traceWith (tableTracer t) $ TraceSnapshot snap
10961105 let conf = tableConfig t
10971106 withOpenTable t $ \ thEnv -> do
@@ -1129,19 +1138,20 @@ snapshot resolve snap label t = do
11291138 -- consistent.
11301139
11311140 snappedLevels <- snapLevels (tableLevels content)
1132- let snapContents = BSC. pack $ show ( label, snappedLevels, tableConfig t)
1141+ let snapContents = encodeSnapshotMetaData ( SnapshotMetaData label tableType ( tableConfig t) snappedLevels )
11331142
11341143 FS. withFile
11351144 (tableHasFS thEnv)
11361145 snapPath
11371146 (FS. WriteMode FS. MustBeNew ) $ \ h ->
1138- void $ FS. hPutAllStrict (tableHasFS thEnv) h snapContents
1147+ void $ FS. hPutAll (tableHasFS thEnv) h snapContents
11391148
11401149 pure $! numSnapRuns snappedLevels
11411150
11421151{-# SPECIALISE open ::
11431152 Session IO h
11441153 -> SnapshotLabel
1154+ -> SnapshotTableType
11451155 -> TableConfigOverride
11461156 -> SnapshotName
11471157 -> ResolveSerialisedValue
@@ -1151,11 +1161,12 @@ open ::
11511161 (MonadFix m , MonadMask m , MonadMVar m , MonadST m , MonadSTM m )
11521162 => Session m h
11531163 -> SnapshotLabel -- ^ Expected label
1164+ -> SnapshotTableType -- ^ Expected table type
11541165 -> TableConfigOverride -- ^ Optional config override
11551166 -> SnapshotName
11561167 -> ResolveSerialisedValue
11571168 -> m (Table m h )
1158- open sesh label override snap resolve = do
1169+ open sesh label tableType override snap resolve = do
11591170 traceWith (sessionTracer sesh) $ TraceOpenSnapshot snap override
11601171 withOpenSession sesh $ \ seshEnv -> do
11611172 withTempRegistry $ \ reg -> do
@@ -1169,8 +1180,18 @@ open sesh label override snap resolve = do
11691180 snapPath
11701181 FS. ReadMode $ \ h ->
11711182 FS. hGetAll (sessionHasFS seshEnv) h
1172- let (label', snappedLevels, conf) = read $ BSC. unpack $ BSC. toStrict $ bs
1173- unless (label == label') $ throwIO (ErrSnapshotWrongType snap)
1183+
1184+ snapMetaData <- case decodeSnapshotMetaData bs of
1185+ Left e -> throwIO (ErrSnapshotDeserialiseFailure e snap)
1186+ Right x -> pure x
1187+ let SnapshotMetaData label' tableType' conf snappedLevels = snapMetaData
1188+
1189+ unless (tableType == tableType') $
1190+ throwIO (ErrSnapshotWrongTableType snap tableType tableType')
1191+
1192+ unless (label == label') $
1193+ throwIO (ErrSnapshotWrongLabel snap label label')
1194+
11741195 let conf' = applyOverride override conf
11751196 am <- newArenaManager
11761197 blobpath <- Paths. tableBlobPath (sessionRoot seshEnv) <$>
0 commit comments