Next: , Previous: , Up: Top   [Contents][Index]


2 Introduction to GNU 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

Next: , Previous: , Up: Top   [Contents][Index]