mdbm(3B)
mdbm: mdbm_open, mdbm_close, mdbm_fetch, mdbm_store, mdbm_delete, mdbm_first, mdbm_firstkey, mdbm_next, mdbm_nextkey, mdbm_pre_split, mdbm_set_alignment, mdbm_limit_size, mdbm_invalidate, mdbm_close_fd, mdbm_sync, mdbm_lock, mdbm_unlock, mdbm_sethash- data base subroutines
As shipped in IRIX 6.5. First release of IRIX 6.5.
NAME mdbm: mdbm_open, mdbm_close, mdbm_fetch, mdbm_store, mdbm_delete, mdbm_first, mdbm_firstkey, mdbm_next, mdbm_nextkey, mdbm_pre_split, mdbm_set_alignment, mdbm_limit_size, mdbm_invalidate, mdbm_close_fd, mdbm_sync, mdbm_lock, mdbm_unlock, mdbm_sethash- data base subroutines SYNOPSIS cc [flag ...] file ... -lmdbm [library ...] #include <mdbm.h> MDBM *mdbm_open(const char *file, int flags, mode_t mode, int pagesize); void mdbm_close(MDBM *db); datum mdbm_fetch(MDBM *db, kvpair kv); int mdbm_store(MDBM *db, datum key, datum content, int flags); int mdbm_delete(MDBM *db, datum key); kvpair mdbm_first(MDBM *db, kvpair kv); datum mdbm_firstkey(MDBM *db, datum key); kvpair mdbm_next(MDBM *db, kvpair kv); datum mdbm_nextkey(MDBM *db, datum key); int mdbm_pre_split(MDBM *db, uint64 pages, int int mdbm_set_alignment(MDBM *db, int power); int mdbm_limit_size(MDBM *db, uint64 pages, int (*func)(MDBM *db, datum key, datum content, void *priority)); int mdbm_invalidate(MDBM *db); void mdbm_close_fd(MDBM *db); void mdbm_sync(MDBM *db); int mdbm_lock(MDBM *db); int mdbm_unlock(MDBM *db); int mdbm_sethash(MDBM *db, int number); int mdbm_set_chain(MDBM *db); datumt mdbm_chain_fetch(MDBM *db, kvpair kv); kvpair mdbm_chain_first(MDBM *db, kvpair kv); kvpair mdbm_chain_next(MDBM *db, kvpair kv); int mdbm_chain_store(MDBM *db, datum key, datum val, int flags); int mdbm_chain_delete(MDBM *db, datum key); int mdbm_bytes_per_page(MDBM *db, int *pages); int mdbm_elem_per_page(MDBM *db, int *pages); DESCRIPTION The mdbm routines are used to store key/content pairs in a high performance mapped hash file. It uses fixed size pages, but the page size can be set on first open. The database does per page writer locking, and readers can detect and automaticly deal with writers. This allows for scalable multiple simultaneous readers and writers to be operating on the same mdbm file at the same time. Core functions are bult into libc, the rest of them require linking with libmdbm. The functions in libc are: mdbm_close, mdbm_close_fd, mdbm_fetch, mdbm_first, mdbm_firstkey, mdbm_invalidate, mdbm_next, mdbm_nextkey, mdbm_open, mdbm_sethash, mdbm_store, mdbm_sync. Before a database can be accessed, it must be opened by mdbm_open. This will open and/or create the given file depending on the flags patameter (see open(2)). The pagesize parameter is a power of two between 8 (256 bytes) and 16 (65536 bytes). Once open, the data stored under a key is accessed by mdbm_fetch . The kvpair argument must be setup as follows: typedef struct { char *dptr; int dsize; } datum; typedef struct { datum key; datum val; } kvpair; kv.key.dptr should point to the key, and kv.key.dsize should be set to the length of the key. kv.val.dptr should be set to allocated memory, which will be used to copy the result into. kv.val.dsize should be the size of the data. If kv.val.dptr is null, the returned datum's dsize will be the size of the key. It is always save to allocate MDBM_PAGE_SIZE(db) bytes. A linear pass through all keys in a database may be made, in an (apparently) random order, by use of mdbm_firstkey (mdbm_first) and mdbm_nextkey(mdbm_next). Mdbm_firstkey will return the first key (key/content) in the database. Mdbm_nextkey will return the next key (key/content) in the database. Space for both the key and the value must be allocated as above. The following code will traverse the data base: int pagesize = MDBM_PAGE_SUZE(db); char *key = alloca(pagesize); char *val = alloca(pagesize); for (kv.key.dptr = key , kv.key.dsize=pagesize, kv.val.dptr = val, kv.val.dsize=pagesize, kv.key = mdbm_firstkey(db,kv); key.dptr != NULL; kv.key.dptr = key , kv.key.dsize=pagesize, kv.val.dptr = val, kv.val.dsize=pagesize, key = mdbm_nextkey(db,kv)) Data is placed under a key by mdbm_store. The flags field can be either MDBM_INSERT or MDBM_REPLACE. MDBM_INSERT will only insert new entries into the database and will not change an existing entry with the same key. MDBM_REPLACE will replace an existing entry if it has the same key. A key (and its associated contents) is deleted by mdbm_delete. The mdbm_pre_split function can be used immediately after first open to expand the directory to a specified size. This helps to reduce the number of pages that will be split when storing a large amount of data. The pages parameter is a power of two for the depth of the tree. The contents may be forced to exist at a particular byte alignment using mdbm_set_alignment so that you can store structures in the database. The parameter is a power of two between 0 and 3. The only time this is needed is when accessing non-copied data from a mdbm file. This is not safe unless all access are protected by global. The flags field can be 0, or MDBM_ALLOC_SPACE. MDBM_ALLOC_SPACE attempts to pre-allocate blocks to back the file if it is on a holely filesystem. It will return -1 if it can not allocate the space. The mdbm_limit_size function can be used after first open to set a maximum size limit on the database. If supplied func is a function which will be called with each item on a page if an item needs to be stored, but there is no space. The priority argument is an integer between 1 and 3 giving the pass number. After three passes through the data, if space has not been freed the store will fail. Mdbm_sync simply forces the data to disk. Since the database is a mapped file most work is simply done in memory, and the state of the disk file is only guarenteed after mdbm_sync. Mdbm_invalidate should be called to mark a mdbm file as invalid or outdated. This should be done before unlinking the mdbm file. If this is not done long running programs that may have the mdbm file open will not detect that another process has remove the file. If the database is a fixed size then the associated file descriptor can be closed using mdbm_close_fd. Otherwise the database will grow the file and possibly remap it into memory as data is added. The routines mdbm_lock/mdbm_unlock can be used to syncronize access to an mdbm file. These use a very unsophisticated spinlock in the shared file to do the locking. It is almost always unecessary to use these functions. Mdbm_sethash will set the has function of a database to number. This must be done immediately after creating the mdbm file. The default hash is 0. 0 32 bit CRC. 1 ejb's hsearch hash. Not recommended. 2 Phong Vo's linear congruential hash. Good for short keys. 3 Ozan Yigit's sdbm hash. Good for long keys. 4 Torek's Duff device hash. Good for ASCII key. Bad for binary key. 5 Fowler/Noll/Vo prime hash. Very good keys under ~20 bytes. There are a number of function that allow storage of unlimited size values via mdbm. These are the the mdbm_chain_* functions. Before any keys are stored in a mdbm database, use the mdbm_set_chain routine to enable this feature in a given database. Use mdbm_open and mdbm_close with a mdbm file that supports chaining. When chaining is enabled, the first character of a key may NOT start with a NULL byte. Also, it is impossible to get a pointer to the copy of the data in the database by passing a NULL value. In this case the val.dsize field will be set the size needed to retrieve the data. Simultaneous replacement and fetching of a single key should not be done with chained data, and can return bogus values. The mdbm_chain_fetch, mdbm_chain_store, and mdbm_chain_delete behave similar to the non chaining versions. The mdbm_chain_first and mdbm_chain_next do NOT return the value. The kv.val should be NULL with a 0 length, and will be set to the size needed to copyout the data. The mdbm_bytes_per_page, and mdbm_elem_per_page take an pointer to array of length MDBM_NUMBER_PAGES(MDBM *db) which will be filled with the appropriate statistic. DIAGNOSTICS All functions that return an int indicate errors with negative values. A zero return indicates ok. Routines that return a datum indicate errors with a null (0) dptr. If dbm_store called with a flags value of DBM_INSERT finds an existing entry with the same key it returns 1. If there is an error during an mdbm call, the global error value errno will be set. The following errors will will be set. EDEADLK A accessed page was locked, and after a number of attempts did not become unlocked. EBADFD During the open of a database the file magic number was not valid. File is not a recognised mdbm file. EBADF During the open or access of a database the file version was not valid, or internal structures are invalid. This implies that the mdbm file is corrupted. EINVAL An invlid argument was passed. ENOEXIST The requested key does not exist in the database. ENOMEM Internal allocation of memory failed. The only allocation that is performed is the MDBM structure that is returned by mdbm_open which is freed by mdbm_close. ENOSPC There is insufficient space in the database to store the requested key. EPERM Permission to perform a write to the mdbm file is denied. ESTALE The mdbm file has been invalidated. It is suggested that an attempt to re-open the database is made, since a writing process may invalidate a mdbm file, and create a new one with the same filename. BUGS The file is designed to contain holes in files. The EFS file system does not implement holes, so the file will frequently be significantly larger than the actual content. The sum of the sizes of a key/content pair must not exceed the internal block size (defaults to 4096 bytes). Moreover all key/content pairs that hash together must fit on a single block. The block size can be set to a maximum of 64KB on first open. Mdbm_store will return an error in the event that a disk block fills with inseparable data. Mdbm_delete does not physically reclaim file space, although it does make it available for reuse. The order of keys presented by mdbm_first, mdbm_firstkey, mdbm_next and mdbm_nextkey depends on a hashing function, not on anything interesting.