@@ -28,7 +28,7 @@ module Database.LSMTree.Internal (
28
28
, TableClosedError (.. )
29
29
, TableCorruptedError (.. )
30
30
, TableTooLargeError (.. )
31
- , TableNotCompatibleError (.. )
31
+ , TableUnionNotCompatibleError (.. )
32
32
, SnapshotExistsError (.. )
33
33
, SnapshotDoesNotExistError (.. )
34
34
, SnapshotCorruptedError (.. )
@@ -1534,27 +1534,30 @@ duplicate t@Table{..} = do
1534
1534
tableArenaManager
1535
1535
content
1536
1536
1537
-
1538
1537
{- ------------------------------------------------------------------------------
1539
1538
Table union
1540
1539
-------------------------------------------------------------------------------}
1541
1540
1542
- -- | An operation was called with two tables that are not compatible.
1543
- data TableNotCompatibleError
1544
- = -- | An operation was called with two tables that are not of the same type.
1545
- --
1546
- -- TODO: This error is no longer used by 'unions'.
1547
- ErrTableTypeMismatch
1548
- -- | Vector index of table @t1@ involved in the mismatch
1549
- Int
1550
- -- | Vector index of table @t2@ involved in the mismatch
1551
- Int
1552
- | -- | An operation was called with two tables that are not in the same session.
1553
- ErrTableSessionMismatch
1554
- -- | Vector index of table @t1@ involved in the mismatch
1555
- Int
1556
- -- | Vector index of table @t2@ involved in the mismatch
1557
- Int
1541
+ -- | A table union was constructed with two tables that are not compatible.
1542
+ data TableUnionNotCompatibleError
1543
+ = ErrTableUnionHandleTypeMismatch
1544
+ -- | The index of the first table.
1545
+ ! Int
1546
+ -- | The type of the filesystem handle of the first table.
1547
+ ! TypeRep
1548
+ -- | The index of the second table.
1549
+ ! Int
1550
+ -- | The type of the filesystem handle of the second table.
1551
+ ! TypeRep
1552
+ | ErrTableUnionSessionMismatch
1553
+ -- | The index of the first table.
1554
+ ! Int
1555
+ -- | The session directory of the first table.
1556
+ ! FsErrorPath
1557
+ -- | The index of the second table.
1558
+ ! Int
1559
+ -- | The session directory of the second table.
1560
+ ! FsErrorPath
1558
1561
deriving stock (Show , Eq )
1559
1562
deriving anyclass (Exception )
1560
1563
@@ -1565,10 +1568,7 @@ unions ::
1565
1568
=> NonEmpty (Table m h )
1566
1569
-> m (Table m h )
1567
1570
unions ts = do
1568
- sesh <-
1569
- matchSessions ts >>= \ case
1570
- Left (i, j) -> throwIO $ ErrTableSessionMismatch i j
1571
- Right sesh -> pure sesh
1571
+ sesh <- ensureSessionsMatch ts
1572
1572
1573
1573
traceWith (sessionTracer sesh) $ TraceUnions (NE. map tableId ts)
1574
1574
@@ -1706,37 +1706,34 @@ writeBufferToNewRun SessionEnv {
1706
1706
tableWriteBuffer
1707
1707
tableWriteBufferBlobs
1708
1708
1709
- -- | Check that all tables in the session match. If so, return the matched
1710
- -- session. If there is a mismatch, return the list indices of the mismatching
1711
- -- tables.
1712
- --
1713
- -- TODO: compare LockFileHandle instead of SessionRoot (?). We can write an Eq
1714
- -- instance for LockFileHandle based on pointer equality, just like base does
1715
- -- for Handle.
1716
- matchSessions ::
1709
+ {-# SPECIALISE ensureSessionsMatch ::
1710
+ NonEmpty (Table IO h)
1711
+ -> IO (Session IO h) #-}
1712
+ -- | Check if all tables have the same session.
1713
+ -- If so, return the session.
1714
+ -- Otherwise, throw a 'TableUnionNotCompatibleError'.
1715
+ ensureSessionsMatch ::
1717
1716
(MonadSTM m , MonadThrow m )
1718
1717
=> NonEmpty (Table m h )
1719
- -> m (Either (Int , Int ) (Session m h ))
1720
- matchSessions = \ (t :| ts) ->
1721
- withSessionRoot t $ \ root -> do
1722
- eith <- go root 1 ts
1723
- pure $ case eith of
1724
- Left i -> Left (0 , i)
1725
- Right () -> Right (tableSession t)
1726
- where
1718
+ -> m (Session m h )
1719
+ ensureSessionsMatch (t :| ts) = do
1720
+ let sesh = tableSession t
1721
+ withOpenSession sesh $ \ seshEnv -> do
1722
+ let root = FS. mkFsErrorPath (sessionHasFS seshEnv) (getSessionRoot (sessionRoot seshEnv))
1727
1723
-- Check that the session roots for all tables are the same. There can only
1728
1724
-- be one *open/active* session per directory because of cooperative file
1729
1725
-- locks, so each unique *open* session has a unique session root. We check
1730
1726
-- that all the table's sessions are open at the same time while comparing
1731
1727
-- the session roots.
1732
- go _ _ [] = pure (Right () )
1733
- go root ! i (t': ts') =
1734
- withSessionRoot t' $ \ root' ->
1735
- if root == root'
1736
- then go root (i+ 1 ) ts'
1737
- else pure (Left i)
1738
-
1739
- withSessionRoot t k = withOpenSession (tableSession t) $ k . sessionRoot
1728
+ for_ (zip [1 .. ] ts) $ \ (i, t') -> do
1729
+ let sesh' = tableSession t'
1730
+ withOpenSession sesh' $ \ seshEnv' -> do
1731
+ let root' = FS. mkFsErrorPath (sessionHasFS seshEnv') (getSessionRoot (sessionRoot seshEnv'))
1732
+ -- TODO: compare LockFileHandle instead of SessionRoot (?).
1733
+ -- We can write an Eq instance for LockFileHandle based on pointer equality,
1734
+ -- just like base does for Handle.
1735
+ unless (root == root') $ throwIO $ ErrTableUnionSessionMismatch 0 root i root'
1736
+ pure sesh
1740
1737
1741
1738
{- ------------------------------------------------------------------------------
1742
1739
Table union: debt and credit
0 commit comments