lsm-tree-1.0.0.0: test/Database/LSMTree/Model/IO.hs
{-# LANGUAGE TypeFamilies #-}
-- | An instance of `Class.IsTable`, modelling potentially closed sessions in
-- @IO@ by lifting the pure session model from "Database.LSMTree.Model.Session".
module Database.LSMTree.Model.IO (
Err (..)
, Session (..)
, Class.SessionArgs (NoSessionArgs)
, Table (..)
, TableConfig (..)
, BlobRef (..)
, Cursor (..)
-- * helpers
, runInOpenSession
) where
import Control.Concurrent.Class.MonadSTM.Strict
import Control.Exception (Exception)
import Control.Monad.Class.MonadThrow (MonadThrow (..))
import qualified Data.List.NonEmpty as NE
import qualified Database.LSMTree.Class as Class
import Database.LSMTree.Model.Session (TableConfig (..))
import qualified Database.LSMTree.Model.Session as Model
newtype Session m = Session (StrictTVar m (Maybe Model.Model))
data Table m k v b = Table {
thSession :: !(Session m)
, thTable :: !(Model.Table k v b)
}
data BlobRef m b = BlobRef {
brSession :: !(Session m)
, brBlobRef :: !(Model.BlobRef b)
}
data Cursor m k v b = Cursor {
cSession :: !(Session m)
, cCursor :: !(Model.Cursor k v b)
}
newtype Err = Err (Model.Err)
deriving stock Show
deriving anyclass Exception
runInOpenSession :: (MonadSTM m, MonadThrow (STM m)) => Session m -> Model.ModelM a -> m a
runInOpenSession (Session var) action = atomically $ do
readTVar var >>= \case
Nothing -> error "session closed"
Just m -> do
let (r, m') = Model.runModelM action m
case r of
Left e -> throwSTM (Err e)
Right x -> writeTVar var (Just m') >> pure x
instance Class.IsSession Session where
data SessionArgs Session m = NoSessionArgs
openSession NoSessionArgs = Session <$> newTVarIO (Just $! Model.initModel)
closeSession (Session var) = atomically $ writeTVar var Nothing
deleteSnapshot s x = runInOpenSession s $ Model.deleteSnapshot x
listSnapshots s = runInOpenSession s $ Model.listSnapshots
instance Class.IsTable Table where
type Session Table = Session
type TableConfig Table = Model.TableConfig
type BlobRef Table = BlobRef
type Cursor Table = Cursor
newTableWith x s = Table s <$> runInOpenSession s (Model.new x)
closeTable (Table s t) = runInOpenSession s (Model.close t)
lookups (Table s t) x1 = fmap (fmap (BlobRef s)) <$>
runInOpenSession s (Model.lookups x1 t)
updates (Table s t) x1 = runInOpenSession s (Model.updates Model.getResolve x1 t)
inserts (Table s t) x1 = runInOpenSession s (Model.inserts Model.getResolve x1 t)
deletes (Table s t) x1 = runInOpenSession s (Model.deletes Model.getResolve x1 t)
upserts (Table s t) x1 = runInOpenSession s (Model.upserts Model.getResolve x1 t)
rangeLookup (Table s t) x1 = fmap (fmap (BlobRef s)) <$>
runInOpenSession s (Model.rangeLookup x1 t)
retrieveBlobs _ s x1 = runInOpenSession s (Model.retrieveBlobs (fmap brBlobRef x1))
newCursor k (Table s t) = Cursor s <$> runInOpenSession s (Model.newCursor k t)
closeCursor _ (Cursor s c) = runInOpenSession s (Model.closeCursor c)
readCursor _ x1 (Cursor s c) = fmap (fmap (BlobRef s)) <$>
runInOpenSession s (Model.readCursor x1 c)
saveSnapshot x1 x2 (Table s t) = runInOpenSession s (Model.saveSnapshot x1 x2 t)
corruptSnapshot _ x (Table s _t) = runInOpenSession s (Model.corruptSnapshot x)
openTableFromSnapshot s x1 x2 = Table s <$> runInOpenSession s (Model.openTableFromSnapshot x1 x2)
duplicate (Table s t) = Table s <$> runInOpenSession s (Model.duplicate t)
union (Table s1 t1) (Table _s2 t2) =
Table s1 <$> runInOpenSession s1 (Model.union Model.getResolve t1 t2)
unions ts =
Table s <$> runInOpenSession s (Model.unions Model.getResolve (fmap thTable ts))
where
Table s _ = NE.head ts
remainingUnionDebt (Table s t) = runInOpenSession s (Model.remainingUnionDebt t)
supplyUnionCredits (Table s t) credits = runInOpenSession s (Model.supplyUnionCredits t credits)