packages feed

leveldb-haskell 0.2.0 → 0.3.0

raw patch · 16 files changed

+1831/−1347 lines, 16 filesdep +asyncdep +leveldb-haskellnew-component:exe:leveldb-example-comparatornew-component:exe:leveldb-example-featuresnew-component:exe:leveldb-example-filterpolicynew-component:exe:leveldb-example-iterforkioPVP ok

version bump matches the API change (PVP)

Dependencies added: async, leveldb-haskell

API changes (from Hackage documentation)

- Database.LevelDB: Comparator :: (ByteString -> ByteString -> Ordering) -> Comparator
- Database.LevelDB: Del :: ByteString -> BatchOp
- Database.LevelDB: FilterPolicy :: String -> ([ByteString] -> ByteString) -> (ByteString -> ByteString -> Bool) -> FilterPolicy
- Database.LevelDB: NoCompression :: Compression
- Database.LevelDB: NumFilesAtLevel :: Int -> Property
- Database.LevelDB: Options :: !Int -> !Int -> !Int -> !(Maybe Comparator) -> !Compression -> !Bool -> !Bool -> !Int -> !Bool -> !Int -> !(Maybe (Either BloomFilter FilterPolicy)) -> Options
- Database.LevelDB: Put :: ByteString -> ByteString -> BatchOp
- Database.LevelDB: ReadOptions :: !Bool -> !Bool -> !(Maybe Snapshot) -> ReadOptions
- Database.LevelDB: SSTables :: Property
- Database.LevelDB: Snappy :: Compression
- Database.LevelDB: Stats :: Property
- Database.LevelDB: WriteOptions :: !Bool -> WriteOptions
- Database.LevelDB: approximateSize :: MonadResource m => DB -> Range -> m Int64
- Database.LevelDB: blockRestartInterval :: Options -> !Int
- Database.LevelDB: blockSize :: Options -> !Int
- Database.LevelDB: bloomFilter :: MonadResource m => Int -> m BloomFilter
- Database.LevelDB: cacheSize :: Options -> !Int
- Database.LevelDB: class (MonadThrow m, MonadUnsafeIO m, MonadIO m, Applicative m) => MonadResource (m :: * -> *)
- Database.LevelDB: comparator :: Options -> !(Maybe Comparator)
- Database.LevelDB: compression :: Options -> !Compression
- Database.LevelDB: createFilter :: FilterPolicy -> [ByteString] -> ByteString
- Database.LevelDB: createIfMissing :: Options -> !Bool
- Database.LevelDB: createSnapshot :: MonadResource m => DB -> m Snapshot
- Database.LevelDB: createSnapshot' :: MonadResource m => DB -> m (ReleaseKey, Snapshot)
- Database.LevelDB: data BatchOp
- Database.LevelDB: data Compression
- Database.LevelDB: data DB
- Database.LevelDB: data FilterPolicy
- Database.LevelDB: data Iterator
- Database.LevelDB: data Options
- Database.LevelDB: data Property
- Database.LevelDB: data ReadOptions
- Database.LevelDB: data Snapshot
- Database.LevelDB: data WriteOptions
- Database.LevelDB: defaultOptions :: Options
- Database.LevelDB: defaultReadOptions :: ReadOptions
- Database.LevelDB: defaultWriteOptions :: WriteOptions
- Database.LevelDB: delete :: MonadResource m => DB -> WriteOptions -> ByteString -> m ()
- Database.LevelDB: destroy :: MonadResource m => FilePath -> Options -> m ()
- Database.LevelDB: errorIfExists :: Options -> !Bool
- Database.LevelDB: fillCache :: ReadOptions -> !Bool
- Database.LevelDB: filterPolicy :: Options -> !(Maybe (Either BloomFilter FilterPolicy))
- Database.LevelDB: fpName :: FilterPolicy -> String
- Database.LevelDB: get :: MonadResource m => DB -> ReadOptions -> ByteString -> m (Maybe ByteString)
- Database.LevelDB: getProperty :: MonadResource m => DB -> Property -> m (Maybe ByteString)
- Database.LevelDB: instance Default Options
- Database.LevelDB: instance Default ReadOptions
- Database.LevelDB: instance Default WriteOptions
- Database.LevelDB: instance Eq BatchOp
- Database.LevelDB: instance Eq Compression
- Database.LevelDB: instance Eq DB
- Database.LevelDB: instance Eq Iterator
- Database.LevelDB: instance Eq Property
- Database.LevelDB: instance Eq ReadOptions
- Database.LevelDB: instance Eq Snapshot
- Database.LevelDB: instance Eq WriteOptions
- Database.LevelDB: instance Show BatchOp
- Database.LevelDB: instance Show Compression
- Database.LevelDB: instance Show Property
- Database.LevelDB: instance Show WriteOptions
- Database.LevelDB: iterFirst :: MonadResource m => Iterator -> m ()
- Database.LevelDB: iterGetError :: MonadResource m => Iterator -> m (Maybe ByteString)
- Database.LevelDB: iterItems :: MonadResource m => Iterator -> m [(ByteString, ByteString)]
- Database.LevelDB: iterKey :: MonadResource m => Iterator -> m (Maybe ByteString)
- Database.LevelDB: iterKeys :: MonadResource m => Iterator -> m [ByteString]
- Database.LevelDB: iterLast :: MonadResource m => Iterator -> m ()
- Database.LevelDB: iterNext :: MonadResource m => Iterator -> m ()
- Database.LevelDB: iterOpen :: MonadResource m => DB -> ReadOptions -> m Iterator
- Database.LevelDB: iterOpen' :: MonadResource m => DB -> ReadOptions -> m (ReleaseKey, Iterator)
- Database.LevelDB: iterPrev :: MonadResource m => Iterator -> m ()
- Database.LevelDB: iterSeek :: MonadResource m => Iterator -> ByteString -> m ()
- Database.LevelDB: iterValid :: MonadResource m => Iterator -> m Bool
- Database.LevelDB: iterValue :: MonadResource m => Iterator -> m (Maybe ByteString)
- Database.LevelDB: iterValues :: MonadResource m => Iterator -> m [ByteString]
- Database.LevelDB: keyMayMatch :: FilterPolicy -> ByteString -> ByteString -> Bool
- Database.LevelDB: liftResourceT :: MonadResource m => ResourceT IO a -> m a
- Database.LevelDB: mapIter :: MonadResource m => (Iterator -> m a) -> Iterator -> m [a]
- Database.LevelDB: maxOpenFiles :: Options -> !Int
- Database.LevelDB: newtype Comparator
- Database.LevelDB: open :: MonadResource m => FilePath -> Options -> m DB
- Database.LevelDB: paranoidChecks :: Options -> !Bool
- Database.LevelDB: put :: MonadResource m => DB -> WriteOptions -> ByteString -> ByteString -> m ()
- Database.LevelDB: repair :: MonadResource m => FilePath -> Options -> m ()
- Database.LevelDB: resourceForkIO :: MonadBaseControl IO m => ResourceT m () -> ResourceT m ThreadId
- Database.LevelDB: runResourceT :: MonadBaseControl IO m => ResourceT m a -> m a
- Database.LevelDB: sync :: WriteOptions -> !Bool
- Database.LevelDB: type Range = (ByteString, ByteString)
- Database.LevelDB: type WriteBatch = [BatchOp]
- Database.LevelDB: useSnapshot :: ReadOptions -> !(Maybe Snapshot)
- Database.LevelDB: verifyCheckSums :: ReadOptions -> !Bool
- Database.LevelDB: version :: MonadResource m => m (Int, Int)
- Database.LevelDB: withIterator :: MonadResource m => DB -> ReadOptions -> (Iterator -> m a) -> m a
- Database.LevelDB: withSnapshot :: MonadResource m => DB -> (Snapshot -> m a) -> m a
- Database.LevelDB: write :: MonadResource m => DB -> WriteOptions -> WriteBatch -> m ()
- Database.LevelDB: writeBufferSize :: Options -> !Int
+ Database.LevelDB.Base: Comparator :: (ByteString -> ByteString -> Ordering) -> Comparator
+ Database.LevelDB.Base: Del :: ByteString -> BatchOp
+ Database.LevelDB.Base: FilterPolicy :: String -> ([ByteString] -> ByteString) -> (ByteString -> ByteString -> Bool) -> FilterPolicy
+ Database.LevelDB.Base: NoCompression :: Compression
+ Database.LevelDB.Base: NumFilesAtLevel :: Int -> Property
+ Database.LevelDB.Base: Options :: !Int -> !Int -> !Int -> !(Maybe Comparator) -> !Compression -> !Bool -> !Bool -> !Int -> !Bool -> !Int -> !(Maybe (Either BloomFilter FilterPolicy)) -> Options
+ Database.LevelDB.Base: Put :: ByteString -> ByteString -> BatchOp
+ Database.LevelDB.Base: ReadOptions :: !Bool -> !Bool -> !(Maybe Snapshot) -> ReadOptions
+ Database.LevelDB.Base: SSTables :: Property
+ Database.LevelDB.Base: Snappy :: Compression
+ Database.LevelDB.Base: Stats :: Property
+ Database.LevelDB.Base: WriteOptions :: !Bool -> WriteOptions
+ Database.LevelDB.Base: approximateSize :: MonadIO m => DB -> Range -> m Int64
+ Database.LevelDB.Base: blockRestartInterval :: Options -> !Int
+ Database.LevelDB.Base: blockSize :: Options -> !Int
+ Database.LevelDB.Base: cacheSize :: Options -> !Int
+ Database.LevelDB.Base: close :: MonadIO m => DB -> m ()
+ Database.LevelDB.Base: comparator :: Options -> !(Maybe Comparator)
+ Database.LevelDB.Base: compression :: Options -> !Compression
+ Database.LevelDB.Base: createBloomFilter :: MonadIO m => Int -> m BloomFilter
+ Database.LevelDB.Base: createFilter :: FilterPolicy -> [ByteString] -> ByteString
+ Database.LevelDB.Base: createIfMissing :: Options -> !Bool
+ Database.LevelDB.Base: createSnapshot :: MonadIO m => DB -> m Snapshot
+ Database.LevelDB.Base: data BatchOp
+ Database.LevelDB.Base: data BloomFilter
+ Database.LevelDB.Base: data Compression
+ Database.LevelDB.Base: data DB
+ Database.LevelDB.Base: data FilterPolicy
+ Database.LevelDB.Base: data Options
+ Database.LevelDB.Base: data Property
+ Database.LevelDB.Base: data ReadOptions
+ Database.LevelDB.Base: data Snapshot
+ Database.LevelDB.Base: data WriteOptions
+ Database.LevelDB.Base: defaultOptions :: Options
+ Database.LevelDB.Base: defaultReadOptions :: ReadOptions
+ Database.LevelDB.Base: defaultWriteOptions :: WriteOptions
+ Database.LevelDB.Base: delete :: MonadIO m => DB -> WriteOptions -> ByteString -> m ()
+ Database.LevelDB.Base: destroy :: MonadIO m => FilePath -> Options -> m ()
+ Database.LevelDB.Base: errorIfExists :: Options -> !Bool
+ Database.LevelDB.Base: fillCache :: ReadOptions -> !Bool
+ Database.LevelDB.Base: filterPolicy :: Options -> !(Maybe (Either BloomFilter FilterPolicy))
+ Database.LevelDB.Base: fpName :: FilterPolicy -> String
+ Database.LevelDB.Base: get :: MonadIO m => DB -> ReadOptions -> ByteString -> m (Maybe ByteString)
+ Database.LevelDB.Base: getProperty :: MonadIO m => DB -> Property -> m (Maybe ByteString)
+ Database.LevelDB.Base: keyMayMatch :: FilterPolicy -> ByteString -> ByteString -> Bool
+ Database.LevelDB.Base: maxOpenFiles :: Options -> !Int
+ Database.LevelDB.Base: newtype Comparator
+ Database.LevelDB.Base: open :: MonadIO m => FilePath -> Options -> m DB
+ Database.LevelDB.Base: paranoidChecks :: Options -> !Bool
+ Database.LevelDB.Base: put :: MonadIO m => DB -> WriteOptions -> ByteString -> ByteString -> m ()
+ Database.LevelDB.Base: releaseBloomFilter :: MonadIO m => BloomFilter -> m ()
+ Database.LevelDB.Base: releaseSnapshot :: MonadIO m => DB -> Snapshot -> m ()
+ Database.LevelDB.Base: repair :: MonadIO m => FilePath -> Options -> m ()
+ Database.LevelDB.Base: sync :: WriteOptions -> !Bool
+ Database.LevelDB.Base: type Range = (ByteString, ByteString)
+ Database.LevelDB.Base: type WriteBatch = [BatchOp]
+ Database.LevelDB.Base: useSnapshot :: ReadOptions -> !(Maybe Snapshot)
+ Database.LevelDB.Base: verifyCheckSums :: ReadOptions -> !Bool
+ Database.LevelDB.Base: version :: MonadIO m => m (Int, Int)
+ Database.LevelDB.Base: withSnapshot :: MonadIO m => DB -> (Snapshot -> IO a) -> m a
+ Database.LevelDB.Base: write :: MonadIO m => DB -> WriteOptions -> WriteBatch -> m ()
+ Database.LevelDB.Base: writeBufferSize :: Options -> !Int
+ Database.LevelDB.C: CompressionOpt :: CInt -> CompressionOpt
+ Database.LevelDB.C: c_leveldb_approximate_sizes :: LevelDBPtr -> CInt -> Ptr CString -> Ptr CSize -> Ptr CString -> Ptr CSize -> Ptr Word64 -> IO ()
+ Database.LevelDB.C: c_leveldb_cache_create_lru :: CSize -> IO CachePtr
+ Database.LevelDB.C: c_leveldb_cache_destroy :: CachePtr -> IO ()
+ Database.LevelDB.C: c_leveldb_close :: LevelDBPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_comparator_create :: StatePtr -> FunPtr Destructor -> FunPtr CompareFun -> FunPtr NameFun -> IO ComparatorPtr
+ Database.LevelDB.C: c_leveldb_comparator_destroy :: ComparatorPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_create_iterator :: LevelDBPtr -> ReadOptionsPtr -> IO IteratorPtr
+ Database.LevelDB.C: c_leveldb_create_snapshot :: LevelDBPtr -> IO SnapshotPtr
+ Database.LevelDB.C: c_leveldb_delete :: LevelDBPtr -> WriteOptionsPtr -> Key -> CSize -> ErrPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_destroy_db :: OptionsPtr -> DBName -> ErrPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_filterpolicy_create :: StatePtr -> FunPtr Destructor -> FunPtr CreateFilterFun -> FunPtr KeyMayMatchFun -> FunPtr NameFun -> IO FilterPolicyPtr
+ Database.LevelDB.C: c_leveldb_filterpolicy_create_bloom :: CInt -> IO FilterPolicyPtr
+ Database.LevelDB.C: c_leveldb_filterpolicy_destroy :: FilterPolicyPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_get :: LevelDBPtr -> ReadOptionsPtr -> Key -> CSize -> Ptr CSize -> ErrPtr -> IO CString
+ Database.LevelDB.C: c_leveldb_iter_destroy :: IteratorPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_iter_get_error :: IteratorPtr -> ErrPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_iter_key :: IteratorPtr -> Ptr CSize -> IO Key
+ Database.LevelDB.C: c_leveldb_iter_next :: IteratorPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_iter_prev :: IteratorPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_iter_seek :: IteratorPtr -> Key -> CSize -> IO ()
+ Database.LevelDB.C: c_leveldb_iter_seek_to_first :: IteratorPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_iter_seek_to_last :: IteratorPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_iter_valid :: IteratorPtr -> IO CUChar
+ Database.LevelDB.C: c_leveldb_iter_value :: IteratorPtr -> Ptr CSize -> IO Val
+ Database.LevelDB.C: c_leveldb_major_version :: IO CInt
+ Database.LevelDB.C: c_leveldb_minor_version :: IO CInt
+ Database.LevelDB.C: c_leveldb_open :: OptionsPtr -> DBName -> ErrPtr -> IO LevelDBPtr
+ Database.LevelDB.C: c_leveldb_options_create :: IO OptionsPtr
+ Database.LevelDB.C: c_leveldb_options_destroy :: OptionsPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_options_set_block_restart_interval :: OptionsPtr -> CInt -> IO ()
+ Database.LevelDB.C: c_leveldb_options_set_block_size :: OptionsPtr -> CSize -> IO ()
+ Database.LevelDB.C: c_leveldb_options_set_cache :: OptionsPtr -> CachePtr -> IO ()
+ Database.LevelDB.C: c_leveldb_options_set_comparator :: OptionsPtr -> ComparatorPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_options_set_compression :: OptionsPtr -> CompressionOpt -> IO ()
+ Database.LevelDB.C: c_leveldb_options_set_create_if_missing :: OptionsPtr -> CUChar -> IO ()
+ Database.LevelDB.C: c_leveldb_options_set_error_if_exists :: OptionsPtr -> CUChar -> IO ()
+ Database.LevelDB.C: c_leveldb_options_set_filter_policy :: OptionsPtr -> FilterPolicyPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_options_set_info_log :: OptionsPtr -> LoggerPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_options_set_max_open_files :: OptionsPtr -> CInt -> IO ()
+ Database.LevelDB.C: c_leveldb_options_set_paranoid_checks :: OptionsPtr -> CUChar -> IO ()
+ Database.LevelDB.C: c_leveldb_options_set_write_buffer_size :: OptionsPtr -> CSize -> IO ()
+ Database.LevelDB.C: c_leveldb_property_value :: LevelDBPtr -> CString -> IO CString
+ Database.LevelDB.C: c_leveldb_put :: LevelDBPtr -> WriteOptionsPtr -> Key -> CSize -> Val -> CSize -> ErrPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_readoptions_create :: IO ReadOptionsPtr
+ Database.LevelDB.C: c_leveldb_readoptions_destroy :: ReadOptionsPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_readoptions_set_fill_cache :: ReadOptionsPtr -> CUChar -> IO ()
+ Database.LevelDB.C: c_leveldb_readoptions_set_snapshot :: ReadOptionsPtr -> SnapshotPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_readoptions_set_verify_checksums :: ReadOptionsPtr -> CUChar -> IO ()
+ Database.LevelDB.C: c_leveldb_release_snapshot :: LevelDBPtr -> SnapshotPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_repair_db :: OptionsPtr -> DBName -> ErrPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_write :: LevelDBPtr -> WriteOptionsPtr -> WriteBatchPtr -> ErrPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_writebatch_clear :: WriteBatchPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_writebatch_create :: IO WriteBatchPtr
+ Database.LevelDB.C: c_leveldb_writebatch_delete :: WriteBatchPtr -> Key -> CSize -> IO ()
+ Database.LevelDB.C: c_leveldb_writebatch_destroy :: WriteBatchPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_writebatch_iterate :: WriteBatchPtr -> Ptr () -> FunPtr (Ptr () -> Key -> CSize -> Val -> CSize) -> FunPtr (Ptr () -> Key -> CSize) -> IO ()
+ Database.LevelDB.C: c_leveldb_writebatch_put :: WriteBatchPtr -> Key -> CSize -> Val -> CSize -> IO ()
+ Database.LevelDB.C: c_leveldb_writeoptions_create :: IO WriteOptionsPtr
+ Database.LevelDB.C: c_leveldb_writeoptions_destroy :: WriteOptionsPtr -> IO ()
+ Database.LevelDB.C: c_leveldb_writeoptions_set_sync :: WriteOptionsPtr -> CUChar -> IO ()
+ Database.LevelDB.C: compressionOpt :: CompressionOpt -> CInt
+ Database.LevelDB.C: data LCache
+ Database.LevelDB.C: data LComparator
+ Database.LevelDB.C: data LFilterPolicy
+ Database.LevelDB.C: data LIterator
+ Database.LevelDB.C: data LLogger
+ Database.LevelDB.C: data LOptions
+ Database.LevelDB.C: data LReadOptions
+ Database.LevelDB.C: data LSnapshot
+ Database.LevelDB.C: data LWriteBatch
+ Database.LevelDB.C: data LWriteOptions
+ Database.LevelDB.C: data LevelDB
+ Database.LevelDB.C: instance Eq CompressionOpt
+ Database.LevelDB.C: instance Show CompressionOpt
+ Database.LevelDB.C: mkCF :: CreateFilterFun -> IO (FunPtr CreateFilterFun)
+ Database.LevelDB.C: mkCmp :: CompareFun -> IO (FunPtr CompareFun)
+ Database.LevelDB.C: mkDest :: Destructor -> IO (FunPtr Destructor)
+ Database.LevelDB.C: mkKMM :: KeyMayMatchFun -> IO (FunPtr KeyMayMatchFun)
+ Database.LevelDB.C: mkName :: NameFun -> IO (FunPtr NameFun)
+ Database.LevelDB.C: newtype CompressionOpt
+ Database.LevelDB.C: noCompression :: CompressionOpt
+ Database.LevelDB.C: snappyCompression :: CompressionOpt
+ Database.LevelDB.C: type CachePtr = Ptr LCache
+ Database.LevelDB.C: type ComparatorPtr = Ptr LComparator
+ Database.LevelDB.C: type CompareFun = StatePtr -> CString -> CSize -> CString -> CSize -> IO CInt
+ Database.LevelDB.C: type CreateFilterFun = StatePtr -> Ptr CString -> Ptr CSize -> CInt -> Ptr CSize -> IO CString
+ Database.LevelDB.C: type DBName = CString
+ Database.LevelDB.C: type Destructor = StatePtr -> ()
+ Database.LevelDB.C: type ErrPtr = Ptr CString
+ Database.LevelDB.C: type FilterPolicyPtr = Ptr LFilterPolicy
+ Database.LevelDB.C: type IteratorPtr = Ptr LIterator
+ Database.LevelDB.C: type Key = CString
+ Database.LevelDB.C: type KeyMayMatchFun = StatePtr -> CString -> CSize -> CString -> CSize -> IO CUChar
+ Database.LevelDB.C: type LevelDBPtr = Ptr LevelDB
+ Database.LevelDB.C: type LoggerPtr = Ptr LLogger
+ Database.LevelDB.C: type NameFun = StatePtr -> CString
+ Database.LevelDB.C: type OptionsPtr = Ptr LOptions
+ Database.LevelDB.C: type ReadOptionsPtr = Ptr LReadOptions
+ Database.LevelDB.C: type SnapshotPtr = Ptr LSnapshot
+ Database.LevelDB.C: type StatePtr = Ptr ()
+ Database.LevelDB.C: type Val = CString
+ Database.LevelDB.C: type WriteBatchPtr = Ptr LWriteBatch
+ Database.LevelDB.C: type WriteOptionsPtr = Ptr LWriteOptions
+ Database.LevelDB.Internal: DB :: LevelDBPtr -> Options' -> DB
+ Database.LevelDB.Internal: Options' :: !OptionsPtr -> !(Maybe CachePtr) -> !(Maybe Comparator') -> !(Maybe (Either FilterPolicyPtr FilterPolicy')) -> Options'
+ Database.LevelDB.Internal: _cachePtr :: Options' -> !(Maybe CachePtr)
+ Database.LevelDB.Internal: _comp :: Options' -> !(Maybe Comparator')
+ Database.LevelDB.Internal: _fpPtr :: Options' -> !(Maybe (Either FilterPolicyPtr FilterPolicy'))
+ Database.LevelDB.Internal: _optsPtr :: Options' -> !OptionsPtr
+ Database.LevelDB.Internal: boolToNum :: Num b => Bool -> b
+ Database.LevelDB.Internal: cIntToInt :: CInt -> Int
+ Database.LevelDB.Internal: cSizeToInt :: CSize -> Int
+ Database.LevelDB.Internal: data Comparator'
+ Database.LevelDB.Internal: data DB
+ Database.LevelDB.Internal: data FilterPolicy'
+ Database.LevelDB.Internal: data Options'
+ Database.LevelDB.Internal: freeCReadOpts :: ReadOptionsPtr -> IO ()
+ Database.LevelDB.Internal: freeComparator :: Comparator' -> IO ()
+ Database.LevelDB.Internal: freeFilterPolicy :: FilterPolicy' -> IO ()
+ Database.LevelDB.Internal: freeOpts :: Options' -> IO ()
+ Database.LevelDB.Internal: instance Eq DB
+ Database.LevelDB.Internal: intToCInt :: Int -> CInt
+ Database.LevelDB.Internal: intToCSize :: Int -> CSize
+ Database.LevelDB.Internal: mkCReadOpts :: ReadOptions -> IO ReadOptionsPtr
+ Database.LevelDB.Internal: mkComparator :: String -> (ByteString -> ByteString -> Ordering) -> IO Comparator'
+ Database.LevelDB.Internal: mkCompareFun :: (ByteString -> ByteString -> Ordering) -> CompareFun
+ Database.LevelDB.Internal: mkCreateFilterFun :: ([ByteString] -> ByteString) -> CreateFilterFun
+ Database.LevelDB.Internal: mkFilterPolicy :: FilterPolicy -> IO FilterPolicy'
+ Database.LevelDB.Internal: mkKeyMayMatchFun :: (ByteString -> ByteString -> Bool) -> KeyMayMatchFun
+ Database.LevelDB.Internal: mkOpts :: Options -> IO Options'
+ Database.LevelDB.Internal: throwIfErr :: String -> (ErrPtr -> IO a) -> IO a
+ Database.LevelDB.Internal: withCReadOpts :: ReadOptions -> (ReadOptionsPtr -> IO a) -> IO a
+ Database.LevelDB.Internal: withCWriteOpts :: WriteOptions -> (WriteOptionsPtr -> IO a) -> IO a
+ Database.LevelDB.Iterator: createIter :: MonadIO m => DB -> ReadOptions -> m Iterator
+ Database.LevelDB.Iterator: data Iterator
+ Database.LevelDB.Iterator: instance Eq Iterator
+ Database.LevelDB.Iterator: iterEntry :: MonadIO m => Iterator -> m (Maybe (ByteString, ByteString))
+ Database.LevelDB.Iterator: iterFirst :: MonadIO m => Iterator -> m ()
+ Database.LevelDB.Iterator: iterGetError :: MonadIO m => Iterator -> m (Maybe ByteString)
+ Database.LevelDB.Iterator: iterItems :: (Functor m, MonadIO m) => Iterator -> m [(ByteString, ByteString)]
+ Database.LevelDB.Iterator: iterKey :: MonadIO m => Iterator -> m (Maybe ByteString)
+ Database.LevelDB.Iterator: iterKeys :: (Functor m, MonadIO m) => Iterator -> m [ByteString]
+ Database.LevelDB.Iterator: iterLast :: MonadIO m => Iterator -> m ()
+ Database.LevelDB.Iterator: iterNext :: MonadIO m => Iterator -> m ()
+ Database.LevelDB.Iterator: iterPrev :: MonadIO m => Iterator -> m ()
+ Database.LevelDB.Iterator: iterSeek :: MonadIO m => Iterator -> ByteString -> m ()
+ Database.LevelDB.Iterator: iterValid :: MonadIO m => Iterator -> m Bool
+ Database.LevelDB.Iterator: iterValue :: MonadIO m => Iterator -> m (Maybe ByteString)
+ Database.LevelDB.Iterator: iterValues :: (Functor m, MonadIO m) => Iterator -> m [ByteString]
+ Database.LevelDB.Iterator: mapIter :: MonadIO m => (Iterator -> m a) -> Iterator -> m [a]
+ Database.LevelDB.Iterator: releaseIter :: MonadIO m => Iterator -> m ()
+ Database.LevelDB.Iterator: withIter :: MonadIO m => DB -> ReadOptions -> (Iterator -> IO a) -> m a
+ Database.LevelDB.MonadResource: Comparator :: (ByteString -> ByteString -> Ordering) -> Comparator
+ Database.LevelDB.MonadResource: Del :: ByteString -> BatchOp
+ Database.LevelDB.MonadResource: FilterPolicy :: String -> ([ByteString] -> ByteString) -> (ByteString -> ByteString -> Bool) -> FilterPolicy
+ Database.LevelDB.MonadResource: NoCompression :: Compression
+ Database.LevelDB.MonadResource: NumFilesAtLevel :: Int -> Property
+ Database.LevelDB.MonadResource: Options :: !Int -> !Int -> !Int -> !(Maybe Comparator) -> !Compression -> !Bool -> !Bool -> !Int -> !Bool -> !Int -> !(Maybe (Either BloomFilter FilterPolicy)) -> Options
+ Database.LevelDB.MonadResource: Put :: ByteString -> ByteString -> BatchOp
+ Database.LevelDB.MonadResource: ReadOptions :: !Bool -> !Bool -> !(Maybe Snapshot) -> ReadOptions
+ Database.LevelDB.MonadResource: SSTables :: Property
+ Database.LevelDB.MonadResource: Snappy :: Compression
+ Database.LevelDB.MonadResource: Stats :: Property
+ Database.LevelDB.MonadResource: WriteOptions :: !Bool -> WriteOptions
+ Database.LevelDB.MonadResource: approximateSize :: MonadResource m => DB -> Range -> m Int64
+ Database.LevelDB.MonadResource: blockRestartInterval :: Options -> !Int
+ Database.LevelDB.MonadResource: blockSize :: Options -> !Int
+ Database.LevelDB.MonadResource: bloomFilter :: MonadResource m => Int -> m BloomFilter
+ Database.LevelDB.MonadResource: cacheSize :: Options -> !Int
+ Database.LevelDB.MonadResource: class (MonadThrow m, MonadIO m, Applicative m, MonadBase IO m) => MonadResource (m :: * -> *)
+ Database.LevelDB.MonadResource: comparator :: Options -> !(Maybe Comparator)
+ Database.LevelDB.MonadResource: compression :: Options -> !Compression
+ Database.LevelDB.MonadResource: createFilter :: FilterPolicy -> [ByteString] -> ByteString
+ Database.LevelDB.MonadResource: createIfMissing :: Options -> !Bool
+ Database.LevelDB.MonadResource: createSnapshot :: MonadResource m => DB -> m Snapshot
+ Database.LevelDB.MonadResource: createSnapshot' :: MonadResource m => DB -> m (ReleaseKey, Snapshot)
+ Database.LevelDB.MonadResource: data BatchOp
+ Database.LevelDB.MonadResource: data Compression
+ Database.LevelDB.MonadResource: data DB
+ Database.LevelDB.MonadResource: data FilterPolicy
+ Database.LevelDB.MonadResource: data Iterator
+ Database.LevelDB.MonadResource: data Options
+ Database.LevelDB.MonadResource: data Property
+ Database.LevelDB.MonadResource: data ReadOptions
+ Database.LevelDB.MonadResource: data Snapshot
+ Database.LevelDB.MonadResource: data WriteOptions
+ Database.LevelDB.MonadResource: defaultOptions :: Options
+ Database.LevelDB.MonadResource: defaultReadOptions :: ReadOptions
+ Database.LevelDB.MonadResource: defaultWriteOptions :: WriteOptions
+ Database.LevelDB.MonadResource: delete :: MonadResource m => DB -> WriteOptions -> ByteString -> m ()
+ Database.LevelDB.MonadResource: destroy :: MonadResource m => FilePath -> Options -> m ()
+ Database.LevelDB.MonadResource: errorIfExists :: Options -> !Bool
+ Database.LevelDB.MonadResource: fillCache :: ReadOptions -> !Bool
+ Database.LevelDB.MonadResource: filterPolicy :: Options -> !(Maybe (Either BloomFilter FilterPolicy))
+ Database.LevelDB.MonadResource: fpName :: FilterPolicy -> String
+ Database.LevelDB.MonadResource: get :: MonadResource m => DB -> ReadOptions -> ByteString -> m (Maybe ByteString)
+ Database.LevelDB.MonadResource: getProperty :: MonadResource m => DB -> Property -> m (Maybe ByteString)
+ Database.LevelDB.MonadResource: iterFirst :: MonadResource m => Iterator -> m ()
+ Database.LevelDB.MonadResource: iterGetError :: MonadResource m => Iterator -> m (Maybe ByteString)
+ Database.LevelDB.MonadResource: iterItems :: MonadResource m => Iterator -> m [(ByteString, ByteString)]
+ Database.LevelDB.MonadResource: iterKey :: MonadResource m => Iterator -> m (Maybe ByteString)
+ Database.LevelDB.MonadResource: iterKeys :: MonadResource m => Iterator -> m [ByteString]
+ Database.LevelDB.MonadResource: iterLast :: MonadResource m => Iterator -> m ()
+ Database.LevelDB.MonadResource: iterNext :: MonadResource m => Iterator -> m ()
+ Database.LevelDB.MonadResource: iterOpen :: MonadResource m => DB -> ReadOptions -> m Iterator
+ Database.LevelDB.MonadResource: iterOpen' :: MonadResource m => DB -> ReadOptions -> m (ReleaseKey, Iterator)
+ Database.LevelDB.MonadResource: iterPrev :: MonadResource m => Iterator -> m ()
+ Database.LevelDB.MonadResource: iterSeek :: MonadResource m => Iterator -> ByteString -> m ()
+ Database.LevelDB.MonadResource: iterValid :: MonadResource m => Iterator -> m Bool
+ Database.LevelDB.MonadResource: iterValue :: MonadResource m => Iterator -> m (Maybe ByteString)
+ Database.LevelDB.MonadResource: iterValues :: MonadResource m => Iterator -> m [ByteString]
+ Database.LevelDB.MonadResource: keyMayMatch :: FilterPolicy -> ByteString -> ByteString -> Bool
+ Database.LevelDB.MonadResource: liftResourceT :: MonadResource m => ResourceT IO a -> m a
+ Database.LevelDB.MonadResource: mapIter :: MonadResource m => (Iterator -> m a) -> Iterator -> m [a]
+ Database.LevelDB.MonadResource: maxOpenFiles :: Options -> !Int
+ Database.LevelDB.MonadResource: newtype Comparator
+ Database.LevelDB.MonadResource: open :: MonadResource m => FilePath -> Options -> m DB
+ Database.LevelDB.MonadResource: paranoidChecks :: Options -> !Bool
+ Database.LevelDB.MonadResource: put :: MonadResource m => DB -> WriteOptions -> ByteString -> ByteString -> m ()
+ Database.LevelDB.MonadResource: repair :: MonadResource m => FilePath -> Options -> m ()
+ Database.LevelDB.MonadResource: resourceForkIO :: MonadBaseControl IO m => ResourceT m () -> ResourceT m ThreadId
+ Database.LevelDB.MonadResource: runResourceT :: MonadBaseControl IO m => ResourceT m a -> m a
+ Database.LevelDB.MonadResource: sync :: WriteOptions -> !Bool
+ Database.LevelDB.MonadResource: type Range = (ByteString, ByteString)
+ Database.LevelDB.MonadResource: type WriteBatch = [BatchOp]
+ Database.LevelDB.MonadResource: useSnapshot :: ReadOptions -> !(Maybe Snapshot)
+ Database.LevelDB.MonadResource: verifyCheckSums :: ReadOptions -> !Bool
+ Database.LevelDB.MonadResource: version :: MonadResource m => m (Int, Int)
+ Database.LevelDB.MonadResource: withIterator :: MonadResource m => DB -> ReadOptions -> (Iterator -> m a) -> m a
+ Database.LevelDB.MonadResource: withSnapshot :: MonadResource m => DB -> (Snapshot -> m a) -> m a
+ Database.LevelDB.MonadResource: write :: MonadResource m => DB -> WriteOptions -> WriteBatch -> m ()
+ Database.LevelDB.MonadResource: writeBufferSize :: Options -> !Int
+ Database.LevelDB.Types: BloomFilter :: FilterPolicyPtr -> BloomFilter
+ Database.LevelDB.Types: Comparator :: (ByteString -> ByteString -> Ordering) -> Comparator
+ Database.LevelDB.Types: Del :: ByteString -> BatchOp
+ Database.LevelDB.Types: FilterPolicy :: String -> ([ByteString] -> ByteString) -> (ByteString -> ByteString -> Bool) -> FilterPolicy
+ Database.LevelDB.Types: NoCompression :: Compression
+ Database.LevelDB.Types: NumFilesAtLevel :: Int -> Property
+ Database.LevelDB.Types: Options :: !Int -> !Int -> !Int -> !(Maybe Comparator) -> !Compression -> !Bool -> !Bool -> !Int -> !Bool -> !Int -> !(Maybe (Either BloomFilter FilterPolicy)) -> Options
+ Database.LevelDB.Types: Put :: ByteString -> ByteString -> BatchOp
+ Database.LevelDB.Types: ReadOptions :: !Bool -> !Bool -> !(Maybe Snapshot) -> ReadOptions
+ Database.LevelDB.Types: SSTables :: Property
+ Database.LevelDB.Types: Snappy :: Compression
+ Database.LevelDB.Types: Snapshot :: SnapshotPtr -> Snapshot
+ Database.LevelDB.Types: Stats :: Property
+ Database.LevelDB.Types: WriteOptions :: !Bool -> WriteOptions
+ Database.LevelDB.Types: blockRestartInterval :: Options -> !Int
+ Database.LevelDB.Types: blockSize :: Options -> !Int
+ Database.LevelDB.Types: cacheSize :: Options -> !Int
+ Database.LevelDB.Types: comparator :: Options -> !(Maybe Comparator)
+ Database.LevelDB.Types: compression :: Options -> !Compression
+ Database.LevelDB.Types: createFilter :: FilterPolicy -> [ByteString] -> ByteString
+ Database.LevelDB.Types: createIfMissing :: Options -> !Bool
+ Database.LevelDB.Types: data BatchOp
+ Database.LevelDB.Types: data Compression
+ Database.LevelDB.Types: data FilterPolicy
+ Database.LevelDB.Types: data Options
+ Database.LevelDB.Types: data Property
+ Database.LevelDB.Types: data ReadOptions
+ Database.LevelDB.Types: data WriteOptions
+ Database.LevelDB.Types: defaultOptions :: Options
+ Database.LevelDB.Types: defaultReadOptions :: ReadOptions
+ Database.LevelDB.Types: defaultWriteOptions :: WriteOptions
+ Database.LevelDB.Types: errorIfExists :: Options -> !Bool
+ Database.LevelDB.Types: fillCache :: ReadOptions -> !Bool
+ Database.LevelDB.Types: filterPolicy :: Options -> !(Maybe (Either BloomFilter FilterPolicy))
+ Database.LevelDB.Types: fpName :: FilterPolicy -> String
+ Database.LevelDB.Types: instance Default Options
+ Database.LevelDB.Types: instance Default ReadOptions
+ Database.LevelDB.Types: instance Default WriteOptions
+ Database.LevelDB.Types: instance Eq BatchOp
+ Database.LevelDB.Types: instance Eq Compression
+ Database.LevelDB.Types: instance Eq Property
+ Database.LevelDB.Types: instance Eq ReadOptions
+ Database.LevelDB.Types: instance Eq Snapshot
+ Database.LevelDB.Types: instance Eq WriteOptions
+ Database.LevelDB.Types: instance Show BatchOp
+ Database.LevelDB.Types: instance Show Compression
+ Database.LevelDB.Types: instance Show Property
+ Database.LevelDB.Types: instance Show WriteOptions
+ Database.LevelDB.Types: keyMayMatch :: FilterPolicy -> ByteString -> ByteString -> Bool
+ Database.LevelDB.Types: maxOpenFiles :: Options -> !Int
+ Database.LevelDB.Types: newtype BloomFilter
+ Database.LevelDB.Types: newtype Comparator
+ Database.LevelDB.Types: newtype Snapshot
+ Database.LevelDB.Types: paranoidChecks :: Options -> !Bool
+ Database.LevelDB.Types: sync :: WriteOptions -> !Bool
+ Database.LevelDB.Types: type WriteBatch = [BatchOp]
+ Database.LevelDB.Types: useSnapshot :: ReadOptions -> !(Maybe Snapshot)
+ Database.LevelDB.Types: verifyCheckSums :: ReadOptions -> !Bool
+ Database.LevelDB.Types: writeBufferSize :: Options -> !Int

Files

+ AUTHORS view
@@ -0,0 +1,8 @@+# The following people, listed in alphabetical order, contributed to the+# leveldb-haskell library:++Austin Seipp+Kim Altintop+Michael Lazarev+Nicolas Trangez+Will Moss
+ CHANGELOG view
@@ -0,0 +1,28 @@+[0.3.0]:++* ResourceT is no longer compulsory+++[0.2.0]:++* requires LevelDB v1.7+* support for filter policy (LevelDB v1.5), either custom or using the built-in+  bloom filter implementation+* write batch values no longer require a `memcpy` to be early-finalizer-safe+  (introduced in 0.1.1)+++[0.1.0]:++* memory (foreign pointers) is managed through+  [ResourceT](http://hackage.haskell.org/package/resourcet). Note that this+  requires to lift monadic actions inside the `MonadResource` monad, see the+  examples.+* links against shared library (LevelDB v1.3 or higher)+* LevelDB 1.3 API fully supported (including custom comparators, excluding+  custom environments)+++[0.0.x]:++* experimental releases
Readme.md view
@@ -1,7 +1,13 @@ This library provides Haskell bindings to [LevelDB](http://leveldb.googlecode.com) +[![Build Status](https://secure.travis-ci.org/kim/leveldb-haskell.png)](http://travis-ci.org/kim/leveldb-haskell)+ ## History++Version 0.3.0:++* ResourceT is no longer compulsory  Version 0.2.0: 
examples/comparator.hs view
@@ -5,7 +5,6 @@ module Main where  import Control.Monad.IO.Class (liftIO)-import Data.ByteString.Char8  (take) import Data.Default  import Database.LevelDB
examples/features.hs view
@@ -6,10 +6,10 @@  import Control.Monad import Control.Monad.IO.Class       (liftIO)+import Control.Monad.Trans.Resource (release) import Data.ByteString.Char8 hiding (take) import Data.Default import Prelude               hiding (putStrLn)-import System.FilePath  import Database.LevelDB @@ -33,8 +33,7 @@                               , Put "c" "three"                               ] -    withIterator db def{useSnapshot = Just snap} $ \iter ->-      dumpEntries iter+    withIterator db def{useSnapshot = Just snap} $ \iter -> dumpEntries iter      -- early release snapshot     release releaseSnap@@ -59,22 +58,23 @@      return () -    where-        dumpEntries iter = do-            iterFirst iter-            iterItems iter >>= liftIO . print+  where -        printProperty l p = liftIO $ do-            putStrLn l-            maybe (putStrLn "n/a") putStrLn $ p+    dumpEntries iter = do+        iterFirst iter+        iterItems iter >>= liftIO . print -        printVersion = do-            v <- versionBS-            liftIO . putStrLn $ "LevelDB Version: " `append` v+    printProperty l p = liftIO $ do+        putStrLn l+        maybe (putStrLn "n/a") putStrLn p -        versionBS = do-            (major, minor) <- version-            return $ intToBs major `append` "." `append` intToBs minor+    printVersion = do+        v <- versionBS+        liftIO . putStrLn $ "LevelDB Version: " `append` v -        intToBs :: Int -> ByteString-        intToBs = pack . show+    versionBS = do+        (major, minor) <- version+        return $ intToBs major `append` "." `append` intToBs minor++    intToBs :: Int -> ByteString+    intToBs = pack . show
− examples/giantwrite.hs
@@ -1,26 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-module Main where--import Control.Monad-import Control.Monad.IO.Class       (liftIO)-import Data.Default-import Data.Word-import Prelude               hiding (putStrLn)-import System.FilePath--import qualified Data.ByteString       as BS-import qualified Data.ByteString.Char8 as BC--import Database.LevelDB-import Debug.Trace---main :: IO ()-main = runResourceT $ do-    db <- open "/tmp/giantwrite"-               defaultOptions { createIfMissing = True }--    let w x = put db def x x-    mapM_ (w . BC.pack . show) [1..100000]--    approximateSize db ("0", "z") >>= liftIO . print
+ examples/iterforkio.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE    OverloadedStrings        #-}+{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}++-- |+-- Simplistic demo of 'Iterator' synchronization, using the 'Base" API+--+module Main where++import Control.Concurrent+import Control.Concurrent.Async+import Control.Exception+import Data.Default++import Database.LevelDB.Base++import qualified Data.ByteString.Char8 as BS++main :: IO ()+main = bracket (open "/tmp/leveltest" def{ createIfMissing = True }) close $ \ db -> do++    let xs = [1..100] :: [Int]++    write db def (map (\ x -> Put (BS.pack . show $ x) "") xs)++    bracket (createIter db def) releaseIter $ \ iter -> do+        _   <- iterFirst iter+        lck <- newMVar iter+        es  <- mapConcurrently (getEntry lck) xs+        mapM (\ (i,e) -> putStrLn $ "#" ++ show i ++ ": " ++ show e) es++    return ()+  where+    getEntry lck i = withMVar lck $ \ iter -> do+        entry <- iterEntry iter+        iterNext iter+        return (i, entry)
leveldb-haskell.cabal view
@@ -1,21 +1,18 @@ name:                leveldb-haskell-version:             0.2.0+version:             0.3.0 synopsis:            Haskell bindings to LevelDB homepage:            http://github.com/kim/leveldb-haskell bug-reports:         http://github.com/kim/leveldb-haskell/issues license:             BSD3 license-file:        LICENSE-author:              Kim Altintop <kim.altintop@gmail.com>-                   , Austin Seipp <mad.one@gmail.com>-                   , Michael Lazarev <lazarev.michael@gmail.com>-                   , Will Moss <wbmoss@gmail.com>+author:              Kim Altintop et.al. (see AUTHORS file) maintainer:          kim.altintop@gmail.com-copyright:           Copyright (c) 2012 The leveldb-haskell Authors+copyright:           Copyright (c) 2012-2014 The leveldb-haskell Authors category:            Database, FFI stability:           Experimental build-type:          Simple cabal-version:       >=1.10-tested-with:         GHC == 7.2.2, GHC == 7.4.1+tested-with:         GHC == 7.2.2, GHC == 7.4.1, GHC == 7.6.3 description:     From <http://leveldb.googlecode.com>:     .@@ -30,34 +27,125 @@     v0.1.0 of this library, LevelDB is no longer bundled and must be installed     on the target system (version 1.7 or greater is required). -extra-source-files:  Readme.md, examples/*.hs+extra-source-files:  Readme.md, AUTHORS, CHANGELOG examples/*.hs  source-repository head   type:     git   location: git://github.com/kim/leveldb-haskell.git +Flag Examples+  description:      Build examples+  default:          False+  manual:           True+ library   exposed-modules:  Database.LevelDB-  other-modules:    Database.LevelDB.Base+                  , Database.LevelDB.Base+                  , Database.LevelDB.C+                  , Database.LevelDB.Internal+                  , Database.LevelDB.Iterator+                  , Database.LevelDB.MonadResource+                  , Database.LevelDB.Types    default-language: Haskell2010-  default-extensions:-                    CPP+  other-extensions: CPP                   , ForeignFunctionInterface                   , EmptyDataDecls                   , RecordWildCards    build-depends:    base >= 3 && < 5                   , bytestring+                  , data-default                   , filepath-                  , transformers                   , resourcet > 0.3.2-                  , data-default+                  , transformers -  ghc-options:      -Wall -O2 -rtsopts-                    -funbox-strict-fields+  ghc-options:      -Wall -rtsopts -funbox-strict-fields   ghc-prof-options: -prof -auto-all    hs-source-dirs:   src    extra-libraries:  leveldb++executable leveldb-example-comparator+  main-is:          comparator.hs++  default-language: Haskell2010++  build-depends:    base >= 3 && < 5+                  , transformers+                  , data-default+                  , leveldb-haskell++  ghc-options:      -Wall -Werror -O -rtsopts+  ghc-prof-options: -prof -auto-all++  hs-source-dirs:   examples++  if flag(Examples)+    buildable:      True+  else+    buildable:      False++executable leveldb-example-features+  main-is:          features.hs++  default-language: Haskell2010++  build-depends:    base >= 3 && < 5+                  , bytestring+                  , transformers+                  , resourcet > 0.3.2+                  , data-default+                  , leveldb-haskell++  ghc-options:      -Wall -Werror -O -rtsopts+  ghc-prof-options: -prof -auto-all++  hs-source-dirs:   examples++  if flag(Examples)+    buildable:      True+  else+    buildable:      False++executable leveldb-example-filterpolicy+  main-is:          filterpolicy.hs++  default-language: Haskell2010++  build-depends:    base >= 3 && < 5+                  , transformers+                  , data-default+                  , leveldb-haskell++  ghc-options:      -Wall -Werror -O -rtsopts+  ghc-prof-options: -prof -auto-all++  hs-source-dirs:   examples++  if flag(Examples)+    buildable:      True+  else+    buildable:      False++executable leveldb-example-iterforkio+  main-is:          iterforkio.hs++  default-language: Haskell2010++  build-depends:    base >= 3 && < 5+                  , async+                  , bytestring+                  , data-default+                  , leveldb-haskell++  ghc-options:      -Wall -Werror -O -rtsopts+  ghc-prof-options: -prof -auto-all++  hs-source-dirs:   examples++  if flag(Examples)+    buildable:      True+  else+    buildable:      False
src/Database/LevelDB.hs view
@@ -1,7 +1,6 @@-{-# LANGUAGE RecordWildCards #-} -- | -- Module      : Database.LevelDB--- Copyright   : (c) 2012 Kim Altintop+-- Copyright   : (c) 2012-2013 The leveldb-haskell Authors -- License     : BSD3 -- Maintainer  : kim.altintop@gmail.com -- Stability   : experimental@@ -12,934 +11,6 @@ -- The API closely follows the C-API of LevelDB. -- For more information, see: <http://leveldb.googlecode.com> -module Database.LevelDB (-  -- * Exported Types-    DB-  , BatchOp(..)-  , Comparator(..)-  , Compression(..)-  , Options(..)-  , ReadOptions(..)-  , Snapshot-  , WriteBatch-  , WriteOptions(..)-  , Range--  -- * Defaults-  , defaultOptions-  , defaultWriteOptions-  , defaultReadOptions--  -- * Basic Database Manipulation-  , withSnapshot-  , open-  , put-  , delete-  , write-  , get-  , createSnapshot-  , createSnapshot'--  -- * Filter Policy / Bloom Filter-  , FilterPolicy(..)-  , bloomFilter--  -- * Administrative Functions-  , Property(..), getProperty-  , destroy-  , repair-  , approximateSize-  , version--  -- * Iteration-  , Iterator-  , withIterator-  , iterOpen-  , iterOpen'-  , iterValid-  , iterSeek-  , iterFirst-  , iterLast-  , iterNext-  , iterPrev-  , iterKey-  , iterValue-  , iterGetError-  , mapIter-  , iterItems-  , iterKeys-  , iterValues--  -- * Re-exports-  , MonadResource(..)-  , runResourceT-  , resourceForkIO-) where--import Control.Applicative                ((<$>), (<*>))-import Control.Concurrent                 (MVar, withMVar, newMVar)-import Control.Exception                  (throwIO)-import Control.Monad                      (liftM, when)-import Control.Monad.IO.Class             (liftIO)-import Control.Monad.Trans.Resource-import Data.ByteString                    (ByteString)-import Data.ByteString.Internal           (ByteString(..))-import Data.Default-import Data.Maybe                         (catMaybes)-import Foreign-import Foreign.C.Error                    (throwErrnoIfNull)-import Foreign.C.String                   (withCString, peekCString)-import Foreign.C.Types                    (CSize, CInt)--import Database.LevelDB.Base--import qualified Data.ByteString          as BS-import qualified Data.ByteString.Char8    as BC-import qualified Data.ByteString.Unsafe   as BU---- import Debug.Trace---- | Database handle-newtype DB = DB LevelDBPtr deriving (Eq)---- | Iterator handle-data Iterator = Iterator-    { _iterPtr  :: !IteratorPtr-    , _iterLock :: !(MVar ())-    } deriving (Eq)---- | Snapshot handle-newtype Snapshot = Snapshot SnapshotPtr deriving (Eq)---- | Compression setting-data Compression = NoCompression | Snappy deriving (Eq, Show)---- | User-defined comparator-newtype Comparator = Comparator (ByteString -> ByteString -> Ordering)--data Comparator' = Comparator' (FunPtr CompareFun)-                               (FunPtr Destructor)-                               (FunPtr NameFun)-                               ComparatorPtr---- | User-defined filter policy-data FilterPolicy = FilterPolicy-    { fpName       :: String-    , createFilter :: [ByteString] -> ByteString-    , keyMayMatch  :: ByteString -> ByteString -> Bool-    }--data FilterPolicy' = FilterPolicy' (FunPtr CreateFilterFun)-                                   (FunPtr KeyMayMatchFun)-                                   (FunPtr Destructor)-                                   (FunPtr NameFun)-                                   FilterPolicyPtr---- | Represents the built-in Bloom Filter-newtype BloomFilter = BloomFilter FilterPolicyPtr--bloomFilter :: MonadResource m => Int -> m BloomFilter-bloomFilter i = do-    let i' = fromInteger . toInteger $ i-    fp_ptr <- snd <$> allocate (c_leveldb_filterpolicy_create_bloom i')-                               (c_leveldb_filterpolicy_destroy)-    return . BloomFilter $ fp_ptr----- | Options when opening a database-data Options = Options-    { blockRestartInterval :: !Int-      -- ^ Number of keys between restart points for delta encoding of keys.-      ---      -- This parameter can be changed dynamically. Most clients should leave-      -- this parameter alone.-      ---      -- Default: 16-    , blockSize            :: !Int-      -- ^ Approximate size of user data packed per block.-      ---      -- Note that the block size specified here corresponds to uncompressed-      -- data. The actual size of the unit read from disk may be smaller if-      -- compression is enabled.-      ---      -- This parameter can be changed dynamically.-      ---      -- Default: 4k-    , cacheSize            :: !Int-      -- ^ Control over blocks (user data is stored in a set of blocks, and a-      -- block is the unit of reading from disk).-      ---      -- If > 0, use the specified cache (in bytes) for blocks. If 0, leveldb-      -- will automatically create and use an 8MB internal cache.-      ---      -- Default: 0-    , comparator           :: !(Maybe Comparator)-      -- ^ Comparator used to defined the order of keys in the table.-      ---      -- If 'Nothing', the default comparator is used, which uses lexicographic-      -- bytes-wise ordering.-      ---      -- NOTE: the client must ensure that the comparator supplied here has the-      -- same name and orders keys /exactly/ the same as the comparator provided-      -- to previous open calls on the same DB.-      ---      -- Default: Nothing-    , compression          :: !Compression-      -- ^ Compress blocks using the specified compression algorithm.-      ---      -- This parameter can be changed dynamically.-      ---      -- Default: 'Snappy'-    , createIfMissing      :: !Bool-      -- ^ If true, the database will be created if it is missing.-      ---      -- Default: False-    , errorIfExists        :: !Bool-      -- ^ It true, an error is raised if the database already exists.-      ---      -- Default: False-    , maxOpenFiles         :: !Int-      -- ^ Number of open files that can be used by the DB.-      ---      -- You may need to increase this if your database has a large working set-      -- (budget one open file per 2MB of working set).-      ---      -- Default: 1000-    , paranoidChecks       :: !Bool-      -- ^ If true, the implementation will do aggressive checking of the data-      -- it is processing and will stop early if it detects any errors.-      ---      -- This may have unforeseen ramifications: for example, a corruption of-      -- one DB entry may cause a large number of entries to become unreadable-      -- or for the entire DB to become unopenable.-      ---      -- Default: False-    , writeBufferSize      :: !Int-      -- ^ Amount of data to build up in memory (backed by an unsorted log on-      -- disk) before converting to a sorted on-disk file.-      ---      -- Larger values increase performance, especially during bulk loads. Up to-      -- to write buffers may be held in memory at the same time, so you may-      -- with to adjust this parameter to control memory usage. Also, a larger-      -- write buffer will result in a longer recovery time the next time the-      -- database is opened.-      ---      -- Default: 4MB-    , filterPolicy         :: !(Maybe (Either BloomFilter FilterPolicy))-    }--defaultOptions :: Options-defaultOptions = Options-    { blockRestartInterval = 16-    , blockSize            = 4096-    , cacheSize            = 0-    , comparator           = Nothing-    , compression          = Snappy-    , createIfMissing      = False-    , errorIfExists        = False-    , maxOpenFiles         = 1000-    , paranoidChecks       = False-    , writeBufferSize      = 4 `shift` 20-    , filterPolicy         = Nothing-    }--instance Default Options where-    def = defaultOptions--data Options' = Options'-    { _optsPtr  :: !OptionsPtr-    , _cachePtr :: !(Maybe CachePtr)-    , _comp     :: !(Maybe Comparator')-    , _fpPtr    :: !(Maybe (Either FilterPolicyPtr FilterPolicy'))-    }---- | Options for write operations-data WriteOptions = WriteOptions-    { sync :: !Bool-      -- ^ If true, the write will be flushed from the operating system buffer-      -- cache (by calling WritableFile::Sync()) before the write is considered-      -- complete. If this flag is true, writes will be slower.-      ---      -- If this flag is false, and the machine crashes, some recent writes may-      -- be lost. Note that if it is just the process that crashes (i.e., the-      -- machine does not reboot), no writes will be lost even if sync==false.-      ---      -- In other words, a DB write with sync==false has similar crash semantics-      -- as the "write()" system call. A DB write with sync==true has similar-      -- crash semantics to a "write()" system call followed by "fsync()".-      ---      -- Default: False-    } deriving (Eq, Show)--defaultWriteOptions :: WriteOptions-defaultWriteOptions = WriteOptions { sync = False }--instance Default WriteOptions where-    def = defaultWriteOptions---- | Options for read operations-data ReadOptions = ReadOptions-    { verifyCheckSums :: !Bool-      -- ^ If true, all data read from underlying storage will be verified-      -- against corresponding checksuyms.-      ---      -- Default: False-    , fillCache       :: !Bool-      -- ^ Should the data read for this iteration be cached in memory? Callers-      -- may with to set this field to false for bulk scans.-      ---      -- Default: True-    , useSnapshot     :: !(Maybe Snapshot)-      -- ^ If 'Just', read as of the supplied snapshot (which must belong to the-      -- DB that is being read and which must not have been released). If-      -- 'Nothing', use an implicit snapshot of the state at the beginning of-      -- this read operation.-      ---      -- Default: Nothing-    } deriving (Eq)--defaultReadOptions :: ReadOptions-defaultReadOptions = ReadOptions-    { verifyCheckSums = False-    , fillCache       = True-    , useSnapshot     = Nothing-    }--instance Default ReadOptions where-    def = defaultReadOptions--type WriteBatch = [BatchOp]--- | Batch operation-data BatchOp = Put ByteString ByteString | Del ByteString-             deriving (Eq, Show)---- | Properties exposed by LevelDB-data Property = NumFilesAtLevel Int | Stats | SSTables-              deriving (Eq, Show)----- | Open a database------ The returned handle will automatically be released when the enclosing--- 'runResourceT' terminates.-open :: MonadResource m => FilePath -> Options -> m DB-open path opts = snd <$> open' path opts--open' :: MonadResource m => FilePath -> Options -> m (ReleaseKey, DB)-open' path opts = do-    opts' <- snd <$> allocate (mkOpts opts) freeOpts-    allocate (mkDB opts') freeDB--    where-        mkDB (Options' opts_ptr _ _ _) =-            withCString path $ \path_ptr ->-                liftM DB-                $ throwIfErr "open"-                $ c_leveldb_open opts_ptr path_ptr--        freeDB (DB db_ptr) = c_leveldb_close db_ptr-{-# INLINE open' #-}---- | Run an action with a snapshot of the database.------ The snapshot will be released when the action terminates or throws an--- exception. Note that this function is provided for convenience and does not--- prevent the 'Snapshot' handle to escape. It will, however, be invalid after--- this function returns and should not be used anymore.-withSnapshot :: MonadResource m => DB -> (Snapshot -> m a) -> m a-withSnapshot db f = do-    (rk, snap) <- createSnapshot' db-    res <- f snap-    release rk-    return res---- | Create a snapshot of the database.------ The returned 'Snapshot' will be released automatically when the enclosing--- 'runResourceT' terminates. It is recommended to use 'createSnapshot'' instead--- and release the resource manually as soon as possible.-createSnapshot :: MonadResource m => DB -> m Snapshot-createSnapshot db = snd <$> createSnapshot' db---- | Create a snapshot of the database which can (and should) be released early.-createSnapshot' :: MonadResource m => DB -> m (ReleaseKey, Snapshot)-createSnapshot' db = allocate (mkSnap db) (freeSnap db)-    where-        mkSnap (DB db_ptr) =-            Snapshot <$> c_leveldb_create_snapshot db_ptr--        freeSnap (DB db_ptr) (Snapshot snap) =-            c_leveldb_release_snapshot db_ptr snap---- | Get a DB property-getProperty :: MonadResource m => DB -> Property -> m (Maybe ByteString)-getProperty (DB db_ptr) p = liftIO $-    withCString (prop p) $ \prop_ptr -> do-        val_ptr <- c_leveldb_property_value db_ptr prop_ptr-        if val_ptr == nullPtr-            then return Nothing-            else do res <- Just <$> BS.packCString val_ptr-                    free val_ptr-                    return res--    where-        prop (NumFilesAtLevel i) = "leveldb.num-files-at-level" ++ show i-        prop Stats    = "leveldb.stats"-        prop SSTables = "leveldb.sstables"---- | Destroy the given leveldb database.-destroy :: MonadResource m => FilePath -> Options -> m ()-destroy path opts = do-    (rk, opts') <- allocate (mkOpts opts) freeOpts-    liftIO $ destroy' opts'-    release rk--    where-        destroy' (Options' opts_ptr _ _ _) =-            withCString path $ \path_ptr ->-                throwIfErr "destroy" $ c_leveldb_destroy_db opts_ptr path_ptr---- | Repair the given leveldb database.-repair :: MonadResource m => FilePath -> Options -> m ()-repair path opts = do-    (rk, opts') <- allocate (mkOpts opts) freeOpts-    liftIO $ repair' opts'-    release rk--    where-        repair' (Options' opts_ptr _ _ _) =-            withCString path $ \path_ptr ->-                throwIfErr "repair" $ c_leveldb_repair_db opts_ptr path_ptr---- TODO: support [Range], like C API does-type Range  = (ByteString, ByteString)---- | Inspect the approximate sizes of the different levels-approximateSize :: MonadResource m => DB -> Range -> m Int64-approximateSize (DB db_ptr) (from, to) = liftIO $-    BU.unsafeUseAsCStringLen from $ \(from_ptr, flen) ->-    BU.unsafeUseAsCStringLen to   $ \(to_ptr, tlen)   ->-    withArray [from_ptr]          $ \from_ptrs        ->-    withArray [intToCSize flen]   $ \flen_ptrs        ->-    withArray [to_ptr]            $ \to_ptrs          ->-    withArray [intToCSize tlen]   $ \tlen_ptrs        ->-    allocaArray 1                 $ \size_ptrs        -> do-        c_leveldb_approximate_sizes db_ptr 1-                                    from_ptrs flen_ptrs-                                    to_ptrs tlen_ptrs-                                    size_ptrs-        liftM head $ peekArray 1 size_ptrs >>= mapM toInt64--    where-        toInt64 = return . fromIntegral---- | Write a key/value pair-put :: MonadResource m => DB -> WriteOptions -> ByteString -> ByteString -> m ()-put (DB db_ptr) opts key value =  do-    (rk, opts_ptr) <- mkCWriteOpts opts--    liftIO $-        BU.unsafeUseAsCStringLen key   $ \(key_ptr, klen) ->-        BU.unsafeUseAsCStringLen value $ \(val_ptr, vlen) ->-            throwIfErr "put"-                $ c_leveldb_put db_ptr opts_ptr-                                key_ptr (intToCSize klen)-                                val_ptr (intToCSize vlen)--    release rk---- | Read a value by key-get :: MonadResource m => DB -> ReadOptions -> ByteString -> m (Maybe ByteString)-get (DB db_ptr) opts key = do-    (rk, opts_ptr) <- mkCReadOptions opts--    res <- liftIO $-        BU.unsafeUseAsCStringLen key $ \(key_ptr, klen) ->-        alloca                       $ \vlen_ptr        -> do-            val_ptr <- throwIfErr "get" $-                c_leveldb_get db_ptr opts_ptr key_ptr (intToCSize klen) vlen_ptr-            vlen <- peek vlen_ptr-            if val_ptr == nullPtr-                then return Nothing-                else do-                    res' <- Just <$> BS.packCStringLen (val_ptr, cSizeToInt vlen)-                    free val_ptr-                    return res'--    release rk-    return res---- | Delete a key/value pair-delete :: MonadResource m => DB -> WriteOptions -> ByteString -> m ()-delete (DB db_ptr) opts key = do-    (rk, opts_ptr) <- mkCWriteOpts opts--    liftIO $ BU.unsafeUseAsCStringLen key $ \(key_ptr, klen) ->-        throwIfErr "delete"-            $ c_leveldb_delete db_ptr opts_ptr key_ptr (intToCSize klen)--    release rk---- | Perform a batch mutation-write :: MonadResource m => DB -> WriteOptions -> WriteBatch -> m ()-write (DB db_ptr) opts batch = do-    (rk_opts, opts_ptr)   <- mkCWriteOpts opts-    (rk_batch, batch_ptr) <- allocate c_leveldb_writebatch_create-                                      c_leveldb_writebatch_destroy--    mapM_ (liftIO . batchAdd batch_ptr) batch--    liftIO-        $ throwIfErr "write"-        $ c_leveldb_write db_ptr opts_ptr batch_ptr--    -- ensure @ByteString@s (and respective shared @CStringLen@s) aren't GC'ed-    -- until here-    mapM_ (liftIO . touch) batch--    release rk_opts-    release rk_batch--    where-        batchAdd batch_ptr (Put key val) =-            BU.unsafeUseAsCStringLen key $ \(key_ptr, klen) ->-            BU.unsafeUseAsCStringLen val $ \(val_ptr, vlen) ->-                c_leveldb_writebatch_put batch_ptr-                                         key_ptr (intToCSize klen)-                                         val_ptr (intToCSize vlen)--        batchAdd batch_ptr (Del key) =-            BU.unsafeUseAsCStringLen key $ \(key_ptr, klen) ->-                c_leveldb_writebatch_delete batch_ptr key_ptr (intToCSize klen)--        touch (Put (PS p _ _) (PS p' _ _)) = do-            touchForeignPtr p-            touchForeignPtr p'--        touch (Del (PS p _ _)) = touchForeignPtr p---- | Run an action with an Iterator. The iterator will be closed after the--- action returns or an error is thrown. Thus, the iterator will /not/ be valid--- after this function terminates.-withIterator :: MonadResource m => DB -> ReadOptions -> (Iterator -> m a) -> m a-withIterator db opts f = do-    (rk, iter) <- iterOpen' db opts-    res <- f iter-    release rk-    return res---- | Create an 'Iterator'.------ The iterator will be released when the enclosing 'runResourceT' terminates.--- You may consider to use 'iterOpen'' instead and manually release the iterator--- as soon as it is no longer needed (alternatively, use 'withIterator').------ Note that an 'Iterator' creates a snapshot of the database implicitly, so--- updates written after the iterator was created are not visible. You may,--- however, specify an older 'Snapshot' in the 'ReadOptions'.-iterOpen :: MonadResource m => DB -> ReadOptions -> m Iterator-iterOpen db opts = snd <$> iterOpen' db opts---- | Create an 'Iterator' which can be released early.-iterOpen' :: MonadResource m => DB -> ReadOptions -> m (ReleaseKey, Iterator)-iterOpen' db opts = do-    (rk, opts_ptr) <- mkCReadOptions opts-    iter <- allocate (mkIter db opts_ptr) freeIter--    release rk-    return iter--    where-        mkIter (DB db_ptr) opts_ptr = do-            lock   <- liftIO $ newMVar ()-            it_ptr <- liftIO-                          $ throwErrnoIfNull "create_iterator"-                          $ c_leveldb_create_iterator db_ptr opts_ptr-            return $ Iterator it_ptr lock--        freeIter (Iterator iter lck) =-            withMVar lck (\_ -> c_leveldb_iter_destroy iter)---- | An iterator is either positioned at a key/value pair, or not valid. This--- function returns /true/ iff the iterator is valid.-iterValid :: MonadResource m => Iterator -> m Bool-iterValid (Iterator iter _) = do-    x <- liftIO $ c_leveldb_iter_valid iter-    return (x /= 0)---- | Position at the first key in the source that is at or past target. The--- iterator is /valid/ after this call iff the source contains an entry that--- comes at or past target.-iterSeek :: MonadResource m => Iterator -> ByteString -> m ()-iterSeek (Iterator iter lck) key = liftIO $ withMVar lck go-    where-        go _ = BU.unsafeUseAsCStringLen key $ \(key_ptr, klen) ->-                   c_leveldb_iter_seek iter key_ptr (intToCSize klen)---- | Position at the first key in the source. The iterator is /valid/ after this--- call iff the source is not empty.-iterFirst :: MonadResource m => Iterator -> m ()-iterFirst (Iterator iter lck) = liftIO $ withMVar lck go-    where-        go _ = c_leveldb_iter_seek_to_first iter---- | Position at the last key in the source. The iterator is /valid/ after this--- call iff the source is not empty.-iterLast :: MonadResource m => Iterator -> m ()-iterLast (Iterator iter lck) = liftIO $ withMVar lck go-    where-        go _ = c_leveldb_iter_seek_to_last iter---- | Moves to the next entry in the source. After this call, 'iterValid' is--- /true/ iff the iterator was not positioned at the last entry in the source.------ If the iterator is not valid, this function does nothing. Note that this is a--- shortcoming of the C API: an 'iterPrev' might still be possible, but we can't--- determine if we're at the last or first entry.-iterNext :: MonadResource m => Iterator -> m ()-iterNext iter@(Iterator iter_ptr lck) = do-    valid <- iterValid iter-    when valid $ liftIO $ withMVar lck go--    where-        go _ = c_leveldb_iter_next iter_ptr---- | Moves to the previous entry in the source. After this call, 'iterValid' is--- /true/ iff the iterator was not positioned at the first entry in the source.------ If the iterator is not valid, this function does nothing. Note that this is a--- shortcoming of the C API: an 'iterNext' might still be possible, but we can't--- determine if we're at the last or first entry.-iterPrev :: MonadResource m => Iterator -> m ()-iterPrev iter@(Iterator iter_ptr lck) = do-    valid <- iterValid iter-    when valid $ liftIO $ withMVar lck go--    where-        go _ = c_leveldb_iter_prev iter_ptr---- | Return the key for the current entry if the iterator is currently--- positioned at an entry, ie. 'iterValid'.-iterKey :: MonadResource m => Iterator -> m (Maybe ByteString)-iterKey iter = do-    valid <- iterValid iter-    if not valid-        then return Nothing-        else iterKey' iter--    where-        iterKey' (Iterator iter_ptr _) = liftIO $-            alloca $ \len_ptr -> do-                key_ptr <- c_leveldb_iter_key iter_ptr len_ptr-                if key_ptr == nullPtr-                    then return Nothing-                    else do-                        klen <- peek len_ptr-                        Just <$> BS.packCStringLen (key_ptr, cSizeToInt klen)---- | Return the value for the current entry if the iterator is currently--- positioned at an entry, ie. 'iterValid'.-iterValue :: MonadResource m => Iterator -> m (Maybe ByteString)-iterValue iter = do-    valid <- iterValid iter-    if not valid-        then return Nothing-        else iterValue' iter--    where-        iterValue' (Iterator iter_ptr _) = liftIO $-            alloca $ \len_ptr -> do-                val_ptr <- c_leveldb_iter_value iter_ptr len_ptr-                if val_ptr == nullPtr-                    then return Nothing-                    else do-                        vlen <- peek len_ptr-                        Just <$> BS.packCStringLen (val_ptr, cSizeToInt vlen)---- | Check for errors------ Note that this captures somewhat severe errors such as a corrupted database.-iterGetError :: MonadResource m => Iterator -> m (Maybe ByteString)-iterGetError (Iterator iter_ptr _) = liftIO $-    alloca $ \err_ptr -> do-        poke err_ptr nullPtr-        c_leveldb_iter_get_error iter_ptr err_ptr-        erra <- peek err_ptr-        if erra == nullPtr-            then return Nothing-            else do-                err <- peekCString erra-                return . Just . BC.pack $ err---- | Map a function over an iterator, advancing the iterator forward and--- returning the value. The iterator should be put in the right position prior--- to calling the function.------ Note that this function accumulates the result strictly, ie. it reads all--- values into memory until the iterator is exhausted. This is most likely not--- what you want for large ranges. You may consider using conduits instead, for--- an example see: <https://gist.github.com/adc8ec348f03483446a5>-mapIter :: MonadResource m => (Iterator -> m a) -> Iterator -> m [a]-mapIter = go []--    where-        go acc f iter = do-            valid <- iterValid iter-            if not valid-                then return acc-                else do-                    val <- f iter-                    _   <- iterNext iter-                    go (val : acc) f iter---- | Return a list of key and value tuples from an iterator. The iterator--- should be put in the right position prior to calling this with the iterator.------ See strictness remarks on 'mapIter'.-iterItems :: MonadResource m => Iterator -> m [(ByteString, ByteString)]-iterItems iter = catMaybes <$> mapIter iterItems' iter--    where-        iterItems' iter' = do-            mkey <- iterKey iter'-            mval <- iterValue iter'-            return $ (,) <$> mkey <*> mval---- | Return a list of key from an iterator. The iterator should be put--- in the right position prior to calling this with the iterator.------ See strictness remarks on 'mapIter'-iterKeys :: MonadResource m => Iterator -> m [ByteString]-iterKeys iter = catMaybes <$> mapIter iterKey iter---- | Return a list of values from an iterator. The iterator should be put--- in the right position prior to calling this with the iterator.------ See strictness remarks on 'mapIter'-iterValues :: MonadResource m => Iterator -> m [ByteString]-iterValues iter = catMaybes <$> mapIter iterValue iter----- | Return the runtime version of the underlying LevelDB library as a (major,--- minor) pair.-version :: MonadResource m => m (Int, Int)-version = do-    major <- liftIO c_leveldb_major_version-    minor <- liftIO c_leveldb_minor_version--    return (cIntToInt major, cIntToInt minor)------- Internal-----mkOpts :: Options -> IO Options'-mkOpts Options{..} = do-    opts_ptr <- c_leveldb_options_create--    c_leveldb_options_set_block_restart_interval opts_ptr-        $ intToCInt blockRestartInterval-    c_leveldb_options_set_block_size opts_ptr-        $ intToCSize blockSize-    c_leveldb_options_set_compression opts_ptr-        $ ccompression compression-    c_leveldb_options_set_create_if_missing opts_ptr-        $ boolToNum createIfMissing-    c_leveldb_options_set_error_if_exists opts_ptr-        $ boolToNum errorIfExists-    c_leveldb_options_set_max_open_files opts_ptr-        $ intToCInt maxOpenFiles-    c_leveldb_options_set_paranoid_checks opts_ptr-        $ boolToNum paranoidChecks-    c_leveldb_options_set_write_buffer_size opts_ptr-        $ intToCSize writeBufferSize--    cache <- maybeSetCache opts_ptr cacheSize-    cmp   <- maybeSetCmp opts_ptr comparator-    fp    <- maybeSetFilterPolicy opts_ptr filterPolicy--    return (Options' opts_ptr cache cmp fp)--    where-        ccompression NoCompression = noCompression-        ccompression Snappy        = snappyCompression--        maybeSetCache :: OptionsPtr -> Int -> IO (Maybe CachePtr)-        maybeSetCache opts_ptr size =-            if size <= 0-                then return Nothing-                else do-                    cache_ptr <- c_leveldb_cache_create_lru $ intToCSize size-                    c_leveldb_options_set_cache opts_ptr cache_ptr-                    return . Just $ cache_ptr--        maybeSetCmp :: OptionsPtr -> Maybe Comparator -> IO (Maybe Comparator')-        maybeSetCmp opts_ptr (Just mcmp) = Just <$> setcmp opts_ptr mcmp-        maybeSetCmp _ Nothing = return Nothing--        setcmp :: OptionsPtr -> Comparator -> IO Comparator'-        setcmp opts_ptr (Comparator cmp) = do-            cmp'@(Comparator' _ _ _ cmp_ptr) <- mkComparator "user-defined" cmp-            c_leveldb_options_set_comparator opts_ptr cmp_ptr-            return cmp'--        maybeSetFilterPolicy :: OptionsPtr-                             -> Maybe (Either BloomFilter FilterPolicy)-                             -> IO (Maybe (Either FilterPolicyPtr FilterPolicy'))-        maybeSetFilterPolicy _ Nothing = return Nothing-        maybeSetFilterPolicy opts_ptr (Just (Left (BloomFilter bloom_ptr))) = do-            c_leveldb_options_set_filter_policy opts_ptr bloom_ptr-            return Nothing -- bloom filter is freed automatically-        maybeSetFilterPolicy opts_ptr (Just (Right fp)) = do-            fp'@(FilterPolicy' _ _ _ _ fp_ptr) <- mkFilterPolicy fp-            c_leveldb_options_set_filter_policy opts_ptr fp_ptr-            return . Just . Right $ fp'--freeOpts :: Options' -> IO ()-freeOpts (Options' opts_ptr mcache_ptr mcmp_ptr mfp) = do-    c_leveldb_options_destroy opts_ptr-    maybe (return ()) c_leveldb_cache_destroy mcache_ptr-    maybe (return ()) freeComparator mcmp_ptr-    maybe (return ())-          (either c_leveldb_filterpolicy_destroy freeFilterPolicy)-          mfp--    return ()--mkCWriteOpts :: MonadResource m => WriteOptions -> m (ReleaseKey, WriteOptionsPtr)-mkCWriteOpts WriteOptions{..} = do-    (rk, opts_ptr) <- allocate c_leveldb_writeoptions_create-                               c_leveldb_writeoptions_destroy--    liftIO-        $ c_leveldb_writeoptions_set_sync opts_ptr-        $ boolToNum sync--    return (rk, opts_ptr)--mkCReadOptions:: MonadResource m => ReadOptions -> m (ReleaseKey, ReadOptionsPtr)-mkCReadOptions ReadOptions{..} = do-    (rk, opts_ptr) <- allocate c_leveldb_readoptions_create-                               c_leveldb_readoptions_destroy--    liftIO-        $ c_leveldb_readoptions_set_verify_checksums opts_ptr-        $ boolToNum verifyCheckSums--    liftIO-        $ c_leveldb_readoptions_set_verify_checksums opts_ptr-        $ boolToNum fillCache--    maybeSetSnapshot opts_ptr useSnapshot--    return (rk, opts_ptr)--    where-        maybeSetSnapshot opts_ptr (Just (Snapshot snap_ptr)) =-            liftIO $ c_leveldb_readoptions_set_snapshot opts_ptr snap_ptr--        maybeSetSnapshot _ Nothing = return ()--throwIfErr :: String -> (ErrPtr -> IO a) -> IO a-throwIfErr s f = alloca $ \err_ptr -> do-    poke err_ptr nullPtr-    res  <- f err_ptr-    erra <- peek err_ptr-    when (erra /= nullPtr) $ do-        err <- peekCString erra-        throwIO $ userError $ s ++ ": " ++ err-    return res--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 #-}--mkCompareFun :: (ByteString -> ByteString -> Ordering) -> CompareFun-mkCompareFun cmp = cmp'--    where-        cmp' _ a alen b blen = do-            a' <- BS.packCStringLen (a, fromInteger . toInteger $ alen)-            b' <- BS.packCStringLen (b, fromInteger . toInteger $ blen)-            return $ case cmp a' b' of-                         EQ ->  0-                         GT ->  1-                         LT -> -1--mkComparator :: String -> (ByteString -> ByteString -> Ordering) -> IO Comparator'-mkComparator name f =-    withCString name $ \cs -> do-        ccmpfun <- mkCmp . mkCompareFun $ f-        cdest   <- mkDest $ \_ -> ()-        cname   <- mkName $ \_ -> cs-        ccmp    <- c_leveldb_comparator_create nullPtr cdest ccmpfun cname-        return $ Comparator' ccmpfun cdest cname ccmp---freeComparator :: Comparator' -> IO ()-freeComparator (Comparator' ccmpfun cdest cname ccmp) = do-    c_leveldb_comparator_destroy ccmp-    freeHaskellFunPtr ccmpfun-    freeHaskellFunPtr cdest-    freeHaskellFunPtr cname--mkCreateFilterFun :: ([ByteString] -> ByteString) -> CreateFilterFun-mkCreateFilterFun f = f'--    where-        f' _ ks ks_lens n_ks flen = do-            let n_ks' = fromInteger . toInteger $ n_ks-            ks'      <- peekArray n_ks' ks-            ks_lens' <- peekArray n_ks' ks_lens-            keys     <- mapM bstr (zip ks' ks_lens')-            let res = f keys-            poke flen (fromIntegral . BS.length $ res)-            BS.useAsCString res $ \cstr -> return cstr--        bstr (x,len) = BS.packCStringLen (x, fromInteger . toInteger $ len)--mkKeyMayMatchFun :: (ByteString -> ByteString -> Bool) -> KeyMayMatchFun-mkKeyMayMatchFun g = g'--    where-        g' _ k klen f flen = do-            k' <- BS.packCStringLen (k, fromInteger . toInteger $ klen)-            f' <- BS.packCStringLen (f, fromInteger . toInteger $ flen)-            return . boolToNum $ g k' f'---mkFilterPolicy :: FilterPolicy -> IO FilterPolicy'-mkFilterPolicy FilterPolicy{..} =-    withCString fpName $ \cs -> do-        cname  <- mkName $ \_ -> cs-        cdest  <- mkDest $ \_ -> ()-        ccffun <- mkCF . mkCreateFilterFun $ createFilter-        ckmfun <- mkKMM . mkKeyMayMatchFun $ keyMayMatch-        cfp    <- c_leveldb_filterpolicy_create nullPtr cdest ccffun ckmfun cname--        return $ FilterPolicy' ccffun ckmfun cdest cname cfp+module Database.LevelDB (module R) where -freeFilterPolicy :: FilterPolicy' -> IO ()-freeFilterPolicy (FilterPolicy' ccffun ckmfun cdest cname cfp) = do-    c_leveldb_filterpolicy_destroy cfp-    freeHaskellFunPtr ccffun-    freeHaskellFunPtr ckmfun-    freeHaskellFunPtr cdest-    freeHaskellFunPtr cname+import Database.LevelDB.MonadResource as R
+ src/Database/LevelDB/Base.hs view
@@ -0,0 +1,254 @@+-- |+-- Module      : Database.LevelDB.Base+-- Copyright   : (c) 2012-2013 The leveldb-haskell Authors+-- License     : BSD3+-- Maintainer  : kim.altintop@gmail.com+-- Stability   : experimental+-- Portability : non-portable+--+-- LevelDB Haskell binding.+--+-- The API closely follows the C-API of LevelDB.+-- For more information, see: <http://leveldb.googlecode.com>++module Database.LevelDB.Base+    ( -- * Exported Types+      DB+    , BatchOp (..)+    , Comparator (..)+    , Compression (..)+    , Options (..)+    , ReadOptions (..)+    , Snapshot+    , WriteBatch+    , WriteOptions (..)+    , Range++    -- * Defaults+    , defaultOptions+    , defaultReadOptions+    , defaultWriteOptions++    -- * Basic Database Manipulations+    , open+    , close+    , put+    , delete+    , write+    , get+    , withSnapshot+    , createSnapshot+    , releaseSnapshot++    -- * Filter Policy / Bloom Filter+    , FilterPolicy (..)+    , BloomFilter+    , createBloomFilter+    , releaseBloomFilter++    -- * Administrative Functions+    , Property (..), getProperty+    , destroy+    , repair+    , approximateSize+    , version++    -- * Iteration+    , module Database.LevelDB.Iterator+    )+where++import           Control.Applicative      ((<$>))+import           Control.Exception        (bracket, bracketOnError, finally)+import           Control.Monad            (liftM)+import           Control.Monad.IO.Class   (MonadIO (liftIO))+import           Data.ByteString          (ByteString)+import           Data.ByteString.Internal (ByteString (..))+import           Foreign+import           Foreign.C.String         (withCString)++import           Database.LevelDB.C+import           Database.LevelDB.Internal+import           Database.LevelDB.Iterator+import           Database.LevelDB.Types++import qualified Data.ByteString          as BS+import qualified Data.ByteString.Unsafe   as BU+++-- | Open a database.+--+-- The returned handle should be released with 'close'.+open :: MonadIO m => FilePath -> Options -> m DB+open path opts = liftIO $ bracketOnError (mkOpts opts) freeOpts mkDB+    where+        mkDB opts'@(Options' opts_ptr _ _ _) =+            withCString path $ \path_ptr ->+                liftM (`DB` opts')+                $ throwIfErr "open"+                $ c_leveldb_open opts_ptr path_ptr++-- | Close a database.+--+-- The handle will be invalid after calling this action and should no+-- longer be used.+close :: MonadIO m => DB -> m ()+close (DB db_ptr opts_ptr) = liftIO $+    c_leveldb_close db_ptr `finally` freeOpts opts_ptr+++-- | Run an action with a 'Snapshot' of the database.+withSnapshot :: MonadIO m => DB -> (Snapshot -> IO a) -> m a+withSnapshot db act = liftIO $+    bracket (createSnapshot db) (releaseSnapshot db) act++-- | Create a snapshot of the database.+--+-- The returned 'Snapshot' should be released with 'releaseSnapshot'.+createSnapshot :: MonadIO m => DB -> m Snapshot+createSnapshot (DB db_ptr _) = liftIO $+    Snapshot <$> c_leveldb_create_snapshot db_ptr++-- | Release a snapshot.+--+-- The handle will be invalid after calling this action and should no+-- longer be used.+releaseSnapshot :: MonadIO m => DB -> Snapshot -> m ()+releaseSnapshot (DB db_ptr _) (Snapshot snap) = liftIO $+    c_leveldb_release_snapshot db_ptr snap++-- | Get a DB property.+getProperty :: MonadIO m => DB -> Property -> m (Maybe ByteString)+getProperty (DB db_ptr _) p = liftIO $+    withCString (prop p) $ \prop_ptr -> do+        val_ptr <- c_leveldb_property_value db_ptr prop_ptr+        if val_ptr == nullPtr+            then return Nothing+            else do res <- Just <$> BS.packCString val_ptr+                    free val_ptr+                    return res+    where+        prop (NumFilesAtLevel i) = "leveldb.num-files-at-level" ++ show i+        prop Stats    = "leveldb.stats"+        prop SSTables = "leveldb.sstables"++-- | Destroy the given LevelDB database.+destroy :: MonadIO m => FilePath -> Options -> m ()+destroy path opts = liftIO $ bracket (mkOpts opts) freeOpts destroy'+    where+        destroy' (Options' opts_ptr _ _ _) =+            withCString path $ \path_ptr ->+                throwIfErr "destroy" $ c_leveldb_destroy_db opts_ptr path_ptr++-- | Repair the given LevelDB database.+repair :: MonadIO m => FilePath -> Options -> m ()+repair path opts = liftIO $ bracket (mkOpts opts) freeOpts repair'+    where+        repair' (Options' opts_ptr _ _ _) =+            withCString path $ \path_ptr ->+                throwIfErr "repair" $ c_leveldb_repair_db opts_ptr path_ptr+++-- TODO: support [Range], like C API does+type Range  = (ByteString, ByteString)++-- | Inspect the approximate sizes of the different levels.+approximateSize :: MonadIO m => DB -> Range -> m Int64+approximateSize (DB db_ptr _) (from, to) = liftIO $+    BU.unsafeUseAsCStringLen from $ \(from_ptr, flen) ->+    BU.unsafeUseAsCStringLen to   $ \(to_ptr, tlen)   ->+    withArray [from_ptr]          $ \from_ptrs        ->+    withArray [intToCSize flen]   $ \flen_ptrs        ->+    withArray [to_ptr]            $ \to_ptrs          ->+    withArray [intToCSize tlen]   $ \tlen_ptrs        ->+    allocaArray 1                 $ \size_ptrs        -> do+        c_leveldb_approximate_sizes db_ptr 1+                                    from_ptrs flen_ptrs+                                    to_ptrs tlen_ptrs+                                    size_ptrs+        liftM head $ peekArray 1 size_ptrs >>= mapM toInt64++    where+        toInt64 = return . fromIntegral+++-- | Write a key/value pair.+put :: MonadIO m => DB -> WriteOptions -> ByteString -> ByteString -> m ()+put (DB db_ptr _) opts key value = liftIO $ withCWriteOpts opts $ \opts_ptr ->+    BU.unsafeUseAsCStringLen key   $ \(key_ptr, klen) ->+    BU.unsafeUseAsCStringLen value $ \(val_ptr, vlen) ->+        throwIfErr "put"+            $ c_leveldb_put db_ptr opts_ptr+                            key_ptr (intToCSize klen)+                            val_ptr (intToCSize vlen)++-- | Read a value by key.+get :: MonadIO m => DB -> ReadOptions -> ByteString -> m (Maybe ByteString)+get (DB db_ptr _) opts key = liftIO $ withCReadOpts opts $ \opts_ptr ->+    BU.unsafeUseAsCStringLen key $ \(key_ptr, klen) ->+    alloca                       $ \vlen_ptr -> do+        val_ptr <- throwIfErr "get" $+            c_leveldb_get db_ptr opts_ptr key_ptr (intToCSize klen) vlen_ptr+        vlen <- peek vlen_ptr+        if val_ptr == nullPtr+            then return Nothing+            else do+                res' <- Just <$> BS.packCStringLen (val_ptr, cSizeToInt vlen)+                free val_ptr+                return res'++-- | Delete a key/value pair.+delete :: MonadIO m => DB -> WriteOptions -> ByteString -> m ()+delete (DB db_ptr _) opts key = liftIO $ withCWriteOpts opts $ \opts_ptr ->+    BU.unsafeUseAsCStringLen key $ \(key_ptr, klen) ->+        throwIfErr "delete"+            $ c_leveldb_delete db_ptr opts_ptr key_ptr (intToCSize klen)++-- | Perform a batch mutation.+write :: MonadIO m => DB -> WriteOptions -> WriteBatch -> m ()+write (DB db_ptr _) opts batch = liftIO $ withCWriteOpts opts $ \opts_ptr ->+    bracket c_leveldb_writebatch_create c_leveldb_writebatch_destroy $ \batch_ptr -> do++    mapM_ (batchAdd batch_ptr) batch++    throwIfErr "write" $ c_leveldb_write db_ptr opts_ptr batch_ptr++    -- ensure @ByteString@s (and respective shared @CStringLen@s) aren't GC'ed+    -- until here+    mapM_ (liftIO . touch) batch++    where+        batchAdd batch_ptr (Put key val) =+            BU.unsafeUseAsCStringLen key $ \(key_ptr, klen) ->+            BU.unsafeUseAsCStringLen val $ \(val_ptr, vlen) ->+                c_leveldb_writebatch_put batch_ptr+                                         key_ptr (intToCSize klen)+                                         val_ptr (intToCSize vlen)++        batchAdd batch_ptr (Del key) =+            BU.unsafeUseAsCStringLen key $ \(key_ptr, klen) ->+                c_leveldb_writebatch_delete batch_ptr key_ptr (intToCSize klen)++        touch (Put (PS p _ _) (PS p' _ _)) = do+            touchForeignPtr p+            touchForeignPtr p'++        touch (Del (PS p _ _)) = touchForeignPtr p++-- | Return the runtime version of the underlying LevelDB library as a (major,+-- minor) pair.+version :: MonadIO m => m (Int, Int)+version = do+    major <- liftIO c_leveldb_major_version+    minor <- liftIO c_leveldb_minor_version++    return (cIntToInt major, cIntToInt minor)++createBloomFilter :: MonadIO m => Int -> m BloomFilter+createBloomFilter i = do+    let i' = fromInteger . toInteger $ i+    fp_ptr <- liftIO $ c_leveldb_filterpolicy_create_bloom i'+    return $ BloomFilter fp_ptr++releaseBloomFilter :: MonadIO m => BloomFilter -> m ()+releaseBloomFilter (BloomFilter fp) = liftIO $ c_leveldb_filterpolicy_destroy fp
− src/Database/LevelDB/Base.hsc
@@ -1,355 +0,0 @@-{-# LANGUAGE CPP, ForeignFunctionInterface, EmptyDataDecls #-}--- |--- Module      : Database.LevelDB.Base--- Copyright   : (c) 2012 Kim Altintop--- License     : BSD3--- Maintainer  : kim.altintop@gmail.com--- Stability   : experimental--- Portability : non-portable-----module Database.LevelDB.Base where--import Foreign-import Foreign.C.Types-import Foreign.C.String--#include <leveldb/c.h>--data LevelDB-data LCache-data LComparator-data LIterator-data LLogger-data LOptions-data LReadOptions-data LSnapshot-data LWriteBatch-data LWriteOptions-data LFilterPolicy--type LevelDBPtr      = Ptr LevelDB-type CachePtr        = Ptr LCache-type ComparatorPtr   = Ptr LComparator-type IteratorPtr     = Ptr LIterator-type LoggerPtr       = Ptr LLogger-type OptionsPtr      = Ptr LOptions-type ReadOptionsPtr  = Ptr LReadOptions-type SnapshotPtr     = Ptr LSnapshot-type WriteBatchPtr   = Ptr LWriteBatch-type WriteOptionsPtr = Ptr LWriteOptions-type FilterPolicyPtr = Ptr LFilterPolicy--type DBName = CString-type ErrPtr = Ptr CString-type Key    = CString-type Val    = CString--newtype CompressionOpt = CompressionOpt { compressionOpt :: CInt }-  deriving (Eq, Show)-#{enum CompressionOpt, CompressionOpt- , noCompression     = 0- , snappyCompression = 1- }---foreign import ccall safe "leveldb/c.h leveldb_open"-  c_leveldb_open :: OptionsPtr -> DBName -> ErrPtr -> IO LevelDBPtr--foreign import ccall safe "leveldb/c.h leveldb_close"-  c_leveldb_close :: LevelDBPtr -> IO ()---foreign import ccall safe "leveldb/c.h leveldb_put"-  c_leveldb_put :: LevelDBPtr-                -> WriteOptionsPtr-                -> Key -> CSize-                -> Val -> CSize-                -> ErrPtr-                -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_delete"-  c_leveldb_delete :: LevelDBPtr-                   -> WriteOptionsPtr-                   -> Key -> CSize-                   -> ErrPtr-                   -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_write"-  c_leveldb_write :: LevelDBPtr-                  -> WriteOptionsPtr-                  -> WriteBatchPtr-                  -> ErrPtr-                  -> IO ()---- | Returns NULL if not found. A malloc()ed array otherwise. Stores the length--- of the array in *vallen.-foreign import ccall safe "leveldb/c.h leveldb_get"-  c_leveldb_get :: LevelDBPtr-                -> ReadOptionsPtr-                -> Key -> CSize-                -> Ptr CSize        -- ^ value length-                -> ErrPtr-                -> IO CString--foreign import ccall safe "leveldb/c.h leveldb_create_snapshot"-  c_leveldb_create_snapshot :: LevelDBPtr -> IO SnapshotPtr--foreign import ccall safe "leveldb/c.h leveldb_release_snapshot"-  c_leveldb_release_snapshot :: LevelDBPtr -> SnapshotPtr -> IO ()---- | Returns NULL if property name is unknown. Else returns a pointer to a--- malloc()-ed null-terminated value.-foreign import ccall safe "leveldb/c.h leveldb_property_value"-  c_leveldb_property_value :: LevelDBPtr -> CString -> IO CString--foreign import ccall safe "leveldb/c.h leveldb_approximate_sizes"-  c_leveldb_approximate_sizes :: LevelDBPtr-                              -> CInt                     -- ^ num ranges-                              -> Ptr CString -> Ptr CSize -- ^ range start keys (array)-                              -> Ptr CString -> Ptr CSize -- ^ range limit keys (array)-                              -> Ptr Word64               -- ^ array of approx. sizes of ranges-                              -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_destroy_db"-  c_leveldb_destroy_db :: OptionsPtr -> DBName -> ErrPtr -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_repair_db"-  c_leveldb_repair_db :: OptionsPtr -> DBName -> ErrPtr -> IO ()-------- Iterator-----foreign import ccall safe "leveldb/c.h leveldb_create_iterator"-  c_leveldb_create_iterator :: LevelDBPtr -> ReadOptionsPtr -> IO IteratorPtr--foreign import ccall safe "leveldb/c.h leveldb_iter_destroy"-  c_leveldb_iter_destroy :: IteratorPtr -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_iter_valid"-  c_leveldb_iter_valid :: IteratorPtr -> IO CUChar--foreign import ccall safe "leveldb/c.h leveldb_iter_seek_to_first"-  c_leveldb_iter_seek_to_first :: IteratorPtr -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_iter_seek_to_last"-  c_leveldb_iter_seek_to_last :: IteratorPtr -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_iter_seek"-  c_leveldb_iter_seek :: IteratorPtr -> Key -> CSize -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_iter_next"-  c_leveldb_iter_next :: IteratorPtr -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_iter_prev"-  c_leveldb_iter_prev :: IteratorPtr -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_iter_key"-  c_leveldb_iter_key :: IteratorPtr -> Ptr CSize -> IO Key--foreign import ccall safe "leveldb/c.h leveldb_iter_value"-  c_leveldb_iter_value :: IteratorPtr -> Ptr CSize -> IO Val--foreign import ccall safe "leveldb/c.h leveldb_iter_get_error"-  c_leveldb_iter_get_error :: IteratorPtr -> ErrPtr -> IO ()-------- Write batch-----foreign import ccall safe "leveldb/c.h leveldb_writebatch_create"-  c_leveldb_writebatch_create :: IO WriteBatchPtr--foreign import ccall safe "leveldb/c.h leveldb_writebatch_destroy"-  c_leveldb_writebatch_destroy :: WriteBatchPtr -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_writebatch_clear"-  c_leveldb_writebatch_clear :: WriteBatchPtr -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_writebatch_put"-  c_leveldb_writebatch_put :: WriteBatchPtr-                           -> Key -> CSize-                           -> Val -> CSize-                           -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_writebatch_delete"-  c_leveldb_writebatch_delete :: WriteBatchPtr -> Key -> CSize -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_writebatch_iterate"-  c_leveldb_writebatch_iterate :: WriteBatchPtr-                               -> Ptr ()                            -- ^ state-                               -> FunPtr (Ptr () -> Key -> CSize -> Val -> CSize) -- ^ put-                               -> FunPtr (Ptr () -> Key -> CSize)     -- ^ delete-                               -> IO ()-------- Options-----foreign import ccall safe "leveldb/c.h leveldb_options_create"-  c_leveldb_options_create :: IO OptionsPtr--foreign import ccall safe "leveldb/c.h leveldb_options_destroy"-  c_leveldb_options_destroy :: OptionsPtr -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_options_set_comparator"-  c_leveldb_options_set_comparator :: OptionsPtr -> ComparatorPtr -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_options_set_filter_policy"-  c_leveldb_options_set_filter_policy :: OptionsPtr -> FilterPolicyPtr -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_options_set_create_if_missing"-  c_leveldb_options_set_create_if_missing :: OptionsPtr -> CUChar -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_options_set_error_if_exists"-  c_leveldb_options_set_error_if_exists :: OptionsPtr -> CUChar -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_options_set_paranoid_checks"-  c_leveldb_options_set_paranoid_checks :: OptionsPtr -> CUChar -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_options_set_info_log"-  c_leveldb_options_set_info_log :: OptionsPtr -> LoggerPtr -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_options_set_write_buffer_size"-  c_leveldb_options_set_write_buffer_size :: OptionsPtr -> CSize -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_options_set_max_open_files"-  c_leveldb_options_set_max_open_files :: OptionsPtr -> CInt -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_options_set_block_size"-  c_leveldb_options_set_block_size :: OptionsPtr -> CSize -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_options_set_block_restart_interval"-  c_leveldb_options_set_block_restart_interval :: OptionsPtr -> CInt -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_options_set_compression"-  c_leveldb_options_set_compression :: OptionsPtr -> CompressionOpt -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_options_set_cache"-  c_leveldb_options_set_cache :: OptionsPtr -> CachePtr -> IO ()-------- Comparator-----type StatePtr   = Ptr ()-type Destructor = StatePtr -> ()-type CompareFun = StatePtr -> CString -> CSize -> CString -> CSize -> IO CInt-type NameFun    = StatePtr -> CString---- | Make a FunPtr to a user-defined comparator function-foreign import ccall "wrapper" mkCmp :: CompareFun -> IO (FunPtr CompareFun)---- | Make a destructor FunPtr-foreign import ccall "wrapper" mkDest :: Destructor -> IO (FunPtr Destructor)---- | Make a name FunPtr-foreign import ccall "wrapper" mkName :: NameFun -> IO (FunPtr NameFun)--foreign import ccall safe "leveldb/c.h leveldb_comparator_create"-  c_leveldb_comparator_create :: StatePtr-                              -> FunPtr Destructor-                              -> FunPtr CompareFun-                              -> FunPtr NameFun-                              -> IO ComparatorPtr--foreign import ccall safe "leveldb/c.h leveldb_comparator_destroy"-  c_leveldb_comparator_destroy :: ComparatorPtr -> IO ()-------- Filter Policy-----type CreateFilterFun = StatePtr-                     -> Ptr CString -- ^ key array-                     -> Ptr CSize   -- ^ key length array-                     -> CInt        -- ^ num keys-                     -> Ptr CSize   -- ^ filter length-                     -> IO CString  -- ^ the filter-type KeyMayMatchFun  = StatePtr-                     -> CString     -- ^ key-                     -> CSize       -- ^ key length-                     -> CString     -- ^ filter-                     -> CSize       -- ^ filter length-                     -> IO CUChar   -- ^ whether key is in filter---- | Make a FunPtr to a user-defined create_filter function-foreign import ccall "wrapper" mkCF :: CreateFilterFun -> IO (FunPtr CreateFilterFun)---- | Make a FunPtr to a user-defined key_may_match function-foreign import ccall "wrapper" mkKMM :: KeyMayMatchFun -> IO (FunPtr KeyMayMatchFun)--foreign import ccall safe "leveldb/c.h leveldb_filterpolicy_create"-  c_leveldb_filterpolicy_create :: StatePtr-                                -> FunPtr Destructor-                                -> FunPtr CreateFilterFun-                                -> FunPtr KeyMayMatchFun-                                -> FunPtr NameFun-                                -> IO FilterPolicyPtr--foreign import ccall safe "leveldb/c.h leveldb_filterpolicy_destroy"-  c_leveldb_filterpolicy_destroy :: FilterPolicyPtr -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_filterpolicy_create_bloom"-  c_leveldb_filterpolicy_create_bloom :: CInt -> IO FilterPolicyPtr------- Read options-----foreign import ccall safe "leveldb/c.h leveldb_readoptions_create"-  c_leveldb_readoptions_create :: IO ReadOptionsPtr--foreign import ccall safe "leveldb/c.h leveldb_readoptions_destroy"-  c_leveldb_readoptions_destroy :: ReadOptionsPtr -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_readoptions_set_verify_checksums"-  c_leveldb_readoptions_set_verify_checksums :: ReadOptionsPtr -> CUChar -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_readoptions_set_fill_cache"-  c_leveldb_readoptions_set_fill_cache :: ReadOptionsPtr -> CUChar -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_readoptions_set_snapshot"-  c_leveldb_readoptions_set_snapshot :: ReadOptionsPtr -> SnapshotPtr -> IO ()-------- Write options-----foreign import ccall safe "leveldb/c.h leveldb_writeoptions_create"-  c_leveldb_writeoptions_create :: IO WriteOptionsPtr--foreign import ccall safe "leveldb/c.h leveldb_writeoptions_destroy"-  c_leveldb_writeoptions_destroy :: WriteOptionsPtr -> IO ()--foreign import ccall safe "leveldb/c.h leveldb_writeoptions_set_sync"-  c_leveldb_writeoptions_set_sync :: WriteOptionsPtr -> CUChar -> IO ()-------- Cache-----foreign import ccall safe "leveldb/c.h leveldb_cache_create_lru"-  c_leveldb_cache_create_lru :: CSize -> IO CachePtr--foreign import ccall safe "leveldb/c.h leveldb_cache_destroy"-  c_leveldb_cache_destroy :: CachePtr -> IO ()-------- Version-----foreign import ccall unsafe "leveldb/c.h leveldb_major_version"-  c_leveldb_major_version :: IO CInt--foreign import ccall unsafe "leveldb/c.h leveldb_minor_version"-  c_leveldb_minor_version :: IO CInt
+ src/Database/LevelDB/C.hsc view
@@ -0,0 +1,355 @@+{-# LANGUAGE CPP, ForeignFunctionInterface, EmptyDataDecls #-}+-- |+-- Module      : Database.LevelDB.C+-- Copyright   : (c) 2012-2013 The leveldb-haskell Authors+-- License     : BSD3+-- Maintainer  : kim.altintop@gmail.com+-- Stability   : experimental+-- Portability : non-portable+--++module Database.LevelDB.C where++import Foreign+import Foreign.C.Types+import Foreign.C.String++#include <leveldb/c.h>++data LevelDB+data LCache+data LComparator+data LIterator+data LLogger+data LOptions+data LReadOptions+data LSnapshot+data LWriteBatch+data LWriteOptions+data LFilterPolicy++type LevelDBPtr      = Ptr LevelDB+type CachePtr        = Ptr LCache+type ComparatorPtr   = Ptr LComparator+type IteratorPtr     = Ptr LIterator+type LoggerPtr       = Ptr LLogger+type OptionsPtr      = Ptr LOptions+type ReadOptionsPtr  = Ptr LReadOptions+type SnapshotPtr     = Ptr LSnapshot+type WriteBatchPtr   = Ptr LWriteBatch+type WriteOptionsPtr = Ptr LWriteOptions+type FilterPolicyPtr = Ptr LFilterPolicy++type DBName = CString+type ErrPtr = Ptr CString+type Key    = CString+type Val    = CString++newtype CompressionOpt = CompressionOpt { compressionOpt :: CInt }+  deriving (Eq, Show)+#{enum CompressionOpt, CompressionOpt+ , noCompression     = 0+ , snappyCompression = 1+ }+++foreign import ccall safe "leveldb/c.h leveldb_open"+  c_leveldb_open :: OptionsPtr -> DBName -> ErrPtr -> IO LevelDBPtr++foreign import ccall safe "leveldb/c.h leveldb_close"+  c_leveldb_close :: LevelDBPtr -> IO ()+++foreign import ccall safe "leveldb/c.h leveldb_put"+  c_leveldb_put :: LevelDBPtr+                -> WriteOptionsPtr+                -> Key -> CSize+                -> Val -> CSize+                -> ErrPtr+                -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_delete"+  c_leveldb_delete :: LevelDBPtr+                   -> WriteOptionsPtr+                   -> Key -> CSize+                   -> ErrPtr+                   -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_write"+  c_leveldb_write :: LevelDBPtr+                  -> WriteOptionsPtr+                  -> WriteBatchPtr+                  -> ErrPtr+                  -> IO ()++-- | Returns NULL if not found. A malloc()ed array otherwise. Stores the length+-- of the array in *vallen.+foreign import ccall safe "leveldb/c.h leveldb_get"+  c_leveldb_get :: LevelDBPtr+                -> ReadOptionsPtr+                -> Key -> CSize+                -> Ptr CSize        -- ^ value length+                -> ErrPtr+                -> IO CString++foreign import ccall safe "leveldb/c.h leveldb_create_snapshot"+  c_leveldb_create_snapshot :: LevelDBPtr -> IO SnapshotPtr++foreign import ccall safe "leveldb/c.h leveldb_release_snapshot"+  c_leveldb_release_snapshot :: LevelDBPtr -> SnapshotPtr -> IO ()++-- | Returns NULL if property name is unknown. Else returns a pointer to a+-- malloc()-ed null-terminated value.+foreign import ccall safe "leveldb/c.h leveldb_property_value"+  c_leveldb_property_value :: LevelDBPtr -> CString -> IO CString++foreign import ccall safe "leveldb/c.h leveldb_approximate_sizes"+  c_leveldb_approximate_sizes :: LevelDBPtr+                              -> CInt                     -- ^ num ranges+                              -> Ptr CString -> Ptr CSize -- ^ range start keys (array)+                              -> Ptr CString -> Ptr CSize -- ^ range limit keys (array)+                              -> Ptr Word64               -- ^ array of approx. sizes of ranges+                              -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_destroy_db"+  c_leveldb_destroy_db :: OptionsPtr -> DBName -> ErrPtr -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_repair_db"+  c_leveldb_repair_db :: OptionsPtr -> DBName -> ErrPtr -> IO ()+++--+-- Iterator+--++foreign import ccall safe "leveldb/c.h leveldb_create_iterator"+  c_leveldb_create_iterator :: LevelDBPtr -> ReadOptionsPtr -> IO IteratorPtr++foreign import ccall safe "leveldb/c.h leveldb_iter_destroy"+  c_leveldb_iter_destroy :: IteratorPtr -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_iter_valid"+  c_leveldb_iter_valid :: IteratorPtr -> IO CUChar++foreign import ccall safe "leveldb/c.h leveldb_iter_seek_to_first"+  c_leveldb_iter_seek_to_first :: IteratorPtr -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_iter_seek_to_last"+  c_leveldb_iter_seek_to_last :: IteratorPtr -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_iter_seek"+  c_leveldb_iter_seek :: IteratorPtr -> Key -> CSize -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_iter_next"+  c_leveldb_iter_next :: IteratorPtr -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_iter_prev"+  c_leveldb_iter_prev :: IteratorPtr -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_iter_key"+  c_leveldb_iter_key :: IteratorPtr -> Ptr CSize -> IO Key++foreign import ccall safe "leveldb/c.h leveldb_iter_value"+  c_leveldb_iter_value :: IteratorPtr -> Ptr CSize -> IO Val++foreign import ccall safe "leveldb/c.h leveldb_iter_get_error"+  c_leveldb_iter_get_error :: IteratorPtr -> ErrPtr -> IO ()+++--+-- Write batch+--++foreign import ccall safe "leveldb/c.h leveldb_writebatch_create"+  c_leveldb_writebatch_create :: IO WriteBatchPtr++foreign import ccall safe "leveldb/c.h leveldb_writebatch_destroy"+  c_leveldb_writebatch_destroy :: WriteBatchPtr -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_writebatch_clear"+  c_leveldb_writebatch_clear :: WriteBatchPtr -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_writebatch_put"+  c_leveldb_writebatch_put :: WriteBatchPtr+                           -> Key -> CSize+                           -> Val -> CSize+                           -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_writebatch_delete"+  c_leveldb_writebatch_delete :: WriteBatchPtr -> Key -> CSize -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_writebatch_iterate"+  c_leveldb_writebatch_iterate :: WriteBatchPtr+                               -> Ptr ()                            -- ^ state+                               -> FunPtr (Ptr () -> Key -> CSize -> Val -> CSize) -- ^ put+                               -> FunPtr (Ptr () -> Key -> CSize)     -- ^ delete+                               -> IO ()+++--+-- Options+--++foreign import ccall safe "leveldb/c.h leveldb_options_create"+  c_leveldb_options_create :: IO OptionsPtr++foreign import ccall safe "leveldb/c.h leveldb_options_destroy"+  c_leveldb_options_destroy :: OptionsPtr -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_options_set_comparator"+  c_leveldb_options_set_comparator :: OptionsPtr -> ComparatorPtr -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_options_set_filter_policy"+  c_leveldb_options_set_filter_policy :: OptionsPtr -> FilterPolicyPtr -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_options_set_create_if_missing"+  c_leveldb_options_set_create_if_missing :: OptionsPtr -> CUChar -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_options_set_error_if_exists"+  c_leveldb_options_set_error_if_exists :: OptionsPtr -> CUChar -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_options_set_paranoid_checks"+  c_leveldb_options_set_paranoid_checks :: OptionsPtr -> CUChar -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_options_set_info_log"+  c_leveldb_options_set_info_log :: OptionsPtr -> LoggerPtr -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_options_set_write_buffer_size"+  c_leveldb_options_set_write_buffer_size :: OptionsPtr -> CSize -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_options_set_max_open_files"+  c_leveldb_options_set_max_open_files :: OptionsPtr -> CInt -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_options_set_block_size"+  c_leveldb_options_set_block_size :: OptionsPtr -> CSize -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_options_set_block_restart_interval"+  c_leveldb_options_set_block_restart_interval :: OptionsPtr -> CInt -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_options_set_compression"+  c_leveldb_options_set_compression :: OptionsPtr -> CompressionOpt -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_options_set_cache"+  c_leveldb_options_set_cache :: OptionsPtr -> CachePtr -> IO ()+++--+-- Comparator+--++type StatePtr   = Ptr ()+type Destructor = StatePtr -> ()+type CompareFun = StatePtr -> CString -> CSize -> CString -> CSize -> IO CInt+type NameFun    = StatePtr -> CString++-- | Make a FunPtr to a user-defined comparator function+foreign import ccall "wrapper" mkCmp :: CompareFun -> IO (FunPtr CompareFun)++-- | Make a destructor FunPtr+foreign import ccall "wrapper" mkDest :: Destructor -> IO (FunPtr Destructor)++-- | Make a name FunPtr+foreign import ccall "wrapper" mkName :: NameFun -> IO (FunPtr NameFun)++foreign import ccall safe "leveldb/c.h leveldb_comparator_create"+  c_leveldb_comparator_create :: StatePtr+                              -> FunPtr Destructor+                              -> FunPtr CompareFun+                              -> FunPtr NameFun+                              -> IO ComparatorPtr++foreign import ccall safe "leveldb/c.h leveldb_comparator_destroy"+  c_leveldb_comparator_destroy :: ComparatorPtr -> IO ()+++--+-- Filter Policy+--++type CreateFilterFun = StatePtr+                     -> Ptr CString -- ^ key array+                     -> Ptr CSize   -- ^ key length array+                     -> CInt        -- ^ num keys+                     -> Ptr CSize   -- ^ filter length+                     -> IO CString  -- ^ the filter+type KeyMayMatchFun  = StatePtr+                     -> CString     -- ^ key+                     -> CSize       -- ^ key length+                     -> CString     -- ^ filter+                     -> CSize       -- ^ filter length+                     -> IO CUChar   -- ^ whether key is in filter++-- | Make a FunPtr to a user-defined create_filter function+foreign import ccall "wrapper" mkCF :: CreateFilterFun -> IO (FunPtr CreateFilterFun)++-- | Make a FunPtr to a user-defined key_may_match function+foreign import ccall "wrapper" mkKMM :: KeyMayMatchFun -> IO (FunPtr KeyMayMatchFun)++foreign import ccall safe "leveldb/c.h leveldb_filterpolicy_create"+  c_leveldb_filterpolicy_create :: StatePtr+                                -> FunPtr Destructor+                                -> FunPtr CreateFilterFun+                                -> FunPtr KeyMayMatchFun+                                -> FunPtr NameFun+                                -> IO FilterPolicyPtr++foreign import ccall safe "leveldb/c.h leveldb_filterpolicy_destroy"+  c_leveldb_filterpolicy_destroy :: FilterPolicyPtr -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_filterpolicy_create_bloom"+  c_leveldb_filterpolicy_create_bloom :: CInt -> IO FilterPolicyPtr++--+-- Read options+--++foreign import ccall safe "leveldb/c.h leveldb_readoptions_create"+  c_leveldb_readoptions_create :: IO ReadOptionsPtr++foreign import ccall safe "leveldb/c.h leveldb_readoptions_destroy"+  c_leveldb_readoptions_destroy :: ReadOptionsPtr -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_readoptions_set_verify_checksums"+  c_leveldb_readoptions_set_verify_checksums :: ReadOptionsPtr -> CUChar -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_readoptions_set_fill_cache"+  c_leveldb_readoptions_set_fill_cache :: ReadOptionsPtr -> CUChar -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_readoptions_set_snapshot"+  c_leveldb_readoptions_set_snapshot :: ReadOptionsPtr -> SnapshotPtr -> IO ()+++--+-- Write options+--++foreign import ccall safe "leveldb/c.h leveldb_writeoptions_create"+  c_leveldb_writeoptions_create :: IO WriteOptionsPtr++foreign import ccall safe "leveldb/c.h leveldb_writeoptions_destroy"+  c_leveldb_writeoptions_destroy :: WriteOptionsPtr -> IO ()++foreign import ccall safe "leveldb/c.h leveldb_writeoptions_set_sync"+  c_leveldb_writeoptions_set_sync :: WriteOptionsPtr -> CUChar -> IO ()+++--+-- Cache+--++foreign import ccall safe "leveldb/c.h leveldb_cache_create_lru"+  c_leveldb_cache_create_lru :: CSize -> IO CachePtr++foreign import ccall safe "leveldb/c.h leveldb_cache_destroy"+  c_leveldb_cache_destroy :: CachePtr -> IO ()+++--+-- Version+--++foreign import ccall unsafe "leveldb/c.h leveldb_major_version"+  c_leveldb_major_version :: IO CInt++foreign import ccall unsafe "leveldb/c.h leveldb_minor_version"+  c_leveldb_minor_version :: IO CInt
+ src/Database/LevelDB/Internal.hs view
@@ -0,0 +1,291 @@+{-# LANGUAGE RecordWildCards #-}+-- |+-- Module      : Database.LevelDB.Internal+-- Copyright   : (c) 2012-2013 The leveldb-haskell Authors+-- License     : BSD3+-- Maintainer  : kim.altintop@gmail.com+-- Stability   : experimental+-- Portability : non-portable+--++module Database.LevelDB.Internal+    ( -- * Types+      DB (..)+    , Comparator'+    , FilterPolicy'+    , Options' (..)++    -- * "Smart" constructors and deconstructors+    , freeCReadOpts+    , freeComparator+    , freeFilterPolicy+    , freeOpts+    , mkCReadOpts+    , mkComparator+    , mkCompareFun+    , mkCreateFilterFun+    , mkFilterPolicy+    , mkKeyMayMatchFun+    , mkOpts++    -- * combinators+    , withCWriteOpts+    , withCReadOpts++    -- * Utilities+    , throwIfErr+    , cSizeToInt+    , intToCSize+    , intToCInt+    , cIntToInt+    , boolToNum+    )+where++import           Control.Applicative    ((<$>))+import           Control.Exception      (bracket, onException, throwIO)+import           Control.Monad          (when)+import           Data.ByteString        (ByteString)+import           Foreign+import           Foreign.C.String       (peekCString, withCString)+import           Foreign.C.Types        (CInt, CSize)++import           Database.LevelDB.C+import           Database.LevelDB.Types++import qualified Data.ByteString        as BS+++-- | Database handle+data DB = DB LevelDBPtr Options'++instance Eq DB where+    (DB pt1 _) == (DB pt2 _) = pt1 == pt2++-- | Internal representation of a 'Comparator'+data Comparator' = Comparator' (FunPtr CompareFun)+                               (FunPtr Destructor)+                               (FunPtr NameFun)+                               ComparatorPtr++-- | Internal representation of a 'FilterPolicy'+data FilterPolicy' = FilterPolicy' (FunPtr CreateFilterFun)+                                   (FunPtr KeyMayMatchFun)+                                   (FunPtr Destructor)+                                   (FunPtr NameFun)+                                   FilterPolicyPtr++-- | Internal representation of the 'Options'+data Options' = Options'+    { _optsPtr  :: !OptionsPtr+    , _cachePtr :: !(Maybe CachePtr)+    , _comp     :: !(Maybe Comparator')+    , _fpPtr    :: !(Maybe (Either FilterPolicyPtr FilterPolicy'))+    }+++mkOpts :: Options -> IO Options'+mkOpts Options{..} = do+    opts_ptr <- c_leveldb_options_create++    c_leveldb_options_set_block_restart_interval opts_ptr+        $ intToCInt blockRestartInterval+    c_leveldb_options_set_block_size opts_ptr+        $ intToCSize blockSize+    c_leveldb_options_set_compression opts_ptr+        $ ccompression compression+    c_leveldb_options_set_create_if_missing opts_ptr+        $ boolToNum createIfMissing+    c_leveldb_options_set_error_if_exists opts_ptr+        $ boolToNum errorIfExists+    c_leveldb_options_set_max_open_files opts_ptr+        $ intToCInt maxOpenFiles+    c_leveldb_options_set_paranoid_checks opts_ptr+        $ boolToNum paranoidChecks+    c_leveldb_options_set_write_buffer_size opts_ptr+        $ intToCSize writeBufferSize++    cache <- maybeSetCache opts_ptr cacheSize+    cmp   <- maybeSetCmp opts_ptr comparator+    fp    <- maybeSetFilterPolicy opts_ptr filterPolicy++    return (Options' opts_ptr cache cmp fp)++  where+    ccompression NoCompression = noCompression+    ccompression Snappy        = snappyCompression++    maybeSetCache :: OptionsPtr -> Int -> IO (Maybe CachePtr)+    maybeSetCache opts_ptr size =+        if size <= 0+            then return Nothing+            else do+                cache_ptr <- c_leveldb_cache_create_lru $ intToCSize size+                c_leveldb_options_set_cache opts_ptr cache_ptr+                return . Just $ cache_ptr++    maybeSetCmp :: OptionsPtr -> Maybe Comparator -> IO (Maybe Comparator')+    maybeSetCmp opts_ptr (Just mcmp) = Just <$> setcmp opts_ptr mcmp+    maybeSetCmp _ Nothing = return Nothing++    setcmp :: OptionsPtr -> Comparator -> IO Comparator'+    setcmp opts_ptr (Comparator cmp) = do+        cmp'@(Comparator' _ _ _ cmp_ptr) <- mkComparator "user-defined" cmp+        c_leveldb_options_set_comparator opts_ptr cmp_ptr+        return cmp'++    maybeSetFilterPolicy :: OptionsPtr+                         -> Maybe (Either BloomFilter FilterPolicy)+                         -> IO (Maybe (Either FilterPolicyPtr FilterPolicy'))+    maybeSetFilterPolicy _ Nothing =+        return Nothing+    maybeSetFilterPolicy opts_ptr (Just (Left (BloomFilter bloom_ptr))) = do+        c_leveldb_options_set_filter_policy opts_ptr bloom_ptr+        return Nothing -- bloom filter is freed automatically+    maybeSetFilterPolicy opts_ptr (Just (Right fp)) = do+        fp'@(FilterPolicy' _ _ _ _ fp_ptr) <- mkFilterPolicy fp+        c_leveldb_options_set_filter_policy opts_ptr fp_ptr+        return . Just . Right $ fp'++freeOpts :: Options' -> IO ()+freeOpts (Options' opts_ptr mcache_ptr mcmp_ptr mfp) = do+    c_leveldb_options_destroy opts_ptr+    maybe (return ()) c_leveldb_cache_destroy mcache_ptr+    maybe (return ()) freeComparator mcmp_ptr+    maybe (return ())+          (either c_leveldb_filterpolicy_destroy freeFilterPolicy)+          mfp++    return ()++withCWriteOpts :: WriteOptions -> (WriteOptionsPtr -> IO a) -> IO a+withCWriteOpts WriteOptions{..} = bracket mkCWriteOpts freeCWriteOpts+  where+    mkCWriteOpts = do+        opts_ptr <- c_leveldb_writeoptions_create+        onException+            (c_leveldb_writeoptions_set_sync opts_ptr $ boolToNum sync)+            (c_leveldb_writeoptions_destroy opts_ptr)+        return opts_ptr++    freeCWriteOpts = c_leveldb_writeoptions_destroy++mkCompareFun :: (ByteString -> ByteString -> Ordering) -> CompareFun+mkCompareFun cmp = cmp'+  where+    cmp' _ a alen b blen = do+        a' <- BS.packCStringLen (a, fromInteger . toInteger $ alen)+        b' <- BS.packCStringLen (b, fromInteger . toInteger $ blen)+        return $ case cmp a' b' of+                     EQ ->  0+                     GT ->  1+                     LT -> -1++mkComparator :: String -> (ByteString -> ByteString -> Ordering) -> IO Comparator'+mkComparator name f =+    withCString name $ \cs -> do+        ccmpfun <- mkCmp . mkCompareFun $ f+        cdest   <- mkDest $ const ()+        cname   <- mkName $ const cs+        ccmp    <- c_leveldb_comparator_create nullPtr cdest ccmpfun cname+        return $ Comparator' ccmpfun cdest cname ccmp+++freeComparator :: Comparator' -> IO ()+freeComparator (Comparator' ccmpfun cdest cname ccmp) = do+    c_leveldb_comparator_destroy ccmp+    freeHaskellFunPtr ccmpfun+    freeHaskellFunPtr cdest+    freeHaskellFunPtr cname++mkCreateFilterFun :: ([ByteString] -> ByteString) -> CreateFilterFun+mkCreateFilterFun f = f'+  where+    f' _ ks ks_lens n_ks flen = do+        let n_ks' = fromInteger . toInteger $ n_ks+        ks'      <- peekArray n_ks' ks+        ks_lens' <- peekArray n_ks' ks_lens+        keys     <- mapM bstr (zip ks' ks_lens')+        let res = f keys+        poke flen (fromIntegral . BS.length $ res)+        BS.useAsCString res $ \cstr -> return cstr++    bstr (x,len) = BS.packCStringLen (x, fromInteger . toInteger $ len)++mkKeyMayMatchFun :: (ByteString -> ByteString -> Bool) -> KeyMayMatchFun+mkKeyMayMatchFun g = g'+  where+    g' _ k klen f flen = do+        k' <- BS.packCStringLen (k, fromInteger . toInteger $ klen)+        f' <- BS.packCStringLen (f, fromInteger . toInteger $ flen)+        return . boolToNum $ g k' f'+++mkFilterPolicy :: FilterPolicy -> IO FilterPolicy'+mkFilterPolicy FilterPolicy{..} =+    withCString fpName $ \cs -> do+        cname  <- mkName $ const cs+        cdest  <- mkDest $ const ()+        ccffun <- mkCF . mkCreateFilterFun $ createFilter+        ckmfun <- mkKMM . mkKeyMayMatchFun $ keyMayMatch+        cfp    <- c_leveldb_filterpolicy_create nullPtr cdest ccffun ckmfun cname++        return $ FilterPolicy' ccffun ckmfun cdest cname cfp++freeFilterPolicy :: FilterPolicy' -> IO ()+freeFilterPolicy (FilterPolicy' ccffun ckmfun cdest cname cfp) = do+    c_leveldb_filterpolicy_destroy cfp+    freeHaskellFunPtr ccffun+    freeHaskellFunPtr ckmfun+    freeHaskellFunPtr cdest+    freeHaskellFunPtr cname++mkCReadOpts :: ReadOptions -> IO ReadOptionsPtr+mkCReadOpts ReadOptions{..} = do+    opts_ptr <- c_leveldb_readoptions_create+    flip onException (c_leveldb_readoptions_destroy opts_ptr) $ do+        c_leveldb_readoptions_set_verify_checksums opts_ptr $ boolToNum verifyCheckSums+        c_leveldb_readoptions_set_fill_cache opts_ptr $ boolToNum fillCache++        case useSnapshot of+            Just (Snapshot snap_ptr) -> c_leveldb_readoptions_set_snapshot opts_ptr snap_ptr+            Nothing -> return ()++    return opts_ptr++freeCReadOpts :: ReadOptionsPtr -> IO ()+freeCReadOpts = c_leveldb_readoptions_destroy++withCReadOpts :: ReadOptions -> (ReadOptionsPtr -> IO a) -> IO a+withCReadOpts opts = bracket (mkCReadOpts opts) freeCReadOpts++throwIfErr :: String -> (ErrPtr -> IO a) -> IO a+throwIfErr s f = alloca $ \err_ptr -> do+    poke err_ptr nullPtr+    res  <- f err_ptr+    erra <- peek err_ptr+    when (erra /= nullPtr) $ do+        err <- peekCString erra+        throwIO $ userError $ s ++ ": " ++ err+    return res++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 #-}
+ src/Database/LevelDB/Iterator.hs view
@@ -0,0 +1,227 @@+-- |+-- Module      : Database.LevelDB.Iterator+-- Copyright   : (c) 2012-2013 The leveldb-haskell Authors+-- License     : BSD3+-- Maintainer  : kim.altintop@gmail.com+-- Stability   : experimental+-- Portability : non-portable+--+-- Iterating over key ranges.+--++module Database.LevelDB.Iterator+    ( Iterator+    , createIter+    , iterEntry+    , iterFirst+    , iterGetError+    , iterItems+    , iterKey+    , iterKeys+    , iterLast+    , iterNext+    , iterPrev+    , iterSeek+    , iterValid+    , iterValue+    , iterValues+    , mapIter+    , releaseIter+    , withIter+    )+where++import           Control.Applicative       ((<$>), (<*>))+import           Control.Exception         (bracket, finally, onException)+import           Control.Monad             (when)+import           Control.Monad.IO.Class    (MonadIO (liftIO))+import           Data.ByteString           (ByteString)+import           Data.Maybe                (catMaybes)+import           Foreign+import           Foreign.C.Error           (throwErrnoIfNull)+import           Foreign.C.String          (CString, peekCString)+import           Foreign.C.Types           (CSize)++import           Database.LevelDB.C+import           Database.LevelDB.Internal+import           Database.LevelDB.Types++import qualified Data.ByteString           as BS+import qualified Data.ByteString.Char8     as BC+import qualified Data.ByteString.Unsafe    as BU++-- | Iterator handle+--+-- Note that an 'Iterator' requires external synchronization if it is shared+-- between multiple threads which mutate it's state. See+-- @examples/iterforkio.hs@ for a simple example of how to do that.+data Iterator = Iterator !IteratorPtr !ReadOptionsPtr deriving (Eq)++-- | Create an 'Iterator'.+--+-- The iterator should be released with 'releaseIter'.+--+-- Note that an 'Iterator' creates a snapshot of the database implicitly, so+-- updates written after the iterator was created are not visible. You may,+-- however, specify an older 'Snapshot' in the 'ReadOptions'.+createIter :: MonadIO m => DB -> ReadOptions -> m Iterator+createIter (DB db_ptr _) opts = liftIO $ do+    opts_ptr <- mkCReadOpts opts+    flip onException (freeCReadOpts opts_ptr) $ do+        iter_ptr <- throwErrnoIfNull "create_iterator" $+                        c_leveldb_create_iterator db_ptr opts_ptr+        return $ Iterator iter_ptr opts_ptr++-- | Release an 'Iterator'.+--+-- The handle will be invalid after calling this action and should no+-- longer be used. Calling this function with an already released 'Iterator'+-- will cause a double-free error!+releaseIter :: MonadIO m => Iterator -> m ()+releaseIter (Iterator iter_ptr opts) = liftIO $+    c_leveldb_iter_destroy iter_ptr `finally` freeCReadOpts opts++-- | Run an action with an 'Iterator'+withIter :: MonadIO m => DB -> ReadOptions -> (Iterator -> IO a) -> m a+withIter db opts = liftIO . bracket (createIter db opts) releaseIter++-- | An iterator is either positioned at a key/value pair, or not valid. This+-- function returns /true/ iff the iterator is valid.+iterValid :: MonadIO m => Iterator -> m Bool+iterValid (Iterator iter_ptr _) = liftIO $ do+    x <- c_leveldb_iter_valid iter_ptr+    return (x /= 0)++-- | Position at the first key in the source that is at or past target. The+-- iterator is /valid/ after this call iff the source contains an entry that+-- comes at or past target.+iterSeek :: MonadIO m => Iterator -> ByteString -> m ()+iterSeek (Iterator iter_ptr _) key = liftIO $+    BU.unsafeUseAsCStringLen key $ \(key_ptr, klen) ->+        c_leveldb_iter_seek iter_ptr key_ptr (intToCSize klen)++-- | Position at the first key in the source. The iterator is /valid/ after this+-- call iff the source is not empty.+iterFirst :: MonadIO m => Iterator -> m ()+iterFirst (Iterator iter_ptr _) = liftIO $ c_leveldb_iter_seek_to_first iter_ptr++-- | Position at the last key in the source. The iterator is /valid/ after this+-- call iff the source is not empty.+iterLast :: MonadIO m => Iterator -> m ()+iterLast (Iterator iter_ptr _) = liftIO $ c_leveldb_iter_seek_to_last iter_ptr++-- | Moves to the next entry in the source. After this call, 'iterValid' is+-- /true/ iff the iterator was not positioned at the last entry in the source.+--+-- If the iterator is not valid, this function does nothing. Note that this is a+-- shortcoming of the C API: an 'iterPrev' might still be possible, but we can't+-- determine if we're at the last or first entry.+iterNext :: MonadIO m => Iterator -> m ()+iterNext (Iterator iter_ptr _) = liftIO $ do+    valid <- c_leveldb_iter_valid iter_ptr+    when (valid /= 0) $ c_leveldb_iter_next iter_ptr++-- | Moves to the previous entry in the source. After this call, 'iterValid' is+-- /true/ iff the iterator was not positioned at the first entry in the source.+--+-- If the iterator is not valid, this function does nothing. Note that this is a+-- shortcoming of the C API: an 'iterNext' might still be possible, but we can't+-- determine if we're at the last or first entry.+iterPrev :: MonadIO m => Iterator -> m ()+iterPrev (Iterator iter_ptr _) = liftIO $ do+    valid <- c_leveldb_iter_valid iter_ptr+    when (valid /= 0) $ c_leveldb_iter_prev iter_ptr++-- | Return the key for the current entry if the iterator is currently+-- positioned at an entry, ie. 'iterValid'.+iterKey :: MonadIO m => Iterator -> m (Maybe ByteString)+iterKey = liftIO . flip iterString c_leveldb_iter_key++-- | Return the value for the current entry if the iterator is currently+-- positioned at an entry, ie. 'iterValid'.+iterValue :: MonadIO m => Iterator -> m (Maybe ByteString)+iterValue = liftIO . flip iterString c_leveldb_iter_value++-- | Return the current entry as a pair, if the iterator is currently positioned+-- at an entry, ie. 'iterValid'.+iterEntry :: MonadIO m => Iterator -> m (Maybe (ByteString, ByteString))+iterEntry iter = liftIO $ do+    mkey <- iterKey iter+    mval <- iterValue iter+    return $ (,) <$> mkey <*> mval++-- | Check for errors+--+-- Note that this captures somewhat severe errors such as a corrupted database.+iterGetError :: MonadIO m => Iterator -> m (Maybe ByteString)+iterGetError (Iterator iter_ptr _) = liftIO $+    alloca $ \err_ptr -> do+        poke err_ptr nullPtr+        c_leveldb_iter_get_error iter_ptr err_ptr+        erra <- peek err_ptr+        if erra == nullPtr+            then return Nothing+            else do+                err <- peekCString erra+                return . Just . BC.pack $ err++-- | Map a function over an iterator, advancing the iterator forward and+-- returning the value. The iterator should be put in the right position prior+-- to calling the function.+--+-- Note that this function accumulates the result strictly, ie. it reads all+-- values into memory until the iterator is exhausted. This is most likely not+-- what you want for large ranges. You may consider using conduits instead, for+-- an example see: <https://gist.github.com/adc8ec348f03483446a5>+mapIter :: MonadIO m => (Iterator -> m a) -> Iterator -> m [a]+mapIter f iter@(Iterator iter_ptr _) = go []+  where+    go acc = do+        valid <- liftIO $ c_leveldb_iter_valid iter_ptr+        if valid == 0+            then return acc+            else do+                val <- f iter+                ()  <- liftIO $ c_leveldb_iter_next iter_ptr+                go (val : acc)++-- | Return a list of key and value tuples from an iterator. The iterator+-- should be put in the right position prior to calling this with the iterator.+--+-- See strictness remarks on 'mapIter'.+iterItems :: (Functor m, MonadIO m) => Iterator -> m [(ByteString, ByteString)]+iterItems iter = catMaybes <$> mapIter iterEntry iter++-- | Return a list of key from an iterator. The iterator should be put+-- in the right position prior to calling this with the iterator.+--+-- See strictness remarks on 'mapIter'+iterKeys :: (Functor m, MonadIO m) => Iterator -> m [ByteString]+iterKeys iter = catMaybes <$> mapIter iterKey iter++-- | Return a list of values from an iterator. The iterator should be put+-- in the right position prior to calling this with the iterator.+--+-- See strictness remarks on 'mapIter'+iterValues :: (Functor m, MonadIO m) => Iterator -> m [ByteString]+iterValues iter = catMaybes <$> mapIter iterValue iter+++--+-- Internal+--++iterString :: Iterator+           -> (IteratorPtr -> Ptr CSize -> IO CString)+           -> IO (Maybe ByteString)+iterString (Iterator iter_ptr _) f = do+    valid <- c_leveldb_iter_valid iter_ptr+    if valid == 0+        then return Nothing+        else alloca $ \len_ptr -> do+                 ptr <- f iter_ptr len_ptr+                 if ptr == nullPtr+                     then return Nothing+                     else do+                         len <- peek len_ptr+                         Just <$> BS.packCStringLen (ptr, cSizeToInt len)
+ src/Database/LevelDB/MonadResource.hs view
@@ -0,0 +1,285 @@+-- |+-- Module      : Database.LevelDB.MonadResource+-- Copyright   : (c) 2012-2013 The leveldb-haskell Authors+-- License     : BSD3+-- Maintainer  : kim.altintop@gmail.com+-- Stability   : experimental+-- Portability : non-portable+--++module Database.LevelDB.MonadResource+    ( -- * Exported Types+      DB+    , BatchOp(..)+    , Comparator(..)+    , Compression(..)+    , Options(..)+    , ReadOptions(..)+    , Snapshot+    , WriteBatch+    , WriteOptions(..)+    , Range++    -- * Defaults+    , defaultOptions+    , defaultWriteOptions+    , defaultReadOptions++    -- * Basic Database Manipulation+    , withSnapshot+    , open+    , put+    , delete+    , write+    , get+    , createSnapshot+    , createSnapshot'++    -- * Filter Policy / Bloom Filter+    , FilterPolicy(..)+    , bloomFilter++    -- * Administrative Functions+    , Property(..), getProperty+    , destroy+    , repair+    , approximateSize+    , version++    -- * Iteration+    , Iterator+    , withIterator+    , iterOpen+    , iterOpen'+    , iterValid+    , iterSeek+    , iterFirst+    , iterLast+    , iterNext+    , iterPrev+    , iterKey+    , iterValue+    , iterGetError+    , mapIter+    , iterItems+    , iterKeys+    , iterValues++    -- * Re-exports+    , MonadResource (..)+    , runResourceT+    , resourceForkIO+    )+where++import           Control.Applicative          ((<$>))+import           Control.Monad.Trans.Resource+import           Data.ByteString              (ByteString)+import           Data.Int                     (Int64)++import           Database.LevelDB.Base        (BatchOp, BloomFilter, Comparator,+                                               Compression, DB, FilterPolicy,+                                               Iterator, Options, Property,+                                               Range, ReadOptions, Snapshot,+                                               WriteBatch, WriteOptions,+                                               defaultOptions,+                                               defaultReadOptions,+                                               defaultWriteOptions)+import qualified Database.LevelDB.Base        as Base+++-- | Create a 'BloomFilter'+bloomFilter :: MonadResource m => Int -> m BloomFilter+bloomFilter i =+    snd <$> allocate (Base.createBloomFilter i)+                      Base.releaseBloomFilter++-- | Open a database+--+-- The returned handle will automatically be released when the enclosing+-- 'runResourceT' terminates.+open :: MonadResource m => FilePath -> Options -> m DB+open path opts = snd <$> open' path opts++open' :: MonadResource m => FilePath -> Options -> m (ReleaseKey, DB)+open' path opts = allocate (Base.open path opts) Base.close+{-# INLINE open' #-}++-- | Run an action with a snapshot of the database.+--+-- The snapshot will be released when the action terminates or throws an+-- exception. Note that this function is provided for convenience and does not+-- prevent the 'Snapshot' handle to escape. It will, however, be invalid after+-- this function returns and should not be used anymore.+withSnapshot :: MonadResource m => DB -> (Snapshot -> m a) -> m a+withSnapshot db f = do+    (rk, snap) <- createSnapshot' db+    res <- f snap+    release rk+    return res++-- | Create a snapshot of the database.+--+-- The returned 'Snapshot' will be released automatically when the enclosing+-- 'runResourceT' terminates. It is recommended to use 'createSnapshot'' instead+-- and release the resource manually as soon as possible.+createSnapshot :: MonadResource m => DB -> m Snapshot+createSnapshot db = snd <$> createSnapshot' db++-- | Create a snapshot of the database which can (and should) be released early.+createSnapshot' :: MonadResource m => DB -> m (ReleaseKey, Snapshot)+createSnapshot' db = allocate (Base.createSnapshot db) (Base.releaseSnapshot db)++-- | Get a DB property+getProperty :: MonadResource m => DB -> Property -> m (Maybe ByteString)+getProperty = Base.getProperty++-- | Destroy the given leveldb database.+destroy :: MonadResource m => FilePath -> Options -> m ()+destroy = Base.destroy++-- | Repair the given leveldb database.+repair :: MonadResource m => FilePath -> Options -> m ()+repair = Base.repair+++-- | Inspect the approximate sizes of the different levels+approximateSize :: MonadResource m => DB -> Range -> m Int64+approximateSize = Base.approximateSize++-- | Write a key/value pair+put :: MonadResource m => DB -> WriteOptions -> ByteString -> ByteString -> m ()+put = Base.put++-- | Read a value by key+get :: MonadResource m => DB -> ReadOptions -> ByteString -> m (Maybe ByteString)+get = Base.get++-- | Delete a key/value pair+delete :: MonadResource m => DB -> WriteOptions -> ByteString -> m ()+delete = Base.delete++-- | Perform a batch mutation+write :: MonadResource m => DB -> WriteOptions -> WriteBatch -> m ()+write = Base.write+++-- | Run an action with an Iterator. The iterator will be closed after the+-- action returns or an error is thrown. Thus, the iterator will /not/ be valid+-- after this function terminates.+withIterator :: MonadResource m => DB -> ReadOptions -> (Iterator -> m a) -> m a+withIterator db opts f = do+    (rk, iter) <- iterOpen' db opts+    res <- f iter+    release rk+    return res++-- | Create an 'Iterator'.+--+-- The iterator will be released when the enclosing 'runResourceT' terminates.+-- You may consider to use 'iterOpen'' instead and manually release the iterator+-- as soon as it is no longer needed (alternatively, use 'withIterator').+--+-- Note that an 'Iterator' creates a snapshot of the database implicitly, so+-- updates written after the iterator was created are not visible. You may,+-- however, specify an older 'Snapshot' in the 'ReadOptions'.+iterOpen :: MonadResource m => DB -> ReadOptions -> m Iterator+iterOpen db opts = snd <$> iterOpen' db opts++-- | Create an 'Iterator' which can be released early.+iterOpen' :: MonadResource m => DB -> ReadOptions -> m (ReleaseKey, Iterator)+iterOpen' db opts = allocate (Base.createIter db opts) Base.releaseIter++-- | An iterator is either positioned at a key/value pair, or not valid. This+-- function returns /true/ iff the iterator is valid.+iterValid :: MonadResource m => Iterator -> m Bool+iterValid = Base.iterValid++-- | Position at the first key in the source that is at or past target. The+-- iterator is /valid/ after this call iff the source contains an entry that+-- comes at or past target.+iterSeek :: MonadResource m => Iterator -> ByteString -> m ()+iterSeek = Base.iterSeek++-- | Position at the first key in the source. The iterator is /valid/ after this+-- call iff the source is not empty.+iterFirst :: MonadResource m => Iterator -> m ()+iterFirst = Base.iterFirst++-- | Position at the last key in the source. The iterator is /valid/ after this+-- call iff the source is not empty.+iterLast :: MonadResource m => Iterator -> m ()+iterLast = Base.iterLast++-- | Moves to the next entry in the source. After this call, 'iterValid' is+-- /true/ iff the iterator was not positioned at the last entry in the source.+--+-- If the iterator is not valid, this function does nothing. Note that this is a+-- shortcoming of the C API: an 'iterPrev' might still be possible, but we can't+-- determine if we're at the last or first entry.+iterNext :: MonadResource m => Iterator -> m ()+iterNext = Base.iterNext++-- | Moves to the previous entry in the source. After this call, 'iterValid' is+-- /true/ iff the iterator was not positioned at the first entry in the source.+--+-- If the iterator is not valid, this function does nothing. Note that this is a+-- shortcoming of the C API: an 'iterNext' might still be possible, but we can't+-- determine if we're at the last or first entry.+iterPrev :: MonadResource m => Iterator -> m ()+iterPrev = Base.iterPrev++-- | Return the key for the current entry if the iterator is currently+-- positioned at an entry, ie. 'iterValid'.+iterKey :: MonadResource m => Iterator -> m (Maybe ByteString)+iterKey = Base.iterKey++-- | Return the value for the current entry if the iterator is currently+-- positioned at an entry, ie. 'iterValid'.+iterValue :: MonadResource m => Iterator -> m (Maybe ByteString)+iterValue = Base.iterValue++-- | Check for errors+--+-- Note that this captures somewhat severe errors such as a corrupted database.+iterGetError :: MonadResource m => Iterator -> m (Maybe ByteString)+iterGetError = Base.iterGetError+++-- | Map a function over an iterator, advancing the iterator forward and+-- returning the value. The iterator should be put in the right position prior+-- to calling the function.+--+-- Note that this function accumulates the result strictly, ie. it reads all+-- values into memory until the iterator is exhausted. This is most likely not+-- what you want for large ranges. You may consider using conduits instead, for+-- an example see: <https://gist.github.com/adc8ec348f03483446a5>+mapIter :: MonadResource m => (Iterator -> m a) -> Iterator -> m [a]+mapIter = Base.mapIter++-- | Return a list of key and value tuples from an iterator. The iterator+-- should be put in the right position prior to calling this with the iterator.+--+-- See strictness remarks on 'mapIter'.+iterItems :: MonadResource m => Iterator -> m [(ByteString, ByteString)]+iterItems = Base.iterItems++-- | Return a list of key from an iterator. The iterator should be put+-- in the right position prior to calling this with the iterator.+--+-- See strictness remarks on 'mapIter'+iterKeys :: MonadResource m => Iterator -> m [ByteString]+iterKeys = Base.iterKeys++-- | Return a list of values from an iterator. The iterator should be put+-- in the right position prior to calling this with the iterator.+--+-- See strictness remarks on 'mapIter'+iterValues :: MonadResource m => Iterator -> m [ByteString]+iterValues = Base.iterValues+++-- | Return the runtime version of the underlying LevelDB library as a (major,+-- minor) pair.+version :: MonadResource m => m (Int, Int)+version = Base.version
+ src/Database/LevelDB/Types.hs view
@@ -0,0 +1,217 @@+-- |+-- Module      : Database.LevelDB.Types+-- Copyright   : (c) 2012-2013 The leveldb-haskell Authors+-- License     : BSD3+-- Maintainer  : kim.altintop@gmail.com+-- Stability   : experimental+-- Portability : non-portable+--++module Database.LevelDB.Types+    ( BatchOp (..)+    , BloomFilter (..)+    , Comparator (..)+    , Compression (..)+    , FilterPolicy (..)+    , Options (..)+    , Property (..)+    , ReadOptions (..)+    , Snapshot (..)+    , WriteBatch+    , WriteOptions (..)++    , defaultOptions+    , defaultReadOptions+    , defaultWriteOptions+    )+where++import           Data.ByteString    (ByteString)+import           Data.Default+import           Foreign++import           Database.LevelDB.C++-- | Snapshot handle+newtype Snapshot = Snapshot SnapshotPtr deriving (Eq)++-- | Compression setting+data Compression = NoCompression | Snappy deriving (Eq, Show)++-- | User-defined comparator+newtype Comparator = Comparator (ByteString -> ByteString -> Ordering)++-- | User-defined filter policy+data FilterPolicy = FilterPolicy+    { fpName       :: String+    , createFilter :: [ByteString] -> ByteString+    , keyMayMatch  :: ByteString -> ByteString -> Bool+    }++-- | Represents the built-in Bloom Filter+newtype BloomFilter = BloomFilter FilterPolicyPtr++-- | Options when opening a database+data Options = Options+    { blockRestartInterval :: !Int+      -- ^ Number of keys between restart points for delta encoding of keys.+      --+      -- This parameter can be changed dynamically. Most clients should leave+      -- this parameter alone.+      --+      -- Default: 16+    , blockSize            :: !Int+      -- ^ Approximate size of user data packed per block.+      --+      -- Note that the block size specified here corresponds to uncompressed+      -- data. The actual size of the unit read from disk may be smaller if+      -- compression is enabled.+      --+      -- This parameter can be changed dynamically.+      --+      -- Default: 4k+    , cacheSize            :: !Int+      -- ^ Control over blocks (user data is stored in a set of blocks, and a+      -- block is the unit of reading from disk).+      --+      -- If > 0, use the specified cache (in bytes) for blocks. If 0, leveldb+      -- will automatically create and use an 8MB internal cache.+      --+      -- Default: 0+    , comparator           :: !(Maybe Comparator)+      -- ^ Comparator used to defined the order of keys in the table.+      --+      -- If 'Nothing', the default comparator is used, which uses lexicographic+      -- bytes-wise ordering.+      --+      -- NOTE: the client must ensure that the comparator supplied here has the+      -- same name and orders keys /exactly/ the same as the comparator provided+      -- to previous open calls on the same DB.+      --+      -- Default: Nothing+    , compression          :: !Compression+      -- ^ Compress blocks using the specified compression algorithm.+      --+      -- This parameter can be changed dynamically.+      --+      -- Default: 'Snappy'+    , createIfMissing      :: !Bool+      -- ^ If true, the database will be created if it is missing.+      --+      -- Default: False+    , errorIfExists        :: !Bool+      -- ^ It true, an error is raised if the database already exists.+      --+      -- Default: False+    , maxOpenFiles         :: !Int+      -- ^ Number of open files that can be used by the DB.+      --+      -- You may need to increase this if your database has a large working set+      -- (budget one open file per 2MB of working set).+      --+      -- Default: 1000+    , paranoidChecks       :: !Bool+      -- ^ If true, the implementation will do aggressive checking of the data+      -- it is processing and will stop early if it detects any errors.+      --+      -- This may have unforeseen ramifications: for example, a corruption of+      -- one DB entry may cause a large number of entries to become unreadable+      -- or for the entire DB to become unopenable.+      --+      -- Default: False+    , writeBufferSize      :: !Int+      -- ^ Amount of data to build up in memory (backed by an unsorted log on+      -- disk) before converting to a sorted on-disk file.+      --+      -- Larger values increase performance, especially during bulk loads. Up to+      -- to write buffers may be held in memory at the same time, so you may+      -- with to adjust this parameter to control memory usage. Also, a larger+      -- write buffer will result in a longer recovery time the next time the+      -- database is opened.+      --+      -- Default: 4MB+    , filterPolicy         :: !(Maybe (Either BloomFilter FilterPolicy))+    }++defaultOptions :: Options+defaultOptions = Options+    { blockRestartInterval = 16+    , blockSize            = 4096+    , cacheSize            = 0+    , comparator           = Nothing+    , compression          = Snappy+    , createIfMissing      = False+    , errorIfExists        = False+    , maxOpenFiles         = 1000+    , paranoidChecks       = False+    , writeBufferSize      = 4 `shift` 20+    , filterPolicy         = Nothing+    }++instance Default Options where+    def = defaultOptions++-- | Options for write operations+data WriteOptions = WriteOptions+    { sync :: !Bool+      -- ^ If true, the write will be flushed from the operating system buffer+      -- cache (by calling WritableFile::Sync()) before the write is considered+      -- complete. If this flag is true, writes will be slower.+      --+      -- If this flag is false, and the machine crashes, some recent writes may+      -- be lost. Note that if it is just the process that crashes (i.e., the+      -- machine does not reboot), no writes will be lost even if sync==false.+      --+      -- In other words, a DB write with sync==false has similar crash semantics+      -- as the "write()" system call. A DB write with sync==true has similar+      -- crash semantics to a "write()" system call followed by "fsync()".+      --+      -- Default: False+    } deriving (Eq, Show)++defaultWriteOptions :: WriteOptions+defaultWriteOptions = WriteOptions { sync = False }++instance Default WriteOptions where+    def = defaultWriteOptions++-- | Options for read operations+data ReadOptions = ReadOptions+    { verifyCheckSums :: !Bool+      -- ^ If true, all data read from underlying storage will be verified+      -- against corresponding checksuyms.+      --+      -- Default: False+    , fillCache       :: !Bool+      -- ^ Should the data read for this iteration be cached in memory? Callers+      -- may with to set this field to false for bulk scans.+      --+      -- Default: True+    , useSnapshot     :: !(Maybe Snapshot)+      -- ^ If 'Just', read as of the supplied snapshot (which must belong to the+      -- DB that is being read and which must not have been released). If+      -- 'Nothing', use an implicit snapshot of the state at the beginning of+      -- this read operation.+      --+      -- Default: Nothing+    } deriving (Eq)++defaultReadOptions :: ReadOptions+defaultReadOptions = ReadOptions+    { verifyCheckSums = False+    , fillCache       = True+    , useSnapshot     = Nothing+    }++instance Default ReadOptions where+    def = defaultReadOptions++type WriteBatch = [BatchOp]++-- | Batch operation+data BatchOp = Put ByteString ByteString | Del ByteString+    deriving (Eq, Show)++-- | Properties exposed by LevelDB+data Property = NumFilesAtLevel Int | Stats | SSTables+    deriving (Eq, Show)