Skip to content

Commit 3b2d995

Browse files
committed
Expose withNewSession and withRestoreSession from the public API
1 parent 5b8cd3c commit 3b2d995

File tree

3 files changed

+234
-8
lines changed

3 files changed

+234
-8
lines changed

src/Database/LSMTree.hs

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,12 @@ module Database.LSMTree (
2121
Session,
2222
withOpenSession,
2323
withOpenSessionIO,
24+
withNewSession,
25+
withRestoreSession,
2426
openSession,
2527
openSessionIO,
28+
newSession,
29+
restoreSession,
2630
closeSession,
2731

2832
-- * Tables
@@ -465,6 +469,110 @@ withOpenSessionIO tracer sessionDir action = do
465469
withIOHasBlockIO hasFS defaultIOCtxParams $ \hasBlockIO ->
466470
withOpenSession tracer hasFS hasBlockIO sessionSalt sessionDirFsPath action
467471

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)
575+
468576
{- |
469577
Open a session from a session directory.
470578
@@ -523,6 +631,86 @@ openSessionIO tracer sessionDir = do
523631
bracketOnError acquireHasBlockIO releaseHasBlockIO $ \hasBlockIO ->
524632
openSession tracer hasFS hasBlockIO sessionSalt sessionDirFsPath
525633

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+
526714
{- |
527715
Close a session.
528716

src/Database/LSMTree/Internal/Unsafe.hs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ module Database.LSMTree.Internal.Unsafe (
3939
, withKeepSessionOpen
4040
-- ** Implementation of public API
4141
, withOpenSession
42+
, withNewSession
43+
, withRestoreSession
4244
, openSession
45+
, newSession
46+
, restoreSession
4347
, closeSession
4448
-- * Table
4549
, Table (..)
@@ -340,6 +344,40 @@ withOpenSession tr hfs hbio salt dir k = do
340344
(openSession tr hfs hbio salt dir)
341345
closeSession
342346
k
347+
348+
{-# INLINE withNewSession #-}
349+
withNewSession ::
350+
forall m h a.
351+
(MonadSTM m, MonadMVar m, PrimMonad m, MonadMask m)
352+
=> Tracer m LSMTreeTrace
353+
-> HasFS m h
354+
-> HasBlockIO m h
355+
-> Bloom.Salt
356+
-> FsPath -- ^ Path to the session directory
357+
-> (Session m h -> m a)
358+
-> m a
359+
withNewSession tr hfs hbio salt dir k = do
360+
bracket
361+
(newSession tr hfs hbio salt dir)
362+
closeSession
363+
k
364+
365+
{-# INLINE withRestoreSession #-}
366+
withRestoreSession ::
367+
forall m h a.
368+
(MonadSTM m, MonadMVar m, PrimMonad m, MonadMask m, MonadEvaluate m)
369+
=> Tracer m LSMTreeTrace
370+
-> HasFS m h
371+
-> HasBlockIO m h
372+
-> FsPath -- ^ Path to the session directory
373+
-> (Session m h -> m a)
374+
-> m a
375+
withRestoreSession tr hfs hbio dir k = do
376+
bracket
377+
(restoreSession tr hfs hbio dir)
378+
closeSession
379+
k
380+
343381
{-# SPECIALISE openSession ::
344382
Tracer IO LSMTreeTrace
345383
-> HasFS IO h

test/Test/Database/LSMTree/Internal.hs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ import Test.Util.FS
3333
tests :: TestTree
3434
tests = testGroup "Test.Database.LSMTree.Internal" [
3535
testGroup "Session" [
36-
testProperty "newSession" newSession
37-
, testProperty "restoreSession" restoreSession
36+
testProperty "prop_newSession" prop_newSession
37+
, testProperty "prop_restoreSession" prop_restoreSession
3838
, testProperty "sessionDirLocked" sessionDirLocked
3939
, testCase "sessionDirCorrupted" sessionDirCorrupted
4040
, testCase "sessionDirDoesNotExist" sessionDirDoesNotExist
@@ -56,13 +56,13 @@ testTableConfig = defaultTableConfig {
5656
confWriteBufferAlloc = AllocNumEntries 3
5757
}
5858

59-
newSession ::
59+
prop_newSession ::
6060
Positive (Small Int)
6161
-> V.Vector (Word64, Entry Word64 Word64)
6262
-> Property
63-
newSession (Positive (Small bufferSize)) es =
63+
prop_newSession (Positive (Small bufferSize)) es =
6464
ioProperty $
65-
withTempIOHasBlockIO "newSession" $ \hfs hbio ->
65+
withTempIOHasBlockIO "prop_newSession" $ \hfs hbio ->
6666
withOpenSession nullTracer hfs hbio testSalt (FS.mkFsPath []) $ \session ->
6767
withTable session conf (updates const es')
6868
where
@@ -71,13 +71,13 @@ newSession (Positive (Small bufferSize)) es =
7171
}
7272
es' = fmap (bimap serialiseKey (bimap serialiseValue serialiseBlob)) es
7373

74-
restoreSession ::
74+
prop_restoreSession ::
7575
Positive (Small Int)
7676
-> V.Vector (Word64, Entry Word64 Word64)
7777
-> Property
78-
restoreSession (Positive (Small bufferSize)) es =
78+
prop_restoreSession (Positive (Small bufferSize)) es =
7979
ioProperty $
80-
withTempIOHasBlockIO "restoreSession" $ \hfs hbio -> do
80+
withTempIOHasBlockIO "prop_restoreSession" $ \hfs hbio -> do
8181
withOpenSession nullTracer hfs hbio testSalt (FS.mkFsPath []) $ \session1 ->
8282
withTable session1 conf (updates const es')
8383
withOpenSession nullTracer hfs hbio testSalt (FS.mkFsPath []) $ \session2 ->

0 commit comments

Comments
 (0)