packages feed

BerkeleyDB 0.1 → 0.2

raw patch · 2 files changed

+225/−152 lines, 2 filesdep +unix

Dependencies added: unix

Files

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);   } }