22{-# OPTIONS_GHC -Wno-orphans #-}
33
44module Database.LSMTree.Internal.Snapshot (
5+ -- * Versioning
6+ SnapshotVersion (.. )
7+ , major
8+ , minor
9+ , fromMajorMinor
10+ , prettySnapshotVersion
11+ , currentSnapshotVersion
12+ -- * Snapshot metadata
13+ , SnapshotMetaData (.. )
14+ , SnapshotLabel (.. )
515 -- * Snapshot format
6- numSnapRuns
16+ , numSnapRuns
717 , SnapLevels
818 , SnapLevel (.. )
919 , SnapMergingRun (.. )
@@ -23,6 +33,7 @@ import Control.Monad.Primitive (PrimMonad)
2333import Control.TempRegistry
2434import Data.Foldable (forM_ )
2535import Data.Primitive.PrimVar
36+ import Data.Text (Text )
2637import qualified Data.Vector as V
2738import Database.LSMTree.Internal.Config
2839import Database.LSMTree.Internal.Entry
@@ -39,6 +50,116 @@ import Database.LSMTree.Internal.UniqCounter (UniqCounter,
3950import System.FS.API (HasFS )
4051import System.FS.BlockIO.API (HasBlockIO )
4152
53+ {- ------------------------------------------------------------------------------
54+ Versioning
55+ -------------------------------------------------------------------------------}
56+
57+ -- | The version of a snapshot.
58+ --
59+ -- When encoding snapshot metadata, 'currentSnapshotVersion' is included in the
60+ -- file. When snapshot metadata is decoded, then the decoded version is checked
61+ -- for compatibility against 'currentSnapshotVersion'. Decoding will fail if the
62+ -- versions are incompatible.
63+ --
64+ -- A version @x.y@ has two components: a major version number @x@ and a minor
65+ -- version number @y@. The major version number is used to signal breaking
66+ -- changes. The minor version number is used to signal non-breaking changes that
67+ -- are backwards compatible. To be precise, @x.y@ is guaranteed to be backwards
68+ -- compatible with @x'.y'@ as long as @x == x'@ and @y' <= y@. If @x > x'@, then
69+ -- backwards compatibility *may* be provided, but is not guaranteed. Forward
70+ -- compatibilitty is never guaranteed.
71+ --
72+ -- If @x.y@ is our current version, and if it @x.y@ is backwards compatible with
73+ -- @x'.y'@, then @x.y@ can decode snapshots that were encoded at version
74+ -- @x'.y'@.
75+ --
76+ -- The version number determines the format of the snapshot metadata file, but
77+ -- it also doubles as versioning information for the entire snapshot itself. For
78+ -- example, if a breaking change is made to the merge scheduling algorithm that
79+ -- would lead to errors when loading an older snapshot, then the major version
80+ -- should be increased as well.
81+ data SnapshotVersion = V0_0
82+ deriving stock (Show , Eq )
83+
84+ -- >>> major currentSnapshotVersion
85+ -- 0
86+ major :: SnapshotVersion -> Word
87+ major V0_0 = 0
88+
89+ -- >>> minor currentSnapshotVersion
90+ -- 0
91+ minor :: SnapshotVersion -> Word
92+ minor V0_0 = 0
93+
94+ fromMajorMinor :: Word -> Word -> Maybe SnapshotVersion
95+ fromMajorMinor 0 0 = Just V0_0
96+ fromMajorMinor _ _ = Nothing
97+
98+ -- >>> prettySnapshotVersion currentSnapshotVersion
99+ -- "v0.0"
100+ prettySnapshotVersion :: SnapshotVersion -> String
101+ prettySnapshotVersion version = prettyVersion (major version) (minor version)
102+
103+ -- >>> prettyVersion 17 32
104+ -- "v17.32"
105+ prettyVersion :: Word -> Word -> String
106+ prettyVersion majo mino =
107+ showChar ' v'
108+ . shows majo
109+ . showChar ' .'
110+ . shows mino
111+ $ " "
112+
113+ -- >>> currentSnapshotVersion
114+ -- V0_0
115+ currentSnapshotVersion :: SnapshotVersion
116+ currentSnapshotVersion = V0_0
117+
118+ _isCompatible :: SnapshotVersion -> Either String ()
119+ _isCompatible otherVersion = do
120+ case ( currentSnapshotVersion, otherVersion ) of
121+ (V0_0 , V0_0 ) -> Right ()
122+
123+ {- ------------------------------------------------------------------------------
124+ Snapshot metadata
125+ -------------------------------------------------------------------------------}
126+
127+ -- | Custom text to include in a snapshot file
128+ newtype SnapshotLabel = SnapshotLabel Text
129+ deriving stock (Show , Eq , Read )
130+
131+ data SnapshotTableType = SnapNormalTable | SnapMonoidalTable
132+ deriving stock (Show , Eq , Read )
133+
134+ data SnapshotMetaData = SnapshotMetaData {
135+ -- | Custom, user-supplied text that is included in the metadata.
136+ --
137+ -- The main use case for this field is for the user to supply textual
138+ -- information about the key\/value\/blob type for the table that
139+ -- corresponds to the snapshot. This information can then be used to
140+ -- dynamically check that a snapshot is opened at the correct
141+ -- key\/value\/blob type.
142+ --
143+ -- One could argue that the 'SnapshotName' could be used to to hold this
144+ -- information, but the file name of snapshot meta data is not guarded by a
145+ -- checksum, wherease the contents of the file are. Therefore using the
146+ -- 'SnapshotLabel' is safer.
147+ snapMetaLabel :: ! SnapshotLabel
148+ -- | Whether a table is normal or monoidal.
149+ --
150+ -- TODO: if we at some point decide to get rid of the normal vs. monoidal
151+ -- distinction, we can get rid of this field.
152+ , snapMetaTableType :: ! SnapshotTableType
153+ -- | The 'TableConfig' for the snapshotted table.
154+ --
155+ -- Some of these configuration options can be overridden when a snapshot is
156+ -- opened: see 'TableConfigOverride'.
157+ , snapMetaConfig :: ! TableConfig
158+ -- | The shape of the LSM tree.
159+ , snapMetaLevels :: ! SnapLevels
160+ }
161+ deriving stock (Show , Eq )
162+
42163{- ------------------------------------------------------------------------------
43164 Levels snapshot format
44165-------------------------------------------------------------------------------}
0 commit comments