BerkeleyDB 0.1 → 0.2
raw patch · 2 files changed
+225/−152 lines, 2 filesdep +unix
Dependencies added: unix
Files
- BerkeleyDB.cabal +2/−2
- Database/BerkeleyDB.hsc +223/−150
BerkeleyDB.cabal view
@@ -1,5 +1,5 @@ name: BerkeleyDB-version: 0.1+version: 0.2 license: BSD3 license-file: LICENSE copyright: John McCall, 2007@@ -8,7 +8,7 @@ stability: alpha homepage: http://www.cs.pdx.edu/~rjmccall/hackage/BerkeleyDB/ category: Database-build-depends: base+build-depends: base, unix synopsis: Bindings for Berkeley DB v1.x description: Provides Haskell bindings for Berkeley DB v1.x, a simple file-backed
Database/BerkeleyDB.hsc view
@@ -1,27 +1,19 @@ {--Haskell bindings for Berkeley DB v1.5, i.e. <db.h> on BSD-derived Unices.-This module is intended to be imported qualified.--The database implementations provided by this module are not safe-against concurrent access; for that, users must seek a more resilient-database.--This module has been written with GHC 6.6 in mind; it is quite-possible that it will function with minimal changes on other-implementations of Haskell or earlier versions of GHC, and patches for-this purpose would be welcome, providing they don't compromise the integrity-of the up-to-date GHC implementation.+ Database.BerkeleyDB v0.2+ Copyright 2007 John McCall+ Licensed for general use under a BSD3-style license; for the exact+ license text, see the LICENSE file included in this distribution. If+ you find this file distributed without a LICENSE file, please contact+ me at rjmccall@gmail.com and tell me where you found it. -The open functions generally interpret IO mode as follows:- - ReadMode attempts to open a database in read-only mode; if the database- doesn't exist, an exception is thrown.- - ReadWriteMode and AppendMode are synonymous; both open the database in- read/write mode, creating it if necessary.- - WriteMode opens the database in read/write mode, but it truncates any- existing database file.+ It's my hope that this module could be used to bootstrap bindings for a+ modern version of Berkeley DB, but I'm not currently working on that. -This file could also be used to bootstrap bindings for a modern version of-Berkeley DB.+ Author: John McCall <rjmccall@gmail.com>+ Maintainer: John McCall <rjmccall@gmail.com>+ History:+ v0.2 2007-04-06 Haddock documentation; FileMode.+ v0.1 2007-04-05 Creation. -} {- We require a preprocessor pass in order to bring the structure@@ -42,6 +34,31 @@ #let alignment type = "alignment (undefined :: Ptr a)" #endif +{-|+Haskell bindings for Berkeley DB v1.85, i.e. @db.h@ on BSD-derived Unices.+This module is intended to be imported qualified.++The database implementations provided by this module are not safe+against concurrent access; for that, users must seek a more resilient+database.++This module has been written with GHC 6.6 in mind; it is quite+possible that it will function with minimal changes on other+implementations of Haskell or earlier versions of GHC, and patches for+this purpose would be welcome, providing they don't compromise the integrity+of the up-to-date GHC implementation.++The open functions generally interpret 'IOMode' as follows:++- 'ReadMode' attempts to open a database in read-only mode; if the database+ doesn't exist, an exception is thrown.++- 'ReadWriteMode' and 'AppendMode' are synonymous; both open the database in+ read\/write mode, creating it if necessary.++- 'WriteMode' opens the database in read\/write mode, but it truncates any+ existing database file.+ -} module Database.BerkeleyDB (HashDB, openHash, HashDBCursor,HashDBConf(..), defaultHashDBConf, TreeDB, openTree, TreeDBCursor,TreeDBConf(..), defaultTreeDBConf, @@ -49,9 +66,13 @@ RecordDBConf(..), defaultRecordDBConf, FixedRecordDB, openFixedRecord, FixedRecordDBCursor, FixedRecordDBConf(..), defaultFixedRecordDBConf,- DB(..), DBCursor(..), IOMode(..), UMask) where+ DB(..), DBCursor(..),+ IOMode(..)) where -import System.IO+import System.IO (IOMode(..)) -- re-exported+import System.Posix.Files -- for FileMode's helpful constants+import System.Posix.Types -- for mode_t+ import Foreign import Foreign.C import Control.Monad (when, liftM)@@ -59,30 +80,27 @@ import Data.ByteString (ByteString, packCStringLen, copyCStringLen, useAsCStringLen) import Prelude hiding (lookup) ------- ELEMENTARY DEFINITIONS ---------{- POSIX file-creation masks; see the manpage for umask(2). -}--type UMask = Int--{- The default umask doesn't restrict created files in any way other than- that specified in the process umask. -}--defaultUmask :: UMask-defaultUmask = 0666+{- We use 0666 as our default umask, but we define it in this crazy way. -}+defaultUmask :: FileMode+defaultUmask = foldl1 unionFileModes [ownerReadMode,+ ownerWriteMode,+ groupReadMode,+ groupWriteMode,+ otherReadMode,+ otherWriteMode] --------- TYPE CLASSES --------- -{- Common operations supported by databases. The database type- functionally defines its key, value, and cursor types. -}+{-| Common operations supported by databases. The database type+ functionally defines its key, value, and cursor types. -} class (DBCursor c k v) => DB t c k v | t -> c k v where - {- The simplified "open" command. Individual database types usually+ {-| The simplified "open" command. Individual database types usually provide a specialized open operation. If no filepath is given, the database will exist primarily in memory or a temporary file. -} open :: Maybe FilePath -> IOMode -> IO t - {- Closes the database. Just as with files, it's important to explicitly+ {-| Closes the database. Just as with files, it's important to explicitly close a database to avoid memory leaks; it's also important to explicitly close a database in order to flush database writes which might currently be cached.@@ -92,66 +110,66 @@ database object after it's been closed. -} close :: t -> IO () - {- Inserts an entry into the database. -}+ {-| Inserts an entry into the database. -} insert :: t -> k -> v -> IO () - {- Looks up an entry in the database. -}+ {-| Looks up an entry in the database. -} lookup :: t -> k -> IO (Maybe v) - {- Deletes an entry from the database. Returns true if the entry existed- before it was deleted. -}+ {-| Deletes an entry from the database. Returns true if the entry existed+ before it was deleted. -} delete :: t -> k -> IO Bool - {- Creates a new cursor for sequential access to the database. The- standard Berkeley DB implementations only support a single cursor- per database, so even if multiple cursors are created, they'll- all change the same state. Other database implementations might- support multiple simultaneous cursors. -}+ {-| Creates a new cursor for sequential access to the database. The+ standard Berkeley DB implementations only support a single cursor+ per database, so even if multiple cursors are created, they'll+ all change the same state. Other database implementations might+ support multiple simultaneous cursors. -} cursor :: t -> IO c - {- Forces a sync with the disk, to the extent that this is possible- with system calls. -}+ {-| Forces a sync with the disk, to the extent that this is possible+ with system calls. -} sync :: t -> IO () -{- A type-class for database cursors. The cursor type functionally- defines the key and value types. -}+{-| A type-class for database cursors. The cursor type functionally+ defines the key and value types. -} class DBCursor c k v | c -> k v where - {- Jumps to the first entry in the database. -}+ {-| Jumps to the first entry in the database. -} jumpFirst :: c -> IO (Maybe (k,v)) - {- Jumps to the last entry in the database. Not all database- implementations support this operation. -}+ {-| Jumps to the last entry in the database. Not all database+ implementations support this operation. -} jumpLast :: c -> IO (Maybe (k,v)) - {- Jumps to an arbitrary place in the database. The returned match- may not be an exact match for the key; see the notes for each- database implementation for more details. -}+ {-| Jumps to an arbitrary place in the database. The returned match+ may not be an exact match for the key; see the notes for each+ database implementation for more details. -} jump :: c -> k -> IO (Maybe (k,v)) - {- Moves to the next entry in the database. -}+ {-| Moves to the next entry in the database. -} next :: c -> IO (Maybe (k,v)) - {- Moves to the previous entry in the database. -}+ {-| Moves to the previous entry in the database. -} previous :: c -> IO (Maybe (k,v)) - {- Replaces the current entry with a new value. The cursor must be- initialized for this operation to succeed. -}+ {-| Replaces the current entry with a new value. The cursor must be+ initialized for this operation to succeed. -} replace :: c -> k -> v -> IO () - {- Removes the entry at the current cursor position. -}+ {-| Removes the entry at the current cursor position. -} remove :: c -> IO () - {- Closes the cursor. For Berkeley databases, this doesn't do anything. -}+ {-| Closes the cursor. For Berkeley databases, this doesn't do anything. -} closeCursor:: c -> IO () -------- GENERAL IMPLEMENTATION ------- {- The type of databases; in C-land, this is "DB". Here, it's- completely opaque, we never try to modify it, and we don't export- it. -}+ completely opaque, we never try to modify it, and we don't export+ it. -} data DBStruct = DBStruct {- The type of "database thangs"; in C-land, this is "DBT". -}@@ -241,7 +259,7 @@ ------- HASHTABLES -------- -{- Hashtable-based databases. -}+{-| Hashtable-based databases. -} data HashDB = HashDB (Ptr DBStruct) Bool HashToken instance DB HashDB HashDBCursor ByteString ByteString where open file mode = openHash file mode defaultUmask defaultHashDBConf@@ -254,7 +272,7 @@ cursor (HashDB ptr sf _) = liftM HashDBCursor $ newCursor ptr sf sync (HashDB ptr sf _) = _sync ptr -{- The type of hashtable database cursors. -}+{-| The type of hashtable database cursors. -} newtype HashDBCursor = HashDBCursor Cursor instance DBCursor HashDBCursor ByteString ByteString where jump (HashDBCursor c) = jump c@@ -266,39 +284,40 @@ remove (HashDBCursor c) = remove c closeCursor (HashDBCursor c) = closeCursor c -{- The configuration of a hashtable database. -}+{-| The configuration of a hashtable database. -} data HashDBConf = HashDBConf { - {- The size of a hash bucket, in bytes. -}+ {-| The size of a hash bucket, in bytes. -} hash_bucketSize :: Int, - {- A desired density for the hashtable. This value approximates the- maximum number of keys allowed in a bucket; the default value is 8. -}+ {-| A desired density for the hashtable. This value approximates the+ maximum number of keys allowed in a bucket; the default value is 8. -} hash_keyDensity :: Int, - {- The initial size of the database. The hashtable will grow gracefully - as keys are added, but performance may temporarily suffer at each- expansion, so it's always better to get this right. -}+ {-| The initial size of the database. The hashtable will grow gracefully + as keys are added, but performance may temporarily suffer at each+ expansion, so it's always better to get this right. -} hash_initialSize :: Int, - {- An advistory maximum size for the in-memory database cache. -}+ {-| An advistory maximum size for the in-memory database cache. -} hash_cacheSize :: Int, - {- The byte order of hashtable metadata; for example, 4321 specifies a- big-endian format. Not all byte orders are necessarily supported, and- this setting is ignored when opening existing databases. 0 means to use- host order. -}+ {-| The byte order of hashtable metadata; for example, 4321 specifies a+ big-endian format. Not all byte orders are necessarily supported, and+ this setting is ignored when opening existing databases. 0 means to use+ host order. -} hash_byteOrder :: Int, - {- A custom hash function. Specifying a custom hash function can- sometimes improve hashtable performance, depending on the expected- range of keys; however, since it requires a callback into Haskell, it- can also hurt performance by requiring "safe" calls into C (which forces- the runtime system to stabilize itself before every database call). -}+ {-| A custom hash function. Specifying a custom hash function can+ sometimes improve hashtable performance, depending on the expected+ range of keys; however, since it requires a callback into Haskell, it+ can also hurt performance by requiring "safe" calls into C (which forces+ the runtime system to stabilize itself before every database call). -} hash_hashFunction :: Maybe (ByteString -> Word32) } -{- The default database configuration. -}+{-| The default database configuration. -}+defaultHashDBConf :: HashDBConf defaultHashDBConf = HashDBConf { hash_bucketSize = 0, hash_keyDensity = 0,@@ -308,15 +327,15 @@ hash_hashFunction = Nothing } -{- Opens or creates a hashtable database. -}-openHash :: Maybe FilePath -> IOMode -> UMask -> HashDBConf -> IO HashDB+{-| Opens or creates a hashtable database. -}+openHash :: Maybe FilePath -> IOMode -> FileMode -> HashDBConf -> IO HashDB openHash path iomode umask conf = withMaybeString path $ \cpath -> alloca $ \info -> allocFunPtr (makeHash $ hash_hashFunction conf) $ \fpHash -> do writeHashDBConf conf fpHash info ptr <- throwErrnoIfNull "BerkeleyDB.openHash"- $ db_open_hash cpath (fromIOMode iomode) (toEnum umask) info+ $ db_open_hash cpath (fromIOMode iomode) umask info let safe = fpHash /= nullFunPtr return $ HashDB ptr safe fpHash @@ -389,7 +408,7 @@ ------- B-TREE DATABASES --------- -{- A database built on a b-tree. -}+{-| A database built on a b-tree. -} data TreeDB = TreeDB (Ptr DBStruct) Bool TreeToken instance DB TreeDB TreeDBCursor ByteString ByteString where open file mode = openTree file mode defaultUmask defaultTreeDBConf@@ -402,7 +421,7 @@ sync (TreeDB ptr sf _) = _sync ptr cursor (TreeDB ptr sf _) = liftM TreeDBCursor (newCursor ptr sf) -{- The cursor for a tree database. -}+{-| The cursor for a tree database. -} newtype TreeDBCursor = TreeDBCursor Cursor instance DBCursor TreeDBCursor ByteString ByteString where jump (TreeDBCursor c) = jump c@@ -414,51 +433,52 @@ remove (TreeDBCursor c) = remove c closeCursor (TreeDBCursor c) = closeCursor c -{- The configuration for a b-tree database. -}+{-| The configuration for a b-tree database. -} data TreeDBConf = TreeDBConf { - {- Permit multiple entries to appear in the database per key. Only- sequential operations can observe the difference. -}+ {-| Permit multiple entries to appear in the database per key. Only+ sequential operations can observe the difference. -} tree_duplicateKeys :: Bool, - {- An advistory maximum size of the in-memory database cache, in- bytes. A default cache size is used if this value is 0. -}+ {-| An advistory maximum size of the in-memory database cache, in+ bytes. A default cache size is used if this value is 0. -} tree_cacheSize :: Int, - {- An advisory maximum number of keys to store on a page. btree(3)- says this isn't implemented. -}+ {-| An advisory maximum number of keys to store on a page. btree(3)+ says this isn't implemented. -} tree_maxKeysPerPage :: Int, - {- The minimum number of keys to store on a page (other than the- root). This can never been less than 2. -}+ {-| The minimum number of keys to store on a page (other than the+ root). This can never been less than 2. -} tree_minKeysPerPage :: Int, - {- The size of each pages of the btree, in bytes. This much be at- least 512 and no more than 64K; if it is zero, a default size is- chosen based on the filesystem block size. This value is ignored- when opening existing databases. -}+ {-| The size of each pages of the btree, in bytes. This much be at+ least 512 and no more than 64K; if it is zero, a default size is+ chosen based on the filesystem block size. This value is ignored+ when opening existing databases. -} tree_pageSize :: Int, - {- The byte order of btree metadata; for example, 4321 specifies a- big-endian format. Not all byte orders are necessarily supported,- and this setting is ignored when opening existing databases. 0 means- to use host order. -}+ {-| The byte order of btree metadata; for example, 4321 specifies a+ big-endian format. Not all byte orders are necessarily supported,+ and this setting is ignored when opening existing databases. 0 means+ to use host order. -} tree_byteOrder :: Int, - {- A comparison function for keys. It is important that the same function- be used every time the tree is opened. The default comparison order is- lexicographic (i.e. shorter keys sort first, then each byte is compared- from the beginning to the end). -}+ {-| A comparison function for keys. It is important that the same function+ be used every time the tree is opened. The default comparison order is+ lexicographic (i.e. shorter keys sort first, then each byte is compared+ from the beginning to the end). -} tree_compare :: Maybe (ByteString -> ByteString -> Ordering), - {- A function indicating how many bytes are required from the second key- argument in order to decide the ordering. If the keys are equal, this- should be the length of the key. This can produce highly-compressed trees- in certain domains. -}+ {-| A function indicating how many bytes are required from the second key+ argument in order to decide the ordering. If the keys are equal, this+ should be the length of the key. This can produce highly-compressed trees+ in certain domains. -} tree_prefix :: Maybe (ByteString -> ByteString -> Int) } -{- The default b-tree configuration. -}+{-| The default b-tree configuration. -}+defaultTreeDBConf :: TreeDBConf defaultTreeDBConf = TreeDBConf { tree_duplicateKeys = False, -- disallow duplicate keys tree_cacheSize = 0, -- use default cache size@@ -470,17 +490,17 @@ tree_byteOrder = 0 -- host order } -{- Opens a b-tree database, failing with an I/O exception if the database- couldn't be opened. -}-openTree :: Maybe FilePath -> IOMode -> UMask -> TreeDBConf -> IO TreeDB-openTree path iomode umask conf =+{-| Opens a b-tree database, failing with an I\/O exception if the database+ couldn't be opened. -}+openTree :: Maybe FilePath -> IOMode -> FileMode -> TreeDBConf -> IO TreeDB+openTree path iomode filemode conf = alloca $ \info -> withMaybeString path $ \cpath -> allocFunPtr (makeCompare $ tree_compare conf) $ \fpCompare -> allocFunPtr (makePrefix $ tree_prefix conf) $ \fpPrefix -> do writeTreeDBConf conf fpCompare fpPrefix info ptr <- throwErrnoIfNull "BerkeleyDB.openTree"- $ db_open_btree cpath (fromIOMode iomode) (toEnum umask) info+ $ db_open_btree cpath (fromIOMode iomode) filemode info let safe = fpCompare /= nullFunPtr || fpPrefix /= nullFunPtr return $ TreeDB ptr safe (fpCompare,fpPrefix) @@ -577,9 +597,9 @@ ------- RECORD DATABASES -------- -{- recno_t, the type of record indices. recno(3) says this is "normally- the largest unsigned integral type available to the implementation", but on- modern systems it's usually just uint32_t. -}+{-| recno_t, the type of record indices. recno(3) says this is "normally+ the largest unsigned integral type available to the implementation", but on+ modern systems it's usually just uint32_t. -} newtype Record = Record Recno deriving (Bits,Bounded,Enum,Eq,Integral,Num, Ord,Read,Real,Show,Storable)@@ -587,6 +607,12 @@ {- The type of record cursors. -} newtype RecCursor = RecCursor (Ptr DBStruct)++-- Haddock wants to publicize this because it mentions Record, but I+-- don't really want to preprocess before running Haddock, because CPP+-- will throw all the HSC stuff in my face. Really, Haddock needs to+-- recognize that this instance is functionally defined by a private+-- type and therefore not expose it. instance DBCursor RecCursor Record ByteString where jump (RecCursor ptr) (Record key) = _cursorRecord ptr key #{const R_CURSOR} jumpFirst (RecCursor ptr) = _cursorRecord ptr 0 #{const R_FIRST}@@ -596,10 +622,11 @@ replace (RecCursor ptr) (Record key) val = _insertRecord ptr key val #{const R_SETCURSOR} remove (RecCursor ptr) = _deleteCursor False ptr -- never needs to be safe closeCursor _ = return ()+ newRecCursor :: Ptr DBStruct -> IO RecCursor newRecCursor ptr = return $ RecCursor ptr -{- Variable-length record databases. -}+{-| Variable-length record databases. -} newtype RecordDB = RecordDB (Ptr DBStruct) instance DB RecordDB RecordDBCursor Record ByteString where open file mode = openRecord file mode defaultUmask defaultRecordDBConf@@ -610,8 +637,8 @@ cursor (RecordDB ptr) = liftM RecordDBCursor $ newRecCursor ptr sync (RecordDB ptr) = _sync ptr -{- The type of variable-length record database cursors. The key returned by- cursor procedures is always 0. -}+{-| The type of variable-length record database cursors. The key returned by+ cursor procedures is always 0. -} newtype RecordDBCursor = RecordDBCursor RecCursor instance DBCursor RecordDBCursor Record ByteString where jump (RecordDBCursor c) = jump c@@ -623,34 +650,56 @@ remove (RecordDBCursor c) = remove c closeCursor (RecordDBCursor c) = closeCursor c -{- A configuration for variable-length record databases. -}+{-| A configuration for variable-length record databases. -} data RecordDBConf = RecordDBConf {--- record_noKey :: Bool,+ {-| Forces a snapshot of the database to be taken when the file+ is opened. -} record_snapshot :: Bool,++ {-| An advisory maximum size of the in-memory database cache. -} record_cacheSize :: Int,++ {-| The page size used for the in-memory database cache, which happens+ to be a b-tree. If this value is 0, a default size will be chosen. -} record_pageSize :: Int,++ {-| The byte order for integers in the database metadata; for example,+ 4321 represents big-endian order. Not all orders are guaranteed to+ be supported; if the byte order is 0, host order will be used.+ Unlike the other database types, record databases have no metadata,+ so it's important to get this right when opening existing+ databases. -} record_byteOrder :: Int,++ {-| The byte value used to separate records in the database. By default,+ this is a newline character (0x0A). -} record_separatorByte :: Word8,++ {-| A file which should be used to store the the in-memory record cache. -} record_treeFile :: Maybe String }++{-| The default variable-length record database configuration. -}+defaultRecordDBConf :: RecordDBConf defaultRecordDBConf = RecordDBConf { -- record_noKey = False, record_snapshot = False, record_cacheSize = 0, record_pageSize = 0, record_byteOrder = 0,- record_separatorByte = 32, -- ' '+ record_separatorByte = 0x0a, record_treeFile = Nothing } -openRecord :: Maybe FilePath -> IOMode -> UMask -> RecordDBConf -> IO RecordDB-openRecord path iomode umask conf =+{-| Opens a variable-length record database. -}+openRecord :: Maybe FilePath -> IOMode -> FileMode -> RecordDBConf -> IO RecordDB+openRecord path iomode filemode conf = withMaybeString path $ \cpath -> withMaybeString (record_treeFile conf) $ \ctreefile -> alloca $ \info -> do writeRecordDBConf conf ctreefile info ptr <- throwErrnoIfNull "BerkeleyDB.openRecord"- $ db_open_recno cpath (fromIOMode iomode) (toEnum umask) info+ $ db_open_recno cpath (fromIOMode iomode) filemode info return $ RecordDB ptr {- Writes a variable-length record database configuration into a C structure.@@ -670,7 +719,7 @@ ri_bfname = bfname } -{- Fixed-length record databases. -}+{-| Fixed-length record databases. -} newtype FixedRecordDB = FixedRecordDB (Ptr DBStruct) instance DB FixedRecordDB FixedRecordDBCursor Record ByteString where open file mode = openFixedRecord file mode defaultUmask defaultFixedRecordDBConf@@ -681,8 +730,8 @@ cursor (FixedRecordDB ptr) = liftM FixedRecordDBCursor $ newRecCursor ptr sync (FixedRecordDB ptr) = _sync ptr -{- The type of fixed-length record database cursors. The key returned by- cursor procedures is always 0. -}+{-| The type of fixed-length record database cursors. The key returned by+ cursor procedures is always 0. -} newtype FixedRecordDBCursor = FixedRecordDBCursor RecCursor instance DBCursor FixedRecordDBCursor Record ByteString where jump (FixedRecordDBCursor c) = jump c@@ -694,37 +743,61 @@ remove (FixedRecordDBCursor c) = remove c closeCursor (FixedRecordDBCursor c) = closeCursor c -{- A configuration for fixed-length record databases. -}+{-| A configuration for fixed-length record databases. -} data FixedRecordDBConf = FixedRecordDBConf {--- fixed_noKey :: Bool,+ {-| Forces a snapshot of the database to be taken when the file+ is opened. -} fixed_snapshot :: Bool,++ {-| An advisory maximum size of the in-memory database cache. -} fixed_cacheSize :: Int,++ {-| The page size used for the in-memory database cache, which happens+ to be a b-tree. If this value is 0, a default size will be chosen. -} fixed_pageSize :: Int,++ {-| The fixed length of the records. This must be manually overridden in+ the default configuration, or an exception will be thrown. -} fixed_recordLength :: Int,++ {-| The byte order for integers in the database metadata; for example,+ 4321 represents big-endian order. Not all orders are guaranteed to+ be supported; if the byte order is 0, host order will be used.+ Unlike the other database types, record databases have no metadata,+ so it's important to get this right when opening existing+ databases. -} fixed_byteOrder :: Int,++ {-| The byte value used to pad fixed-length records in the database.+ By default, this is a space character (0x20). -} fixed_paddingByte :: Word8,++ {-| A file which should be used to store the the in-memory record cache. -} fixed_treeFile :: Maybe String }++{-| The default configuration for fixed-length record databases. -}+defaultFixedRecordDBConf :: FixedRecordDBConf defaultFixedRecordDBConf = FixedRecordDBConf {--- fixed_noKey = False, fixed_snapshot = False, fixed_cacheSize = 0, fixed_pageSize = 0, fixed_recordLength = 0, fixed_byteOrder = 0,- fixed_paddingByte = 10, -- '\n'+ fixed_paddingByte = 0x20, fixed_treeFile = Nothing } -{- Opens or creates a fixed-length record database. -}-openFixedRecord :: Maybe FilePath -> IOMode -> UMask -> FixedRecordDBConf -> IO FixedRecordDB-openFixedRecord path iomode umask conf =+{-| Opens or creates a fixed-length record database. -}+openFixedRecord :: Maybe FilePath -> IOMode -> FileMode -> FixedRecordDBConf -> IO FixedRecordDB+openFixedRecord path iomode filemode conf =+ if (fixed_recordLength conf <= 0) then fail "non-positive record length" else withMaybeString path $ \cpath -> withMaybeString (fixed_treeFile conf) $ \ctreefile -> alloca $ \info -> do writeFixedRecordDBConf conf ctreefile info ptr <- throwErrnoIfNull "BerkeleyDB.openFixedRecord"- $ db_open_recno cpath (fromIOMode iomode) (toEnum umask) info+ $ db_open_recno cpath (fromIOMode iomode) filemode info return $ FixedRecordDB ptr {- Writes a fixed record database configuration into a C structure.@@ -898,25 +971,25 @@ {- Creation calls are all unsafe. -} foreign import ccall unsafe "db_open_recno"- db_open_recno :: CString -> CInt -> CInt -> Ptr RECNOINFO -> IO (Ptr DBStruct)+ db_open_recno :: CString -> CInt -> CMode -> Ptr RECNOINFO -> IO (Ptr DBStruct) #{def- DB *db_open_recno(const char *path, int flags, int umask, RECNOINFO *info) {+ DB *db_open_recno(const char *path, int flags, mode_t umask, RECNOINFO *info) { return dbopen(path, flags, umask, DB_RECNO, info); } } foreign import ccall unsafe "db_open_hash"- db_open_hash :: CString -> CInt -> CInt -> Ptr HASHINFO -> IO (Ptr DBStruct)+ db_open_hash :: CString -> CInt -> CMode -> Ptr HASHINFO -> IO (Ptr DBStruct) #{def- DB *db_open_hash(const char *path, int flags, int umask, HASHINFO *info) {+ DB *db_open_hash(const char *path, int flags, mode_t umask, HASHINFO *info) { return dbopen(path, flags, umask, DB_HASH, info); } } foreign import ccall unsafe "db_open_btree"- db_open_btree :: CString -> CInt -> CInt -> Ptr BTREEINFO -> IO (Ptr DBStruct)+ db_open_btree :: CString -> CInt -> CMode -> Ptr BTREEINFO -> IO (Ptr DBStruct) #{def- DB *db_open_btree(const char *path, int flags, int umask, BTREEINFO *info) {+ DB *db_open_btree(const char *path, int flags, mode_t umask, BTREEINFO *info) { return dbopen(path, flags, umask, DB_BTREE, info); } }