{-# LANGUAGE RecordWildCards #-}
-- |
-- Module : Database.RocksDB.Internal
-- Copyright : (c) 2012-2013 The leveldb-haskell Authors
-- (c) 2014-2020 The rocksdb-haskell Authors
-- License : BSD3
-- Maintainer : jprupp@protonmail.ch
-- Stability : experimental
-- Portability : non-portable
--
module Database.RocksDB.Internal
( Config (..)
, DB (..)
-- * Smart constructors & extractors
, withOptions
, withOptionsCF
, withReadOpts
, withWriteOpts
-- * Utilities
, freeCString
, throwIfErr
, cSizeToInt
, intToCSize
, intToCInt
, cIntToInt
, boolToNum
) where
import Control.Monad
import Data.Default
import Database.RocksDB.C
import UnliftIO
import UnliftIO.Foreign
data DB = DB { rocksDB :: !RocksDB
, columnFamilies :: ![ColumnFamily]
, readOpts :: !ReadOpts
, writeOpts :: !WriteOpts
}
data Config = Config { createIfMissing :: !Bool
, errorIfExists :: !Bool
, paranoidChecks :: !Bool
, maxFiles :: !(Maybe Int)
, prefixLength :: !(Maybe Int)
} deriving (Eq, Show)
instance Default Config where
def = Config { createIfMissing = False
, errorIfExists = False
, paranoidChecks = False
, maxFiles = Nothing
, prefixLength = Nothing
}
withOptions :: MonadUnliftIO m => Config -> (Options -> m a) -> m a
withOptions Config {..} f =
bracket create_opts destroy_opts (f . fst)
where
destroy_opts (opts_ptr, maybe_pfx_extract) = liftIO $ do
c_rocksdb_options_destroy opts_ptr
forM_ maybe_pfx_extract c_rocksdb_slicetransform_destroy
create_opts = liftIO $ do
opts_ptr <- c_rocksdb_options_create
c_rocksdb_options_set_create_if_missing
opts_ptr (boolToCBool createIfMissing)
c_rocksdb_options_set_error_if_exists
opts_ptr (boolToCBool errorIfExists)
c_rocksdb_options_set_paranoid_checks
opts_ptr (boolToCBool paranoidChecks)
case maxFiles of
Nothing -> return ()
Just n -> c_rocksdb_options_set_max_open_files
opts_ptr
(intToCInt n)
maybe_pfx_extract <- case prefixLength of
Nothing -> return Nothing
Just n -> do
pfx_extract <- c_rocksdb_slicetransform_create_fixed_prefix
(intToCSize n)
return $ Just pfx_extract
return (opts_ptr, maybe_pfx_extract)
withOptionsCF :: MonadUnliftIO m => [Config] -> ([Options] -> m a) -> m a
withOptionsCF cfgs f =
go [] cfgs
where
go acc [] = f (reverse acc)
go acc (c:cs) = withOptions c $ \o -> go (o:acc) cs
withReadOpts :: MonadUnliftIO m => Maybe Snapshot -> (ReadOpts -> m a) -> m a
withReadOpts maybe_snap_ptr =
bracket
create_read_opts
(liftIO . c_rocksdb_readoptions_destroy)
where
create_read_opts = liftIO $ do
read_opts_ptr <- c_rocksdb_readoptions_create
forM_ maybe_snap_ptr $ c_rocksdb_readoptions_set_snapshot read_opts_ptr
return read_opts_ptr
withWriteOpts :: MonadUnliftIO m => (WriteOpts -> m a) -> m a
withWriteOpts =
bracket
(liftIO c_rocksdb_writeoptions_create)
(liftIO . c_rocksdb_writeoptions_destroy)
freeCString :: CString -> IO ()
freeCString = c_rocksdb_free
throwIfErr :: MonadUnliftIO m => String -> (ErrPtr -> m a) -> m a
throwIfErr s f = alloca $ \err_ptr -> do
liftIO $ poke err_ptr nullPtr
res <- f err_ptr
erra <- liftIO $ peek err_ptr
when (erra /= nullPtr) $ do
err <- liftIO $ peekCString erra
throwIO $ userError $ s ++ ": " ++ err
return res
boolToCBool :: Bool -> CBool
boolToCBool True = 1
boolToCBool False = 0
{-# INLINE boolToCBool #-}
cSizeToInt :: CSize -> Int
cSizeToInt = fromIntegral
{-# INLINE cSizeToInt #-}
intToCSize :: Int -> CSize
intToCSize = fromIntegral
{-# INLINE intToCSize #-}
intToCInt :: Int -> CInt
intToCInt = fromIntegral
{-# INLINE intToCInt #-}
cIntToInt :: CInt -> Int
cIntToInt = fromIntegral
{-# INLINE cIntToInt #-}
boolToNum :: Num b => Bool -> b
boolToNum True = fromIntegral (1 :: Int)
boolToNum False = fromIntegral (0 :: Int)
{-# INLINE boolToNum #-}