Skip to content

Commit f1709ef

Browse files
committed
Allow ResourceT for iterators and snapshots
1 parent 5379d97 commit f1709ef

File tree

5 files changed

+69
-17
lines changed

5 files changed

+69
-17
lines changed

Diff for: CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.1.4
2+
3+
* Add ResourceT support for snapshots and iterators.
4+
15
## 2.1.3
26

37
* Correct bug where database was ignoring prefix length config.

Diff for: package.yaml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: rocksdb-haskell-jprupp
2-
version: 2.1.3
2+
version: 2.1.4
33
synopsis: Haskell bindings for RocksDB
44
description: See README at <https://github.com/jprupp/rocksdb-haskell#readme>
55
maintainer: Jean-Pierre Rupp <[email protected]>
@@ -19,6 +19,7 @@ dependencies:
1919
- bytestring
2020
- data-default
2121
- directory
22+
- resourcet
2223
- unliftio
2324

2425
library:

Diff for: rocksdb-haskell-jprupp.cabal

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
cabal-version: 1.12
22

3-
-- This file has been generated from package.yaml by hpack version 0.33.0.
3+
-- This file has been generated from package.yaml by hpack version 0.34.4.
44
--
55
-- see: https://github.com/sol/hpack
66
--
7-
-- hash: 094c0ad3842293bfb0c2b11fda87cf96076e2f497046a7e82023bfd4d96d4e0d
7+
-- hash: 48b49def634c00156ec5f8bc2f4a8c92caf0aca334fca3cef6507f51febe9867
88

99
name: rocksdb-haskell-jprupp
10-
version: 2.1.3
10+
version: 2.1.4
1111
synopsis: Haskell bindings for RocksDB
1212
description: See README at <https://github.com/jprupp/rocksdb-haskell#readme>
1313
category: Database, FFI
@@ -45,6 +45,7 @@ library
4545
, bytestring
4646
, data-default
4747
, directory
48+
, resourcet
4849
, unliftio
4950
default-language: Haskell2010
5051

@@ -63,6 +64,7 @@ test-suite spec
6364
, data-default
6465
, directory
6566
, hspec
67+
, resourcet
6668
, rocksdb-haskell-jprupp
6769
, string-conversions
6870
, unliftio

Diff for: src/Database/RocksDB/Base.hs

+25-10
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ module Database.RocksDB.Base
3333
, get
3434
, getCF
3535
, withSnapshot
36+
, snapshot
37+
, createSnapshot
38+
, releaseSnapshot
3639

3740
-- * Administrative Functions
3841
, Property (..), getProperty
@@ -44,7 +47,7 @@ module Database.RocksDB.Base
4447
, module Database.RocksDB.Iterator
4548
) where
4649

47-
import Control.Monad (when, (>=>), forM)
50+
import Control.Monad (forM, when, (>=>))
4851
import Data.ByteString (ByteString)
4952
import qualified Data.ByteString as BS
5053
import Data.ByteString.Internal (ByteString (..))
@@ -55,6 +58,7 @@ import Database.RocksDB.Iterator
5558
import UnliftIO
5659
import UnliftIO.Directory
5760
import UnliftIO.Foreign
61+
import UnliftIO.Resource
5862

5963
-- | Properties exposed by RocksDB
6064
data Property = NumFilesAtLevel Int | Stats | SSTables
@@ -166,14 +170,25 @@ withDBCF path config cf_cfgs f =
166170
-- | Run an action with a snapshot of the database.
167171
-- The 'DB' object is not valid after the action ends.
168172
withSnapshot :: MonadUnliftIO m => DB -> (DB -> m a) -> m a
169-
withSnapshot db@DB{rocksDB = db_ptr} f =
170-
bracket create_snapshot release_snapshot (f . fst)
171-
where
172-
release_snapshot = liftIO . c_rocksdb_release_snapshot db_ptr . snd
173-
create_snapshot = liftIO $ do
174-
snap_ptr <- c_rocksdb_create_snapshot db_ptr
175-
withReadOpts (Just snap_ptr) $ \read_opts ->
176-
return (db{readOpts = read_opts}, snap_ptr)
173+
withSnapshot db f =
174+
bracket (createSnapshot db) releaseSnapshot (f . fst)
175+
176+
-- | The 'DB' snapshot is not valid outside of 'MonadResource'.
177+
snapshot :: (MonadIO m, MonadResource m) => DB -> m DB
178+
snapshot db =
179+
fst . snd <$> allocate (createSnapshot db) releaseSnapshot
180+
181+
-- | Manually create an unmanaged snapshot.
182+
createSnapshot :: MonadIO m => DB -> m (DB, Snapshot)
183+
createSnapshot db@DB{rocksDB = db_ptr} = liftIO $ do
184+
snap_ptr <- c_rocksdb_create_snapshot db_ptr
185+
withReadOpts (Just snap_ptr) $ \read_opts ->
186+
return (db{readOpts = read_opts}, snap_ptr)
187+
188+
-- | Function to release an unmanaged snapshot.
189+
releaseSnapshot :: MonadIO m => (DB, Snapshot) -> m ()
190+
releaseSnapshot (DB{rocksDB = db_ptr}, snap_ptr) =
191+
liftIO $ c_rocksdb_release_snapshot db_ptr snap_ptr
177192

178193
-- | Get a DB property.
179194
getProperty :: MonadIO m => DB -> Property -> m (Maybe ByteString)
@@ -340,5 +355,5 @@ withStrings :: MonadUnliftIO m => [String] -> ([CString] -> m a) -> m a
340355
withStrings ss f =
341356
go [] ss
342357
where
343-
go acc [] = f (reverse acc)
358+
go acc [] = f (reverse acc)
344359
go acc (x:xs) = withCString x $ \p -> go (p:acc) xs

Diff for: src/Database/RocksDB/Iterator.hs

+33-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ module Database.RocksDB.Iterator
1515
( Iterator
1616
, withIter
1717
, withIterCF
18+
, iter
19+
, iterCF
20+
, iterator
21+
, createIterator
22+
, destroyIterator
1823
, iterEntry
1924
, iterFirst
2025
, iterGetError
@@ -39,6 +44,7 @@ import Foreign.C.Error (throwErrnoIfNull)
3944
import Foreign.C.String (CString, peekCString)
4045
import Foreign.C.Types (CSize)
4146
import UnliftIO
47+
import UnliftIO.Resource
4248

4349
-- | Create 'Iterator' and use it.
4450
--
@@ -53,6 +59,13 @@ withIter db = withIterCommon db Nothing
5359
withIterCF :: MonadUnliftIO m => DB -> ColumnFamily -> (Iterator -> m a) -> m a
5460
withIterCF db cf = withIterCommon db (Just cf)
5561

62+
-- | Variation on 'iterator' below.
63+
iter :: (MonadIO m, MonadResource m) => DB -> m Iterator
64+
iter db = iterator db Nothing
65+
66+
iterCF :: (MonadIO m, MonadResource m) => DB -> ColumnFamily -> m Iterator
67+
iterCF db cf = iterator db (Just cf)
68+
5669
withIterCommon :: MonadUnliftIO m
5770
=> DB
5871
-> Maybe ColumnFamily
@@ -67,6 +80,23 @@ withIterCommon DB{rocksDB = rocks_db, readOpts = read_opts} mcf =
6780
Just cf -> c_rocksdb_create_iterator_cf rocks_db read_opts cf
6881
Nothing -> c_rocksdb_create_iterator rocks_db read_opts
6982

83+
-- | Iterator is not valid outside of 'ResourceT' context.
84+
iterator :: (MonadIO m, MonadResource m)
85+
=> DB -> Maybe ColumnFamily -> m Iterator
86+
iterator db mcf =
87+
snd <$> allocate (createIterator db mcf) destroyIterator
88+
89+
-- | Manually create unmanaged iterator.
90+
createIterator :: MonadIO m => DB -> Maybe ColumnFamily -> m Iterator
91+
createIterator DB{rocksDB = rocks_db, readOpts = read_opts} mcf = liftIO $
92+
throwErrnoIfNull "create_iterator" $ case mcf of
93+
Just cf -> c_rocksdb_create_iterator_cf rocks_db read_opts cf
94+
Nothing -> c_rocksdb_create_iterator rocks_db read_opts
95+
96+
-- | Destroy unmanaged iterator.
97+
destroyIterator :: MonadIO m => Iterator -> m ()
98+
destroyIterator = liftIO . c_rocksdb_iter_destroy
99+
70100
-- | An iterator is either positioned at a key/value pair, or not valid. This
71101
-- function returns /true/ iff the iterator is valid.
72102
iterValid :: MonadIO m => Iterator -> m Bool
@@ -127,9 +157,9 @@ iterValue = liftIO . flip iterString c_rocksdb_iter_value
127157
-- | Return the current entry as a pair, if the iterator is currently positioned
128158
-- at an entry, ie. 'iterValid'.
129159
iterEntry :: MonadIO m => Iterator -> m (Maybe (ByteString, ByteString))
130-
iterEntry iter = liftIO $ do
131-
mkey <- iterKey iter
132-
mval <- iterValue iter
160+
iterEntry it = liftIO $ do
161+
mkey <- iterKey it
162+
mval <- iterValue it
133163
return $ (,) <$> mkey <*> mval
134164

135165
-- | Check for errors

0 commit comments

Comments
 (0)