Skip to content

Commit 6904297

Browse files
authored
Merge pull request #473 from IntersectMBO/jdral/revisit-snapshot-label
Revisit snapshot labels
2 parents 1559cc8 + a2a03c6 commit 6904297

File tree

15 files changed

+164
-160
lines changed

15 files changed

+164
-160
lines changed

bench/macro/lsm-tree-bench-wp8.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ type K = BS.ShortByteString
8787
type V = BS.ShortByteString
8888
type B = Void
8989

90-
instance LSM.Labellable (K, V, B) where
91-
makeSnapshotLabel _ = "K V B"
90+
label :: LSM.SnapshotLabel
91+
label = LSM.SnapshotLabel "K V B"
9292

9393
-- | We generate 34 byte keys by using a PRNG to extend a word64 to 32 bytes
9494
-- and then appending two constant bytes. This corresponds relatively closely
@@ -418,7 +418,7 @@ doSetup' gopts opts = do
418418
| i <- NE.toList batch
419419
]
420420

421-
LSM.createSnapshot name tbl
421+
LSM.createSnapshot label name tbl
422422

423423
-------------------------------------------------------------------------------
424424
-- dry-run
@@ -577,7 +577,7 @@ doRun gopts opts = do
577577
-- necessary for testing to load the whole snapshot).
578578
tbl <- if check opts
579579
then LSM.new @IO @K @V @B session (mkTableConfigRun gopts LSM.defaultTableConfig)
580-
else LSM.openSnapshot @IO @K @V @B session (mkTableConfigOverride gopts) name
580+
else LSM.openSnapshot @IO @K @V @B session (mkTableConfigOverride gopts) label name
581581

582582
-- In checking mode, compare each output against a pure reference.
583583
checkvar <- newIORef $ pureReference

src/Database/LSMTree.hs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ module Database.LSMTree (
6666
-- * Durability (snapshots)
6767
, SnapshotName
6868
, Common.mkSnapshotName
69-
, Common.Labellable (..)
69+
, Common.SnapshotLabel (..)
7070
, createSnapshot
7171
, openSnapshot
7272
, Common.TableConfigOverride
@@ -464,42 +464,40 @@ retrieveBlobs (Internal.Session' (sesh :: Internal.Session m h)) refs =
464464
-------------------------------------------------------------------------------}
465465

466466
{-# SPECIALISE createSnapshot ::
467-
(Common.Labellable (k, v, blob), ResolveValue v)
468-
=> SnapshotName
467+
ResolveValue v
468+
=> Common.SnapshotLabel
469+
-> SnapshotName
469470
-> Table IO k v blob
470471
-> IO () #-}
471472
createSnapshot :: forall m k v blob.
472473
( IOLike m
473-
, Common.Labellable (k, v, blob)
474474
, ResolveValue v
475475
)
476-
=> SnapshotName
476+
=> Common.SnapshotLabel
477+
-> SnapshotName
477478
-> Table m k v blob
478479
-> m ()
479-
createSnapshot snap (Internal.Table' t) =
480+
createSnapshot label snap (Internal.Table' t) =
480481
void $ Internal.createSnapshot (resolve (Proxy @v)) snap label Internal.SnapFullTable t
481-
where
482-
label = Internal.SnapshotLabel $ Common.makeSnapshotLabel (Proxy @(k, v, blob))
483482

484483
{-# SPECIALISE openSnapshot ::
485-
(Common.Labellable (k, v, blob), ResolveValue v)
484+
ResolveValue v
486485
=> Session IO
487486
-> Common.TableConfigOverride
487+
-> Common.SnapshotLabel
488488
-> SnapshotName
489489
-> IO (Table IO k v blob ) #-}
490490
openSnapshot :: forall m k v blob.
491491
( IOLike m
492-
, Common.Labellable (k, v, blob)
493492
, ResolveValue v
494493
)
495494
=> Session m
496495
-> Common.TableConfigOverride -- ^ Optional config override
496+
-> Common.SnapshotLabel
497497
-> SnapshotName
498498
-> m (Table m k v blob)
499-
openSnapshot (Internal.Session' sesh) override snap =
499+
openSnapshot (Internal.Session' sesh) override label snap =
500500
Internal.Table' <$!> Internal.openSnapshot sesh label Internal.SnapFullTable override snap (resolve (Proxy @v))
501-
where
502-
label = Internal.SnapshotLabel $ Common.makeSnapshotLabel (Proxy @(k, v, blob))
503501

504502
{-------------------------------------------------------------------------------
505503
Mutiple writable tables

src/Database/LSMTree/Common.hs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ module Database.LSMTree.Common (
1818
-- * Small types
1919
, Internal.Range (..)
2020
-- * Snapshots
21-
, Labellable (..)
21+
, SnapshotLabel (..)
2222
, deleteSnapshot
2323
, listSnapshots
2424
-- ** Snapshot names
@@ -52,8 +52,7 @@ import Control.Monad.Class.MonadThrow
5252
import Control.Monad.Primitive (PrimMonad)
5353
import Control.Tracer (Tracer)
5454
import Data.Kind (Type)
55-
import Data.Text (Text)
56-
import Data.Typeable (Proxy, Typeable)
55+
import Data.Typeable (Typeable)
5756
import qualified Database.LSMTree.Internal as Internal
5857
import qualified Database.LSMTree.Internal.BlobRef as Internal
5958
import qualified Database.LSMTree.Internal.Config as Internal
@@ -62,6 +61,7 @@ import qualified Database.LSMTree.Internal.MergeSchedule as Internal
6261
import qualified Database.LSMTree.Internal.Paths as Internal
6362
import qualified Database.LSMTree.Internal.Range as Internal
6463
import Database.LSMTree.Internal.Serialise.Class
64+
import Database.LSMTree.Internal.Snapshot (SnapshotLabel (..))
6565
import System.FS.API (FsPath, HasFS)
6666
import System.FS.BlockIO.API (HasBlockIO)
6767
import System.FS.IO (HandleIO)
@@ -186,13 +186,6 @@ closeSession (Internal.Session' sesh) = Internal.closeSession sesh
186186
Snapshots
187187
-------------------------------------------------------------------------------}
188188

189-
-- TODO: we might replace this with some other form of dynamic checking of
190-
-- snapshot types. For example, we could ask the user to produce a label/version
191-
-- directly instead, instead of deriving the label from a type using this type
192-
-- class.
193-
class Labellable a where
194-
makeSnapshotLabel :: Proxy a -> Text
195-
196189
{-# SPECIALISE deleteSnapshot ::
197190
Session IO
198191
-> Internal.SnapshotName

src/Database/LSMTree/Internal/Snapshot.hs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,12 @@ import System.FS.BlockIO.API (HasBlockIO)
5757
Snapshot metadata
5858
-------------------------------------------------------------------------------}
5959

60-
-- | Custom text to include in a snapshot file
60+
-- | Custom, user-supplied text that is included in the metadata.
61+
--
62+
-- The main use case for a 'SnapshotLabel' is for the user to supply textual
63+
-- information about the key\/value\/blob type for the table that corresponds to
64+
-- the snapshot. This information is used to dynamically check that a snapshot
65+
-- is opened at the correct key\/value\/blob type.
6166
newtype SnapshotLabel = SnapshotLabel Text
6267
deriving stock (Show, Eq)
6368

@@ -66,17 +71,11 @@ data SnapshotTableType = SnapNormalTable | SnapMonoidalTable | SnapFullTable
6671
deriving stock (Show, Eq)
6772

6873
data SnapshotMetaData = SnapshotMetaData {
69-
-- | Custom, user-supplied text that is included in the metadata.
70-
--
71-
-- The main use case for this field is for the user to supply textual
72-
-- information about the key\/value\/blob type for the table that
73-
-- corresponds to the snapshot. This information can then be used to
74-
-- dynamically check that a snapshot is opened at the correct
75-
-- key\/value\/blob type.
74+
-- | See 'SnapshotLabel'.
7675
--
7776
-- One could argue that the 'SnapshotName' could be used to to hold this
78-
-- information, but the file name of snapshot metadata is not guarded by a
79-
-- checksum, wherease the contents of the file are. Therefore using the
77+
-- type information, but the file name of snapshot metadata is not guarded
78+
-- by a checksum, wherease the contents of the file are. Therefore using the
8079
-- 'SnapshotLabel' is safer.
8180
snapMetaLabel :: !SnapshotLabel
8281
-- | Whether a table is normal or monoidal.

src/Database/LSMTree/Monoidal.hs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ module Database.LSMTree.Monoidal (
8383
-- * Durability (snapshots)
8484
, SnapshotName
8585
, Common.mkSnapshotName
86-
, Common.Labellable (..)
86+
, Common.SnapshotLabel (..)
8787
, createSnapshot
8888
, openSnapshot
8989
, Common.TableConfigOverride
@@ -517,8 +517,9 @@ mupserts t = updates t . fmap (second Mupsert)
517517
-------------------------------------------------------------------------------}
518518

519519
{-# SPECIALISE createSnapshot ::
520-
(ResolveValue v, Common.Labellable (k, v))
521-
=> SnapshotName
520+
ResolveValue v
521+
=> Common.SnapshotLabel
522+
-> SnapshotName
522523
-> Table IO k v
523524
-> IO () #-}
524525
-- | Make the current value of a table durable on-disk by taking a snapshot and
@@ -546,20 +547,19 @@ mupserts t = updates t . fmap (second Mupsert)
546547
createSnapshot :: forall m k v.
547548
( IOLike m
548549
, ResolveValue v
549-
, Common.Labellable (k, v)
550550
)
551-
=> SnapshotName
551+
=> Common.SnapshotLabel
552+
-> SnapshotName
552553
-> Table m k v
553554
-> m ()
554-
createSnapshot snap (Internal.MonoidalTable t) =
555+
createSnapshot label snap (Internal.MonoidalTable t) =
555556
Internal.createSnapshot (resolve @v Proxy) snap label Internal.SnapMonoidalTable t
556-
where
557-
label = Internal.SnapshotLabel $ Common.makeSnapshotLabel (Proxy @(k, v))
558557

559558
{-# SPECIALISE openSnapshot ::
560-
(ResolveValue v, Common.Labellable (k, v))
559+
ResolveValue v
561560
=> Session IO
562561
-> Common.TableConfigOverride
562+
-> Common.SnapshotLabel
563563
-> SnapshotName
564564
-> IO (Table IO k v) #-}
565565
-- | Open a table from a named snapshot, returning a new table.
@@ -583,13 +583,13 @@ createSnapshot snap (Internal.MonoidalTable t) =
583583
openSnapshot :: forall m k v.
584584
( IOLike m
585585
, ResolveValue v
586-
, Common.Labellable (k, v)
587586
)
588587
=> Session m
589588
-> Common.TableConfigOverride -- ^ Optional config override
589+
-> Common.SnapshotLabel
590590
-> SnapshotName
591591
-> m (Table m k v)
592-
openSnapshot (Internal.Session' sesh) override snap =
592+
openSnapshot (Internal.Session' sesh) override label snap =
593593
Internal.MonoidalTable <$>
594594
Internal.openSnapshot
595595
sesh
@@ -598,8 +598,6 @@ openSnapshot (Internal.Session' sesh) override snap =
598598
override
599599
snap
600600
(resolve @v Proxy)
601-
where
602-
label = Internal.SnapshotLabel $ Common.makeSnapshotLabel (Proxy @(k, v))
603601

604602
{-------------------------------------------------------------------------------
605603
Multiple writable tables

src/Database/LSMTree/Normal.hs

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ module Database.LSMTree.Normal (
8484
-- * Durability (snapshots)
8585
, SnapshotName
8686
, Common.mkSnapshotName
87-
, Common.Labellable (..)
87+
, Common.SnapshotLabel (..)
8888
, createSnapshot
8989
, openSnapshot
9090
, Common.TableConfigOverride
@@ -115,7 +115,7 @@ import Control.Exception (throw)
115115
import Control.Monad
116116
import Data.Bifunctor (Bifunctor (..))
117117
import Data.Kind (Type)
118-
import Data.Typeable (Proxy (..), eqT, type (:~:) (Refl))
118+
import Data.Typeable (eqT, type (:~:) (Refl))
119119
import qualified Data.Vector as V
120120
import Database.LSMTree.Common (BlobRef (BlobRef), IOLike, Range (..),
121121
SerialiseKey, SerialiseValue, Session, SnapshotName,
@@ -635,8 +635,8 @@ retrieveBlobs (Internal.Session' (sesh :: Internal.Session m h)) refs =
635635
-------------------------------------------------------------------------------}
636636

637637
{-# SPECIALISE createSnapshot ::
638-
Common.Labellable (k, v, blob)
639-
=> SnapshotName
638+
Common.SnapshotLabel
639+
-> SnapshotName
640640
-> Table IO k v blob
641641
-> IO () #-}
642642
-- | Make the current value of a table durable on-disk by taking a snapshot and
@@ -647,6 +647,11 @@ retrieveBlobs (Internal.Session' (sesh :: Internal.Session m h)) refs =
647647
-- via that name. Names are strings and the management of the names is up to
648648
-- the user of the library.
649649
--
650+
-- Snapshot labels are included in the snapshot metadata when a snapshot is
651+
-- created. Labels are text and the management of the labels is up to the user
652+
-- of the library. Labels assigns a dynamically checked "type" to a snapshot.
653+
-- See 'Common.SnapshotLabel' for more information.
654+
--
650655
-- The names correspond to disk files, which imposes some constraints on length
651656
-- and what characters can be used.
652657
--
@@ -661,25 +666,26 @@ retrieveBlobs (Internal.Session' (sesh :: Internal.Session m h)) refs =
661666
-- * It is safe to concurrently make snapshots from any table, provided that
662667
-- the snapshot names are distinct (otherwise this would be a race).
663668
createSnapshot :: forall m k v blob.
664-
( IOLike m
665-
, Common.Labellable (k, v, blob)
666-
)
667-
=> SnapshotName
669+
IOLike m
670+
=> Common.SnapshotLabel
671+
-> SnapshotName
668672
-> Table m k v blob
669673
-> m ()
670-
createSnapshot snap (Internal.NormalTable t) =
674+
createSnapshot label snap (Internal.NormalTable t) =
671675
Internal.createSnapshot const snap label Internal.SnapNormalTable t
672-
where
673-
label = Internal.SnapshotLabel $ Common.makeSnapshotLabel (Proxy @(k, v, blob))
674676

675677
{-# SPECIALISE openSnapshot ::
676-
Common.Labellable (k, v, blob)
677-
=> Session IO
678+
Session IO
678679
-> Common.TableConfigOverride
680+
-> Common.SnapshotLabel
679681
-> SnapshotName
680682
-> IO (Table IO k v blob ) #-}
681683
-- | Open a table from a named snapshot, returning a new table.
682684
--
685+
-- This function requires passing in an expected label that will be checked
686+
-- against the label that was included in the snapshot metadata. If there is a
687+
-- mismatch, an exception is thrown.
688+
--
683689
-- NOTE: close tables using 'close' as soon as they are
684690
-- unused.
685691
--
@@ -697,14 +703,13 @@ createSnapshot snap (Internal.NormalTable t) =
697703
-- 'openSnapshot' \@IO \@Bool \@Bool \@Bool session "intTable"
698704
-- @
699705
openSnapshot :: forall m k v blob.
700-
( IOLike m
701-
, Common.Labellable (k, v, blob)
702-
)
706+
IOLike m
703707
=> Session m
704708
-> Common.TableConfigOverride -- ^ Optional config override
709+
-> Common.SnapshotLabel
705710
-> SnapshotName
706711
-> m (Table m k v blob)
707-
openSnapshot (Internal.Session' sesh) override snap =
712+
openSnapshot (Internal.Session' sesh) override label snap =
708713
Internal.NormalTable <$!>
709714
Internal.openSnapshot
710715
sesh
@@ -713,8 +718,6 @@ openSnapshot (Internal.Session' sesh) override snap =
713718
override
714719
snap
715720
const
716-
where
717-
label = Internal.SnapshotLabel $ Common.makeSnapshotLabel (Proxy @(k, v, blob))
718721

719722
{-------------------------------------------------------------------------------
720723
Mutiple writable tables

0 commit comments

Comments
 (0)