Notes about Berkeley DB





Berkeley DB is a programming library used to create embeded database. It is a suitable solution if you need a database for a single process. Berkeley DB library does not provide any high level facilities (such as SQL or client/server connexions) you can find in other "standard" database packages (MySql, PostgreSql, Orcale, ...). If you need such facility, you must write your own wraper code around the Berkeley' library.

Basically, Berkeley DB library allows you to manage (key, data) records, that's all. It is pretty simple, pretty basic but very efficient. This may not be suitable for all kinds of applications, some application requires SQL or client/server architecture. But, for simple data storage, it is just fine.

A detailed description of Berkeley DB library can be found at the following location:

http://dlp.cs.berkeley.edu/admin/BerkeleyDB/

The 2 following codes shows how to use the C API.

  • The first example:
    • Create a database.
    • Insert records into the database.
    • Lookup the database.
    • Delete records from the database.
    • Close the database.
  • The second example doest the same that the first one, except that we create 2 databases (within the same file).

The next example shows how to:

  • Append records to the end of a RECNO database (very fast).
  • Use cursors to move across the database.
  • Use cursors to update a given cursor.


Exemple 1


First example - testdb1.c

/* ---------------------------------------------------------------------- */
/* This simple program illustrates the use of Berkley DB for simple data- */
/* -base management. */
/* */
/* o Open (and create if necessary) a database. */
/* o Insert data into the database. */
/* o Extract data from the database. */
/* o Delete records from the database. */
/* o Closing the database. */
/* ---------------------------------------------------------------------- */


#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "db.h"


#define BUFF_SIZE 1000
#define REC_NUMBER 500

int main (int argc, char *argv[])
{
  DB *dbd;
  DBT key, data;
  int cr, i;
  char vkey[BUFF_SIZE], vdata[BUFF_SIZE];

  /* ------------------------------------------------ */
  /* Check command line */
  /* ------------------------------------------------ */

  if (argc != 2)
  {
    fprintf (stderr, "\nUsage: testdb <file name>\n");
    return 1;
  }

  /* ------------------------------------------------ */
  /* Create a data base handler */
  /* ------------------------------------------------ */

  cr = db_create (
                   &dbd, /* Database hanler to initialize */
                   NULL, /* No special environement */
                   0 /* No special flag */
                 );

  if (cr != 0)
  {
    fprintf (stderr, "\nERROR: Can not create DB handler - %s", db_strerror(cr));
    return 1;
  }

  /* ------------------------------------------------ */
  /* Open a database */
  /* ------------------------------------------------ */

  cr = dbd->open (
                   dbd, /* Previously created DB handler */
                   argv[1], /* Name of the file that hold the database */
                   NULL, /* No database name specified */
                   DB_BTREE, /* Creeate a binary tree structure */
                   DB_CREATE, /* If the file does not exist, create it */
                   0 /* Set default UNIX access permissions */
                 );

  if (cr != 0)
  {
    fprintf (stderr, "\nERROR: Can not open database - %s", db_strerror(cr));
    return 1;
  }

  /* ------------------------------------------------ */
  /* Put data into database */
  /* ------------------------------------------------ */

  fprintf (stdout, "\n");
  fprintf (stdout, "\nPutting data into the database");
  fprintf (stdout, "\n------------------------------");
  fprintf (stdout, "\n");

  for (i=0; i<REC_NUMBER; i++)
  {
    sprintf (vkey, "key%d", i);
    sprintf (vdata, "data%d", i);

    memset(&key, 0, sizeof(key)); /* WARNING: you MUST set database data to all zeros */
    memset(&data, 0, sizeof(data)); /* WARNING: you MUST set database data to all zeros */

    key.data = vkey;
    key.size = strlen(vkey)+1;

    data.data = vdata;
    data.size = strlen(vdata)+1;

    cr = dbd->put (
                    dbd, /* DB handler */
                    NULL, /* No transaction required */
                    &key, /* Pointer to the record's key */
                    &data, /* Pointer to the record's data */
                    DB_NOOVERWRITE /* Does not add data if the key already exists */
                  );

    switch (cr)
    {
      case 0: break;
      case DB_KEYEXIST: { fprintf (stderr, "\nWarning: key %s already exists\n", vkey); }
                          break;
      default: {
                            fprintf (stderr, "\nERROR: Can not add record - %s", db_strerror(cr));
                            return 1;
                          }
    }
  }

  /* ------------------------------------------------ */
  /* Extract data from the database */
  /* ------------------------------------------------ */

  fprintf (stdout, "\n");
  fprintf (stdout, "\nExtracting data from database");
  fprintf (stdout, "\n-----------------------------");
  fprintf (stdout, "\n");

  for (i=0; i<REC_NUMBER; i++)
  {
    sprintf (vkey, "key%d", i);

    memset(&key, 0, sizeof(key)); /* WARNING: you MUST set database data to all zeros */
    memset(&data, 0, sizeof(data)); /* WARNING: you MUST set database data to all zeros */

    key.data = vkey;
    key.size = strlen(vkey)+1;

    cr = dbd->get (
                    dbd, /* DB handler */
                    NULL, /* No transaction required */
                    &key, /* Pointer to the record's key */
                    &data, /* Pointer to the record's data */
                    0 /* No special options */
                  );

    switch (cr)
    {
      case 0: {
                           fprintf (stdout, "\nKey %s found, value is %s (%d bytes)",
                                   (char*)key.data,
                                   (char*)data.data,
                                   (int)data.size);
                         }; break;
      case DB_NOTFOUND: {
                           fprintf (stdout, "\nKey %s not found", (char*)key.data);
                         }; break;
      default: {
                           fprintf (stderr, "\nERROR: Can not get data - %s", db_strerror(cr));
                           return 1;
                         }
    }
  }

  /* ------------------------------------------------ */
  /* Delete records from database */
  /* ------------------------------------------------ */

  fprintf (stdout, "\n");
  fprintf (stdout, "\nDeleting data from database");
  fprintf (stdout, "\n---------------------------");
  fprintf (stdout, "\n");

  for (i=0; i<REC_NUMBER; i++)
  {
    sprintf (vkey, "key%d", i);

    memset(&key, 0, sizeof(key)); /* WARNING: you MUST set database data to all zeros */
    memset(&data, 0, sizeof(data)); /* WARNING: you MUST set database data to all zeros */

    key.data = vkey;
    key.size = strlen(vkey)+1;

    cr = dbd->del (
                    dbd, /* DB handler */
                    NULL, /* No transaction required */
                    &key, /* Pointer to the record's key */
                    0 /* No special options */
                  );

    switch (cr)
    {
      case 0: {
                           fprintf (stdout, "\nRecord(%s) deleted",
                                   (char*)key.data);
                         }; break;
      case DB_NOTFOUND: {
                           fprintf (stdout, "\nRecord(%s) not found",
                                   (char*)key.data);
                         }; break;
      default: {
                           fprintf (stderr, "\nERROR: Can not delete record - %s", db_strerror(cr));
                           return 1;
                         }
    }
  }


  /* ------------------------------------------------ */
  /* Close the database handler */
  /* ------------------------------------------------ */

  cr = dbd->close (
                    dbd,
                    0
                  );

  if (cr != 0)
  {
    fprintf (stderr, "\nERROR: Error while closing the DB handler - %s", db_strerror(cr));
    return 1;
  }



  return 0;
}




Exemple 2


Second example - testdb2.c

/* ---------------------------------------------------------------------- */
/* This simple program illustrates how to create two databases in a single*/
/* file */
/* */
/* o Open (and create if necessary) a 2 databases. */
/* o Insert data into the database. */
/* o Extract data from the database. */
/* o Delete records from the database. */
/* o Closing the database. */
/* ---------------------------------------------------------------------- */


#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "db.h"


#define BUFF_SIZE 1000
#define REC_NUMBER 5

int main (int argc, char *argv[])
{
  DB *dbd1, *dbd2;
  DBT key, data;
  int cr, i;
  char vkey[BUFF_SIZE], vdata[BUFF_SIZE];

  /* ------------------------------------------------ */
  /* Check command line */
  /* ------------------------------------------------ */

  if (argc != 2)
  {
    fprintf (stderr, "\nUsage: testdb <file name>\n");
    return 1;
  }

  /* ------------------------------------------------ */
  /* Create the first data base handler */
  /* ------------------------------------------------ */

  cr = db_create (
                   &dbd1, /* Database hanler to initialize */
                   NULL, /* No special environement */
                   0 /* No special flag */
                 );

  if (cr != 0)
  {
    fprintf (stderr, "\nERROR: Can not create DB handler - %s", db_strerror(cr));
    return 1;
  }

  /* ------------------------------------------------ */
  /* Create the second data base handle */
  /* ------------------------------------------------ */

  cr = db_create (
                   &dbd2, /* Database hanler to initialize */
                   NULL, /* No special environement */
                   0 /* No special flag */
                 );

  if (cr != 0)
  {
    fprintf (stderr, "\nERROR: Can not create DB handler - %s", db_strerror(cr));
    return 1;
  }

  /* ------------------------------------------------ */
  /* Open the firt database */
  /* ------------------------------------------------ */

  cr = dbd1->open (
                    dbd1, /* Previously created DB handler */
                    argv[1], /* Name of the file that hold the database */
                    "db1", /* No database name specified */
                    DB_BTREE, /* Creeate a binary tree structure */
                    DB_CREATE, /* If the file does not exist, create it */
                    0 /* Set default UNIX access permissions */
                  );

  if (cr != 0)
  {
    fprintf (stderr, "\nERROR: Can not open database - %s", db_strerror(cr));
    return 1;
  }

  /* ------------------------------------------------ */
  /* Open the second database */
  /* ------------------------------------------------ */

  cr = dbd2->open (
                    dbd2, /* Previously created DB handler */
                    argv[1], /* Name of the file that hold the database */
                    "db2", /* No database name specified */
                    DB_BTREE, /* Creeate a binary tree structure */
                    DB_CREATE, /* If the file does not exist, create it */
                    0 /* Set default UNIX access permissions */
                  );

  if (cr != 0)
  {
    fprintf (stderr, "\nERROR: Can not open database - %s", db_strerror(cr));
    return 1;
  }

  /* ------------------------------------------------ */
  /* Put data into first database */
  /* ------------------------------------------------ */

  fprintf (stdout, "\n");
  fprintf (stdout, "\nPutting data into the first database");
  fprintf (stdout, "\n------------------------------------");
  fprintf (stdout, "\n");

  for (i=0; i<REC_NUMBER; i++)
  {
    sprintf (vkey, "key%d", i);
    sprintf (vdata, "data%d", i);

    fprintf (stdout, "\nAdding record (%s,%s)", vkey, vdata);

    memset(&key, 0, sizeof(key)); /* WARNING: you MUST set database data to all zeros */
    memset(&data, 0, sizeof(data)); /* WARNING: you MUST set database data to all zeros */

    key.data = vkey;
    key.size = strlen(vkey)+1;

    data.data = vdata;
    data.size = strlen(vdata)+1;

    cr = dbd1->put (
                     dbd1, /* DB handler */
                     NULL, /* No transaction required */
                     &key, /* Pointer to the record's key */
                     &data, /* Pointer to the record's data */
                     DB_NOOVERWRITE /* Does not add data if the key already exists */
                   );

    switch (cr)
    {
      case 0: break;
      case DB_KEYEXIST: { fprintf (stderr, "\nWarning: key %s already exists\n", vkey); }
                          break;
      default: {
                            fprintf (stderr, "\nERROR: Can not add record - %s", db_strerror(cr));
                            return 1;
                          }
    }
  }

  /* ------------------------------------------------ */
  /* Put data into second database */
  /* ------------------------------------------------ */

  fprintf (stdout, "\n");
  fprintf (stdout, "\nPutting data into the second database");
  fprintf (stdout, "\n-------------------------------------");
  fprintf (stdout, "\n");

  for (i=0; i<REC_NUMBER; i++)
  {
    sprintf (vkey, "key%d", i);
    sprintf (vdata, "data_%d", i);

    fprintf (stdout, "\nAdding record (%s,%s)", vkey, vdata);

    memset(&key, 0, sizeof(key)); /* WARNING: you MUST set database data to all zeros */
    memset(&data, 0, sizeof(data)); /* WARNING: you MUST set database data to all zeros */

    key.data = vkey;
    key.size = strlen(vkey)+1;

    data.data = vdata;
    data.size = strlen(vdata)+1;

    cr = dbd2->put (
                     dbd2, /* DB handler */
                     NULL, /* No transaction required */
                     &key, /* Pointer to the record's key */
                     &data, /* Pointer to the record's data */
                     DB_NOOVERWRITE /* Does not add data if the key already exists */
                   );

    switch (cr)
    {
      case 0: break;
      case DB_KEYEXIST: { fprintf (stderr, "\nWarning: key %s already exists\n", vkey); }
                          break;
      default: {
                            fprintf (stderr, "\nERROR: Can not add record - %s", db_strerror(cr));
                            return 1;
                          }
    }
  }

  /* ------------------------------------------------ */
  /* Extract data from the first database */
  /* ------------------------------------------------ */

  fprintf (stdout, "\n");
  fprintf (stdout, "\nExtracting data from the first database");
  fprintf (stdout, "\n---------------------------------------");
  fprintf (stdout, "\n");

  for (i=0; i<REC_NUMBER; i++)
  {
    sprintf (vkey, "key%d", i);

    memset(&key, 0, sizeof(key)); /* WARNING: you MUST set database data to all zeros */
    memset(&data, 0, sizeof(data)); /* WARNING: you MUST set database data to all zeros */

    key.data = vkey;
    key.size = strlen(vkey)+1;

    cr = dbd1->get (
                     dbd1, /* DB handler */
                     NULL, /* No transaction required */
                     &key, /* Pointer to the record's key */
                     &data, /* Pointer to the record's data */
                     0 /* No special options */
                   );

    switch (cr)
    {
      case 0: {
                           fprintf (stdout, "\nKey %s found, value is %s (%d bytes)",
                                   (char*)key.data,
                                   (char*)data.data,
                                   (int)data.size);
                         }; break;
      case DB_NOTFOUND: {
                           fprintf (stdout, "\nKey %s not found", (char*)key.data);
                         }; break;
      default: {
                           fprintf (stderr, "\nERROR: Can not get data - %s", db_strerror(cr));
                           return 1;
                         }
    }
  }

  /* ------------------------------------------------ */
  /* Extract data from the second database */
  /* ------------------------------------------------ */

  fprintf (stdout, "\n");
  fprintf (stdout, "\nExtracting data from the second database");
  fprintf (stdout, "\n----------------------------------------");
  fprintf (stdout, "\n");

  for (i=0; i<REC_NUMBER; i++)
  {
    sprintf (vkey, "key%d", i);

    memset(&key, 0, sizeof(key)); /* WARNING: you MUST set database data to all zeros */
    memset(&data, 0, sizeof(data)); /* WARNING: you MUST set database data to all zeros */

    key.data = vkey;
    key.size = strlen(vkey)+1;

    cr = dbd2->get (
                     dbd2, /* DB handler */
                     NULL, /* No transaction required */
                     &key, /* Pointer to the record's key */
                     &data, /* Pointer to the record's data */
                     0 /* No special options */
                   );

    switch (cr)
    {
      case 0: {
                           fprintf (stdout, "\nKey %s found, value is %s (%d bytes)",
                                   (char*)key.data,
                                   (char*)data.data,
                                   (int)data.size);
                         }; break;
      case DB_NOTFOUND: {
                           fprintf (stdout, "\nKey %s not found", (char*)key.data);
                         }; break;
      default: {
                           fprintf (stderr, "\nERROR: Can not get data - %s", db_strerror(cr));
                           return 1;
                         }
    }
  }



  /* ------------------------------------------------ */
  /* Delete records from databases */
  /* ------------------------------------------------ */

  fprintf (stdout, "\n");
  fprintf (stdout, "\nDeleting data from databases");
  fprintf (stdout, "\n----------------------------");
  fprintf (stdout, "\n");

  for (i=0; i<REC_NUMBER; i++)
  {
    sprintf (vkey, "key%d", i);

    memset(&key, 0, sizeof(key)); /* WARNING: you MUST set database data to all zeros */
    memset(&data, 0, sizeof(data)); /* WARNING: you MUST set database data to all zeros */

    key.data = vkey;
    key.size = strlen(vkey)+1;

    cr = dbd1->del (
                     dbd1, /* DB handler */
                     NULL, /* No transaction required */
                     &key, /* Pointer to the record's key */
                     0 /* No special options */
                   );

    switch (cr)
    {
      case 0: {
                           fprintf (stdout, "\ndatabase 1: Record(%s) deleted",
                                   (char*)key.data);
                         }; break;
      case DB_NOTFOUND: {
                           fprintf (stdout, "\ndatabase 1: Record(%s) not found",
                                   (char*)key.data);
                         }; break;
      default: {
                           fprintf (stderr, "\nERROR: Can not delete record - %s", db_strerror(cr));
                           return 1;
                         }
    }

    cr = dbd2->del (
                     dbd2, /* DB handler */
                     NULL, /* No transaction required */
                     &key, /* Pointer to the record's key */
                     0 /* No special options */
                   );

    switch (cr)
    {
      case 0: {
                           fprintf (stdout, "\ndatabase 2: Record(%s) deleted",
                                   (char*)key.data);
                         }; break;
      case DB_NOTFOUND: {
                           fprintf (stdout, "\ndatabase 2: Record(%s) not found",
                                   (char*)key.data);
                         }; break;
      default: {
                           fprintf (stderr, "\nERROR: Can not delete record - %s", db_strerror(cr));
                           return 1;
                         }
    }
  }


  /* ------------------------------------------------ */
  /* Close the database handlers */
  /* ------------------------------------------------ */

  cr = dbd1->close (
                     dbd1,
                     0
                   );

  if (cr != 0)
  {
    fprintf (stderr, "\nERROR: Error while closing the DB handler - %s", db_strerror(cr));
    return 1;
  }

  cr = dbd2->close (
                     dbd2,
                     0
                   );

  if (cr != 0)
  {
    fprintf (stderr, "\nERROR: Error while closing the DB handler - %s", db_strerror(cr));
    return 1;
  }




  return 0;
}


Makefile


############################################################
# Source tree #
############################################################

INCLUDE_DIR = .
SRC_DIR = .
OBJ_DIR = .
BIN_DIR = .

############################################################
# Berkeley DB header files and libraries #
############################################################

BERKELEY_HEADERS_DIR = /home/users/dbeurive/BIN/berkeley_db/include
BERKELEY_LIBS_DIR = /home/users/dbeurive/BIN/berkeley_db/lib

############################################################
# Compiler options #
############################################################

CC = gcc
CCFLAGS = -Wall -I${BERKELEY_HEADERS_DIR} -L${BERKELEY_LIBS_DIR} -o $@

############################################################
# Binaries #
############################################################

${BIN_DIR}/testdb1: ${SRC_DIR}/testdb1.c
        ${CC} ${CCFLAGS} ${SRC_DIR}/testdb1.c -ldb

${BIN_DIR}/testdb2: ${SRC_DIR}/testdb2.c
        ${CC} ${CCFLAGS} ${SRC_DIR}/testdb2.c -ldb

############################################################
# Rules #
############################################################

all: ${BIN_DIR}/testdb1 \
     ${BIN_DIR}/testdb2

clean:
        rm -f ${BIN_DIR}/testdb1
        rm -f ${BIN_DIR}/testdb2




Exemple 3


test_recno.c (Append records to the end of a database + using cursors)

/* ----------------------------------------------- */
/* This simple program performs the following */
/* operations: */
/* */
/* (1) Create a RECNO database. */
/* (2) Insert records into the database. Insersion */
/* is done at the end of the DB file. */
/* (3) Dump a record using a cursor that moves */
/* from the begining to the end of the */
/* databasei. Once a record is dumped, its */
/* value is doubled. */
/* */
/* This shows: */
/* */
/* + How to append records to the end of a RECNO. */
/* + How to use cursors to move across a database. */
/* + How to use cursors to update a given records. */
/* ----------------------------------------------- */

#include <string.h>
#include "db.h"

#define DB_NAME "output.db"

/* ----------------------------------------------- */
/* Define data to insert */
/* ----------------------------------------------- */

#define NUMBER_OF_RECORDS 4

struct sdata {
               db_recno_t record_number;
               int value;
             };

struct sdata SDATA[NUMBER_OF_RECORDS] = {
                                          { 1, 10 },
                                          { 2, 20 },
                                          { 3, 30 },
                                          { 4, 40 }
                                        };

/* ----------------------------------------------- */
/* Main entry point */
/* ----------------------------------------------- */


int main (int argc, char *argv[])
{
  int cr, i;
  DB *dbd;
  DBT key, data;
  DBC *cursor;
  db_recno_t rn;
  struct sdata *prec, nrec;

  /* --------------------------------------------- */
  /* Create Berkeley DB handler */
  /* --------------------------------------------- */

  cr = db_create (
                   &dbd, /* Database hanler to initialize */
                   NULL, /* No special environement */
                   0 /* No special flag */
                 );

  if (cr != 0)
  {
    fprintf (stderr, "\nERROR: Can not create DB handler - %s", db_strerror(cr));
    return 1;
  }

  /* --------------------------------------------- */
  /* Open the Berkeley database */
  /* --------------------------------------------- */

  cr = dbd->open (
                   dbd, /* Previously created DB handler */
                   DB_NAME, /* Name of the file that hold the database */
                   NULL, /* No database name specified */
                   DB_RECNO, /* Creeate a binary tree structure */
                   DB_CREATE, /* If the file does not exist, create it */
                   0 /* Set default UNIX access permissions */
                 );

  if (cr != 0)
  {
    fprintf (stderr, "\nERROR: Can not open database - %s", db_strerror(cr));
    return 1;
  }

  /* --------------------------------------------- */
  /* Insert records */
  /* --------------------------------------------- */

  for (i=0; i<NUMBER_OF_RECORDS; i++)
  {
    memset(&key, 0, sizeof(DBT)); /* WARNING: you MUST set database data to all zeros */
    memset(&data, 0, sizeof(DBT)); /* WARNING: you MUST set database data to all zeros */

    rn = (db_recno_t)(i+1);

    key.data = &rn;
    key.size = sizeof(db_recno_t);

    data.data = SDATA+i;
    data.size = sizeof(struct sdata);

    cr = dbd->put (
                    dbd, /* DB handler */
                    NULL, /* No transaction required */
                    &key, /* Pointer to the record's key */
                    &data, /* Pointer to the record's data */
                    DB_APPEND /* Add record to the end of the DB file */
                  );

    switch (cr)
    {
      case 0: break;
      case DB_KEYEXIST: break;
      default: {
                            fprintf (stderr, "\nERROR: Can not add record - %s", db_strerror(cr));
                            return 1;
                          }
    }
  }

  /* --------------------------------------------- */
  /* Dump the database using a cursor */
  /* AND */
  /* Double each value */
  /* --------------------------------------------- */

        /* --------------------------------------- */
        /* Create the cursor */
        /* --------------------------------------- */

  cr = dbd->cursor (
                     dbd,
                     NULL,
                     &cursor,
                     0
                   );

  if (cr != 0)
  {
    fprintf (stderr, "\nERROR: Can not create cursor - %s", db_strerror(cr));
    return 1;
  }

        /* --------------------------------------- */
        /* Set the cursor to the first record */
        /* --------------------------------------- */

  memset(&key, 0, sizeof(DBT));
  memset(&data, 0, sizeof(DBT));

  cr = cursor->c_get (
                       cursor,
                       &key,
                       &data,
                       DB_FIRST
                     );

  switch (cr)
  {
    case 0: break;
    case DB_NOTFOUND: {
                           fprintf (stdout, "\nTable Frequency_recno is empty");
                        }; break;
    default: {
                           cursor->c_close(cursor);
                           fprintf (stderr, "\nERROR: cursor operation failed - %s", db_strerror(cr));
                           return 1;
                        }
  }

        /* --------------------------------------- */
        /* Now move cursor until the last record */
        /* --------------------------------------- */

  while (cr == 0)
  {

                 /* ------------------------------ */
                 /* Print actual value */
                 /* ------------------------------ */

    prec = (struct sdata*)(data.data);
    fprintf (stdout, "\nRECNO: %u", prec->record_number);
    fprintf (stdout, "\n %d\n", prec->value);

                 /* ------------------------------ */
                 /* Double actual value */
                 /* ------------------------------ */

    nrec.record_number = prec->record_number;
    nrec.value = prec->value * 2;
    rn = *((db_recno_t*)(key.data));

    memset(&key, 0, sizeof(DBT));
    memset(&data, 0, sizeof(DBT));

    key.data = &rn;
    key.size = sizeof(db_recno_t);

    data.data = &nrec;
    data.size = sizeof(struct sdata);

    cr = cursor->c_put (
                         cursor,
                         &key,
                         &data,
                         DB_CURRENT
                       );

    if (cr != 0)
    {
      fprintf (stderr, "\nERROR: cursor operation failed - %s", db_strerror(cr));
      return 1;
    }

                 /* ------------------------------ */
                 /* Move to the next record */
                 /* ------------------------------ */

    memset(&key, 0, sizeof(DBT));
    memset(&data, 0, sizeof(DBT));

    cr = cursor->c_get (
                         cursor,
                         &key,
                         &data,
                         DB_NEXT
                       );
  }

  if (cr != DB_NOTFOUND)
  {
    fprintf (stderr, "\nERROR: cursor operation failed - %s", db_strerror(cr));
    return 1;
  }

        /* --------------------------------------- */
        /* Close the cursor */
        /* --------------------------------------- */

  cr = cursor->c_close(cursor);

  if (cr != 0)
  {
    fprintf (stderr, "\nERROR: Error while closing cursor - %s", db_strerror(cr));
    return 1;
  }

  /* --------------------------------------------- */
  /* Close all open handlers */
  /* --------------------------------------------- */

  cr = dbd->close (
                    dbd,
                    0
                  );

  if (cr != 0)
  {
    fprintf (stderr, "\nERROR: Error while closing the DB handler - %s", db_strerror(cr));
    return 1;
  }


  return 0;
}