@@ -68,7 +68,6 @@ import Control.Monad.Primitive
68
68
import Control.TempRegistry
69
69
import Control.Tracer
70
70
import Data.Arena (ArenaManager , newArenaManager )
71
- import Data.Bifunctor (Bifunctor (.. ))
72
71
import qualified Data.ByteString.Char8 as BSC
73
72
import Data.Char (isNumber )
74
73
import Data.Foldable
@@ -90,19 +89,19 @@ import qualified Database.LSMTree.Internal.Entry as Entry
90
89
import Database.LSMTree.Internal.Lookup (ByteCountDiscrepancy ,
91
90
ResolveSerialisedValue , lookupsIO )
92
91
import Database.LSMTree.Internal.MergeSchedule
93
- import Database.LSMTree.Internal.Paths (RunFsPaths (.. ),
94
- SessionRoot ( .. ), SnapshotName )
92
+ import Database.LSMTree.Internal.Paths (SessionRoot (.. ),
93
+ SnapshotName )
95
94
import qualified Database.LSMTree.Internal.Paths as Paths
96
95
import Database.LSMTree.Internal.Range (Range (.. ))
97
96
import qualified Database.LSMTree.Internal.RawBytes as RB
98
97
import Database.LSMTree.Internal.Run (Run )
99
98
import qualified Database.LSMTree.Internal.Run as Run
100
- import Database.LSMTree.Internal.RunNumber
101
99
import qualified Database.LSMTree.Internal.RunReader as Reader
102
100
import Database.LSMTree.Internal.RunReaders (OffsetKey (.. ))
103
101
import qualified Database.LSMTree.Internal.RunReaders as Readers
104
102
import Database.LSMTree.Internal.Serialise (SerialisedBlob (.. ),
105
103
SerialisedKey , SerialisedValue )
104
+ import Database.LSMTree.Internal.Snapshot
106
105
import Database.LSMTree.Internal.UniqCounter
107
106
import qualified Database.LSMTree.Internal.Vector as V
108
107
import qualified Database.LSMTree.Internal.WriteBuffer as WB
@@ -1214,14 +1213,18 @@ snapshot resolve snap label th = do
1214
1213
traceWith (tableTracer th) $ TraceSnapshot snap
1215
1214
let conf = tableConfig th
1216
1215
withOpenTable th $ \ thEnv -> do
1216
+ let hfs = tableHasFS thEnv
1217
+ let snapPath = Paths. snapshot (tableSessionRoot thEnv) snap
1218
+ FS. doesFileExist (tableHasFS thEnv) snapPath >>= \ b ->
1219
+ when b $ throwIO (ErrSnapshotExists snap)
1220
+
1217
1221
-- For the temporary implementation it is okay to just flush the buffer
1218
1222
-- before taking the snapshot.
1219
- let hfs = tableHasFS thEnv
1220
1223
content <- modifyWithTempRegistry
1221
1224
(RW. unsafeAcquireWriteAccess (tableContent thEnv))
1222
1225
(atomically . RW. unsafeReleaseWriteAccess (tableContent thEnv))
1223
1226
$ \ reg content -> do
1224
- r <- flushWriteBuffer
1227
+ content' <- flushWriteBuffer
1225
1228
(TraceMerge `contramap` tableTracer th)
1226
1229
conf
1227
1230
resolve
@@ -1231,35 +1234,29 @@ snapshot resolve snap label th = do
1231
1234
(tableSessionUniqCounter thEnv)
1232
1235
reg
1233
1236
content
1234
- pure (r, r )
1237
+ pure (content', content' )
1235
1238
-- At this point, we've flushed the write buffer but we haven't created the
1236
1239
-- snapshot file yet. If an asynchronous exception happens beyond this
1237
1240
-- point, we'll take that loss, as the inner state of the table is still
1238
1241
-- consistent.
1239
- runNumbers <- V. forM (tableLevels content) $ \ (Level mr rs) -> do
1240
- (,V. map (runNumber . Run. runRunFsPaths) rs) <$>
1241
- case mr of
1242
- SingleRun r -> pure (True , runNumber (Run. runRunFsPaths r))
1243
- MergingRun _ _ var -> do
1244
- withMVar var $ \ case
1245
- CompletedMerge r -> pure (False , runNumber (Run. runRunFsPaths r))
1246
- OngoingMerge {} -> error " snapshot: OngoingMerge not yet supported" -- TODO: implement
1247
- let snapPath = Paths. snapshot (tableSessionRoot thEnv) snap
1248
- FS. doesFileExist (tableHasFS thEnv) snapPath >>= \ b ->
1249
- when b $ throwIO (ErrSnapshotExists snap)
1242
+
1243
+ snappedLevels <- snapLevels (tableLevels content)
1244
+ let snapContents = BSC. pack $ show (label, snappedLevels, tableConfig th)
1245
+
1250
1246
FS. withFile
1251
1247
(tableHasFS thEnv)
1252
1248
snapPath
1253
1249
(FS. WriteMode FS. MustBeNew ) $ \ h ->
1254
- void $ FS. hPutAllStrict (tableHasFS thEnv) h
1255
- ( BSC. pack $ show (label, runNumbers, tableConfig th))
1256
- pure $! V. sum ( V. map ( \ ((_ :: ( Bool , RunNumber )), rs) -> 1 + V. length rs) runNumbers)
1250
+ void $ FS. hPutAllStrict (tableHasFS thEnv) h snapContents
1251
+
1252
+ pure $! numSnapRuns snappedLevels
1257
1253
1258
1254
{-# SPECIALISE open ::
1259
1255
Session IO h
1260
1256
-> SnapshotLabel
1261
1257
-> TableConfigOverride
1262
1258
-> SnapshotName
1259
+ -> ResolveSerialisedValue
1263
1260
-> IO (TableHandle IO h) #-}
1264
1261
-- | See 'Database.LSMTree.Normal.open'.
1265
1262
open ::
@@ -1268,8 +1265,9 @@ open ::
1268
1265
-> SnapshotLabel -- ^ Expected label
1269
1266
-> TableConfigOverride -- ^ Optional config override
1270
1267
-> SnapshotName
1268
+ -> ResolveSerialisedValue
1271
1269
-> m (TableHandle m h )
1272
- open sesh label override snap = do
1270
+ open sesh label override snap resolve = do
1273
1271
traceWith (sessionTracer sesh) $ TraceOpenSnapshot snap override
1274
1272
withOpenSession sesh $ \ seshEnv -> do
1275
1273
withTempRegistry $ \ reg -> do
@@ -1283,26 +1281,17 @@ open sesh label override snap = do
1283
1281
snapPath
1284
1282
FS. ReadMode $ \ h ->
1285
1283
FS. hGetAll (sessionHasFS seshEnv) h
1286
- let (label', runNumbers, conf) =
1287
- -- why we are using read for this?
1288
- -- apparently this is a temporary solution, to be done properly in WP15
1289
- read @ (SnapshotLabel , V. Vector ((Bool , RunNumber ), V. Vector RunNumber ), TableConfig ) $
1290
- BSC. unpack $ BSC. toStrict $ bs
1291
-
1292
- let conf' = applyOverride override conf
1284
+ let (label', snappedLevels, conf) = read $ BSC. unpack $ BSC. toStrict $ bs
1293
1285
unless (label == label') $ throwIO (ErrSnapshotWrongType snap)
1294
- let runPaths = V. map (bimap (second $ RunFsPaths (Paths. activeDir $ sessionRoot seshEnv))
1295
- (V. map (RunFsPaths (Paths. activeDir $ sessionRoot seshEnv))))
1296
- runNumbers
1297
-
1286
+ let conf' = applyOverride override conf
1298
1287
am <- newArenaManager
1299
1288
blobpath <- Paths. tableBlobPath (sessionRoot seshEnv) <$>
1300
1289
incrUniqCounter (sessionUniqCounter seshEnv)
1301
1290
tableWriteBufferBlobs
1302
1291
<- allocateTemp reg
1303
1292
(WBB. new hfs blobpath)
1304
1293
WBB. removeReference
1305
- tableLevels <- openLevels reg hfs hbio (confDiskCachePolicy conf') runPaths
1294
+ tableLevels <- openLevels reg hfs hbio conf (sessionRoot seshEnv) resolve snappedLevels
1306
1295
tableCache <- mkLevelsCache reg tableLevels
1307
1296
newWith reg sesh seshEnv conf' am $! TableContent {
1308
1297
tableWriteBuffer = WB. empty
@@ -1311,37 +1300,6 @@ open sesh label override snap = do
1311
1300
, tableCache
1312
1301
}
1313
1302
1314
- {-# SPECIALISE openLevels ::
1315
- TempRegistry IO
1316
- -> HasFS IO h
1317
- -> HasBlockIO IO h
1318
- -> DiskCachePolicy
1319
- -> V.Vector ((Bool, RunFsPaths), V.Vector RunFsPaths)
1320
- -> IO (Levels IO h) #-}
1321
- -- | Open multiple levels.
1322
- openLevels ::
1323
- (MonadFix m , MonadMask m , MonadMVar m , MonadSTM m , PrimMonad m )
1324
- => TempRegistry m
1325
- -> HasFS m h
1326
- -> HasBlockIO m h
1327
- -> DiskCachePolicy
1328
- -> V. Vector ((Bool , RunFsPaths ), V. Vector RunFsPaths )
1329
- -> m (Levels m h )
1330
- openLevels reg hfs hbio diskCachePolicy levels =
1331
- flip V. imapMStrict levels $ \ i (mrPath, rsPaths) -> do
1332
- let ln = LevelNo (i+ 1 ) -- level 0 is the write buffer
1333
- caching = diskCachePolicyForLevel diskCachePolicy ln
1334
- ! r <- allocateTemp reg
1335
- (Run. openFromDisk hfs hbio caching (snd mrPath))
1336
- Run. removeReference
1337
- ! rs <- flip V. mapMStrict rsPaths $ \ run ->
1338
- allocateTemp reg
1339
- (Run. openFromDisk hfs hbio caching run)
1340
- Run. removeReference
1341
- let ! mr = if fst mrPath then SingleRun r
1342
- else error " openLevels: OngoingMerge not yet supported"
1343
- pure $! Level mr rs
1344
-
1345
1303
{-# SPECIALISE deleteSnapshot ::
1346
1304
Session IO h
1347
1305
-> SnapshotName
0 commit comments