dbm
GNU dbm
(GDBM
) is a library of database functions that use
extensible hashing and work similar to the standard UNIX dbm
functions. These routines are provided to a programmer needing to
create and manipulate a hashed database. (GDBM
is NOT a
complete database package for an end user.)
The basic use of GDBM
is to store key/data pairs in a data file.
Each key must be unique and each key is paired with only one data item.
The keys can not be directly accessed in sorted order. The basic unit
of data in GDBM
is the structure:
typedef struct { char *dptr; int dsize; } datum;
This structure allows for arbitrary sized keys and data items. In
particular, zero-length keys or data (dsize = 0
) are allowed.
However, the dptr
field is required to point to a valid memory
location. In other words, dptr
cannot be NULL. Note also that
its type is char *
for purely historic reasons. You can use
any C data type (either scalar or aggregate) both as for key and for
data.
The key/data pairs are stored in a GDBM
disk file, called a
gdbm database. An application must open a GDBM
database
to be able manipulate the keys and data contained in it.
GDBM
allows an application to have multiple databases open at the
same time. When an application opens a GDBM
database, it is
designated as a reader
or a writer
. A GDBM
database can be opened by at most one writer at a time. However, many
readers may open the database simultaneously. Readers and writers can
not open the GDBM
database at the same time.
Speaking about application we usually mean a separate process.
However, it is entirely normal for a multi-thread program to operate
as a GDBM
reader in one thread and writer in another, provided,
of course, that the two threads don’t operate on the same database
simultaneously.
To use the GDBM
functions, the programmer must first include
the header file gdbm.h.
This file defines, among others, the GDBM_FILE
data type, an
opaque pointer to the structure that represents the opened GDBM
database. To access the database, the programmer must first open it
using the gdbm_open
function. The function takes several
arguments, the name of the database file being one of them, and
returns a GDBM_FILE
object on success. This object is then
passed to other functions in order to manipulate the database. When
the database is no longer needed, the programmer closes it using
the gdbm_close
call.
These and other functions are discussed in detail in chapters that
follow. Here we show an example illustrating the use of GDBM
to look up a key in the database.
#include <stdio.h> #include <string.h> #include <gdbm.h> int main (int argc, char **argv) { GDBM_FILE gdbf; /* Database file object pointer */ datum key, content; /* Key and content data */ int status = 0; /* Exit status of the program: 0 - OK, 1 - key not found, 2 - error. */ /* * Validate arguments. */ if (argc != 3) { fprintf (stderr, "usage: %s DBFILE KEY\n", argv[0]); return 2; } /* * Open the database. The GDBM_READER flag indicates that we only * intend to read from it. */ gdbf = gdbm_open (argv[1], 0, GDBM_READER, 0, NULL); if (gdbf == NULL) { fprintf (stderr, "can't open database: %s\n", gdbm_strerror (gdbm_errno)); } /* * Prepare the lookup key. Notice, that the terminating \0 character * is not counted in the dsize computation. */ key.dptr = argv[2]; key.dsize = strlen (argv[2]); /* * Look up the key in the database. */ content = gdbm_fetch (gdbf, key); /* * Analyze the return. */ if (content.dptr != NULL) { /* * The key is found. Print the content on the stdout and * indicate success. */ fwrite (content.dptr, content.dsize, 1, stdout); putchar ('\n'); status = 0; } else if (gdbm_errno == GDBM_ITEM_NOT_FOUND) { /* * There is no such key in the database. */ fprintf (stderr, "no such key\n"); status = 1; } else { /* * An error occurred. */ fprintf (stderr, "%s\n", gdbm_db_strerror (gdbf)); status = 2; } /* * Close the database and return. */ gdbm_close (gdbf); return status; }
To compile this example, run
cc -oexample example.c -lgdbm
To run it, you will need an example database. The easiest way to
create it is by using the gdbtool
program, which is part
of the GDBM
package (see gdbmtool):
$ gdbmtool test.gdbm store foo bar
This creates database file test.gdbm and stores a single record in it. The record’s key is ‘foo’, and the value is ‘bar’. Now you can run the example program to see how it works:
$ ./example test.gdbm foo bar $ ./example test.gdbm baz no such key