@@ -104,9 +104,7 @@ import Database.LSMTree.Internal.Serialise (SerialisedBlob (..),
104
104
SerialisedKey , SerialisedValue )
105
105
import Database.LSMTree.Internal.UniqCounter
106
106
import qualified Database.LSMTree.Internal.Vector as V
107
- import Database.LSMTree.Internal.WriteBuffer (WriteBuffer )
108
107
import qualified Database.LSMTree.Internal.WriteBuffer as WB
109
- import Database.LSMTree.Internal.WriteBufferBlobs (WriteBufferBlobs )
110
108
import qualified Database.LSMTree.Internal.WriteBufferBlobs as WBB
111
109
import qualified System.FS.API as FS
112
110
import System.FS.API (FsError , FsErrorPath (.. ), FsPath , Handle ,
@@ -620,53 +618,58 @@ withTable sesh conf = bracket (new sesh conf) close
620
618
-> IO (TableHandle IO h) #-}
621
619
-- | See 'Database.LSMTree.Normal.new'.
622
620
new ::
623
- (MonadSTM m , MonadThrow m , MonadMVar m , PrimMonad m )
621
+ (MonadSTM m , MonadMVar m , PrimMonad m , MonadMask m )
624
622
=> Session m h
625
623
-> TableConfig
626
624
-> m (TableHandle m h )
627
625
new sesh conf = do
628
626
traceWith (sessionTracer sesh) TraceNewTable
629
- withOpenSession sesh $ \ seshEnv -> do
630
- am <- newArenaManager
631
- blobpath <- Paths. tableBlobPath (sessionRoot seshEnv) <$>
632
- incrUniqCounter (sessionUniqCounter seshEnv)
633
- wbblobs <- WBB. new (sessionHasFS seshEnv) blobpath
634
- newWith sesh seshEnv conf am WB. empty wbblobs V. empty
627
+ withOpenSession sesh $ \ seshEnv ->
628
+ withTempRegistry $ \ reg -> do
629
+ am <- newArenaManager
630
+ blobpath <- Paths. tableBlobPath (sessionRoot seshEnv) <$>
631
+ incrUniqCounter (sessionUniqCounter seshEnv)
632
+ tableWriteBufferBlobs
633
+ <- allocateTemp reg
634
+ (WBB. new (sessionHasFS seshEnv) blobpath)
635
+ WBB. removeReference
636
+ let tableWriteBuffer = WB. empty
637
+ tableLevels = V. empty
638
+ tableCache <- mkLevelsCache tableLevels
639
+ let tc = TableContent {
640
+ tableWriteBuffer
641
+ , tableWriteBufferBlobs
642
+ , tableLevels
643
+ , tableCache
644
+ }
645
+ newWith reg sesh seshEnv conf am tc
635
646
636
647
{-# SPECIALISE newWith ::
637
- Session IO h
648
+ TempRegistry IO
649
+ -> Session IO h
638
650
-> SessionEnv IO h
639
651
-> TableConfig
640
652
-> ArenaManager RealWorld
641
- -> WriteBuffer
642
- -> WriteBufferBlobs IO h
643
- -> Levels IO h
653
+ -> TableContent IO h
644
654
-> IO (TableHandle IO h) #-}
645
655
newWith ::
646
656
(MonadSTM m , MonadMVar m )
647
- => Session m h
657
+ => TempRegistry m
658
+ -> Session m h
648
659
-> SessionEnv m h
649
660
-> TableConfig
650
661
-> ArenaManager (PrimState m )
651
- -> WriteBuffer
652
- -> WriteBufferBlobs m h
653
- -> Levels m h
662
+ -> TableContent m h
654
663
-> m (TableHandle m h )
655
- newWith sesh seshEnv conf ! am ! wb ! wbblobs ! levels = do
664
+ newWith reg sesh seshEnv conf ! am ! tc = do
656
665
tableId <- incrUniqCounter (sessionUniqCounter seshEnv)
657
666
let tr = TraceTable (uniqueToWord64 tableId) `contramap` sessionTracer sesh
658
667
traceWith tr $ TraceCreateTableHandle conf
659
- cache <- mkLevelsCache levels
660
668
-- The session is kept open until we've updated the session's set of tracked
661
669
-- tables. If 'closeSession' is called by another thread while this code
662
670
-- block is being executed, that thread will block until it reads the
663
671
-- /updated/ set of tracked tables.
664
- contentVar <- RW. new $ TableContent
665
- { tableWriteBuffer = wb
666
- , tableWriteBufferBlobs = wbblobs
667
- , tableLevels = levels
668
- , tableCache = cache
669
- }
672
+ contentVar <- RW. new $ tc
670
673
tableVar <- RW. new $ TableHandleOpen $ TableHandleEnv {
671
674
tableSession = sesh
672
675
, tableSessionEnv = seshEnv
@@ -675,7 +678,8 @@ newWith sesh seshEnv conf !am !wb !wbblobs !levels = do
675
678
}
676
679
let ! th = TableHandle conf tableVar am tr
677
680
-- Track the current table
678
- modifyMVar_ (sessionOpenTables seshEnv) $ pure . Map. insert (uniqueToWord64 tableId) th
681
+ freeTemp reg $ modifyMVar_ (sessionOpenTables seshEnv)
682
+ $ pure . Map. insert (uniqueToWord64 tableId) th
679
683
pure $! th
680
684
681
685
{-# SPECIALISE close :: TableHandle IO h -> IO () #-}
@@ -686,17 +690,17 @@ close ::
686
690
-> m ()
687
691
close th = do
688
692
traceWith (tableTracer th) TraceCloseTable
689
- RW. withWriteAccess_ (tableHandleState th) $ \ case
693
+ modifyWithTempRegistry_
694
+ (RW. unsafeAcquireWriteAccess (tableHandleState th))
695
+ (atomically . RW. unsafeReleaseWriteAccess (tableHandleState th)) $ \ reg -> \ case
690
696
TableHandleClosed -> pure TableHandleClosed
691
697
TableHandleOpen thEnv -> do
692
698
-- Since we have a write lock on the table state, we know that we are the
693
699
-- only thread currently closing the table. We can safely make the session
694
700
-- forget about this table.
695
- -- TODO: use TempRegistry
696
- tableSessionUntrackTable thEnv
701
+ freeTemp reg (tableSessionUntrackTable thEnv)
697
702
RW. withWriteAccess_ (tableContent thEnv) $ \ tc -> do
698
- forRunM_ (tableLevels tc) Run. removeReference
699
- WBB. removeReference (tableWriteBufferBlobs tc)
703
+ removeReferenceTableContent reg tc
700
704
pure tc
701
705
pure TableHandleClosed
702
706
@@ -1289,12 +1293,22 @@ open sesh label override snap = do
1289
1293
let runPaths = V. map (bimap (second $ RunFsPaths (Paths. activeDir $ sessionRoot seshEnv))
1290
1294
(V. map (RunFsPaths (Paths. activeDir $ sessionRoot seshEnv))))
1291
1295
runNumbers
1292
- lvls <- openLevels reg hfs hbio (confDiskCachePolicy conf') runPaths
1296
+
1293
1297
am <- newArenaManager
1294
1298
blobpath <- Paths. tableBlobPath (sessionRoot seshEnv) <$>
1295
1299
incrUniqCounter (sessionUniqCounter seshEnv)
1296
- wbblobs <- WBB. new hfs blobpath
1297
- newWith sesh seshEnv conf' am WB. empty wbblobs lvls
1300
+ tableWriteBufferBlobs
1301
+ <- allocateTemp reg
1302
+ (WBB. new hfs blobpath)
1303
+ WBB. removeReference
1304
+ tableLevels <- openLevels reg hfs hbio (confDiskCachePolicy conf') runPaths
1305
+ tableCache <- mkLevelsCache tableLevels
1306
+ newWith reg sesh seshEnv conf' am $! TableContent {
1307
+ tableWriteBuffer = WB. empty
1308
+ , tableWriteBufferBlobs
1309
+ , tableLevels
1310
+ , tableCache
1311
+ }
1298
1312
1299
1313
{-# SPECIALISE openLevels ::
1300
1314
TempRegistry IO
@@ -1390,21 +1404,12 @@ duplicate th = do
1390
1404
-- The table contents escape the read access, but we just added references
1391
1405
-- to each run so it is safe.
1392
1406
content <- RW. withReadAccess (tableContent thEnv) $ \ content -> do
1393
- forRunM_ (tableLevels content) $ \ r -> do
1394
- allocateTemp reg
1395
- (Run. addReference r)
1396
- (\ _ -> Run. removeReference r)
1407
+ addReferenceTableContent reg content
1397
1408
pure content
1398
- WBB. addReference (tableWriteBufferBlobs content)
1399
- -- TODO: Fix possible double-free! See 'newCursor'.
1400
- -- In `newWith`, the table handle (in the open state) gets added to
1401
- -- `sessionOpenTables', even if later an async exception occurs and
1402
- -- the temp registry rolls back all allocations.
1403
1409
newWith
1410
+ reg
1404
1411
(tableSession thEnv)
1405
1412
(tableSessionEnv thEnv)
1406
1413
(tableConfig th)
1407
1414
(tableHandleArenaManager th)
1408
- (tableWriteBuffer content)
1409
- (tableWriteBufferBlobs content)
1410
- (tableLevels content)
1415
+ content
0 commit comments