Skip to content

Commit 0036a87

Browse files
authored
Merge pull request #542 from IntersectMBO/wenkokke/corrupt-snapshot-wb
fix: validate checksums in openWriteBuffer
2 parents c202034 + 1cc5921 commit 0036a87

File tree

3 files changed

+30
-19
lines changed

3 files changed

+30
-19
lines changed

src/Database/LSMTree/Internal/Paths.hs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ module Database.LSMTree.Internal.Paths (
3131
, fromChecksumsFile
3232
-- * Checksums for WriteBuffer files
3333
, toChecksumsFileForWriteBufferFiles
34+
, fromChecksumsFileForWriteBufferFiles
3435
-- * ForRunFiles abstraction
3536
, ForKOps (..)
3637
, ForBlob (..)
@@ -51,10 +52,8 @@ module Database.LSMTree.Internal.Paths (
5152

5253
import Control.Applicative (Applicative (..))
5354
import Control.DeepSeq (NFData (..))
54-
import Data.Bifunctor (Bifunctor (..))
5555
import qualified Data.ByteString.Char8 as BS
5656
import Data.Foldable (toList)
57-
import Data.Function ((&))
5857
import qualified Data.Map as Map
5958
import Data.Maybe (fromMaybe)
6059
import Data.String (IsString (..))
@@ -321,10 +320,18 @@ writeBufferFilePathWithExt (WriteBufferFsPaths dir n) ext =
321320
-------------------------------------------------------------------------------}
322321

323322
toChecksumsFileForWriteBufferFiles :: (ForKOps CRC.CRC32C, ForBlob CRC.CRC32C) -> CRC.ChecksumsFile
324-
toChecksumsFileForWriteBufferFiles checksums =
325-
Map.fromList . toList $ checksums & bimap
326-
((toChecksumsFileName writeBufferKOpsExt,) . unForKOps)
327-
((toChecksumsFileName writeBufferBlobExt,) . unForBlob)
323+
toChecksumsFileForWriteBufferFiles (ForKOps kOpsChecksum, ForBlob blobChecksum) =
324+
Map.fromList
325+
[ (toChecksumsFileName writeBufferKOpsExt, kOpsChecksum)
326+
, (toChecksumsFileName writeBufferBlobExt, blobChecksum)
327+
]
328328
where
329-
toChecksumsFileName :: String -> CRC.ChecksumsFileName
330329
toChecksumsFileName = CRC.ChecksumsFileName . BS.pack
330+
331+
fromChecksumsFileForWriteBufferFiles :: CRC.ChecksumsFile -> Either String (ForKOps CRC.CRC32C, ForBlob CRC.CRC32C)
332+
fromChecksumsFileForWriteBufferFiles file = do
333+
(,) <$> (ForKOps <$> fromChecksumFile writeBufferKOpsExt) <*> (ForBlob <$> fromChecksumFile writeBufferBlobExt)
334+
where
335+
fromChecksumFile key =
336+
maybe (Left $ "key not found: " <> key) Right $
337+
Map.lookup (CRC.ChecksumsFileName . fromString $ key) file

src/Database/LSMTree/Internal/Snapshot.hs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,19 @@ import Data.Text (Text)
4141
import Data.Traversable (for)
4242
import qualified Data.Vector as V
4343
import Database.LSMTree.Internal.Config
44+
import Database.LSMTree.Internal.CRC32C (checkCRC)
45+
import qualified Database.LSMTree.Internal.CRC32C as CRC
4446
import Database.LSMTree.Internal.Entry
4547
import Database.LSMTree.Internal.Lookup (ResolveSerialisedValue)
4648
import Database.LSMTree.Internal.Merge (MergeType (..))
4749
import qualified Database.LSMTree.Internal.Merge as Merge
4850
import Database.LSMTree.Internal.MergeSchedule
4951
import Database.LSMTree.Internal.MergingRun (NumRuns (..))
5052
import qualified Database.LSMTree.Internal.MergingRun as MR
51-
import Database.LSMTree.Internal.Paths (ActiveDir (..), ForKOps (..),
52-
NamedSnapshotDir (..), RunFsPaths (..),
53-
WriteBufferFsPaths (..), pathsForRunFiles,
53+
import Database.LSMTree.Internal.Paths (ActiveDir (..), ForBlob (..),
54+
ForKOps (..), NamedSnapshotDir (..), RunFsPaths (..),
55+
WriteBufferFsPaths (..),
56+
fromChecksumsFileForWriteBufferFiles, pathsForRunFiles,
5457
runChecksumsPath, writeBufferBlobPath,
5558
writeBufferChecksumsPath, writeBufferKOpsPath)
5659
import Database.LSMTree.Internal.Run (Run)
@@ -301,6 +304,14 @@ openWriteBuffer ::
301304
-> WriteBufferFsPaths
302305
-> m (WriteBuffer, Ref (WriteBufferBlobs m h))
303306
openWriteBuffer reg resolve hfs hbio uc activeDir snapWriteBufferPaths = do
307+
-- Check the checksums
308+
-- TODO: This reads the blobfile twice: once to check the CRC and once more
309+
-- to copy it from the snapshot directory to the active directory.
310+
(expectedChecksumForKOps, expectedChecksumForBlob) <-
311+
CRC.expectValidFile (writeBufferChecksumsPath snapWriteBufferPaths) . fromChecksumsFileForWriteBufferFiles
312+
=<< CRC.readChecksumsFile hfs (writeBufferChecksumsPath snapWriteBufferPaths)
313+
checkCRC hfs hbio False (unForKOps expectedChecksumForKOps) (writeBufferKOpsPath snapWriteBufferPaths)
314+
checkCRC hfs hbio False (unForBlob expectedChecksumForBlob) (writeBufferBlobPath snapWriteBufferPaths)
304315
-- Copy the write buffer blobs file to the active directory and open it.
305316
activeWriteBufferNumber <- uniqueToInt <$> incrUniqCounter uc
306317
let activeWriteBufferBlobPath =

test/Test/Database/LSMTree/Internal/Snapshot/FS.hs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -211,15 +211,8 @@ prop_flipSnapshotBit
211211
tabFlippedBit = tabulate "Flipped bit" [showPowersOf10 j]
212212
counterFlippedBit = counterexample ("Flipped bit: " ++ show j)
213213

214-
let isUncheckedFile =
215-
path == getNamedSnapshotDir namedSnapDir </> FS.mkFsPath ["0.keyops"]
216-
|| path == getNamedSnapshotDir namedSnapDir </> FS.mkFsPath ["0.blobs"]
217-
|| path == getNamedSnapshotDir namedSnapDir </> FS.mkFsPath ["0.checksums"]
218-
219-
-- TODO: remove once write buffer files have checksum verification
220-
if isUncheckedFile then
221-
pure discard
222-
else if n <= 0 then -- file is empty
214+
-- TODO: check forgotten refs
215+
if n <= 0 then -- file is empty
223216
pure $ tabulate "Result" ["No corruption applied"] True
224217
else do -- file is non-empty
225218

0 commit comments

Comments
 (0)