@@ -19,10 +19,14 @@ module Database.LSMTree (
1919
2020 -- * Sessions
2121 Session ,
22- withSession ,
23- withSessionIO ,
22+ withOpenSession ,
23+ withOpenSessionIO ,
24+ withNewSession ,
25+ withRestoreSession ,
2426 openSession ,
2527 openSessionIO ,
28+ newSession ,
29+ restoreSession ,
2630 closeSession ,
2731
2832 -- * Tables
@@ -200,8 +204,8 @@ import Control.DeepSeq (NFData (..))
200204import Control.Exception.Base (assert )
201205import Control.Monad.Class.MonadAsync (MonadAsync )
202206import Control.Monad.Class.MonadST (MonadST )
203- import Control.Monad.Class.MonadThrow (MonadCatch (.. ), MonadMask ,
204- MonadThrow (.. ))
207+ import Control.Monad.Class.MonadThrow (MonadCatch (.. ), MonadEvaluate ,
208+ MonadMask , MonadThrow (.. ))
205209import Control.Monad.Primitive (PrimMonad )
206210import Control.Tracer (Tracer )
207211import Data.Bifunctor (Bifunctor (.. ))
@@ -290,6 +294,7 @@ type IOLike m =
290294 , MonadMask m
291295 , PrimMonad m
292296 , MonadST m
297+ , MonadEvaluate m
293298 )
294299
295300--------------------------------------------------------------------------------
@@ -384,7 +389,7 @@ runExample action = do
384389 let createSessionDir = Dir.createDirectoryIfMissing True sessionDir
385390 let removeSessionDir = Dir.removeDirectoryRecursive sessionDir
386391 bracket_ createSessionDir removeSessionDir $ do
387- LSMT.withSessionIO mempty sessionDir $ \session -> do
392+ LSMT.withOpenSessionIO mempty sessionDir $ \session -> do
388393 LSMT.withTable session $ \table ->
389394 action session table
390395:}
@@ -399,8 +404,8 @@ runExample action = do
399404{- |
400405Run an action with access to a session opened from a session directory.
401406
402- If the session directory is empty, a new session is created.
403- Otherwise, the session directory is opened as an existing session.
407+ If the session directory is empty, a new session is created using the given salt .
408+ Otherwise, the session directory is restored as an existing session ignoring the given salt .
404409
405410If there are no open tables or cursors when the session terminates, then the disk I\/O complexity of this operation is \(O(1)\).
406411Otherwise, 'closeTable' is called for each open table and 'closeCursor' is called for each open cursor.
@@ -426,7 +431,7 @@ Throws the following exceptions:
426431 If the session directory is malformed.
427432-}
428433{-# SPECIALISE
429- withSession ::
434+ withOpenSession ::
430435 Tracer IO LSMTreeTrace ->
431436 HasFS IO HandleIO ->
432437 HasBlockIO IO HandleIO ->
@@ -435,7 +440,7 @@ Throws the following exceptions:
435440 (Session IO -> IO a) ->
436441 IO a
437442 #-}
438- withSession ::
443+ withOpenSession ::
439444 forall m h a .
440445 (IOLike m , Typeable h ) =>
441446 Tracer m LSMTreeTrace ->
@@ -447,28 +452,132 @@ withSession ::
447452 FsPath ->
448453 (Session m -> m a ) ->
449454 m a
450- withSession tracer hasFS hasBlockIO sessionSalt sessionDir action = do
451- Internal. withSession tracer hasFS hasBlockIO sessionSalt sessionDir (action . Session )
455+ withOpenSession tracer hasFS hasBlockIO sessionSalt sessionDir action = do
456+ Internal. withSessionOpen tracer hasFS hasBlockIO sessionSalt sessionDir (action . Session )
452457
453- -- | Variant of 'withSession ' that is specialised to 'IO' using the real filesystem.
454- withSessionIO ::
458+ -- | Variant of 'withOpenSession ' that is specialised to 'IO' using the real filesystem.
459+ withOpenSessionIO ::
455460 Tracer IO LSMTreeTrace ->
456461 FilePath ->
457462 (Session IO -> IO a ) ->
458463 IO a
459- withSessionIO tracer sessionDir action = do
464+ withOpenSessionIO tracer sessionDir action = do
460465 let mountPoint = MountPoint sessionDir
461466 let sessionDirFsPath = mkFsPath []
462467 let hasFS = ioHasFS mountPoint
463468 sessionSalt <- randomIO
464469 withIOHasBlockIO hasFS defaultIOCtxParams $ \ hasBlockIO ->
465- withSession tracer hasFS hasBlockIO sessionSalt sessionDirFsPath action
470+ withOpenSession tracer hasFS hasBlockIO sessionSalt sessionDirFsPath action
471+
472+ {- |
473+ Run an action with access to a new session.
474+
475+ The session directory must be empty.
476+
477+ If there are no open tables or cursors when the session terminates, then the disk I\/O complexity of this operation is \(O(1)\).
478+ Otherwise, 'closeTable' is called for each open table and 'closeCursor' is called for each open cursor.
479+ Consequently, the worst-case disk I\/O complexity of this operation depends on the merge policy of the open tables in the session.
480+ The following assumes all tables in the session have the same merge policy:
481+
482+ ['LazyLevelling']:
483+ \(O(o \: T \log_T \frac{n}{B})\).
484+
485+ The variable \(o\) refers to the number of open tables and cursors in the session.
486+
487+ This function is exception-safe for both synchronous and asynchronous exceptions.
488+
489+ It is recommended to use this function instead of 'newSession' and 'closeSession'.
490+
491+ Throws the following exceptions:
492+
493+ ['SessionDirDoesNotExistError']:
494+ If the session directory does not exist.
495+ ['SessionDirLockedError']:
496+ If the session directory is locked by another process.
497+ ['SessionDirCorruptedError']:
498+ If the session directory is malformed.
499+ -}
500+ {-# SPECIALISE
501+ withNewSession ::
502+ Tracer IO LSMTreeTrace ->
503+ HasFS IO HandleIO ->
504+ HasBlockIO IO HandleIO ->
505+ Salt ->
506+ FsPath ->
507+ (Session IO -> IO a) ->
508+ IO a
509+ #-}
510+ withNewSession ::
511+ forall m h a .
512+ (IOLike m , Typeable h ) =>
513+ Tracer m LSMTreeTrace ->
514+ HasFS m h ->
515+ HasBlockIO m h ->
516+ -- | The session salt.
517+ Salt ->
518+ -- | The session directory.
519+ FsPath ->
520+ (Session m -> m a ) ->
521+ m a
522+ withNewSession tracer hasFS hasBlockIO sessionSalt sessionDir action = do
523+ Internal. withNewSession tracer hasFS hasBlockIO sessionSalt sessionDir (action . Session )
524+
525+ {- |
526+ Run an action with access to a restored session.
527+
528+ The session directory must be non-empty: a session must have previously been
529+ opened and closed in this directory.
530+
531+ If there are no open tables or cursors when the session terminates, then the disk I\/O complexity of this operation is \(O(1)\).
532+ Otherwise, 'closeTable' is called for each open table and 'closeCursor' is called for each open cursor.
533+ Consequently, the worst-case disk I\/O complexity of this operation depends on the merge policy of the open tables in the session.
534+ The following assumes all tables in the session have the same merge policy:
535+
536+ ['LazyLevelling']:
537+ \(O(o \: T \log_T \frac{n}{B})\).
538+
539+ The variable \(o\) refers to the number of open tables and cursors in the session.
540+
541+ This function is exception-safe for both synchronous and asynchronous exceptions.
542+
543+ It is recommended to use this function instead of 'restoreSession' and 'closeSession'.
544+
545+ Throws the following exceptions:
546+
547+ ['SessionDirDoesNotExistError']:
548+ If the session directory does not exist.
549+ ['SessionDirLockedError']:
550+ If the session directory is locked by another process.
551+ ['SessionDirCorruptedError']:
552+ If the session directory is malformed.
553+ -}
554+ {-# SPECIALISE
555+ withRestoreSession ::
556+ Tracer IO LSMTreeTrace ->
557+ HasFS IO HandleIO ->
558+ HasBlockIO IO HandleIO ->
559+ FsPath ->
560+ (Session IO -> IO a) ->
561+ IO a
562+ #-}
563+ withRestoreSession ::
564+ forall m h a .
565+ (IOLike m , Typeable h ) =>
566+ Tracer m LSMTreeTrace ->
567+ HasFS m h ->
568+ HasBlockIO m h ->
569+ -- | The session directory.
570+ FsPath ->
571+ (Session m -> m a ) ->
572+ m a
573+ withRestoreSession tracer hasFS hasBlockIO sessionDir action = do
574+ Internal. withRestoreSession tracer hasFS hasBlockIO sessionDir (action . Session )
466575
467576{- |
468577Open a session from a session directory.
469578
470- If the session directory is empty, a new session is created.
471- Otherwise, the session directory is opened as an existing session.
579+ If the session directory is empty, a new session is created using the given salt .
580+ Otherwise, the session directory is restored as an existing session ignoring the given salt .
472581
473582The worst-case disk I\/O complexity of this operation is \(O(1)\).
474583
@@ -522,6 +631,86 @@ openSessionIO tracer sessionDir = do
522631 bracketOnError acquireHasBlockIO releaseHasBlockIO $ \ hasBlockIO ->
523632 openSession tracer hasFS hasBlockIO sessionSalt sessionDirFsPath
524633
634+ {- |
635+ Create a new session.
636+
637+ The session directory must be empty.
638+
639+ The worst-case disk I\/O complexity of this operation is \(O(1)\).
640+
641+ __Warning:__ Sessions hold open resources and must be closed using 'closeSession'.
642+
643+ Throws the following exceptions:
644+
645+ ['SessionDirDoesNotExistError']:
646+ If the session directory does not exist.
647+ ['SessionDirLockedError']:
648+ If the session directory is locked by another process.
649+ ['SessionDirCorruptedError']:
650+ If the session directory is malformed.
651+ -}
652+ {-# SPECIALISE
653+ newSession ::
654+ Tracer IO LSMTreeTrace ->
655+ HasFS IO HandleIO ->
656+ HasBlockIO IO HandleIO ->
657+ Salt ->
658+ FsPath ->
659+ IO (Session IO)
660+ #-}
661+ newSession ::
662+ forall m h .
663+ (IOLike m , Typeable h ) =>
664+ Tracer m LSMTreeTrace ->
665+ HasFS m h ->
666+ HasBlockIO m h ->
667+ -- | The session salt.
668+ Salt ->
669+ -- | The session directory.
670+ FsPath ->
671+ m (Session m )
672+ newSession tracer hasFS hasBlockIO sessionSalt sessionDir =
673+ Session <$> Internal. newSession tracer hasFS hasBlockIO sessionSalt sessionDir
674+
675+ {- |
676+ Restore a session from a session directory.
677+
678+ The session directory must be non-empty: a session must have previously been
679+ opened (and closed) in this directory.
680+
681+ The worst-case disk I\/O complexity of this operation is \(O(1)\).
682+
683+ __Warning:__ Sessions hold open resources and must be closed using 'closeSession'.
684+
685+ Throws the following exceptions:
686+
687+ ['SessionDirDoesNotExistError']:
688+ If the session directory does not exist.
689+ ['SessionDirLockedError']:
690+ If the session directory is locked by another process.
691+ ['SessionDirCorruptedError']:
692+ If the session directory is malformed.
693+ -}
694+ {-# SPECIALISE
695+ restoreSession ::
696+ Tracer IO LSMTreeTrace ->
697+ HasFS IO HandleIO ->
698+ HasBlockIO IO HandleIO ->
699+ FsPath ->
700+ IO (Session IO)
701+ #-}
702+ restoreSession ::
703+ forall m h .
704+ (IOLike m , Typeable h ) =>
705+ Tracer m LSMTreeTrace ->
706+ HasFS m h ->
707+ HasBlockIO m h ->
708+ -- | The session directory.
709+ FsPath ->
710+ m (Session m )
711+ restoreSession tracer hasFS hasBlockIO sessionDir =
712+ Session <$> Internal. restoreSession tracer hasFS hasBlockIO sessionDir
713+
525714{- |
526715Close a session.
527716
0 commit comments