onak-conf.o: onak-conf.c onak-conf.h
        $(CC) $(CFLAGS) -DCONFIGFILE=\"@sysconfdir@/onak.conf\" \
-               -DDBFUNCS=keydb_@DBTYPE@_funcs -c onak-conf.c
+               -DDBINIT=keydb_@DBTYPE@_init -c onak-conf.c
 
 # HACK: onak-conf.o needs to be able to see keydb_@DBTYPE@_funcs, but
 # keydctl doesn't want to link against the DB stuff. To be fixed more cleanly.
 keydctl.o: keydctl.c keyd.h
-       $(CC) $(CFLAGS) -DDBFUNCS=keydb_@DBTYPE@_funcs -c keydctl.c
+       $(CC) $(CFLAGS) -DDBINIT=keydb_@DBTYPE@_init -c keydctl.c
 
 onak-mail.pl: onak-mail.pl.in
        sed 's:@CONFIG@:@sysconfdir@/onak.conf:g' < onak-mail.pl.in > onak-mail.pl
 
        struct buffer_ctx            ctx;
        int                          count = 0;
        int                          i;
+       struct onak_dbctx           *dbctx;
 
        memset(&ctx, 0, sizeof(ctx));
 
                                fclose(stderr);
                        }
                        catchsignals();
-                       config.dbbackend->initdb(false);
+                       dbctx = config.dbinit(false);
                        
                        count = cleankeys(keys);
                        logthing(LOGTHING_INFO, "%d keys cleaned.",
                                        count);
 
-                       count = config.dbbackend->update_keys(&keys, true);
+                       count = dbctx->update_keys(dbctx, &keys, true);
                        logthing(LOGTHING_NOTICE, "Got %d new keys.",
                                count);
 
                                keys = NULL;
                        }
                        
-                       config.dbbackend->cleanupdb();
+                       dbctx->cleanupdb(dbctx);
                } else {
                        puts("No OpenPGP packets found in input.");
                        end_html();
 
        return op;
 }
 
-int getkeyspath(uint64_t have, uint64_t want, int count)
+int getkeyspath(struct onak_dbctx *dbctx,
+               uint64_t have, uint64_t want, int count)
 {
        struct openpgp_publickey *publickey = NULL;
        struct openpgp_packet_list *packets = NULL;
        uint64_t fullhave, fullwant;
        int pathlen = 0;
 
-       fullhave = config.dbbackend->getfullkeyid(have);
-       fullwant = config.dbbackend->getfullkeyid(want);
+       fullhave = dbctx->getfullkeyid(dbctx, have);
+       fullwant = dbctx->getfullkeyid(dbctx, want);
 
        /*
         * Make sure the keys we have and want are in the cache.
         */
-       config.dbbackend->cached_getkeysigs(fullhave);
-       config.dbbackend->cached_getkeysigs(fullwant);
+       dbctx->cached_getkeysigs(dbctx, fullhave);
+       dbctx->cached_getkeysigs(dbctx, fullwant);
 
        if ((keyinfoa = findinhash(fullhave)) == NULL) {
                return 1;
                 * Fill the tree info up.
                 */
                initcolour(true);
-               findpath(keyinfoa, keyinfob);
+               findpath(dbctx, keyinfoa, keyinfob);
                keyinfob->parent = 0;
                if (keyinfoa->colour == 0) {
                        pathlen = count;
                        curkey = findinhash(keyinfoa->parent);
                        while (curkey != NULL && curkey->keyid != 0) {
                                if (curkey->keyid != fullwant &&
-                                               config.dbbackend->fetch_key_id(
+                                               dbctx->fetch_key_id(dbctx,
                                                curkey->keyid,
                                                &publickey, false)) {
                                        flatten_publickey(publickey,
        /*
         * Add the destination key to the list of returned keys.
         */
-       if (config.dbbackend->fetch_key_id(fullwant, &publickey, false)) {
+       if (dbctx->fetch_key_id(dbctx, fullwant, &publickey, false)) {
                flatten_publickey(publickey,
                                &packets,
                                &list_end);
        char     **cgiparams = NULL;    /* Our CGI parameter block */
        uint64_t   from = 0, to = 0;
        int        op = OP_UNKNOWN;
+       struct onak_dbctx *dbctx;
 
        cgiparams = getcgivars(argc, argv);
 
        readconfig(NULL);
        initlogthing("gpgwww", config.logfile);
        catchsignals();
-       config.dbbackend->initdb(true);
+       dbctx = config.dbinit(true);
        inithash();
        logthing(LOGTHING_NOTICE, "Looking for path from 0x%016" PRIX64
                        " to 0x%016"
                        from,
                        to);
        if (op == OP_GET) {
-               getkeyspath(from, to, 3);
+               getkeyspath(dbctx, from, to, 3);
        } else {
-               dofindpath(from, to, true, 3);
+               dofindpath(dbctx, from, to, true, 3);
        }
        destroyhash();
-       config.dbbackend->cleanupdb();
+       dbctx->cleanupdb(dbctx);
        cleanuplogthing();
        cleanupconfig();
 
 
        uint8_t **hashes;
        struct buffer_ctx cgipostbuf;
        struct openpgp_publickey **keys;
+       struct onak_dbctx *dbctx;
 
        readconfig(NULL);
        initlogthing("hashquery", config.logfile);
                doerror("Couldn't allocate memory for reply.\n");
        }
 
-       if (config.dbbackend->fetch_key_skshash == NULL) {
+       catchsignals();
+       dbctx = config.dbinit(false);
+
+       if (dbctx->fetch_key_skshash == NULL) {
+               dbctx->cleanupdb(dbctx);
                doerror("Can't fetch by skshash with this backend.");
        }
 
-       catchsignals();
-       config.dbbackend->initdb(false);
-
        for (i = 0; i < count; i++) {
-               config.dbbackend->fetch_key_skshash(
+               dbctx->fetch_key_skshash(dbctx,
                                (struct skshash *) hashes[i], &keys[found]);
                if (keys[found] != NULL) {
                        found++;
        free(hashes);
        hashes = NULL;
 
-       config.dbbackend->cleanupdb();
+       dbctx->cleanupdb(dbctx);
 
        puts("Content-Type: pgp/keys\n");
        marshal_array(stdout_putchar, NULL,
 
        return fd;
 }
 
-int sock_do(int fd)
+int sock_do(struct onak_dbctx *dbctx, int fd)
 {
        uint32_t cmd = KEYD_CMD_UNKNOWN;
        ssize_t  bytes = 0;
                                                "Fetching 0x%" PRIX64
                                                ", result: %d",
                                                keyid,
-                                               config.dbbackend->
-                                               fetch_key_id(keyid,
+                                               dbctx->fetch_key_id(dbctx,
+                                                       keyid,
                                                        &key, false));
                                if (key != NULL) {
                                        storebuf.size = 8192;
                                logthing(LOGTHING_INFO,
                                                "Fetching by fingerprint"
                                                ", result: %d",
-                                               config.dbbackend->
-                                               fetch_key_fp(fp, bytes,
+                                               dbctx->fetch_key_fp(dbctx,
+                                                       fp, bytes,
                                                        &key, false));
                                if (key != NULL) {
                                        storebuf.size = 8192;
                                logthing(LOGTHING_INFO,
                                                "Fetching %s, result: %d",
                                                search,
-                                               config.dbbackend->
-                                               fetch_key_text(search, &key));
+                                               dbctx->fetch_key_text(dbctx,
+                                                       search, &key));
                                if (key != NULL) {
                                        storebuf.size = 8192;
                                        storebuf.buffer = malloc(8192);
                                                &packets,
                                                0);
                                parse_keys(packets, &key);
-                               config.dbbackend->store_key(key, false, false);
+                               dbctx->store_key(dbctx, key, false, false);
                                free_packet_list(packets);
                                packets = NULL;
                                free_publickey(key);
                                                "Deleting 0x%" PRIX64
                                                ", result: %d",
                                                keyid,
-                                               config.dbbackend->delete_key(
+                                               dbctx->delete_key(dbctx,
                                                        keyid, false));
                        }
                        break;
                                ret = 1;
                        }
                        if (ret == 0) {
-                               keyid = config.dbbackend->getfullkeyid(keyid);
+                               keyid = dbctx->getfullkeyid(dbctx, keyid);
                                cmd = sizeof(keyid);
                                write(fd, &cmd, sizeof(cmd));
                                write(fd, &keyid, sizeof(keyid));
                case KEYD_CMD_KEYITER:
                        cmd = KEYD_REPLY_OK;
                        write(fd, &cmd, sizeof(cmd));
-                       config.dbbackend->iterate_keys(iteratefunc,
+                       dbctx->iterate_keys(dbctx, iteratefunc,
                                        &fd);
                        bytes = 0;
                        write(fd, &bytes, sizeof(bytes));
                                logthing(LOGTHING_INFO,
                                                "Fetching by hash"
                                                ", result: %d",
-                                               config.dbbackend->
-                                               fetch_key_skshash(&hash,
-                                                       &key));
+                                               dbctx->fetch_key_skshash(dbctx,
+                                                       &hash, &key));
                                if (key != NULL) {
                                        storebuf.size = 8192;
                                        storebuf.buffer = malloc(8192);
        char *configfile = NULL;
        bool foreground = false;
        int optchar;
+       struct onak_dbctx *dbctx;
 
        while ((optchar = getopt(argc, argv, "c:fh")) != -1 ) {
                switch (optchar) {
                maxfd = fd;
                memset(clients, -1, sizeof (clients));
 
-               config.dbbackend->initdb(false);
+               dbctx = config.dbinit(false);
 
                logthing(LOGTHING_NOTICE, "Accepting connections.");
                while (!cleanup() && select(maxfd + 1, &rfds, NULL, NULL, NULL) != -1) {
                                                FD_ISSET(clients[i], &rfds)) {
                                        logthing(LOGTHING_DEBUG,
                                                "Handling connection for client %d.", i);
-                                       if (sock_do(clients[i])) {
+                                       if (sock_do(dbctx, clients[i])) {
                                                sock_close(clients[i]);
                                                clients[i] = -1;
                                                logthing(LOGTHING_DEBUG,
                                }
                        }
                }
-               config.dbbackend->cleanupdb();
+               dbctx->cleanupdb(dbctx);
                sock_close(fd);
                unlink(sockname);
        }
 
  *     keyid2uid - Takes a keyid and returns the primary UID for it.
  *     @keyid: The keyid to lookup.
  */
-char *generic_keyid2uid(uint64_t keyid)
+char *generic_keyid2uid(struct onak_dbctx *dbctx, uint64_t keyid)
 {
        struct openpgp_publickey *publickey = NULL;
        struct openpgp_signedpacket_list *curuid = NULL;
        char buf[1024];
 
        buf[0]=0;
-       if (config.dbbackend->fetch_key_id(keyid, &publickey, false) &&
+       if (dbctx->fetch_key_id(dbctx, keyid, &publickey, false) &&
                        publickey != NULL) {
                curuid = publickey->uids;
                while (curuid != NULL && buf[0] == 0) {
  *     indexing and doing stats bits. If revoked is non-NULL then if the key
  *     is revoked it's set to true.
  */
-struct ll *generic_getkeysigs(uint64_t keyid, bool *revoked)
+struct ll *generic_getkeysigs(struct onak_dbctx *dbctx,
+               uint64_t keyid, bool *revoked)
 {
        struct ll *sigs = NULL;
        struct openpgp_signedpacket_list *uids = NULL;
        struct openpgp_publickey *publickey = NULL;
 
-       config.dbbackend->fetch_key_id(keyid, &publickey, false);
+       dbctx->fetch_key_id(dbctx, keyid, &publickey, false);
        
        if (publickey != NULL) {
                for (uids = publickey->uids; uids != NULL; uids = uids->next) {
  *     getkeysigs function above except we use the hash module to cache the
  *     data so if we need it again it's already loaded.
  */
-struct ll *generic_cached_getkeysigs(uint64_t keyid)
+struct ll *generic_cached_getkeysigs(struct onak_dbctx *dbctx, uint64_t keyid)
 {
        struct stats_key *key = NULL;
        struct stats_key *signedkey = NULL;
        key = findinhash(keyid);
 
        if (key == NULL || key->gotsigs == false) {
-               sigs = config.dbbackend->getkeysigs(keyid, &revoked);
+               sigs = dbctx->getkeysigs(dbctx, keyid, &revoked);
                if (sigs == NULL) {
                        return NULL;
                }
  *     This function maps a 32bit key id to the full 64bit one. It returns the
  *     full keyid. If the key isn't found a keyid of 0 is returned.
  */
-uint64_t generic_getfullkeyid(uint64_t keyid)
+uint64_t generic_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid)
 {
        struct openpgp_publickey *publickey = NULL;
 
        if (keyid < 0x100000000LL) {
-               config.dbbackend->fetch_key_id(keyid, &publickey, false);
+               dbctx->fetch_key_id(dbctx, keyid, &publickey, false);
                if (publickey != NULL) {
                        get_keyid(publickey, &keyid);
                        free_publickey(publickey);
  *     we had before to what we have now (ie the set of data that was added to
  *     the DB). Returns the number of entirely new keys added.
  */
-int generic_update_keys(struct openpgp_publickey **keys, bool sendsync)
+int generic_update_keys(struct onak_dbctx *dbctx,
+               struct openpgp_publickey **keys, bool sendsync)
 {
        struct openpgp_publickey *curkey = NULL;
        struct openpgp_publickey *oldkey = NULL;
        uint64_t keyid;
 
        for (curkey = *keys; curkey != NULL; curkey = curkey->next) {
-               intrans = config.dbbackend->starttrans();
+               intrans = dbctx->starttrans(dbctx);
                get_keyid(curkey, &keyid);
                logthing(LOGTHING_INFO,
                        "Fetching key 0x%" PRIX64 ", result: %d",
                        keyid,
-                       config.dbbackend->fetch_key_id(keyid, &oldkey,
+                       dbctx->fetch_key_id(dbctx, keyid, &oldkey,
                                        intrans));
 
                /*
                                prev = curkey;
                                logthing(LOGTHING_INFO,
                                        "Merged key; storing updated key.");
-                               config.dbbackend->store_key(oldkey, intrans,
+                               dbctx->store_key(dbctx, oldkey, intrans,
                                        true);
                        }
                        free_publickey(oldkey);
                } else {
                        logthing(LOGTHING_INFO,
                                "Storing completely new key.");
-                       config.dbbackend->store_key(curkey, intrans, false);
+                       dbctx->store_key(dbctx, curkey, intrans, false);
                        newkeys++;
                }
-               config.dbbackend->endtrans();
+               dbctx->endtrans(dbctx);
                intrans = false;
        }
 
 #endif /* NEED_UPDATEKEYS */
 
 #ifdef NEED_GET_FP
-static int generic_fetch_key_fp(uint8_t *fp, size_t fpsize,
-               struct openpgp_publickey **publickey, bool intrans)
+static int generic_fetch_key_fp(struct onak_dbctx *dbctx,
+               uint8_t *fp, size_t fpsize,
+               struct openpgp_publickey **publickey, bool intrans)
 {
        uint64_t keyid;
        int i;
                keyid = (keyid << 8) + fp[i];
        }
 
-       return config.dbbackend->fetch_key_id(keyid, publickey, intrans);
+       return dbctx->fetch_key_id(dbctx, keyid, publickey, intrans);
 }
 #endif
 
 #include "ll.h"
 
 /**
- * @brief All of the functions a DB backend exports.
+ * @brief Context for a database backend
  */
-struct dbfuncs {
-/**
- * @brief Initialize the key database.
- * @param readonly If we'll only be reading the DB, not writing to it.
- *
- * This function should be called before any of the other functions in
- * this file are called in order to allow the DB to be initialized ready
- * for access.
- */
-       void (*initdb)(bool readonly);
-
+struct onak_dbctx {
 /**
  * @brief De-initialize the key database.
  *
  * This function should be called upon program exit to allow the DB to
  * cleanup after itself.
  */
-       void (*cleanupdb)(void);
+       void (*cleanupdb)(struct onak_dbctx *);
 
 /**
  * @brief Start a transaction.
  * operations on the database to help speed it all up, or if we want
  * something to only succeed if all relevant operations are successful.
  */
-       bool (*starttrans)(void);
+       bool (*starttrans)(struct onak_dbctx *);
 
 /**
  * @brief End a transaction.
  *
  * Ends a transaction.
  */
-       void (*endtrans)(void);
+       void (*endtrans)(struct onak_dbctx *);
 
 /**
  * @brief Given a keyid fetch the key from storage.
  *
  * TODO: What about keyid collisions? Should we use fingerprint instead?
  */
-       int (*fetch_key_id)(uint64_t keyid,
+       int (*fetch_key_id)(struct onak_dbctx *,
+                       uint64_t keyid,
                        struct openpgp_publickey **publickey,
                        bool intrans);
 
  * This function returns a public key from whatever storage mechanism we
  * are using.
  */
-       int (*fetch_key_fp)(uint8_t *fp,
+       int (*fetch_key_fp)(struct onak_dbctx *,
+                       uint8_t *fp,
                        size_t fpsize,
                        struct openpgp_publickey **publickey,
                        bool intrans);
  *
  * TODO: Do we store multiple keys of the same id? Or only one and replace it?
  */
-       int (*store_key)(struct openpgp_publickey *publickey, bool intrans,
+       int (*store_key)(struct onak_dbctx *,
+                       struct openpgp_publickey *publickey, bool intrans,
                        bool update);
 
 /**
  * This function deletes a public key from whatever storage mechanism we
  * are using. Returns 0 if the key existed.
  */
-       int (*delete_key)(uint64_t keyid, bool intrans);
+       int (*delete_key)(struct onak_dbctx *, uint64_t keyid, bool intrans);
 
 /**
  * @brief Trys to find the keys that contain the supplied text.
  * This function searches for the supplied text and returns the keys that
  * contain it.
  */
-       int (*fetch_key_text)(const char *search,
+       int (*fetch_key_text)(struct onak_dbctx *, const char *search,
                        struct openpgp_publickey **publickey);
 
 /**
  * This function looks for the key that is referenced by the supplied
  * SKS hash and returns it.
  */
-       int (*fetch_key_skshash)(const struct skshash *hash,
+       int (*fetch_key_skshash)(struct onak_dbctx *,
+                       const struct skshash *hash,
                        struct openpgp_publickey **publickey);
 
 /**
  * If sendsync is true then we send out a keysync mail to our sync peers
  * with the update.
  */
-       int (*update_keys)(struct openpgp_publickey **keys, bool sendsync);
+       int (*update_keys)(struct onak_dbctx *,
+                       struct openpgp_publickey **keys, bool sendsync);
 
 /**
  * @brief Takes a keyid and returns the primary UID for it.
  * This function returns a UID for the given key. Returns NULL if the key
  * isn't found.
  */
-       char * (*keyid2uid)(uint64_t keyid);
+       char * (*keyid2uid)(struct onak_dbctx *, uint64_t keyid);
 
 /**
  * @brief Gets a linked list of the signatures on a key.
  * indexing and doing stats bits. If revoked is non-NULL then if the key
  * is revoked it's set to true.
  */
-       struct ll * (*getkeysigs)(uint64_t keyid, bool *revoked);
+       struct ll * (*getkeysigs)(struct onak_dbctx *,
+                       uint64_t keyid, bool *revoked);
 
 /**
  * @brief Gets the signatures on a key.
  * This function gets the signatures on a key. It's the same as the
  * getkeysigs function above except we use the hash module to cache the
  */
-       struct ll * (*cached_getkeysigs)(uint64_t keyid);
+       struct ll * (*cached_getkeysigs)(struct onak_dbctx *,
+                       uint64_t keyid);
 
 /**
  * @brief Maps a 32 bit key id to a 64 bit one.
  * This function maps a 32 bit key id to the full 64 bit one. It returns the
  * full keyid. If the key isn't found a keyid of 0 is returned.
  */
-       uint64_t (*getfullkeyid)(uint64_t keyid);
+       uint64_t (*getfullkeyid)(struct onak_dbctx *, uint64_t keyid);
 
 /**
  * @brief call a function once for each key in the db.
  *
  * Returns the number of keys we iterated over.
  */
-       int (*iterate_keys)(void (*iterfunc)(void *ctx,
+       int (*iterate_keys)(struct onak_dbctx *,
+                       void (*iterfunc)(void *ctx,
                        struct openpgp_publickey *key), void *ctx);
+
+/**
+ * @brief Private backend context information.
+ */
+       void *priv;
 };
 
 #endif /* __KEYDB_H__ */
 
 
 #define DB4_UPGRADE_FILE "db_upgrade.lck"
 
-/**
- *     dbenv - our database environment.
- */
-static DB_ENV *dbenv = NULL;
-
-/**
- *     numdb - The number of database files we have.
- */
-static int numdbs = 16;
-
-/**
- *     dbconn - our connections to the key database files.
- */
-static DB **dbconns = NULL;
-
-/**
- *     worddb - our connection to the word database.
- */
-static DB *worddb = NULL;
-
-/**
- *     id32db - our connection to the 32bit ID database.
- */
-static DB *id32db = NULL;
-
-/**
- *     skshashdb - our connection to the SKS hash database.
- */
-static DB *skshashdb = NULL;
-
-/**
- *     subkeydb - our connection to the subkey ID lookup database.
- */
-static DB *subkeydb = NULL;
-
-/**
- *     txn - our current transaction id.
- */
-static DB_TXN *txn = NULL;
+struct onak_db4_dbctx {
+       DB_ENV *dbenv;  /* The database environment context */
+       int numdbs;     /* Number of data databases in use */
+       DB **dbconns;   /* Connections to the key data databases */
+       DB *worddb;     /* Connection to the word lookup database */
+       DB *id32db;     /* Connection to the 32 bit ID lookup database */
+       DB *skshashdb;  /* Connection to the SKS hash database */
+       DB *subkeydb;   /* Connection to the subkey ID lookup database */
+       DB_TXN *txn;    /* Our current transaction ID */
+};
 
-DB *keydb(uint64_t keyid)
+DB *keydb(struct onak_db4_dbctx *privctx, uint64_t keyid)
 {
        uint64_t keytrun;
 
        keytrun = keyid >> 8;
 
-       return(dbconns[keytrun % numdbs]);
+       return(privctx->dbconns[keytrun % privctx->numdbs]);
 }
 
 /**
  *     operations on the database to help speed it all up, or if we want
  *     something to only succeed if all relevant operations are successful.
  */
-static bool db4_starttrans(void)
+static bool db4_starttrans(struct onak_dbctx *dbctx)
 {
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
        int ret;
 
-       log_assert(dbenv != NULL);
-       log_assert(txn == NULL);
+       log_assert(privctx->dbenv != NULL);
+       log_assert(privctx->txn == NULL);
 
-       ret = dbenv->txn_begin(dbenv,
+       ret = privctx->dbenv->txn_begin(privctx->dbenv,
                NULL, /* No parent transaction */
-               &txn,
+               &privctx->txn,
                0);
        if (ret != 0) {
                logthing(LOGTHING_CRITICAL,
  *
  *     Ends a transaction.
  */
-static void db4_endtrans(void)
+static void db4_endtrans(struct onak_dbctx *dbctx)
 {
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
        int ret;
 
-       log_assert(dbenv != NULL);
-       log_assert(txn != NULL);
+       log_assert(privctx->dbenv != NULL);
+       log_assert(privctx->txn != NULL);
 
-       ret = txn->commit(txn,
+       ret = privctx->txn->commit(privctx->txn,
                0);
        if (ret != 0) {
                logthing(LOGTHING_CRITICAL,
                                db_strerror(ret));
                exit(1);
        }
-       txn = NULL;
+       privctx->txn = NULL;
 
        return;
 }
 
-/**
- *     cleanupdb - De-initialize the key database.
- *
- *     This function should be called upon program exit to allow the DB to
- *     cleanup after itself.
- */
-static void db4_cleanupdb(void)
-{
-       int i = 0;
-
-       if (dbenv != NULL) {
-               dbenv->txn_checkpoint(dbenv, 0, 0, 0);
-               if (subkeydb != NULL) {
-                       subkeydb->close(subkeydb, 0);
-                       subkeydb = NULL;
-               }
-               if (skshashdb != NULL) {
-                       skshashdb->close(skshashdb, 0);
-                       skshashdb = NULL;
-               }
-               if (id32db != NULL) {
-                       id32db->close(id32db, 0);
-                       id32db = NULL;
-               }
-               if (worddb != NULL) {
-                       worddb->close(worddb, 0);
-                       worddb = NULL;
-               }
-               for (i = 0; i < numdbs; i++) {
-                       if (dbconns[i] != NULL) {
-                               dbconns[i]->close(dbconns[i], 0);
-                               dbconns[i] = NULL;
-                       }
-               }
-               free(dbconns);
-               dbconns = NULL;
-               dbenv->close(dbenv, 0);
-               dbenv = NULL;
-       }
-}
-
 /**
  *     db4_upgradedb - Upgrade a DB4 database
  *
  *     we're running with a newer version of db4 than the database was
  *     created with.
  */
-static int db4_upgradedb(int numdb)
+static int db4_upgradedb(struct onak_db4_dbctx *privctx)
 {
        DB *curdb = NULL;
        int ret;
        close(lockfile_fd);
 
        logthing(LOGTHING_NOTICE, "Upgrading DB4 database");
-       ret = db_env_create(&dbenv, 0);
-       dbenv->set_errcall(dbenv, &db4_errfunc);
-       dbenv->remove(dbenv, config.db_dir, 0);
-       dbenv = NULL;
-       for (i = 0; i < numdb; i++) {
+       ret = db_env_create(&privctx->dbenv, 0);
+       privctx->dbenv->set_errcall(privctx->dbenv, &db4_errfunc);
+       privctx->dbenv->remove(privctx->dbenv, config.db_dir, 0);
+       privctx->dbenv = NULL;
+       for (i = 0; i < privctx->numdbs; i++) {
                ret = db_create(&curdb, NULL, 0);
                if (ret == 0) {
                        snprintf(buf, sizeof(buf) - 1, "%s/keydb.%d.db",
 }
 
 /**
- *     initdb - Initialize the key database.
+ *     getfullkeyid - Maps a 32bit key id to a 64bit one.
+ *     @keyid: The 32bit keyid.
  *
- *     This function should be called before any of the other functions in
- *     this file are called in order to allow the DB to be initialized ready
- *     for access.
+ *     This function maps a 32bit key id to the full 64bit one. It returns the
+ *     full keyid. If the key isn't found a keyid of 0 is returned.
  */
-static void db4_initdb(bool readonly)
+static uint64_t db4_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid)
 {
-       char       buf[1024];
-       FILE      *numdb = NULL;
-       int        ret = 0;
-       int        i = 0;
-       uint32_t   flags = 0;
-       struct stat statbuf;
-       int        maxlocks;
-
-       snprintf(buf, sizeof(buf) - 1, "%s/%s", config.db_dir,
-                       DB4_UPGRADE_FILE);
-       ret = stat(buf, &statbuf);
-       while ((ret == 0) || (errno != ENOENT)) {
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL, "Couldn't stat upgrade "
-                               "lock file: %s (%d)", strerror(errno), ret);
-                       exit(1);
-               }
-               logthing(LOGTHING_DEBUG, "DB4 upgrade in progress; waiting.");
-               sleep(5);
-               ret = stat(buf, &statbuf);
-       }
-       ret = 0;
-
-       snprintf(buf, sizeof(buf) - 1, "%s/num_keydb", config.db_dir);
-       numdb = fopen(buf, "r");
-       if (numdb != NULL) {
-               if (fgets(buf, sizeof(buf), numdb) != NULL) {
-                       numdbs = atoi(buf);
-               }
-               fclose(numdb);
-       } else if (!readonly) {
-               logthing(LOGTHING_ERROR, "Couldn't open num_keydb: %s",
-                               strerror(errno));
-               numdb = fopen(buf, "w");
-               if (numdb != NULL) {
-                       fprintf(numdb, "%d", numdbs);
-                       fclose(numdb);
-               } else {
-                       logthing(LOGTHING_ERROR,
-                               "Couldn't write num_keydb: %s",
-                               strerror(errno));
-               }
-       }
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
+       DBT       key, data;
+       DBC      *cursor = NULL;
+       uint32_t  shortkeyid = 0;
+       int       ret = 0;
 
-       dbconns = calloc(numdbs, sizeof (DB *));
-       if (dbconns == NULL) {
-               logthing(LOGTHING_CRITICAL,
-                               "Couldn't allocate memory for dbconns");
-               ret = 1;
-       }
+       if (keyid < 0x100000000LL) {
+               ret = privctx->id32db->cursor(privctx->id32db,
+                               privctx->txn,
+                               &cursor,
+                               0);   /* flags */
 
-       if (ret == 0) {
-               ret = db_env_create(&dbenv, 0);
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL,
-                               "db_env_create: %s", db_strerror(ret));
-               }
-       }
+               shortkeyid = keyid & 0xFFFFFFFF;
 
-       /*
-        * Up the number of locks we're allowed at once. We base this on
-        * the maximum number of keys we're going to return.
-        */
-       maxlocks = config.maxkeys * 16;
-       if (maxlocks < 1000) {
-               maxlocks = 1000;
-       }
-       dbenv->set_lk_max_locks(dbenv, maxlocks);
-       dbenv->set_lk_max_objects(dbenv, maxlocks);
+               memset(&key, 0, sizeof(key));
+               memset(&data, 0, sizeof(data));
+               key.data = &shortkeyid;
+               key.size = sizeof(shortkeyid);
+               data.flags = DB_DBT_MALLOC;
 
-       /*
-        * Enable deadlock detection so that we don't block indefinitely on
-        * anything. What we really want is simple 2 state locks, but I'm not
-        * sure how to make the standard DB functions do that yet.
-        */
-       if (ret == 0) {
-               dbenv->set_errcall(dbenv, &db4_errfunc);
-               ret = dbenv->set_lk_detect(dbenv, DB_LOCK_DEFAULT);
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL,
-                               "db_env_create: %s", db_strerror(ret));
-               }
-       }
+               ret = cursor->c_get(cursor,
+                       &key,
+                       &data,
+                       DB_SET);
 
-       if (ret == 0) {
-               ret = dbenv->open(dbenv, config.db_dir,
-                               DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK |
-                               DB_INIT_TXN |
-                               DB_CREATE,
-                               0);
-#ifdef DB_VERSION_MISMATCH
-               if (ret == DB_VERSION_MISMATCH) {
-                       dbenv->close(dbenv, 0);
-                       dbenv = NULL;
-                       ret = db4_upgradedb(numdbs);
-                       if (ret == 0) {
-                               ret = db_env_create(&dbenv, 0);
-                       }
-                       if (ret == 0) {
-                               dbenv->set_errcall(dbenv, &db4_errfunc);
-                               dbenv->set_lk_detect(dbenv, DB_LOCK_DEFAULT);
-                               ret = dbenv->open(dbenv, config.db_dir,
-                                       DB_INIT_LOG | DB_INIT_MPOOL |
-                                       DB_INIT_LOCK | DB_INIT_TXN |
-                                       DB_CREATE | DB_RECOVER,
-                                       0);
+               if (ret == 0) {
+                       keyid = *(uint64_t *) data.data;
 
-                               if (ret == 0) {
-                                       dbenv->txn_checkpoint(dbenv,
-                                                       0,
-                                                       0,
-                                                       DB_FORCE);
-                               }
+                       if (data.data != NULL) {
+                               free(data.data);
+                               data.data = NULL;
                        }
                }
-#endif
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL,
-                                       "Error opening db environment: %s (%s)",
-                                       config.db_dir,
-                                       db_strerror(ret));
-                       dbenv->close(dbenv, 0);
-                       dbenv = NULL;
-               }
-       }
 
-       if (ret == 0) {
-               db4_starttrans();
+               ret = cursor->c_close(cursor);
+               cursor = NULL;
+       }
 
-               for (i = 0; !ret && i < numdbs; i++) {
-                       ret = db_create(&dbconns[i], dbenv, 0);
-                       if (ret != 0) {
-                               logthing(LOGTHING_CRITICAL,
-                                       "db_create: %s", db_strerror(ret));
-                       }
+       return keyid;
+}
 
-                       if (ret == 0) {
-                               snprintf(buf, 1023, "keydb.%d.db", i);
-                               flags = DB_CREATE;
-                               if (readonly) {
-                                       flags = DB_RDONLY;
-                               }
-                               ret = dbconns[i]->open(dbconns[i],
-                                               txn,
-                                               buf,
-                                               "keydb",
-                                               DB_HASH,
-                                               flags,
-                                               0664);
-                               if (ret != 0) {
-                                       logthing(LOGTHING_CRITICAL,
-                                               "Error opening key database:"
-                                               " %s (%s)",
-                                               buf,
-                                               db_strerror(ret));
-                               }
-                       }
-               }
+/**
+ *     fetch_key_id - Given a keyid fetch the key from storage.
+ *     @keyid: The keyid to fetch.
+ *     @publickey: A pointer to a structure to return the key in.
+ *     @intrans: If we're already in a transaction.
+ *
+ *     We use the hex representation of the keyid as the filename to fetch the
+ *     key from. The key is stored in the file as a binary OpenPGP stream of
+ *     packets, so we can just use read_openpgp_stream() to read the packets
+ *     in and then parse_keys() to parse the packets into a publickey
+ *     structure.
+ */
+static int db4_fetch_key_id(struct onak_dbctx *dbctx, uint64_t keyid,
+               struct openpgp_publickey **publickey,
+               bool intrans)
+{
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
+       struct openpgp_packet_list *packets = NULL;
+       DBT key, data;
+       int ret = 0;
+       int numkeys = 0;
+       struct buffer_ctx fetchbuf;
 
+       if (keyid < 0x100000000LL) {
+               keyid = db4_getfullkeyid(dbctx, keyid);
        }
 
-       if (ret == 0) {
-               ret = db_create(&worddb, dbenv, 0);
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL, "db_create: %s",
-                                       db_strerror(ret));
-               }
-       }
+       memset(&key, 0, sizeof(key));
+       memset(&data, 0, sizeof(data));
 
-       if (ret == 0) {
-               ret = worddb->set_flags(worddb, DB_DUP);
-       }
+       data.size = 0;
+       data.data = NULL;
 
-       if (ret == 0) {
-               ret = worddb->open(worddb, txn, "worddb", "worddb", DB_BTREE,
-                               flags,
-                               0664);
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL,
-                                       "Error opening word database: %s (%s)",
-                                       "worddb",
-                                       db_strerror(ret));
-               }
-       }
+       key.size = sizeof(keyid);
+       key.data = &keyid;
 
-       if (ret == 0) {
-               ret = db_create(&id32db, dbenv, 0);
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL, "db_create: %s",
-                                       db_strerror(ret));
-               }
+       if (!intrans) {
+               db4_starttrans(dbctx);
        }
 
-       if (ret == 0) {
-               ret = id32db->set_flags(id32db, DB_DUP);
-       }
-
-       if (ret == 0) {
-               ret = id32db->open(id32db, txn, "id32db", "id32db", DB_HASH,
-                               flags,
-                               0664);
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL,
-                                       "Error opening id32 database: %s (%s)",
-                                       "id32db",
-                                       db_strerror(ret));
-               }
-       }
-
-       if (ret == 0) {
-               ret = db_create(&skshashdb, dbenv, 0);
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL, "db_create: %s",
-                                       db_strerror(ret));
-               }
-       }
-
-       if (ret == 0) {
-               ret = skshashdb->open(skshashdb, txn, "skshashdb",
-                               "skshashdb", DB_HASH,
-                               flags,
-                               0664);
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL,
-                               "Error opening skshash database: %s (%s)",
-                               "skshashdb",
-                               db_strerror(ret));
-               }
-       }
-
-       if (ret == 0) {
-               ret = db_create(&subkeydb, dbenv, 0);
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL, "db_create: %s",
-                                       db_strerror(ret));
-               }
-       }
-
-       if (ret == 0) {
-               ret = subkeydb->open(subkeydb, txn, "subkeydb", "subkeydb",
-                               DB_HASH,
-                               flags,
-                               0664);
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL,
-                               "Error opening subkey database: %s (%s)",
-                               "subkeydb",
-                               db_strerror(ret));
-               }
-       }
-
-       if (txn != NULL) {
-               db4_endtrans();
-       }
-
-       if (ret != 0) {
-               db4_cleanupdb();
-               logthing(LOGTHING_CRITICAL,
-                               "Error opening database; exiting");
-               exit(EXIT_FAILURE);
-       }
-       
-       return;
-}
-
-/**
- *     getfullkeyid - Maps a 32bit key id to a 64bit one.
- *     @keyid: The 32bit keyid.
- *
- *     This function maps a 32bit key id to the full 64bit one. It returns the
- *     full keyid. If the key isn't found a keyid of 0 is returned.
- */
-static uint64_t db4_getfullkeyid(uint64_t keyid)
-{
-       DBT       key, data;
-       DBC      *cursor = NULL;
-       uint32_t  shortkeyid = 0;
-       int       ret = 0;
-
-       if (keyid < 0x100000000LL) {
-               ret = id32db->cursor(id32db,
-                               txn,
-                               &cursor,
-                               0);   /* flags */
-
-               shortkeyid = keyid & 0xFFFFFFFF;
-
-               memset(&key, 0, sizeof(key));
-               memset(&data, 0, sizeof(data));
-               key.data = &shortkeyid;
-               key.size = sizeof(shortkeyid);
-               data.flags = DB_DBT_MALLOC;
-
-               ret = cursor->c_get(cursor,
-                       &key,
-                       &data,
-                       DB_SET);
-
-               if (ret == 0) {
-                       keyid = *(uint64_t *) data.data;
-
-                       if (data.data != NULL) {
-                               free(data.data);
-                               data.data = NULL;
-                       }
-               }
-
-               ret = cursor->c_close(cursor);
-               cursor = NULL;
-       }
-       
-       return keyid;
-}
-
-/**
- *     fetch_key_id - Given a keyid fetch the key from storage.
- *     @keyid: The keyid to fetch.
- *     @publickey: A pointer to a structure to return the key in.
- *     @intrans: If we're already in a transaction.
- *
- *     We use the hex representation of the keyid as the filename to fetch the
- *     key from. The key is stored in the file as a binary OpenPGP stream of
- *     packets, so we can just use read_openpgp_stream() to read the packets
- *     in and then parse_keys() to parse the packets into a publickey
- *     structure.
- */
-static int db4_fetch_key_id(uint64_t keyid,
-               struct openpgp_publickey **publickey,
-               bool intrans)
-{
-       struct openpgp_packet_list *packets = NULL;
-       DBT key, data;
-       int ret = 0;
-       int numkeys = 0;
-       struct buffer_ctx fetchbuf;
-
-       if (keyid < 0x100000000LL) {
-               keyid = db4_getfullkeyid(keyid);
-       }
-
-       memset(&key, 0, sizeof(key));
-       memset(&data, 0, sizeof(data));
-
-       data.size = 0;
-       data.data = NULL;
-
-       key.size = sizeof(keyid);
-       key.data = &keyid;
-
-       if (!intrans) {
-               db4_starttrans();
-       }
-
-       ret = keydb(keyid)->get(keydb(keyid),
-                       txn,
-                       &key,
-                       &data,
-                       0); /* flags*/
+       ret = keydb(privctx, keyid)->get(keydb(privctx, keyid),
+                       privctx->txn,
+                       &key,
+                       &data,
+                       0); /* flags*/
 
        if (ret == DB_NOTFOUND) {
                /* If we didn't find the key ID see if it's a subkey ID */
                key.size = sizeof(keyid);
                key.data = &keyid;
 
-               ret = subkeydb->get(subkeydb,
-                       txn,
+               ret = privctx->subkeydb->get(privctx->subkeydb,
+                       privctx->txn,
                        &key,
                        &data,
                        0); /* flags*/
                        key.size = sizeof(keyid);
                        key.data = &keyid;
 
-                       ret = keydb(keyid)->get(keydb(keyid),
-                               txn,
+                       ret = keydb(privctx, keyid)->get(keydb(privctx, keyid),
+                               privctx->txn,
                                &key,
                                &data,
                                0); /* flags*/
        }
 
        if (!intrans) {
-               db4_endtrans();
+               db4_endtrans(dbctx);
        }
 
        return (numkeys);
  *     This function searches for the supplied text and returns the keys that
  *     contain it.
  */
-static int db4_fetch_key_text(const char *search,
+static int db4_fetch_key_text(struct onak_dbctx *dbctx, const char *search,
                struct openpgp_publickey **publickey)
 {
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
        DBC *cursor = NULL;
        DBT key, data;
        int ret;
        wordlist = makewordlist(wordlist, searchtext);
 
        for (curword = wordlist; curword != NULL; curword = curword->next) {
-               db4_starttrans();
+               db4_starttrans(dbctx);
 
-               ret = worddb->cursor(worddb,
-                               txn,
+               ret = privctx->worddb->cursor(privctx->worddb,
+                               privctx->txn,
                                &cursor,
                                0);   /* flags */
 
                ret = cursor->c_close(cursor);
                cursor = NULL;
                firstpass = 0;
-               db4_endtrans();
+               db4_endtrans(dbctx);
        }
        llfree(wordlist, NULL);
        wordlist = NULL;
        if (keylist.count > config.maxkeys) {
                keylist.count = config.maxkeys;
        }
-       
-       db4_starttrans();
+
+       db4_starttrans(dbctx);
        for (i = 0; i < keylist.count; i++) {
-               numkeys += db4_fetch_key_id(keylist.keys[i],
+               numkeys += db4_fetch_key_id(dbctx, keylist.keys[i],
                        publickey,
                        true);
        }
        free(searchtext);
        searchtext = NULL;
 
-       db4_endtrans();
-       
+       db4_endtrans(dbctx);
+
        return (numkeys);
 }
 
-static int db4_fetch_key_skshash(const struct skshash *hash,
+static int db4_fetch_key_skshash(struct onak_dbctx *dbctx,
+               const struct skshash *hash,
                struct openpgp_publickey **publickey)
 {
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
        DBT       key, data;
        DBC      *cursor = NULL;
        uint64_t  keyid = 0;
        int       ret = 0;
 
-       ret = skshashdb->cursor(skshashdb,
-                       txn,
+       ret = privctx->skshashdb->cursor(privctx->skshashdb,
+                       privctx->txn,
                        &cursor,
                        0);   /* flags */
 
        ret = cursor->c_close(cursor);
        cursor = NULL;
 
-       return db4_fetch_key_id(keyid, publickey, false);
+       return db4_fetch_key_id(dbctx, keyid, publickey, false);
 }
 
 /**
  *     This function deletes a public key from whatever storage mechanism we
  *     are using. Returns 0 if the key existed.
  */
-static int db4_delete_key(uint64_t keyid, bool intrans)
+static int db4_delete_key(struct onak_dbctx *dbctx,
+               uint64_t keyid, bool intrans)
 {
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
        struct openpgp_publickey *publickey = NULL;
        DBT key, data;
        DBC *cursor = NULL;
        struct skshash hash;
 
        if (!intrans) {
-               db4_starttrans();
+               db4_starttrans(dbctx);
        }
 
-       db4_fetch_key_id(keyid, &publickey, true);
+       db4_fetch_key_id(dbctx, keyid, &publickey, true);
 
        /*
         * Walk through the uids removing the words from the worddb.
                for (i = 0; ret == 0 && uids[i] != NULL; i++) {
                        wordlist = makewordlist(wordlist, uids[i]);
                }
-                               
-               ret = worddb->cursor(worddb,
-                       txn,
+
+               ret = privctx->worddb->cursor(privctx->worddb,
+                       privctx->txn,
                        &cursor,
                        0);   /* flags */
 
                ret = cursor->c_close(cursor);
                cursor = NULL;
 
-               ret = skshashdb->cursor(skshashdb,
-                       txn,
+               ret = privctx->skshashdb->cursor(privctx->skshashdb,
+                       privctx->txn,
                        &cursor,
                        0);   /* flags */
                get_skshash(publickey, &hash);
        }
 
        if (!deadlock) {
-               ret = id32db->cursor(id32db,
-                       txn,
+               ret = privctx->id32db->cursor(privctx->id32db,
+                       privctx->txn,
                        &cursor,
                        0);   /* flags */
 
                        memset(&key, 0, sizeof(key));
                        key.data = &subkeyids[i];
                        key.size = sizeof(subkeyids[i]);
-                       subkeydb->del(subkeydb, txn, &key, 0);
+                       privctx->subkeydb->del(privctx->subkeydb,
+                                       privctx->txn, &key, 0);
                        if (ret != 0) {
                                logthing(LOGTHING_ERROR,
                                        "Problem deleting subkey id: %s "
                key.data = &keyid;
                key.size = sizeof(keyid);
 
-               keydb(keyid)->del(keydb(keyid),
-                               txn,
+               keydb(privctx, keyid)->del(keydb(privctx, keyid),
+                               privctx->txn,
                                &key,
                                0); /* flags */
        }
 
        if (!intrans) {
-               db4_endtrans();
+               db4_endtrans(dbctx);
        }
 
        return deadlock ? (-1) : (ret == DB_NOTFOUND);
  *     the file. If update is true then we delete the old key first, otherwise
  *     we trust that it doesn't exist.
  */
-static int db4_store_key(struct openpgp_publickey *publickey, bool intrans,
+static int db4_store_key(struct onak_dbctx *dbctx,
+               struct openpgp_publickey *publickey, bool intrans,
                bool update)
 {
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
        struct     openpgp_packet_list *packets = NULL;
        struct     openpgp_packet_list *list_end = NULL;
        struct     openpgp_publickey *next = NULL;
        }
 
        if (!intrans) {
-               db4_starttrans();
+               db4_starttrans(dbctx);
        }
 
        /*
         * it definitely needs updated.
         */
        if (update) {
-               deadlock = (db4_delete_key(keyid, true) == -1);
+               deadlock = (db4_delete_key(dbctx, keyid, true) == -1);
        }
 
        /*
                flatten_publickey(publickey, &packets, &list_end);
                publickey->next = next;
 
-               storebuf.offset = 0; 
+               storebuf.offset = 0;
                storebuf.size = 8192;
                storebuf.buffer = malloc(8192);
-       
+
                write_openpgp_stream(buffer_putchar, &storebuf, packets);
 
                /*
                data.size = storebuf.offset;
                data.data = storebuf.buffer;
 
-               ret = keydb(keyid)->put(keydb(keyid),
-                               txn,
+               ret = keydb(privctx, keyid)->put(keydb(privctx, keyid),
+                               privctx->txn,
                                &key,
                                &data,
                                0); /* flags*/
                free(storebuf.buffer);
                storebuf.buffer = NULL;
                storebuf.size = 0;
-               storebuf.offset = 0; 
-       
+               storebuf.offset = 0;
+
                free_packet_list(packets);
                packets = NULL;
        }
                        worddb_data[ 8] = (keyid >> 24) & 0xFF;
                        worddb_data[ 9] = (keyid >> 16) & 0xFF;
                        worddb_data[10] = (keyid >>  8) & 0xFF;
-                       worddb_data[11] = keyid & 0xFF; 
-                       ret = worddb->put(worddb,
-                               txn,
+                       worddb_data[11] = keyid & 0xFF;
+                       ret = privctx->worddb->put(privctx->worddb,
+                               privctx->txn,
                                &key,
                                &data,
                                0);
                data.data = &keyid;
                data.size = sizeof(keyid);
 
-               ret = id32db->put(id32db,
-                       txn,
+               ret = privctx->id32db->put(privctx->id32db,
+                       privctx->txn,
                        &key,
                        &data,
                        0);
                        data.data = &keyid;
                        data.size = sizeof(keyid);
 
-                       ret = subkeydb->put(subkeydb,
-                               txn,
+                       ret = privctx->subkeydb->put(privctx->subkeydb,
+                               privctx->txn,
                                &key,
                                &data,
                                0);
                        data.data = &keyid;
                        data.size = sizeof(keyid);
 
-                       ret = id32db->put(id32db,
-                               txn,
+                       ret = privctx->id32db->put(privctx->id32db,
+                               privctx->txn,
                                &key,
                                &data,
                                0);
                data.data = &keyid;
                data.size = sizeof(keyid);
 
-               ret = skshashdb->put(skshashdb,
-                       txn,
+               ret = privctx->skshashdb->put(privctx->skshashdb,
+                       privctx->txn,
                        &key,
                        &data,
                        0);
        }
 
        if (!intrans) {
-               db4_endtrans();
+               db4_endtrans(dbctx);
        }
 
        return deadlock ? -1 : 0 ;
  *
  *     Returns the number of keys we iterated over.
  */
-static int db4_iterate_keys(void (*iterfunc)(void *ctx,
-               struct openpgp_publickey *key), void *ctx)
+static int db4_iterate_keys(struct onak_dbctx *dbctx,
+               void (*iterfunc)(void *ctx, struct openpgp_publickey *key),
+               void *ctx)
 {
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
        DBT                         dbkey, data;
        DBC                        *cursor = NULL;
        int                         ret = 0;
        struct openpgp_packet_list *packets = NULL;
        struct openpgp_publickey   *key = NULL;
 
-       for (i = 0; i < numdbs; i++) {
-               ret = dbconns[i]->cursor(dbconns[i],
+       for (i = 0; i < privctx->numdbs; i++) {
+               ret = privctx->dbconns[i]->cursor(privctx->dbconns[i],
                        NULL,
                        &cursor,
                        0);   /* flags */
                        parse_keys(packets, &key);
 
                        iterfunc(ctx, key);
-                       
+
                        free_publickey(key);
                        key = NULL;
                        free_packet_list(packets);
                        packets = NULL;
-                       
+
                        memset(&dbkey, 0, sizeof(dbkey));
                        memset(&data, 0, sizeof(data));
                        ret = cursor->c_get(cursor, &dbkey, &data,
                ret = cursor->c_close(cursor);
                cursor = NULL;
        }
-       
+
        return numkeys;
 }
 
 #define NEED_GET_FP 1
 #include "keydb.c"
 
-struct dbfuncs keydb_db4_funcs = {
-       .initdb                 = db4_initdb,
-       .cleanupdb              = db4_cleanupdb,
-       .starttrans             = db4_starttrans,
-       .endtrans               = db4_endtrans,
-       .fetch_key_id           = db4_fetch_key_id,
-       .fetch_key_fp           = generic_fetch_key_fp,
-       .fetch_key_text         = db4_fetch_key_text,
-       .fetch_key_skshash      = db4_fetch_key_skshash,
-       .store_key              = db4_store_key,
-       .update_keys            = generic_update_keys,
-       .delete_key             = db4_delete_key,
-       .getkeysigs             = generic_getkeysigs,
-       .cached_getkeysigs      = generic_cached_getkeysigs,
-       .keyid2uid              = generic_keyid2uid,
-       .getfullkeyid           = db4_getfullkeyid,
-       .iterate_keys           = db4_iterate_keys,
-};
+/**
+ *     cleanupdb - De-initialize the key database.
+ *
+ *     This function should be called upon program exit to allow the DB to
+ *     cleanup after itself.
+ */
+static void db4_cleanupdb(struct onak_dbctx *dbctx)
+{
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
+       int i = 0;
+
+       if (privctx->dbenv != NULL) {
+               privctx->dbenv->txn_checkpoint(privctx->dbenv, 0, 0, 0);
+               if (privctx->subkeydb != NULL) {
+                       privctx->subkeydb->close(privctx->subkeydb, 0);
+                       privctx->subkeydb = NULL;
+               }
+               if (privctx->skshashdb != NULL) {
+                       privctx->skshashdb->close(privctx->skshashdb, 0);
+                       privctx->skshashdb = NULL;
+               }
+               if (privctx->id32db != NULL) {
+                       privctx->id32db->close(privctx->id32db, 0);
+                       privctx->id32db = NULL;
+               }
+               if (privctx->worddb != NULL) {
+                       privctx->worddb->close(privctx->worddb, 0);
+                       privctx->worddb = NULL;
+               }
+               for (i = 0; i < privctx->numdbs; i++) {
+                       if (privctx->dbconns[i] != NULL) {
+                               privctx->dbconns[i]->close(privctx->dbconns[i],
+                                               0);
+                               privctx->dbconns[i] = NULL;
+                       }
+               }
+               free(privctx->dbconns);
+               privctx->dbconns = NULL;
+               privctx->dbenv->close(privctx->dbenv, 0);
+               privctx->dbenv = NULL;
+       }
+
+       free(privctx);
+       dbctx->priv = NULL;
+       free(dbctx);
+}
+
+/**
+ *     initdb - Initialize the key database.
+ *
+ *     This function should be called before any of the other functions in
+ *     this file are called in order to allow the DB to be initialized ready
+ *     for access.
+ */
+struct onak_dbctx *keydb_db4_init(bool readonly)
+{
+       char       buf[1024];
+       FILE      *numdb = NULL;
+       int        ret = 0;
+       int        i = 0;
+       uint32_t   flags = 0;
+       struct stat statbuf;
+       int        maxlocks;
+       struct onak_dbctx *dbctx;
+       struct onak_db4_dbctx *privctx;
+
+       dbctx = malloc(sizeof(*dbctx));
+       if (dbctx == NULL) {
+               return NULL;
+       }
+       dbctx->priv = privctx = calloc(1, sizeof(*privctx));
+       if (privctx == NULL) {
+               free(dbctx);
+               return NULL;
+       }
+
+       /* Default to 16 key data DBs */
+       privctx->numdbs = 16;
+
+       snprintf(buf, sizeof(buf) - 1, "%s/%s", config.db_dir,
+                       DB4_UPGRADE_FILE);
+       ret = stat(buf, &statbuf);
+       while ((ret == 0) || (errno != ENOENT)) {
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL, "Couldn't stat upgrade "
+                               "lock file: %s (%d)", strerror(errno), ret);
+                       exit(1);
+               }
+               logthing(LOGTHING_DEBUG, "DB4 upgrade in progress; waiting.");
+               sleep(5);
+               ret = stat(buf, &statbuf);
+       }
+       ret = 0;
+
+       snprintf(buf, sizeof(buf) - 1, "%s/num_keydb", config.db_dir);
+       numdb = fopen(buf, "r");
+       if (numdb != NULL) {
+               if (fgets(buf, sizeof(buf), numdb) != NULL) {
+                       privctx->numdbs = atoi(buf);
+               }
+               fclose(numdb);
+       } else if (!readonly) {
+               logthing(LOGTHING_ERROR, "Couldn't open num_keydb: %s",
+                               strerror(errno));
+               numdb = fopen(buf, "w");
+               if (numdb != NULL) {
+                       fprintf(numdb, "%d", privctx->numdbs);
+                       fclose(numdb);
+               } else {
+                       logthing(LOGTHING_ERROR,
+                               "Couldn't write num_keydb: %s",
+                               strerror(errno));
+               }
+       }
+
+       privctx->dbconns = calloc(privctx->numdbs, sizeof (DB *));
+       if (privctx->dbconns == NULL) {
+               logthing(LOGTHING_CRITICAL,
+                               "Couldn't allocate memory for dbconns");
+               ret = 1;
+       }
+
+       if (ret == 0) {
+               ret = db_env_create(&privctx->dbenv, 0);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                               "db_env_create: %s", db_strerror(ret));
+               }
+       }
+
+       /*
+        * Up the number of locks we're allowed at once. We base this on
+        * the maximum number of keys we're going to return.
+        */
+       maxlocks = config.maxkeys * 16;
+       if (maxlocks < 1000) {
+               maxlocks = 1000;
+       }
+       privctx->dbenv->set_lk_max_locks(privctx->dbenv, maxlocks);
+       privctx->dbenv->set_lk_max_objects(privctx->dbenv, maxlocks);
+
+       /*
+        * Enable deadlock detection so that we don't block indefinitely on
+        * anything. What we really want is simple 2 state locks, but I'm not
+        * sure how to make the standard DB functions do that yet.
+        */
+       if (ret == 0) {
+               privctx->dbenv->set_errcall(privctx->dbenv, &db4_errfunc);
+               ret = privctx->dbenv->set_lk_detect(privctx->dbenv, DB_LOCK_DEFAULT);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                               "db_env_create: %s", db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = privctx->dbenv->open(privctx->dbenv, config.db_dir,
+                               DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK |
+                               DB_INIT_TXN |
+                               DB_CREATE,
+                               0);
+#ifdef DB_VERSION_MISMATCH
+               if (ret == DB_VERSION_MISMATCH) {
+                       privctx->dbenv->close(privctx->dbenv, 0);
+                       privctx->dbenv = NULL;
+                       ret = db4_upgradedb(privctx);
+                       if (ret == 0) {
+                               ret = db_env_create(&privctx->dbenv, 0);
+                       }
+                       if (ret == 0) {
+                               privctx->dbenv->set_errcall(privctx->dbenv,
+                                       &db4_errfunc);
+                               privctx->dbenv->set_lk_detect(privctx->dbenv,
+                                       DB_LOCK_DEFAULT);
+                               ret = privctx->dbenv->open(privctx->dbenv,
+                                       config.db_dir,
+                                       DB_INIT_LOG | DB_INIT_MPOOL |
+                                       DB_INIT_LOCK | DB_INIT_TXN |
+                                       DB_CREATE | DB_RECOVER,
+                                       0);
+
+                               if (ret == 0) {
+                                       privctx->dbenv->txn_checkpoint(
+                                                       privctx->dbenv,
+                                                       0,
+                                                       0,
+                                                       DB_FORCE);
+                               }
+                       }
+               }
+#endif
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                                       "Error opening db environment: %s (%s)",
+                                       config.db_dir,
+                                       db_strerror(ret));
+                       privctx->dbenv->close(privctx->dbenv, 0);
+                       privctx->dbenv = NULL;
+               }
+       }
+
+       if (ret == 0) {
+               db4_starttrans(dbctx);
+
+               for (i = 0; !ret && i < privctx->numdbs; i++) {
+                       ret = db_create(&privctx->dbconns[i],
+                                       privctx->dbenv, 0);
+                       if (ret != 0) {
+                               logthing(LOGTHING_CRITICAL,
+                                       "db_create: %s", db_strerror(ret));
+                       }
+
+                       if (ret == 0) {
+                               snprintf(buf, 1023, "keydb.%d.db", i);
+                               flags = DB_CREATE;
+                               if (readonly) {
+                                       flags = DB_RDONLY;
+                               }
+                               ret = privctx->dbconns[i]->open(
+                                               privctx->dbconns[i],
+                                               privctx->txn,
+                                               buf,
+                                               "keydb",
+                                               DB_HASH,
+                                               flags,
+                                               0664);
+                               if (ret != 0) {
+                                       logthing(LOGTHING_CRITICAL,
+                                               "Error opening key database:"
+                                               " %s (%s)",
+                                               buf,
+                                               db_strerror(ret));
+                               }
+                       }
+               }
+       }
+
+       if (ret == 0) {
+               ret = db_create(&privctx->worddb, privctx->dbenv, 0);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL, "db_create: %s",
+                                       db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = privctx->worddb->set_flags(privctx->worddb, DB_DUP);
+       }
+
+       if (ret == 0) {
+               ret = privctx->worddb->open(privctx->worddb, privctx->txn,
+                               "worddb", "worddb", DB_BTREE,
+                               flags,
+                               0664);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                                       "Error opening word database: %s (%s)",
+                                       "worddb",
+                                       db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = db_create(&privctx->id32db, privctx->dbenv, 0);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL, "db_create: %s",
+                                       db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = privctx->id32db->set_flags(privctx->id32db, DB_DUP);
+       }
+
+       if (ret == 0) {
+               ret = privctx->id32db->open(privctx->id32db, privctx->txn,
+                               "id32db", "id32db", DB_HASH,
+                               flags,
+                               0664);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                                       "Error opening id32 database: %s (%s)",
+                                       "id32db",
+                                       db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = db_create(&privctx->skshashdb, privctx->dbenv, 0);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL, "db_create: %s",
+                                       db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = privctx->skshashdb->open(privctx->skshashdb, privctx->txn,
+                               "skshashdb",
+                               "skshashdb", DB_HASH,
+                               flags,
+                               0664);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                               "Error opening skshash database: %s (%s)",
+                               "skshashdb",
+                               db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = db_create(&privctx->subkeydb, privctx->dbenv, 0);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL, "db_create: %s",
+                                       db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = privctx->subkeydb->open(privctx->subkeydb, privctx->txn,
+                               "subkeydb", "subkeydb",
+                               DB_HASH,
+                               flags,
+                               0664);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                               "Error opening subkey database: %s (%s)",
+                               "subkeydb",
+                               db_strerror(ret));
+               }
+       }
+
+       if (privctx->txn != NULL) {
+               db4_endtrans(dbctx);
+       }
+
+       if (ret != 0) {
+               db4_cleanupdb(dbctx);
+               logthing(LOGTHING_CRITICAL,
+                               "Error opening database; exiting");
+               exit(EXIT_FAILURE);
+       }
+
+       dbctx->cleanupdb                = db4_cleanupdb;
+       dbctx->starttrans               = db4_starttrans;
+       dbctx->endtrans                 = db4_endtrans;
+       dbctx->fetch_key_id             = db4_fetch_key_id;
+       dbctx->fetch_key_fp             = generic_fetch_key_fp;
+       dbctx->fetch_key_text           = db4_fetch_key_text;
+       dbctx->fetch_key_skshash        = db4_fetch_key_skshash;
+       dbctx->store_key                = db4_store_key;
+       dbctx->update_keys              = generic_update_keys;
+       dbctx->delete_key               = db4_delete_key;
+       dbctx->getkeysigs               = generic_getkeysigs;
+       dbctx->cached_getkeysigs        = generic_cached_getkeysigs;
+       dbctx->keyid2uid                = generic_keyid2uid;
+       dbctx->getfullkeyid             = db4_getfullkeyid;
+       dbctx->iterate_keys             = db4_iterate_keys;
+
+       return dbctx;
+}
 
 #include "parsekey.h"
 #include "sendsync.h"
 
-static struct dbfuncs *loaded_backend = NULL;
-static void *backend_handle;
+struct onak_dynamic_dbctx {
+       struct onak_dbctx *loadeddbctx;
+       void              *backend_handle;
+};
 
-static bool close_backend(void)
+static bool dynamic_starttrans(struct onak_dbctx *dbctx)
 {
-       loaded_backend = NULL;
-       dlclose(backend_handle);
-       backend_handle = NULL;
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
-       return true;
+       return privctx->loadeddbctx->starttrans(privctx->loadeddbctx);
 }
 
-static bool load_backend(void)
+static void dynamic_endtrans(struct onak_dbctx *dbctx)
 {
-       char *soname = NULL;
-       char *funcsname = NULL;
-
-       if (loaded_backend != NULL) {
-               close_backend();
-               loaded_backend = NULL;
-       }
-
-       if (config.use_keyd) {
-               free(config.db_backend);
-               config.db_backend = strdup("keyd");
-       }
-
-       if (!config.db_backend) {
-               logthing(LOGTHING_CRITICAL, "No database backend defined.");
-               exit(EXIT_FAILURE);
-       }
-
-       if (config.backends_dir == NULL) {
-               soname = malloc(strlen(config.db_backend)
-                       + strlen("./libkeydb_")
-                       + strlen(".so")
-                       + 1);
-
-               sprintf(soname, "./libkeydb_%s.so", config.db_backend);
-       } else {
-               soname = malloc(strlen(config.db_backend)
-                       + strlen("/libkeydb_")
-                       + strlen(".so")
-                       + strlen(config.backends_dir)
-                       + 1);
-
-               sprintf(soname, "%s/libkeydb_%s.so", config.backends_dir,
-                       config.db_backend);
-       }
-               
-       logthing(LOGTHING_INFO, "Loading dynamic backend: %s", soname);
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
-       backend_handle = dlopen(soname, RTLD_LAZY);
-       if (backend_handle == NULL) {
-               logthing(LOGTHING_CRITICAL,
-                               "Failed to open handle to library '%s': %s",
-                               soname, dlerror());
-               free(soname);
-               soname = NULL;
-               exit(EXIT_FAILURE);
-       }
+       privctx->loadeddbctx->endtrans(privctx->loadeddbctx);
+}
 
-       funcsname = malloc(strlen(config.db_backend)
-                       + strlen("keydb_")
-                       + strlen("_funcs")
-                       + 1);
-       sprintf(funcsname, "keydb_%s_funcs", config.db_backend);
+static int dynamic_fetch_key_id(struct onak_dbctx *dbctx, uint64_t keyid,
+               struct openpgp_publickey **publickey, bool intrans)
+{
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
-       loaded_backend = dlsym(backend_handle, funcsname);
-       free(funcsname);
+       return privctx->loadeddbctx->fetch_key_id(privctx->loadeddbctx, keyid,
+                       publickey, intrans);
+}
 
-       if (loaded_backend == NULL) {
-               logthing(LOGTHING_CRITICAL,
-                               "Failed to find dbfuncs structure in library "
-                               "'%s' : %s", soname, dlerror());
-               free(soname);
-               soname = NULL;
-               exit(EXIT_FAILURE);
-       }
-       free(soname);
-       soname = NULL;
+static int dynamic_fetch_key_fp(struct onak_dbctx *dbctx,
+               uint8_t *fp, size_t fpsize,
+               struct openpgp_publickey **publickey, bool intrans)
+{
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
-       return true;
+       return privctx->loadeddbctx->fetch_key_fp(privctx->loadeddbctx,
+                       fp, fpsize, publickey, intrans);
 }
 
-static bool dynamic_starttrans()
+static int dynamic_fetch_key_text(struct onak_dbctx *dbctx,
+               const char *search,
+               struct openpgp_publickey **publickey)
 {
-       if (loaded_backend == NULL) {
-               load_backend();
-       }
-       
-       if (loaded_backend != NULL) {
-               if (loaded_backend->starttrans != NULL) {
-                       return loaded_backend->starttrans();
-               }
-       }
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
-       return false;
+       return privctx->loadeddbctx->fetch_key_text(privctx->loadeddbctx,
+                       search, publickey);
 }
 
-static void dynamic_endtrans()
+static int dynamic_fetch_key_skshash(struct onak_dbctx *dbctx,
+               const struct skshash *hash,
+               struct openpgp_publickey **publickey)
 {
-       if (loaded_backend == NULL) {
-               load_backend();
-       }
-       
-       if (loaded_backend != NULL) {
-               if (loaded_backend->endtrans != NULL) {
-                       loaded_backend->endtrans();
-               }
-       }
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
+
+       return privctx->loadeddbctx->fetch_key_skshash(privctx->loadeddbctx,
+                       hash, publickey);
 }
 
-static int dynamic_fetch_key_id(uint64_t keyid,
-               struct openpgp_publickey **publickey, bool intrans)
+static int dynamic_store_key(struct onak_dbctx *dbctx,
+               struct openpgp_publickey *publickey, bool intrans,
+               bool update)
 {
-       if (loaded_backend == NULL) {
-               load_backend();
-       }
-
-       if (loaded_backend != NULL) {
-               if (loaded_backend->fetch_key_id != NULL) {
-                       return loaded_backend->fetch_key_id(keyid,
-                               publickey, intrans);
-               }
-       }
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
-       return -1;
+       return privctx->loadeddbctx->store_key(privctx->loadeddbctx,
+                       publickey, intrans, update);
 }
 
-static int dynamic_fetch_key_fp(uint8_t *fp, size_t fpsize,
-               struct openpgp_publickey **publickey, bool intrans)
+static int dynamic_delete_key(struct onak_dbctx *dbctx, uint64_t keyid,
+               bool intrans)
 {
-       if (loaded_backend == NULL) {
-               load_backend();
-       }
-
-       if (loaded_backend != NULL) {
-               if (loaded_backend->fetch_key_id != NULL) {
-                       return loaded_backend->fetch_key_fp(fp, fpsize,
-                               publickey, intrans);
-               }
-       }
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
-       return -1;
+       return privctx->loadeddbctx->delete_key(privctx->loadeddbctx,
+                       keyid, intrans);
 }
 
+static int dynamic_update_keys(struct onak_dbctx *dbctx,
+               struct openpgp_publickey **keys, bool sendsync)
+{
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
+       return privctx->loadeddbctx->update_keys(privctx->loadeddbctx,
+                       keys, sendsync);
+}
 
-static int dynamic_store_key(struct openpgp_publickey *publickey, bool intrans,
-               bool update)
+static struct ll *dynamic_getkeysigs(struct onak_dbctx *dbctx,
+               uint64_t keyid, bool *revoked)
 {
-       if (loaded_backend == NULL) {
-               load_backend();
-       }
-       
-       if (loaded_backend != NULL) {
-               if (loaded_backend->store_key != NULL) {
-                       return loaded_backend->store_key(publickey,intrans,update);
-               }
-       }
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
-       return -1;
+       return privctx->loadeddbctx->getkeysigs(privctx->loadeddbctx,
+                       keyid, revoked);
 }
 
-static int dynamic_delete_key(uint64_t keyid, bool intrans)
+static struct ll *dynamic_cached_getkeysigs(struct onak_dbctx *dbctx,
+               uint64_t keyid)
 {
-       if (loaded_backend == NULL) {
-               load_backend();
-       }
-       
-       if (loaded_backend != NULL) {
-               if (loaded_backend->delete_key != NULL) {
-                       return loaded_backend->delete_key(keyid, intrans);
-               }
-       }
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
-       return -1;
+       return privctx->loadeddbctx->cached_getkeysigs(privctx->loadeddbctx,
+                       keyid);
 }
 
-static int dynamic_fetch_key_text(const char *search,
-               struct openpgp_publickey **publickey)
+static char *dynamic_keyid2uid(struct onak_dbctx *dbctx,
+                       uint64_t keyid)
 {
-       if (loaded_backend == NULL) {
-               load_backend();
-       }
-       
-       if (loaded_backend != NULL) {
-               if (loaded_backend->fetch_key_text != NULL) {
-                       return loaded_backend->fetch_key_text(search, publickey);
-               }
-       }
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
-       return -1;
+       return privctx->loadeddbctx->keyid2uid(privctx->loadeddbctx,
+                       keyid);
 }
 
-static int dynamic_fetch_key_skshash(const struct skshash *hash,
-               struct openpgp_publickey **publickey)
+static uint64_t dynamic_getfullkeyid(struct onak_dbctx *dbctx,
+               uint64_t keyid)
 {
-       if (loaded_backend == NULL) {
-               load_backend();
-       }
-       
-       if (loaded_backend != NULL) {
-               if (loaded_backend->fetch_key_skshash != NULL) {
-                       return loaded_backend->fetch_key_skshash(hash,
-                                                               publickey);
-               }
-       }
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
-       return -1;
+       return privctx->loadeddbctx->getfullkeyid(privctx->loadeddbctx, keyid);
 }
 
-static int dynamic_iterate_keys(void (*iterfunc)(void *ctx,
-               struct openpgp_publickey *key), void *ctx)
+static int dynamic_iterate_keys(struct onak_dbctx *dbctx,
+               void (*iterfunc)(void *ctx, struct openpgp_publickey *key),
+               void *ctx)
 {
-       if (loaded_backend == NULL) {
-               load_backend();
-       }
-       
-       if (loaded_backend != NULL) {
-               if (loaded_backend->iterate_keys != NULL) {
-                       return loaded_backend->iterate_keys(iterfunc, ctx);
-               }
-       }
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
-       return -1;
+       return privctx->loadeddbctx->iterate_keys(privctx->loadeddbctx,
+                       iterfunc, ctx);
 }
 
-/**
- *     keyid2uid - Takes a keyid and returns the primary UID for it.
- *     @keyid: The keyid to lookup.
- */
-static char *dynamic_keyid2uid(uint64_t keyid)
+static void dynamic_cleanupdb(struct onak_dbctx *dbctx)
 {
-       struct openpgp_publickey *publickey = NULL;
-       struct openpgp_signedpacket_list *curuid = NULL;
-       char buf[1024];
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
-       if (loaded_backend == NULL) {
-               load_backend();
-       }
-       
-       if (loaded_backend != NULL) {
-               if (loaded_backend->keyid2uid != NULL) {
-                       return loaded_backend->keyid2uid(keyid);
+       if (privctx->loadeddbctx != NULL) {
+               if (privctx->loadeddbctx->cleanupdb != NULL) {
+                       privctx->loadeddbctx->cleanupdb(privctx->loadeddbctx);
+                       privctx->loadeddbctx = NULL;
                }
        }
-       
-       buf[0]=0;
-       if (dynamic_fetch_key_id(keyid, &publickey, false) &&
-                       publickey != NULL) {
-               curuid = publickey->uids;
-               while (curuid != NULL && buf[0] == 0) {
-                       if (curuid->packet->tag == OPENPGP_PACKET_UID) {
-                               snprintf(buf, 1023, "%.*s",
-                                               (int) curuid->packet->length,
-                                               curuid->packet->data);
-                       }
-                       curuid = curuid -> next;
-               }
-               free_publickey(publickey);
-       }
 
-       if (buf[0] == 0) {
-               return NULL;
-       } else {
-               return strdup(buf);
+       if (privctx->backend_handle != NULL) {
+               dlclose(privctx->backend_handle);
+               privctx->backend_handle = NULL;
        }
-}
 
-/**
- *     getkeysigs - Gets a linked list of the signatures on a key.
- *     @keyid: The keyid to get the sigs for.
- *     @revoked: Is the key revoked?
- *
- *     This function gets the list of signatures on a key. Used for key 
- *     indexing and doing stats bits. If revoked is non-NULL then if the key
- *     is revoked it's set to true.
- */
-static struct ll *dynamic_getkeysigs(uint64_t keyid, bool *revoked)
-{
-       struct ll *sigs = NULL;
-       struct openpgp_signedpacket_list *uids = NULL;
-       struct openpgp_publickey *publickey = NULL;
-       
-       if ( loaded_backend == NULL ) {
-               load_backend();
-       }
-       
-       if (loaded_backend != NULL) {
-               if (loaded_backend->getkeysigs != NULL) {
-                       return loaded_backend->getkeysigs(keyid,revoked);
-               }
+       if (dbctx->priv != NULL) {
+               free(dbctx->priv);
+               dbctx->priv = NULL;
        }
 
-       dynamic_fetch_key_id(keyid, &publickey, false);
-       
-       if (publickey != NULL) {
-               for (uids = publickey->uids; uids != NULL; uids = uids->next) {
-                       sigs = keysigs(sigs, uids->sigs);
-               }
-               if (revoked != NULL) {
-                       *revoked = publickey->revoked;
-               }
-               free_publickey(publickey);
+       if (dbctx != NULL) {
+               free(dbctx);
        }
-
-       return sigs;
 }
 
-/**
- *     cached_getkeysigs - Gets the signatures on a key.
- *     @keyid: The key we want the signatures for.
- *     
- *     This function gets the signatures on a key. It's the same as the
- *     getkeysigs function above except we use the hash module to cache the
- *     data so if we need it again it's already loaded.
- */
-static struct ll *dynamic_cached_getkeysigs(uint64_t keyid)
+struct onak_dbctx *keydb_dynamic_init(bool readonly)
 {
-       struct stats_key *key = NULL;
-       struct stats_key *signedkey = NULL;
-       struct ll        *cursig = NULL;
-       bool              revoked = false;
+       struct onak_dbctx *dbctx;
+       char *soname;
+       char *initname;
+       struct onak_dbctx *(*backend_init)(bool);
+       struct onak_dynamic_dbctx *privctx;
+
+       dbctx = malloc(sizeof(struct onak_dbctx));
 
-       if (keyid == 0)  {
+       if (dbctx == NULL) {
                return NULL;
        }
-       
-       if (loaded_backend == NULL) {
-               load_backend();
-       }
-       
-       if (loaded_backend != NULL) {
-               if (loaded_backend->cached_getkeysigs != NULL) {
-                       return loaded_backend->cached_getkeysigs(keyid);
-               }
-       }
-
-       key = createandaddtohash(keyid);
 
-       if (key->gotsigs == false) {
-               key->sigs = dynamic_getkeysigs(key->keyid, &revoked);
-               key->revoked = revoked;
-               for (cursig = key->sigs; cursig != NULL;
-                               cursig = cursig->next) {
-                       signedkey = (struct stats_key *) cursig->object;
-                       signedkey->signs = lladd(signedkey->signs, key);
-               }
-               key->gotsigs = true;
+       dbctx->priv = privctx = malloc(sizeof(struct onak_dynamic_dbctx));
+       if (dbctx->priv == NULL) {
+               free(dbctx);
+               return (NULL);
        }
 
-       return key->sigs;
-}
-
-/**
- *     getfullkeyid - Maps a 32bit key id to a 64bit one.
- *     @keyid: The 32bit keyid.
- *
- *     This function maps a 32bit key id to the full 64bit one. It returns the
- *     full keyid. If the key isn't found a keyid of 0 is returned.
- */
-static uint64_t dynamic_getfullkeyid(uint64_t keyid)
-{
-       struct openpgp_publickey *publickey = NULL;
-
-       if (loaded_backend == NULL) {
-               load_backend();
-       }
-       
-       if (loaded_backend != NULL) {
-               if (loaded_backend->getfullkeyid != NULL) {
-                       return loaded_backend->getfullkeyid(keyid);
-               }
+       if (config.use_keyd) {
+               free(config.db_backend);
+               config.db_backend = strdup("keyd");
        }
 
-       if (keyid < 0x100000000LL) {
-               dynamic_fetch_key_id(keyid, &publickey, false);
-               if (publickey != NULL) {
-                       get_keyid(publickey, &keyid);
-                       free_publickey(publickey);
-                       publickey = NULL;
-               } else {
-                       keyid = 0;
-               }
+       if (!config.db_backend) {
+               logthing(LOGTHING_CRITICAL, "No database backend defined.");
+               exit(EXIT_FAILURE);
        }
-       
-       return keyid;
-}
 
-/**
- *     update_keys - Takes a list of public keys and updates them in the DB.
- *     @keys: The keys to update in the DB.
- *     @sendsync: Should we send a sync mail to our peers.
- *
- *     Takes a list of keys and adds them to the database, merging them with
- *     the key in the database if it's already present there. The key list is
- *     update to contain the minimum set of updates required to get from what
- *     we had before to what we have now (ie the set of data that was added to
- *     the DB). Returns the number of entirely new keys added.
- */
-static int dynamic_update_keys(struct openpgp_publickey **keys, bool sendsync)
-{
-       struct openpgp_publickey *curkey = NULL;
-       struct openpgp_publickey *oldkey = NULL;
-       struct openpgp_publickey *prev = NULL;
-       int newkeys = 0;
-       bool intrans;
-       uint64_t keyid;
-       
-       if (loaded_backend == NULL) {
-               load_backend();
-       }
-       
-       if (loaded_backend != NULL) {
-               if (loaded_backend->update_keys != NULL) {
-                       return loaded_backend->update_keys(keys, sendsync);
-               }
-       }
+       if (config.backends_dir == NULL) {
+               soname = malloc(strlen(config.db_backend)
+                       + strlen("./libkeydb_")
+                       + strlen(".so")
+                       + 1);
 
-       for (curkey = *keys; curkey != NULL; curkey = curkey->next) {
-               intrans = dynamic_starttrans();
-               get_keyid(curkey, &keyid);
-               logthing(LOGTHING_INFO,
-                       "Fetching key 0x%" PRIX64 ", result: %d",
-                       keyid,
-                       dynamic_fetch_key_id(keyid, &oldkey, intrans));
-
-               /*
-                * If we already have the key stored in the DB then merge it
-                * with the new one that's been supplied. Otherwise the key
-                * we've just got is the one that goes in the DB and also the
-                * one that we send out.
-                */
-               if (oldkey != NULL) {
-                       merge_keys(oldkey, curkey);
-                       if (curkey->sigs == NULL &&
-                                       curkey->uids == NULL &&
-                                       curkey->subkeys == NULL) {
-                               if (prev == NULL) {
-                                       *keys = curkey->next;
-                               } else {
-                                       prev->next = curkey->next;
-                                       curkey->next = NULL;
-                                       free_publickey(curkey);
-                                       curkey = prev;
-                               }
-                       } else {
-                               prev = curkey;
-                               logthing(LOGTHING_INFO,
-                                       "Merged key; storing updated key.");
-                               dynamic_store_key(oldkey, intrans, true);
-                       }
-                       free_publickey(oldkey);
-                       oldkey = NULL;
-               
-               } else {
-                       logthing(LOGTHING_INFO,
-                               "Storing completely new key.");
-                       dynamic_store_key(curkey, intrans, false);
-                       newkeys++;
-               }
-               dynamic_endtrans();
-               intrans = false;
-       }
+               sprintf(soname, "./libkeydb_%s.so", config.db_backend);
+       } else {
+               soname = malloc(strlen(config.db_backend)
+                       + strlen("/libkeydb_")
+                       + strlen(".so")
+                       + strlen(config.backends_dir)
+                       + 1);
 
-       if (sendsync && keys != NULL) {
-               sendkeysync(*keys);
+               sprintf(soname, "%s/libkeydb_%s.so", config.backends_dir,
+                       config.db_backend);
        }
 
-       return newkeys;
-}
+       logthing(LOGTHING_INFO, "Loading dynamic backend: %s", soname);
 
-static void dynamic_initdb(bool readonly)
-{
-       if (loaded_backend == NULL) {
-               load_backend();
+       privctx->backend_handle = dlopen(soname, RTLD_LAZY);
+       if (privctx->backend_handle == NULL) {
+               logthing(LOGTHING_CRITICAL,
+                               "Failed to open handle to library '%s': %s",
+                               soname, dlerror());
+               free(soname);
+               soname = NULL;
+               exit(EXIT_FAILURE);
        }
 
-       if (loaded_backend != NULL) {
-               if (loaded_backend->initdb != NULL) {
-                       loaded_backend->initdb(readonly);
-               }
-       }
-}
+       initname = malloc(strlen(config.db_backend)
+                       + strlen("keydb_")
+                       + strlen("_init")
+                       + 1);
+       sprintf(initname, "keydb_%s_init", config.db_backend);
 
-static void dynamic_cleanupdb(void)
-{
-       if (loaded_backend != NULL) {
-               if (loaded_backend->cleanupdb != NULL) {
-                       loaded_backend->cleanupdb();
-               }
+       *(void **) (&backend_init) = dlsym(privctx->backend_handle, initname);
+       free(initname);
+
+       if (backend_init == NULL) {
+               logthing(LOGTHING_CRITICAL,
+                               "Failed to find dbfuncs structure in library "
+                               "'%s' : %s", soname, dlerror());
+               free(soname);
+               soname = NULL;
+               exit(EXIT_FAILURE);
        }
+       free(soname);
+       soname = NULL;
 
-       close_backend();
+       privctx->loadeddbctx = backend_init(readonly);
+
+       if (privctx->loadeddbctx != NULL) {
+               dbctx->cleanupdb = dynamic_cleanupdb;
+               dbctx->starttrans = dynamic_starttrans;
+               dbctx->endtrans = dynamic_endtrans;
+               dbctx->fetch_key_id = dynamic_fetch_key_id;
+               dbctx->fetch_key_fp = dynamic_fetch_key_fp;
+               dbctx->fetch_key_text = dynamic_fetch_key_text;
+               dbctx->fetch_key_skshash = dynamic_fetch_key_skshash;
+               dbctx->store_key = dynamic_store_key;
+               dbctx->update_keys = dynamic_update_keys;
+               dbctx->delete_key = dynamic_delete_key;
+               dbctx->getkeysigs = dynamic_getkeysigs;
+               dbctx->cached_getkeysigs = dynamic_cached_getkeysigs;
+               dbctx->keyid2uid = dynamic_keyid2uid;
+               dbctx->getfullkeyid = dynamic_getfullkeyid;
+               dbctx->iterate_keys = dynamic_iterate_keys;
+       }
+
+       return dbctx;
 }
-
-struct dbfuncs keydb_dynamic_funcs = {
-       .initdb                 = dynamic_initdb,
-       .cleanupdb              = dynamic_cleanupdb,
-       .starttrans             = dynamic_starttrans,
-       .endtrans               = dynamic_endtrans,
-       .fetch_key_id           = dynamic_fetch_key_id,
-       .fetch_key_fp           = dynamic_fetch_key_fp,
-       .fetch_key_text         = dynamic_fetch_key_text,
-       .fetch_key_skshash      = dynamic_fetch_key_skshash,
-       .store_key              = dynamic_store_key,
-       .update_keys            = dynamic_update_keys,
-       .delete_key             = dynamic_delete_key,
-       .getkeysigs             = dynamic_getkeysigs,
-       .cached_getkeysigs      = dynamic_cached_getkeysigs,
-       .keyid2uid              = dynamic_keyid2uid,
-       .getfullkeyid           = dynamic_getfullkeyid,
-       .iterate_keys           = dynamic_iterate_keys,
-};
 
 #include "onak-conf.h"
 #include "parsekey.h"
 
-/**
- *     initdb - Initialize the key database.
- *
- *     This is just a no-op for flat file access.
- */
-static void file_initdb(bool readonly)
-{
-}
-
-/**
- *     cleanupdb - De-initialize the key database.
- *
- *     This is just a no-op for flat file access.
- */
-static void file_cleanupdb(void)
-{
-}
-
 /**
  *     starttrans - Start a transaction.
  *
  *     This is just a no-op for flat file access.
  */
-static bool file_starttrans(void)
+static bool file_starttrans(struct onak_dbctx *dbctx)
 {
        return true;
 }
  *
  *     This is just a no-op for flat file access.
  */
-static void file_endtrans(void)
+static void file_endtrans(struct onak_dbctx *dbctx)
 {
        return;
 }
  *     in and then parse_keys() to parse the packets into a publickey
  *     structure.
  */
-static int file_fetch_key_id(uint64_t keyid,
+static int file_fetch_key_id(struct onak_dbctx *dbctx,
+               uint64_t keyid,
                struct openpgp_publickey **publickey,
                bool intrans)
 {
+       char *db_dir = (char *) dbctx->priv;
        struct openpgp_packet_list *packets = NULL;
        char keyfile[1024];
        int fd = -1;
 
-       snprintf(keyfile, 1023, "%s/0x%" PRIX64, config.db_dir,
+       snprintf(keyfile, 1023, "%s/0x%" PRIX64, db_dir,
                        keyid & 0xFFFFFFFF);
        fd = open(keyfile, O_RDONLY); // | O_SHLOCK);
 
  *     packets and then use write_openpgp_stream() to write the stream out to
  *     the file.
  */
-static int file_store_key(struct openpgp_publickey *publickey, bool intrans,
+static int file_store_key(struct onak_dbctx *dbctx,
+               struct openpgp_publickey *publickey, bool intrans,
                bool update)
 {
+       char *db_dir = (char *) dbctx->priv;
        struct openpgp_packet_list *packets = NULL;
        struct openpgp_packet_list *list_end = NULL;
        struct openpgp_publickey *next = NULL;
                logthing(LOGTHING_ERROR, "Couldn't find key ID for key.");
                return 0;
        }
-       snprintf(keyfile, 1023, "%s/0x%" PRIX64, config.db_dir,
+       snprintf(keyfile, 1023, "%s/0x%" PRIX64, db_dir,
                        keyid & 0xFFFFFFFF);
        fd = open(keyfile, O_WRONLY | O_CREAT, 0664); // | O_EXLOCK);
 
  *     This function deletes a public key from whatever storage mechanism we
  *     are using. Returns 0 if the key existed.
  */
-static int file_delete_key(uint64_t keyid, bool intrans)
+static int file_delete_key(struct onak_dbctx *dbctx,
+               uint64_t keyid, bool intrans)
 {
+       char *db_dir = (char *) dbctx->priv;
        char keyfile[1024];
 
-       snprintf(keyfile, 1023, "%s/0x%" PRIX64, config.db_dir,
+       snprintf(keyfile, 1023, "%s/0x%" PRIX64, db_dir,
                        keyid & 0xFFFFFFFF);
 
        return unlink(keyfile);
  *
  *     TODO: Write for flat file access. Some sort of grep?
  */
-static int file_fetch_key_text(const char *search,
+static int file_fetch_key_text(struct onak_dbctx *dbctx,
+               const char *search,
                struct openpgp_publickey **publickey)
 {
        return 0;
  *
  *     Returns the number of keys we iterated over.
  */
-static int file_iterate_keys(void (*iterfunc)(void *ctx,
-               struct openpgp_publickey *key), void *ctx)
+static int file_iterate_keys(struct onak_dbctx *dbctx,
+               void (*iterfunc)(void *ctx, struct openpgp_publickey *key),
+               void *ctx)
 {
+       char *db_dir = (char *) dbctx->priv;
        int                         numkeys = 0;
        struct openpgp_packet_list *packets = NULL;
        struct openpgp_publickey   *key = NULL;
        int                         fd = -1;
        struct dirent              *curfile = NULL;
 
-       dir = opendir(config.db_dir);
+       dir = opendir(db_dir);
 
        if (dir != NULL) {
                while ((curfile = readdir(dir)) != NULL) {
                        if (curfile->d_name[0] == '0' &&
                                        curfile->d_name[1] == 'x') {
                                snprintf(keyfile, 1023, "%s/%s",
-                                               config.db_dir,
+                                               db_dir,
                                                curfile->d_name);
                                fd = open(keyfile, O_RDONLY);
 
 #define NEED_GET_FP 1
 #include "keydb.c"
 
-struct dbfuncs keydb_file_funcs = {
-       .initdb                 = file_initdb,
-       .cleanupdb              = file_cleanupdb,
-       .starttrans             = file_starttrans,
-       .endtrans               = file_endtrans,
-       .fetch_key_id           = file_fetch_key_id,
-       .fetch_key_fp           = generic_fetch_key_fp,
-       .fetch_key_text         = file_fetch_key_text,
-       .store_key              = file_store_key,
-       .update_keys            = generic_update_keys,
-       .delete_key             = file_delete_key,
-       .getkeysigs             = generic_getkeysigs,
-       .cached_getkeysigs      = generic_cached_getkeysigs,
-       .keyid2uid              = generic_keyid2uid,
-       .getfullkeyid           = generic_getfullkeyid,
-       .iterate_keys           = file_iterate_keys,
-};
+/**
+ *     cleanupdb - De-initialize the key database.
+ *
+ *     This is just a no-op for flat file access.
+ */
+static void file_cleanupdb(struct onak_dbctx *dbctx)
+{
+       if (dbctx->priv != NULL) {
+               free(dbctx->priv);
+               dbctx->priv = NULL;
+       }
+
+       if (dbctx != NULL) {
+               free(dbctx);
+       }
+}
+
+/**
+ *     initdb - Initialize the key database.
+ *
+ *     This is just a no-op for flat file access.
+ */
+struct onak_dbctx *keydb_file_init(bool readonly)
+{
+       struct onak_dbctx *dbctx;
+
+       dbctx = malloc(sizeof(struct onak_dbctx));
+       if (dbctx == NULL) {
+               return NULL;
+       }
+
+       dbctx->priv = strdup(config.db_dir);
+
+       dbctx->cleanupdb                = file_cleanupdb;
+       dbctx->starttrans               = file_starttrans;
+       dbctx->endtrans                 = file_endtrans;
+       dbctx->fetch_key_id             = file_fetch_key_id;
+       dbctx->fetch_key_fp             = generic_fetch_key_fp;
+       dbctx->fetch_key_text           = file_fetch_key_text;
+       dbctx->store_key                = file_store_key;
+       dbctx->update_keys              = generic_update_keys;
+       dbctx->delete_key               = file_delete_key;
+       dbctx->getkeysigs               = generic_getkeysigs;
+       dbctx->cached_getkeysigs        = generic_cached_getkeysigs;
+       dbctx->keyid2uid                = generic_keyid2uid;
+       dbctx->getfullkeyid             = generic_getfullkeyid;
+       dbctx->iterate_keys             = file_iterate_keys;
+
+       return dbctx;
+}
 
 #define PATH_MAX 1024
 #endif
 
-static int keydb_lockfile_fd = -1;
-static bool keydb_lockfile_readonly;
+struct onak_fs_dbctx {
+       int lockfile_fd;
+       bool lockfile_readonly;
+};
 
 /*****************************************************************************/
 
 
 /*****************************************************************************/
 
-/**
- *     initdb - Initialize the key database.
- */
-static void fs_initdb(bool readonly)
-{
-       char buffer[PATH_MAX];
-
-       keydb_lockfile_readonly = readonly;
-
-       snprintf(buffer, sizeof(buffer), "%s/.lock", config.db_dir);
-
-       if (access(config.db_dir, R_OK | W_OK | X_OK) == -1) {
-               if (errno != ENOENT) {
-                       logthing(LOGTHING_CRITICAL,
-                                "Unable to access keydb_fs root of '%s'. (%s)",
-                                config.db_dir, strerror(errno));
-                       exit(1);        /* Lacking rwx on the key dir */
-               }
-               mkdir(config.db_dir, 0777);
-               keydb_lockfile_fd = open(buffer, O_RDWR | O_CREAT, 0600);
-       }
-       chdir(config.db_dir);
-       if (keydb_lockfile_fd == -1)
-               keydb_lockfile_fd = open(buffer,
-                                        (keydb_lockfile_readonly) ?
-                                        O_RDONLY : O_RDWR);
-       if (keydb_lockfile_fd == -1)
-               keydb_lockfile_fd = open(buffer, O_RDWR | O_CREAT, 0600);
-       if (keydb_lockfile_fd == -1) {
-               logthing(LOGTHING_CRITICAL,
-                        "Unable to open lockfile '%s'. (%s)",
-                        buffer, strerror(errno));
-               exit(1);        /* Lacking rwx on the key dir */
-       }
-}
-
-/**
- *     cleanupdb - De-initialize the key database.
- */
-static void fs_cleanupdb(void)
-{
-       /* Mmmm nothing to do here? */
-       close(keydb_lockfile_fd);
-}
-
 /**
  *     starttrans - Start a transaction.
  */
-static bool fs_starttrans(void)
+static bool fs_starttrans(struct onak_dbctx *dbctx)
 {
+       struct onak_fs_dbctx *privctx = (struct onak_fs_dbctx *) dbctx->priv;
        struct flock lockstruct;
        int remaining = 20;
        lockstruct.l_type =
-           F_RDLCK | ((keydb_lockfile_readonly) ? 0 : F_WRLCK);
+           F_RDLCK | ((privctx->lockfile_readonly) ? 0 : F_WRLCK);
        lockstruct.l_whence = SEEK_SET;
        lockstruct.l_start = 0;
        lockstruct.l_len = 1;
 
-       while (fcntl(keydb_lockfile_fd, F_SETLK, &lockstruct) == -1) {
+       while (fcntl(privctx->lockfile_fd, F_SETLK, &lockstruct) == -1) {
                if (remaining-- == 0)
                        return false;   /* Hope to hell that noodles DTRT */
                usleep(100);
 /**
  *     endtrans - End a transaction.
  */
-static void fs_endtrans(void)
+static void fs_endtrans(struct onak_dbctx *dbctx)
 {
+       struct onak_fs_dbctx *privctx = (struct onak_fs_dbctx *) dbctx->priv;
        struct flock lockstruct;
 
        lockstruct.l_type = F_UNLCK;
        lockstruct.l_whence = SEEK_SET;
        lockstruct.l_start = 0;
        lockstruct.l_len = 1;
-       fcntl(keydb_lockfile_fd, F_SETLK, &lockstruct);
+       fcntl(privctx->lockfile_fd, F_SETLK, &lockstruct);
 }
 
-static uint64_t fs_getfullkeyid(uint64_t keyid)
+static uint64_t fs_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid)
 {
        static char buffer[PATH_MAX];
        DIR *d = NULL;
  *     @publickey: A pointer to a structure to return the key in.
  *     @intrans: If we're already in a transaction.
  */
-static int fs_fetch_key_id(uint64_t keyid,
+static int fs_fetch_key_id(struct onak_dbctx *dbctx,
+             uint64_t keyid,
              struct openpgp_publickey **publickey,
              bool intrans)
 {
        struct openpgp_packet_list *packets = NULL;
 
        if (!intrans)
-               fs_starttrans();
+               fs_starttrans(dbctx);
 
        if ((keyid >> 32) == 0)
-               keyid = fs_getfullkeyid(keyid);
+               keyid = fs_getfullkeyid(dbctx, keyid);
 
        keypath(buffer, sizeof(buffer), keyid);
        if ((fd = open(buffer, O_RDONLY)) != -1) {
        }
 
        if (!intrans)
-               fs_endtrans();
+               fs_endtrans(dbctx);
        return ret;
 }
 
  *     @intrans: If we're already in a transaction.
  *     @update: If true the key exists and should be updated.
  */
-static int fs_store_key(struct openpgp_publickey *publickey, bool intrans,
+static int fs_store_key(struct onak_dbctx *dbctx,
+             struct openpgp_publickey *publickey, bool intrans,
              bool update)
 {
        static char buffer[PATH_MAX];
        }
 
        if (!intrans)
-               fs_starttrans();
+               fs_starttrans(dbctx);
 
        prove_path_to(keyid, "key");
        keypath(buffer, sizeof(buffer), keyid);
        }
 
        if (!intrans)
-               fs_endtrans();
+               fs_endtrans(dbctx);
        return ret;
 }
 
  *     @keyid: The keyid to delete.
  *     @intrans: If we're already in a transaction.
  */
-static int fs_delete_key(uint64_t keyid, bool intrans)
+static int fs_delete_key(struct onak_dbctx *dbctx, uint64_t keyid, bool intrans)
 {
        static char buffer[PATH_MAX];
        int ret;
        int i = 0;
 
        if ((keyid >> 32) == 0)
-               keyid = fs_getfullkeyid(keyid);
+               keyid = fs_getfullkeyid(dbctx, keyid);
 
        if (!intrans)
-               fs_starttrans();
+               fs_starttrans(dbctx);
 
-       ret = fs_fetch_key_id(keyid, &pk, true);
+       ret = fs_fetch_key_id(dbctx, keyid, &pk, true);
 
        if (ret) {
                logthing(LOGTHING_DEBUG, "Wordlist for key %016" PRIX64,
        unlink(buffer);
 
        if (!intrans)
-               fs_endtrans();
+               fs_endtrans(dbctx);
        return 1;
 }
 
  *     @search: The text to search for.
  *     @publickey: A pointer to a structure to return the key in.
  */
-static int fs_fetch_key_text(const char *search,
+static int fs_fetch_key_text(struct onak_dbctx *dbctx,
+                  const char *search,
                   struct openpgp_publickey **publickey)
 {
        struct ll *wordlist = NULL, *wl = NULL;
        while (wl) {
                logthing(LOGTHING_DEBUG, "Adding key: %s", wl->object);
                addedkeys +=
-                   fs_fetch_key_id(strtoull(wl->object, NULL, 16), publickey,
+                   fs_fetch_key_id(dbctx,
+                             strtoull(wl->object, NULL, 16), publickey,
                              false);
                if (addedkeys >= config.maxkeys)
                        break;
  *     @publickey: A pointer to a structure to return the key in.
  *     @intrans: If we're already in a transaction.
  */
-static int fs_fetch_key_skshash(const struct skshash *hash,
+static int fs_fetch_key_skshash(struct onak_dbctx *dbctx,
+             const struct skshash *hash,
              struct openpgp_publickey **publickey)
 {
        static char buffer[PATH_MAX];
  *
  *     Returns the number of keys we iterated over.
  */
-static int fs_iterate_keys(void (*iterfunc)(void *ctx,
+static int fs_iterate_keys(struct onak_dbctx *dbctx,
+               void (*iterfunc)(void *ctx,
                struct openpgp_publickey *key), void *ctx)
 {
        return 0;
 #define NEED_GET_FP 1
 #include "keydb.c"
 
-struct dbfuncs keydb_fs_funcs = {
-       .initdb                 = fs_initdb,
-       .cleanupdb              = fs_cleanupdb,
-       .starttrans             = fs_starttrans,
-       .endtrans               = fs_endtrans,
-       .fetch_key_id           = fs_fetch_key_id,
-       .fetch_key_fp           = generic_fetch_key_fp,
-       .fetch_key_text         = fs_fetch_key_text,
-       .fetch_key_skshash      = fs_fetch_key_skshash,
-       .store_key              = fs_store_key,
-       .update_keys            = generic_update_keys,
-       .delete_key             = fs_delete_key,
-       .getkeysigs             = generic_getkeysigs,
-       .cached_getkeysigs      = generic_cached_getkeysigs,
-       .keyid2uid              = generic_keyid2uid,
-       .getfullkeyid           = fs_getfullkeyid,
-       .iterate_keys           = fs_iterate_keys,
-};
+/**
+ *     cleanupdb - De-initialize the key database.
+ */
+static void fs_cleanupdb(struct onak_dbctx *dbctx)
+{
+       struct onak_fs_dbctx *privctx = (struct onak_fs_dbctx *) dbctx->priv;
+
+       /* Mmmm nothing to do here? */
+       close(privctx->lockfile_fd);
+}
+
+/**
+ *     initdb - Initialize the key database.
+ */
+struct onak_dbctx *keydb_fs_init(bool readonly)
+{
+       char buffer[PATH_MAX];
+       struct onak_dbctx *dbctx;
+       struct onak_fs_dbctx *privctx;
+
+       dbctx = malloc(sizeof(struct onak_dbctx));
+       if (dbctx == NULL) {
+               return NULL;
+       }
+       dbctx->priv = privctx = malloc(sizeof(*privctx));
+       if (privctx == NULL) {
+               free(dbctx);
+               return NULL;
+       }
+
+       privctx->lockfile_readonly = readonly;
+
+       snprintf(buffer, sizeof(buffer), "%s/.lock", config.db_dir);
+
+       if (access(config.db_dir, R_OK | W_OK | X_OK) == -1) {
+               if (errno != ENOENT) {
+                       logthing(LOGTHING_CRITICAL,
+                                "Unable to access keydb_fs root of '%s'. (%s)",
+                                config.db_dir, strerror(errno));
+                       exit(1);        /* Lacking rwx on the key dir */
+               }
+               mkdir(config.db_dir, 0777);
+               privctx->lockfile_fd = open(buffer, O_RDWR | O_CREAT, 0600);
+       }
+       chdir(config.db_dir);
+       if (privctx->lockfile_fd == -1)
+               privctx->lockfile_fd = open(buffer,
+                                        (privctx->lockfile_readonly) ?
+                                        O_RDONLY : O_RDWR);
+       if (privctx->lockfile_fd == -1)
+               privctx->lockfile_fd = open(buffer, O_RDWR | O_CREAT, 0600);
+       if (privctx->lockfile_fd == -1) {
+               logthing(LOGTHING_CRITICAL,
+                        "Unable to open lockfile '%s'. (%s)",
+                        buffer, strerror(errno));
+               exit(1);        /* Lacking rwx on the key dir */
+       }
+
+       dbctx->cleanupdb                = fs_cleanupdb;
+       dbctx->starttrans               = fs_starttrans;
+       dbctx->endtrans                 = fs_endtrans;
+       dbctx->fetch_key_id             = fs_fetch_key_id;
+       dbctx->fetch_key_fp             = generic_fetch_key_fp;
+       dbctx->fetch_key_text           = fs_fetch_key_text;
+       dbctx->fetch_key_skshash        = fs_fetch_key_skshash;
+       dbctx->store_key                = fs_store_key;
+       dbctx->update_keys              = generic_update_keys;
+       dbctx->delete_key               = fs_delete_key;
+       dbctx->getkeysigs               = generic_getkeysigs;
+       dbctx->cached_getkeysigs        = generic_cached_getkeysigs;
+       dbctx->keyid2uid                = generic_keyid2uid;
+       dbctx->getfullkeyid             = fs_getfullkeyid;
+       dbctx->iterate_keys             = fs_iterate_keys;
+
+       return dbctx;
+}
 
 #include "parsekey.h"
 #include "version.h"
 
-static CURL *curl = NULL;
-
-static char hkpbase[1024];
+struct onak_hkp_dbctx {
+       CURL *curl;
+       char hkpbase[1024];
+};
 
-static int hkp_parse_url(const char *url)
+static int hkp_parse_url(struct onak_hkp_dbctx *privctx, const char *url)
 {
        char proto[6], host[256];
        unsigned int port;
                if (port == 0) {
                        port = 11371;
                }
-               snprintf(hkpbase, sizeof(hkpbase),
+               snprintf(privctx->hkpbase, sizeof(privctx->hkpbase),
                        "http://%s:%u/pks", host, port);
        } else if (!strcmp(proto, "hkps")) {
                if (port == 0) {
                        port = 11372;
                }
-               snprintf(hkpbase, sizeof(hkpbase),
+               snprintf(privctx->hkpbase, sizeof(privctx->hkpbase),
                        "https://%s:%u/pks", host, port);
        } else if (strcmp(proto, "http") && strcmp(proto, "https")) {
                logthing(LOGTHING_CRITICAL, "Unknown HKP protocol: %s",
                ret = 0;
                goto out;
        } else if (port == 0) {
-               snprintf(hkpbase, sizeof(hkpbase),
+               snprintf(privctx->hkpbase, sizeof(privctx->hkpbase),
                        "%s://%s/pks", proto, host);
        } else {
-               snprintf(hkpbase, sizeof(hkpbase),
+               snprintf(privctx->hkpbase, sizeof(privctx->hkpbase),
                        "%s://%s:%u/pks", proto, host, port);
        }
 
        return ret;
 }
 
-/**
- *     cleanupdb - De-initialize the key database.
- *
- *     We cleanup CURL here.
- */
-static void hkp_cleanupdb(void)
-{
-       if (curl) {
-               curl_easy_cleanup(curl);
-               curl = NULL;
-       }
-       curl_global_cleanup();
-}
-
-/**
- *     initdb - Initialize the key database.
- *
- *     We initialize CURL here.
- */
-static void hkp_initdb(bool readonly)
-{
-       curl_version_info_data *curl_info;
-
-       if (!hkp_parse_url(config.db_dir)) {
-               exit(EXIT_FAILURE);
-       }
-       curl_global_init(CURL_GLOBAL_DEFAULT);
-       curl = curl_easy_init();
-       if (curl == NULL) {
-               logthing(LOGTHING_CRITICAL, "Could not initialize CURL.");
-               exit(EXIT_FAILURE);
-       }
-       curl_easy_setopt(curl, CURLOPT_USERAGENT, "onak/" ONAK_VERSION);
-
-       if (strncmp(hkpbase, "https://", 8) == 0) {
-               curl_info = curl_version_info(CURLVERSION_NOW);
-               if (! (curl_info->features & CURL_VERSION_SSL)) {
-                       logthing(LOGTHING_CRITICAL,
-                               "CURL lacks SSL support; cannot use HKP url: %s",
-                               hkpbase);
-                       hkp_cleanupdb();
-                       exit(EXIT_FAILURE);
-               }
-       }
-}
-
 /**
  *     Receive data from a CURL request and process it into a buffer context.
  */
        return (nmemb * size);
 }
 
-static int hkp_fetch_key_url(char *url,
+static int hkp_fetch_key_url(struct onak_dbctx *dbctx,
+               char *url,
                struct openpgp_publickey **publickey,
                bool intrans)
 {
+       struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv;
        struct openpgp_packet_list *packets = NULL;
        CURLcode res;
        struct buffer_ctx buf;
        buf.size = 8192;
        buf.buffer = malloc(8192);
 
-       curl_easy_setopt(curl, CURLOPT_URL, url);
-       curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
+       curl_easy_setopt(privctx->curl, CURLOPT_URL, url);
+       curl_easy_setopt(privctx->curl, CURLOPT_WRITEFUNCTION,
                        hkp_curl_recv_data);
-       curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf);
-       res = curl_easy_perform(curl);
+       curl_easy_setopt(privctx->curl, CURLOPT_WRITEDATA, &buf);
+       res = curl_easy_perform(privctx->curl);
 
        if (res == 0) {
                buf.offset = 0;
 /**
  *     hkp_fetch_key_id - Given a keyid fetch the key from HKP server.
  */
-static int hkp_fetch_key_id(uint64_t keyid,
+static int hkp_fetch_key_id(struct onak_dbctx *dbctx,
+               uint64_t keyid,
                struct openpgp_publickey **publickey,
                bool intrans)
 {
+       struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv;
        char keyurl[1024];
 
        snprintf(keyurl, sizeof(keyurl),
                        "%s/lookup?op=get&search=0x%08" PRIX64,
-                       hkpbase, keyid);
+                       privctx->hkpbase, keyid);
 
-       return (hkp_fetch_key_url(keyurl, publickey, intrans));
+       return (hkp_fetch_key_url(dbctx, keyurl, publickey, intrans));
 }
 
 /**
  *     hkp_fetch_key_fp - Given a fingerprint fetch the key from HKP server.
  */
-static int hkp_fetch_key_fp(uint8_t *fp, size_t fpsize,
+static int hkp_fetch_key_fp(struct onak_dbctx *dbctx,
+               uint8_t *fp, size_t fpsize,
                struct openpgp_publickey **publickey,
                bool intrans)
 {
+       struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv;
        char keyurl[1024];
        int i, ofs;
 
        }
 
        ofs = snprintf(keyurl, sizeof(keyurl),
-                       "%s/lookup?op=get&search=0x", hkpbase);
+                       "%s/lookup?op=get&search=0x", privctx->hkpbase);
 
        if ((ofs + fpsize * 2 + 1)> sizeof(keyurl)) {
                return 0;
                ofs += sprintf(&keyurl[ofs], "%02X", fp[i]);
        }
 
-       return (hkp_fetch_key_url(keyurl, publickey, intrans));
+       return (hkp_fetch_key_url(dbctx, keyurl, publickey, intrans));
 }
 
 /**
  *
  *     TODO: Write for flat file access. Some sort of grep?
  */
-static int hkp_fetch_key_text(const char *search,
+static int hkp_fetch_key_text(struct onak_dbctx *dbctx,
+               const char *search,
                struct openpgp_publickey **publickey)
 {
+       struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv;
        char keyurl[1024];
 
        snprintf(keyurl, sizeof(keyurl),
                        "%s/lookup?op=get&search=%s",
-                       hkpbase, search);
+                       privctx->hkpbase, search);
 
-       return (hkp_fetch_key_url(keyurl, publickey, false));
+       return (hkp_fetch_key_url(dbctx, keyurl, publickey, false));
 }
 
 /**
  *     @update: If true the key exists and should be updated.
  *
  */
-static int hkp_store_key(struct openpgp_publickey *publickey, bool intrans,
+static int hkp_store_key(struct onak_dbctx *dbctx,
+               struct openpgp_publickey *publickey, bool intrans,
                bool update)
 {
+       struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv;
        struct openpgp_packet_list *packets = NULL;
        struct openpgp_packet_list *list_end = NULL;
        char keyurl[1024];
 
        flatten_publickey(publickey, &packets, &list_end);
        armor_openpgp_stream(buffer_putchar, &buf, packets);
-       addform = curl_easy_escape(curl, buf.buffer, buf.offset);
+       addform = curl_easy_escape(privctx->curl, buf.buffer, buf.offset);
        addform[7] = '=';
 
-       snprintf(keyurl, sizeof(keyurl), "%s/add", hkpbase);
+       snprintf(keyurl, sizeof(keyurl), "%s/add", privctx->hkpbase);
 
-       curl_easy_setopt(curl, CURLOPT_URL, keyurl);
-       curl_easy_setopt(curl, CURLOPT_POSTFIELDS, addform);
-       curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
+       curl_easy_setopt(privctx->curl, CURLOPT_URL, keyurl);
+       curl_easy_setopt(privctx->curl, CURLOPT_POSTFIELDS, addform);
+       curl_easy_setopt(privctx->curl, CURLOPT_WRITEFUNCTION,
                        hkp_curl_recv_data);
        buf.offset = 0;
-       curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf);
-       res = curl_easy_perform(curl);
+       curl_easy_setopt(privctx->curl, CURLOPT_WRITEDATA, &buf);
+       res = curl_easy_perform(privctx->curl);
 
        if (res != 0) {
                logthing(LOGTHING_ERROR, "Couldn't send key: %s (%d)",
  *
  *     No op for HKP.
  */
-static int hkp_delete_key(uint64_t keyid, bool intrans)
+static int hkp_delete_key(struct onak_dbctx *dbctx,
+               uint64_t keyid, bool intrans)
 {
        return -1;
 }
  *
  *     Not applicable for HKP backend.
  */
-static int hkp_iterate_keys(void (*iterfunc)(void *ctx,
-               struct openpgp_publickey *key), void *ctx)
+static int hkp_iterate_keys(struct onak_dbctx *dbctx,
+               void (*iterfunc)(void *ctx, struct openpgp_publickey *key),
+               void *ctx)
 {
        return 0;
 }
  *
  *     This is just a no-op for HKP access.
  */
-static bool hkp_starttrans(void)
+static bool hkp_starttrans(struct onak_dbctx *dbctx)
 {
        return true;
 }
  *
  *     This is just a no-op for HKP access.
  */
-static void hkp_endtrans(void)
+static void hkp_endtrans(struct onak_dbctx *dbctx)
 {
        return;
 }
 #define NEED_UPDATEKEYS 1
 #include "keydb.c"
 
-struct dbfuncs keydb_hkp_funcs = {
-       .initdb                 = hkp_initdb,
-       .cleanupdb              = hkp_cleanupdb,
-       .starttrans             = hkp_starttrans,
-       .endtrans               = hkp_endtrans,
-       .fetch_key_id           = hkp_fetch_key_id,
-       .fetch_key_fp           = hkp_fetch_key_fp,
-       .fetch_key_text         = hkp_fetch_key_text,
-       .store_key              = hkp_store_key,
-       .update_keys            = generic_update_keys,
-       .delete_key             = hkp_delete_key,
-       .getkeysigs             = generic_getkeysigs,
-       .cached_getkeysigs      = generic_cached_getkeysigs,
-       .keyid2uid              = generic_keyid2uid,
-       .getfullkeyid           = generic_getfullkeyid,
-       .iterate_keys           = hkp_iterate_keys,
-};
+/**
+ *     cleanupdb - De-initialize the key database.
+ *
+ *     We cleanup CURL here.
+ */
+static void hkp_cleanupdb(struct onak_dbctx *dbctx)
+{
+       struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv;
+
+       if (privctx->curl) {
+               curl_easy_cleanup(privctx->curl);
+               privctx->curl = NULL;
+       }
+       curl_global_cleanup();
+       free(privctx);
+       free(dbctx);
+}
+
+/**
+ *     initdb - Initialize the key database.
+ *
+ *     We initialize CURL here.
+ */
+struct onak_dbctx *keydb_hkp_init(bool readonly)
+{
+       struct onak_dbctx *dbctx;
+       struct onak_hkp_dbctx *privctx;
+       curl_version_info_data *curl_info;
+
+       dbctx = malloc(sizeof(struct onak_dbctx));
+       if (dbctx == NULL) {
+               return NULL;
+       }
+
+       dbctx->priv = privctx = malloc(sizeof(*privctx));
+       dbctx->cleanupdb                = hkp_cleanupdb;
+       dbctx->starttrans               = hkp_starttrans;
+       dbctx->endtrans                 = hkp_endtrans;
+       dbctx->fetch_key_id             = hkp_fetch_key_id;
+       dbctx->fetch_key_fp             = hkp_fetch_key_fp;
+       dbctx->fetch_key_text           = hkp_fetch_key_text;
+       dbctx->store_key                = hkp_store_key;
+       dbctx->update_keys              = generic_update_keys;
+       dbctx->delete_key               = hkp_delete_key;
+       dbctx->getkeysigs               = generic_getkeysigs;
+       dbctx->cached_getkeysigs        = generic_cached_getkeysigs;
+       dbctx->keyid2uid                = generic_keyid2uid;
+       dbctx->getfullkeyid             = generic_getfullkeyid;
+       dbctx->iterate_keys             = hkp_iterate_keys;
+
+       if (!hkp_parse_url(privctx, config.db_dir)) {
+               exit(EXIT_FAILURE);
+       }
+       curl_global_init(CURL_GLOBAL_DEFAULT);
+       privctx->curl = curl_easy_init();
+       if (privctx->curl == NULL) {
+               logthing(LOGTHING_CRITICAL, "Could not initialize CURL.");
+               hkp_cleanupdb(dbctx);
+               dbctx = NULL;
+               exit(EXIT_FAILURE);
+       }
+       curl_easy_setopt(privctx->curl, CURLOPT_USERAGENT,
+               "onak/" ONAK_VERSION);
+
+       if (strncmp(privctx->hkpbase, "https://", 8) == 0) {
+               curl_info = curl_version_info(CURLVERSION_NOW);
+               if (! (curl_info->features & CURL_VERSION_SSL)) {
+                       logthing(LOGTHING_CRITICAL,
+                               "CURL lacks SSL support; cannot use HKP url: %s",
+                               privctx->hkpbase);
+                       hkp_cleanupdb(dbctx);
+                       dbctx = NULL;
+                       exit(EXIT_FAILURE);
+               }
+       }
+
+       return dbctx;
+}
 
 #include "onak-conf.h"
 #include "parsekey.h"
 
-/**
- *     keyd_fd - our file descriptor for the socket connection to keyd.
- */
-static int keyd_fd = -1;
-
-/**
- *     initdb - Initialize the key database.
- *     @readonly: If we'll only be reading the DB, not writing to it.
- *
- *     This function should be called before any of the other functions in
- *     this file are called in order to allow the DB to be initialized ready
- *     for access.
- */
-static void keyd_initdb(bool readonly)
-{
-       struct sockaddr_un sock;
-       uint32_t           cmd = KEYD_CMD_UNKNOWN;
-       uint32_t           reply = KEYD_REPLY_UNKNOWN_CMD;
-       ssize_t            count;
-
-       keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
-       if (keyd_fd < 0) {
-               logthing(LOGTHING_CRITICAL,
-                               "Couldn't open socket: %s (%d)",
-                               strerror(errno),
-                               errno);
-               exit(EXIT_FAILURE);
-       }
-
-       sock.sun_family = AF_UNIX;
-       snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
-                       config.db_dir,
-                       KEYD_SOCKET);
-       if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
-               logthing(LOGTHING_CRITICAL,
-                               "Couldn't connect to socket %s: %s (%d)",
-                               sock.sun_path,
-                               strerror(errno),
-                               errno);
-               exit(EXIT_FAILURE);
-       }
-
-       cmd = KEYD_CMD_VERSION;
-       if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
-               logthing(LOGTHING_CRITICAL,
-                               "Couldn't write version cmd: %s (%d)",
-                               strerror(errno),
-                               errno);
-       } else {
-               count = read(keyd_fd, &reply, sizeof(reply));
-               if (count == sizeof(reply) && reply == KEYD_REPLY_OK) {
-                       count = read(keyd_fd, &reply, sizeof(reply));
-                       if (count != sizeof(reply) || reply != sizeof(reply)) {
-                               logthing(LOGTHING_CRITICAL,
-                                       "Error! Unexpected keyd version "
-                                       "length: %d != %d",
-                                       reply, sizeof(reply));
-                               exit(EXIT_FAILURE);
-                       }
-
-                       count = read(keyd_fd, &reply, sizeof(reply));
-                       logthing(LOGTHING_DEBUG,
-                                       "keyd protocol version %d",
-                                       reply);
-                       if (reply != keyd_version) {
-                               logthing(LOGTHING_CRITICAL,
-                                       "Error! keyd protocol version "
-                                       "mismatch. (us = %d, it = %d)",
-                                               keyd_version, reply);
-                       }
-               }
-       }
-
-       return;
-}
-
-/**
- *     cleanupdb - De-initialize the key database.
- *
- *     This function should be called upon program exit to allow the DB to
- *     cleanup after itself.
- */
-static void keyd_cleanupdb(void)
-{
-       uint32_t cmd = KEYD_CMD_CLOSE;
-
-       if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
-               logthing(LOGTHING_CRITICAL,
-                               "Couldn't send close cmd: %s (%d)",
-                               strerror(errno),
-                               errno);
-       }
-       
-       if (read(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
-               logthing(LOGTHING_CRITICAL,
-                       "Couldn't read close cmd reply: %s (%d)",
-                       strerror(errno),
-                       errno);
-       } else if (cmd != KEYD_REPLY_OK) {
-               logthing(LOGTHING_CRITICAL,
-                       "Got bad reply to KEYD_CMD_CLOSE: %d", cmd);
-       }
-
-       if (shutdown(keyd_fd, SHUT_RDWR) < 0) {
-               logthing(LOGTHING_NOTICE, "Error shutting down socket: %d",
-                               errno);
-       }
-       if (close(keyd_fd) < 0) {
-               logthing(LOGTHING_NOTICE, "Error closing down socket: %d",
-                               errno);
-       }
-       keyd_fd = -1;
-
-       return;
-}
-
-
 /**
  *     starttrans - Start a transaction.
  *
  *     operations on the database to help speed it all up, or if we want
  *     something to only succeed if all relevant operations are successful.
  */
-static bool keyd_starttrans(void)
+static bool keyd_starttrans(struct onak_dbctx *dbctx)
 {
        return true;
 }
  *
  *     Ends a transaction.
  */
-static void keyd_endtrans(void)
+static void keyd_endtrans(struct onak_dbctx *dbctx)
 {
        return;
 }
  *
  *      TODO: What about keyid collisions? Should we use fingerprint instead?
  */
-static int keyd_fetch_key_id(uint64_t keyid,
+static int keyd_fetch_key_id(struct onak_dbctx *dbctx,
+               uint64_t keyid,
                struct openpgp_publickey **publickey,
                bool intrans)
 {
+       int keyd_fd = (intptr_t) dbctx->priv;
        struct buffer_ctx           keybuf;
        struct openpgp_packet_list *packets = NULL;
        uint32_t                    cmd = KEYD_CMD_GET_ID;
        return (count > 0) ? 1 : 0;
 }
 
-static int keyd_fetch_key_fp(uint8_t *fp, size_t fpsize,
+static int keyd_fetch_key_fp(struct onak_dbctx *dbctx,
+               uint8_t *fp, size_t fpsize,
                struct openpgp_publickey **publickey,
                bool intrans)
 {
+       int keyd_fd = (intptr_t) dbctx->priv;
        struct buffer_ctx           keybuf;
        struct openpgp_packet_list *packets = NULL;
        uint32_t                    cmd = KEYD_CMD_GET_FP;
 *      This function deletes a public key from whatever storage mechanism we
 *      are using. Returns 0 if the key existed.
 */
-static int keyd_delete_key(uint64_t keyid, bool intrans)
+static int keyd_delete_key(struct onak_dbctx *dbctx,
+               uint64_t keyid, bool intrans)
 {
+       int keyd_fd = (intptr_t) dbctx->priv;
        uint32_t cmd = KEYD_CMD_DELETE;
 
        write(keyd_fd, &cmd, sizeof(cmd));
  *     TODO: Do we store multiple keys of the same id? Or only one and replace
  *     it?
  */
-static int keyd_store_key(struct openpgp_publickey *publickey, bool intrans,
+static int keyd_store_key(struct onak_dbctx *dbctx,
+               struct openpgp_publickey *publickey, bool intrans,
                bool update)
 {
+       int keyd_fd = (intptr_t) dbctx->priv;
        struct buffer_ctx           keybuf;
        struct openpgp_packet_list *packets = NULL;
        struct openpgp_packet_list *list_end = NULL;
                logthing(LOGTHING_ERROR, "Couldn't find key ID for key.");
                return 0;
        }
-       
+
        if (update) {
-               keyd_delete_key(keyid, false);
+               keyd_delete_key(dbctx, keyid, false);
        }
 
        write(keyd_fd, &cmd, sizeof(cmd));
                keybuf.buffer = NULL;
                keybuf.size = keybuf.offset = 0;
        }
-       
+
        return 0;
 }
 
  *     This function searches for the supplied text and returns the keys that
  *     contain it.
  */
-static int keyd_fetch_key_text(const char *search,
+static int keyd_fetch_key_text(struct onak_dbctx *dbctx,
+               const char *search,
                struct openpgp_publickey **publickey)
 {
+       int keyd_fd = (intptr_t) dbctx->priv;
        struct buffer_ctx           keybuf;
        struct openpgp_packet_list *packets = NULL;
        uint32_t                    cmd = KEYD_CMD_GET_TEXT;
                        keybuf.size = 0;
                }
        }
-       
+
        return (count > 0) ? 1 : 0;
 
        return 0;
 }
 
-static int keyd_fetch_key_skshash(const struct skshash *hash,
+static int keyd_fetch_key_skshash(struct onak_dbctx *dbctx,
+               const struct skshash *hash,
                struct openpgp_publickey **publickey)
 {
+       int keyd_fd = (intptr_t) dbctx->priv;
        struct buffer_ctx           keybuf;
        struct openpgp_packet_list *packets = NULL;
        uint32_t                    cmd = KEYD_CMD_GET_SKSHASH;
                        keybuf.size = 0;
                }
        }
-       
+
        return (count > 0) ? 1 : 0;
 }
 
  *     This function maps a 32bit key id to the full 64bit one. It returns the
  *     full keyid. If the key isn't found a keyid of 0 is returned.
  */
-static uint64_t keyd_getfullkeyid(uint64_t keyid)
+static uint64_t keyd_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid)
 {
+       int keyd_fd = (intptr_t) dbctx->priv;
        uint32_t cmd = KEYD_CMD_GETFULLKEYID;
 
        write(keyd_fd, &cmd, sizeof(cmd));
  *
  *     Returns the number of keys we iterated over.
  */
-static int keyd_iterate_keys(void (*iterfunc)(void *ctx,
+static int keyd_iterate_keys(struct onak_dbctx *dbctx,
+               void (*iterfunc)(void *ctx,
                struct openpgp_publickey *key), void *ctx)
 {
+       int keyd_fd = (intptr_t) dbctx->priv;
        struct buffer_ctx           keybuf;
        struct openpgp_packet_list *packets = NULL;
        struct openpgp_publickey   *key = NULL;
                        read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
                }
        }
-       
+
        return numkeys;
 }
 
 #define NEED_UPDATEKEYS 1
 #include "keydb.c"
 
-struct dbfuncs keydb_keyd_funcs = {
-       .initdb                 = keyd_initdb,
-       .cleanupdb              = keyd_cleanupdb,
-       .starttrans             = keyd_starttrans,
-       .endtrans               = keyd_endtrans,
-       .fetch_key_id           = keyd_fetch_key_id,
-       .fetch_key_fp           = keyd_fetch_key_fp,
-       .fetch_key_text         = keyd_fetch_key_text,
-       .fetch_key_skshash      = keyd_fetch_key_skshash,
-       .store_key              = keyd_store_key,
-       .update_keys            = generic_update_keys,
-       .delete_key             = keyd_delete_key,
-       .getkeysigs             = generic_getkeysigs,
-       .cached_getkeysigs      = generic_cached_getkeysigs,
-       .keyid2uid              = generic_keyid2uid,
-       .getfullkeyid           = keyd_getfullkeyid,
-       .iterate_keys           = keyd_iterate_keys,
-};
+/**
+ *     cleanupdb - De-initialize the key database.
+ *
+ *     This function should be called upon program exit to allow the DB to
+ *     cleanup after itself.
+ */
+static void keyd_cleanupdb(struct onak_dbctx *dbctx)
+{
+       int keyd_fd = (intptr_t) dbctx->priv;
+       uint32_t cmd = KEYD_CMD_CLOSE;
+
+       if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
+               logthing(LOGTHING_CRITICAL,
+                               "Couldn't send close cmd: %s (%d)",
+                               strerror(errno),
+                               errno);
+       }
+
+       if (read(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
+               logthing(LOGTHING_CRITICAL,
+                       "Couldn't read close cmd reply: %s (%d)",
+                       strerror(errno),
+                       errno);
+       } else if (cmd != KEYD_REPLY_OK) {
+               logthing(LOGTHING_CRITICAL,
+                       "Got bad reply to KEYD_CMD_CLOSE: %d", cmd);
+       }
+
+       if (shutdown(keyd_fd, SHUT_RDWR) < 0) {
+               logthing(LOGTHING_NOTICE, "Error shutting down socket: %d",
+                               errno);
+       }
+       if (close(keyd_fd) < 0) {
+               logthing(LOGTHING_NOTICE, "Error closing down socket: %d",
+                               errno);
+       }
+       keyd_fd = -1;
+
+       free(dbctx);
+
+       return;
+}
+
+/**
+ *     initdb - Initialize the key database.
+ *     @readonly: If we'll only be reading the DB, not writing to it.
+ *
+ *     This function should be called before any of the other functions in
+ *     this file are called in order to allow the DB to be initialized ready
+ *     for access.
+ */
+struct onak_dbctx *keydb_keyd_init(bool readonly)
+{
+       struct sockaddr_un sock;
+       uint32_t           cmd = KEYD_CMD_UNKNOWN;
+       uint32_t           reply = KEYD_REPLY_UNKNOWN_CMD;
+       ssize_t            count;
+       int keyd_fd;
+       struct onak_dbctx *dbctx;
+
+       dbctx = malloc(sizeof(*dbctx));
+       if (dbctx == NULL) {
+               return NULL;
+       }
+
+       keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
+       if (keyd_fd < 0) {
+               logthing(LOGTHING_CRITICAL,
+                               "Couldn't open socket: %s (%d)",
+                               strerror(errno),
+                               errno);
+               exit(EXIT_FAILURE);
+       }
+
+       sock.sun_family = AF_UNIX;
+       snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
+                       config.db_dir,
+                       KEYD_SOCKET);
+       if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
+               logthing(LOGTHING_CRITICAL,
+                               "Couldn't connect to socket %s: %s (%d)",
+                               sock.sun_path,
+                               strerror(errno),
+                               errno);
+               exit(EXIT_FAILURE);
+       }
+
+       cmd = KEYD_CMD_VERSION;
+       if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
+               logthing(LOGTHING_CRITICAL,
+                               "Couldn't write version cmd: %s (%d)",
+                               strerror(errno),
+                               errno);
+       } else {
+               count = read(keyd_fd, &reply, sizeof(reply));
+               if (count == sizeof(reply) && reply == KEYD_REPLY_OK) {
+                       count = read(keyd_fd, &reply, sizeof(reply));
+                       if (count != sizeof(reply) || reply != sizeof(reply)) {
+                               logthing(LOGTHING_CRITICAL,
+                                       "Error! Unexpected keyd version "
+                                       "length: %d != %d",
+                                       reply, sizeof(reply));
+                               exit(EXIT_FAILURE);
+                       }
+
+                       count = read(keyd_fd, &reply, sizeof(reply));
+                       logthing(LOGTHING_DEBUG,
+                                       "keyd protocol version %d",
+                                       reply);
+                       if (reply != keyd_version) {
+                               logthing(LOGTHING_CRITICAL,
+                                       "Error! keyd protocol version "
+                                       "mismatch. (us = %d, it = %d)",
+                                               keyd_version, reply);
+                       }
+               }
+       }
+
+       dbctx->priv                     = (void *) (intptr_t) keyd_fd;
+       dbctx->cleanupdb                = keyd_cleanupdb;
+       dbctx->starttrans               = keyd_starttrans;
+       dbctx->endtrans                 = keyd_endtrans;
+       dbctx->fetch_key_id             = keyd_fetch_key_id;
+       dbctx->fetch_key_fp             = keyd_fetch_key_fp;
+       dbctx->fetch_key_text           = keyd_fetch_key_text;
+       dbctx->fetch_key_skshash        = keyd_fetch_key_skshash;
+       dbctx->store_key                = keyd_store_key;
+       dbctx->update_keys              = generic_update_keys;
+       dbctx->delete_key               = keyd_delete_key;
+       dbctx->getkeysigs               = generic_getkeysigs;
+       dbctx->cached_getkeysigs        = generic_cached_getkeysigs;
+       dbctx->keyid2uid                = generic_keyid2uid;
+       dbctx->getfullkeyid             = keyd_getfullkeyid;
+       dbctx->iterate_keys             = keyd_iterate_keys;
+
+       return dbctx;
+}
 
 #include "onak-conf.h"
 #include "parsekey.h"
 
-/**
- *     dbconn - our connection to the database.
- */
-static PGconn *dbconn = NULL;
+struct pg_fc_ctx {
+       PGconn *dbconn;
+       int fd;
+};
 
 /**
  *     keydb_fetchchar - Fetches a char from a file.
  */
-static int keydb_fetchchar(void *fd, size_t count, void *c)
+static int keydb_fetchchar(void *_ctx, size_t count, void *c)
 {
-       return (!lo_read(dbconn, *(int *) fd, (char *) c, count));
-}
+       struct pg_fc_ctx *ctx = (struct pg_fc_ctx *) _ctx;
 
-/**
- *     keydb_putchar - Puts a char to a file.
- */
-static int keydb_putchar(void *fd, size_t count, void *c)
-{
-       return !(lo_write(dbconn, *(int *) fd, (char *) c, count));
+       return (!lo_read(ctx->dbconn, ctx->fd, (char *) c, count));
 }
 
 /**
- *     initdb - Initialize the key database.
- *
- *     This function should be called before any of the other functions in
- *     this file are called in order to allow the DB to be initialized ready
- *     for access.
+ *     keydb_putchar - Puts a char to a file.
  */
-static void pg_initdb(bool readonly)
+static int keydb_putchar(void *_ctx, size_t count, void *c)
 {
-       dbconn = PQsetdbLogin(config.pg_dbhost, // host
-                       NULL, // port
-                       NULL, // options
-                       NULL, // tty
-                       config.pg_dbname, // database
-                       config.pg_dbuser,  //login
-                       config.pg_dbpass); // password
+       struct pg_fc_ctx *ctx = (struct pg_fc_ctx *) _ctx;
 
-       if (PQstatus(dbconn) == CONNECTION_BAD) {
-               logthing(LOGTHING_CRITICAL, "Connection to database failed.");
-               logthing(LOGTHING_CRITICAL, "%s", PQerrorMessage(dbconn));
-               PQfinish(dbconn);
-               dbconn = NULL;
-               exit(1);
-       }
-}
-
-/**
- *     cleanupdb - De-initialize the key database.
- *
- *     This function should be called upon program exit to allow the DB to
- *     cleanup after itself.
- */
-static void pg_cleanupdb(void)
-{
-       PQfinish(dbconn);
-       dbconn = NULL;
+       return !(lo_write(ctx->dbconn, ctx->fd, (char *) c, count));
 }
 
 /**
  *     operations on the database to help speed it all up, or if we want
  *     something to only succeed if all relevant operations are successful.
  */
-static bool pg_starttrans(void)
+static bool pg_starttrans(struct onak_dbctx *dbctx)
 {
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
        
        result = PQexec(dbconn, "BEGIN");
  *
  *     Ends a transaction.
  */
-static void pg_endtrans(void)
+static void pg_endtrans(struct onak_dbctx *dbctx)
 {
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
 
        result = PQexec(dbconn, "COMMIT");
  *     in and then parse_keys() to parse the packets into a publickey
  *     structure.
  */
-static int pg_fetch_key_id(uint64_t keyid,
+static int pg_fetch_key_id(struct onak_dbctx *dbctx,
+               uint64_t keyid,
                struct openpgp_publickey **publickey,
                bool intrans)
 {
        struct openpgp_packet_list *packets = NULL;
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
        char *oids = NULL;
        char statement[1024];
-       int fd = -1;
        int i = 0;
        int numkeys = 0;
        Oid key_oid;
+       struct pg_fc_ctx fcctx;
 
        if (!intrans) {
                result = PQexec(dbconn, "BEGIN");
                        oids = PQgetvalue(result, i, 0);
                        key_oid = (Oid) atoi(oids);
 
-                       fd = lo_open(dbconn, key_oid, INV_READ);
-                       if (fd < 0) {
+                       fcctx.fd = lo_open(dbconn, key_oid, INV_READ);
+                       if (fcctx.fd < 0) {
                                logthing(LOGTHING_ERROR,
                                                "Can't open large object.");
                        } else {
-                               read_openpgp_stream(keydb_fetchchar, &fd,
+                               fcctx.dbconn = dbconn;
+                               read_openpgp_stream(keydb_fetchchar, &fcctx,
                                                &packets, 0);
                                parse_keys(packets, publickey);
-                               lo_close(dbconn, fd);
+                               lo_close(dbconn, fcctx.fd);
                                free_packet_list(packets);
                                packets = NULL;
                        }
  *     This function searches for the supplied text and returns the keys that
  *     contain it.
  */
-static int pg_fetch_key_text(const char *search,
+static int pg_fetch_key_text(struct onak_dbctx *dbctx,
+               const char *search,
                struct openpgp_publickey **publickey)
 {
        struct openpgp_packet_list *packets = NULL;
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
        char *oids = NULL;
        char statement[1024];
-       int fd = -1;
        int i = 0;
        int numkeys = 0;
        Oid key_oid;
        char *newsearch = NULL;
+       struct pg_fc_ctx fcctx;
 
        result = PQexec(dbconn, "BEGIN");
        PQclear(result);
                        oids = PQgetvalue(result, i, 0);
                        key_oid = (Oid) atoi(oids);
 
-                       fd = lo_open(dbconn, key_oid, INV_READ);
-                       if (fd < 0) {
+                       fcctx.fd = lo_open(dbconn, key_oid, INV_READ);
+                       if (fcctx.fd < 0) {
                                logthing(LOGTHING_ERROR,
                                                "Can't open large object.");
                        } else {
-                               read_openpgp_stream(keydb_fetchchar, &fd,
+                               fcctx.dbconn = dbconn;
+                               read_openpgp_stream(keydb_fetchchar, &fcctx,
                                                &packets,
                                                0);
                                parse_keys(packets, publickey);
-                               lo_close(dbconn, fd);
+                               lo_close(dbconn, fcctx.fd);
                                free_packet_list(packets);
                                packets = NULL;
                        }
  *     This function deletes a public key from whatever storage mechanism we
  *     are using. Returns 0 if the key existed.
  */
-static int pg_delete_key(uint64_t keyid, bool intrans)
+static int pg_delete_key(struct onak_dbctx *dbctx, uint64_t keyid, bool intrans)
 {
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
        char *oids = NULL;
        char statement[1024];
  *     the file. If update is true then we delete the old key first, otherwise
  *     we trust that it doesn't exist.
  */
-static int pg_store_key(struct openpgp_publickey *publickey, bool intrans,
+static int pg_store_key(struct onak_dbctx *dbctx,
+               struct openpgp_publickey *publickey, bool intrans,
                bool update)
 {
        struct openpgp_packet_list *packets = NULL;
        struct openpgp_packet_list *list_end = NULL;
        struct openpgp_publickey *next = NULL;
        struct openpgp_signedpacket_list *curuid = NULL;
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
        char statement[1024];
        Oid key_oid;
-       int fd;
        char **uids = NULL;
        char *primary = NULL;
        char *safeuid = NULL;
        int i;
        uint64_t keyid;
+       struct pg_fc_ctx fcctx;
 
        if (!intrans) {
                result = PQexec(dbconn, "BEGIN");
         * it definitely needs updated.
         */
        if (update) {
-               pg_delete_key(keyid, true);
+               pg_delete_key(dbctx, keyid, true);
        }
 
        next = publickey->next;
        if (key_oid == 0) {
                logthing(LOGTHING_ERROR, "Can't create key OID");
        } else {
-               fd = lo_open(dbconn, key_oid, INV_WRITE);
-               write_openpgp_stream(keydb_putchar, &fd, packets);
-               lo_close(dbconn, fd);
+               fcctx.fd = lo_open(dbconn, key_oid, INV_WRITE);
+               fcctx.dbconn = dbconn;
+               write_openpgp_stream(keydb_putchar, &fcctx, packets);
+               lo_close(dbconn, fcctx.fd);
        }
        free_packet_list(packets);
        packets = NULL;
  *     keyid2uid - Takes a keyid and returns the primary UID for it.
  *     @keyid: The keyid to lookup.
  */
-static char *pg_keyid2uid(uint64_t keyid)
+static char *pg_keyid2uid(struct onak_dbctx *dbctx, uint64_t keyid)
 {
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
        char statement[1024];
        char *uid = NULL;
  *     This function gets the list of signatures on a key. Used for key 
  *     indexing and doing stats bits.
  */
-static struct ll *pg_getkeysigs(uint64_t keyid, bool *revoked)
+static struct ll *pg_getkeysigs(struct onak_dbctx *dbctx,
+                       uint64_t keyid, bool *revoked)
 {
        struct ll *sigs = NULL;
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
        uint64_t signer;
        char statement[1024];
  *
  *     Returns the number of keys we iterated over.
  */
-static int pg_iterate_keys(void (*iterfunc)(void *ctx,
+static int pg_iterate_keys(struct onak_dbctx *dbctx,
+               void (*iterfunc)(void *ctx,
                struct openpgp_publickey *key), void *ctx)
 {
        struct openpgp_packet_list *packets = NULL;
        struct openpgp_publickey *key = NULL;
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
        char *oids = NULL;
-       int fd = -1;
        int i = 0;
        int numkeys = 0;
        Oid key_oid;
+       struct pg_fc_ctx fcctx;
 
        result = PQexec(dbconn, "SELECT keydata FROM onak_keys;");
 
                        oids = PQgetvalue(result, i, 0);
                        key_oid = (Oid) atoi(oids);
 
-                       fd = lo_open(dbconn, key_oid, INV_READ);
-                       if (fd < 0) {
+                       fcctx.fd = lo_open(dbconn, key_oid, INV_READ);
+                       if (fcctx.fd < 0) {
                                logthing(LOGTHING_ERROR,
                                                "Can't open large object.");
                        } else {
-                               read_openpgp_stream(keydb_fetchchar, &fd,
+                               fcctx.dbconn = dbconn;
+                               read_openpgp_stream(keydb_fetchchar, &fcctx,
                                                &packets, 0);
                                parse_keys(packets, &key);
-                               lo_close(dbconn, fd);
+                               lo_close(dbconn, fcctx.fd);
 
                                iterfunc(ctx, key);
                                        
 #define NEED_GET_FP 1
 #include "keydb.c"
 
-struct dbfuncs keydb_pg_funcs = {
-       .initdb                 = pg_initdb,
-       .cleanupdb              = pg_cleanupdb,
-       .starttrans             = pg_starttrans,
-       .endtrans               = pg_endtrans,
-       .fetch_key_id           = pg_fetch_key_id,
-       .fetch_key_fp           = generic_fetch_key_fp,
-       .fetch_key_text         = pg_fetch_key_text,
-       .store_key              = pg_store_key,
-       .update_keys            = generic_update_keys,
-       .delete_key             = pg_delete_key,
-       .getkeysigs             = pg_getkeysigs,
-       .cached_getkeysigs      = generic_cached_getkeysigs,
-       .keyid2uid              = pg_keyid2uid,
-       .getfullkeyid           = generic_getfullkeyid,
-       .iterate_keys           = pg_iterate_keys,
-};
+/**
+ *     cleanupdb - De-initialize the key database.
+ *
+ *     This function should be called upon program exit to allow the DB to
+ *     cleanup after itself.
+ */
+static void pg_cleanupdb(struct onak_dbctx *dbctx)
+{
+       PGconn *dbconn = (PGconn *) dbctx->priv;
+
+       PQfinish(dbconn);
+       dbconn = NULL;
+
+       free(dbctx);
+}
+
+/**
+ *     initdb - Initialize the key database.
+ *
+ *     This function should be called before any of the other functions in
+ *     this file are called in order to allow the DB to be initialized ready
+ *     for access.
+ */
+struct onak_dbctx *keydb_pg_init(bool readonly)
+{
+       struct onak_dbctx *dbctx;
+       PGconn *dbconn;
+
+       dbctx = malloc(sizeof(struct onak_dbctx));
+       if (dbctx == NULL) {
+               return NULL;
+       }
+
+       dbconn = PQsetdbLogin(config.pg_dbhost, // host
+                       NULL, // port
+                       NULL, // options
+                       NULL, // tty
+                       config.pg_dbname, // database
+                       config.pg_dbuser,  //login
+                       config.pg_dbpass); // password
+
+       if (PQstatus(dbconn) == CONNECTION_BAD) {
+               logthing(LOGTHING_CRITICAL, "Connection to database failed.");
+               logthing(LOGTHING_CRITICAL, "%s", PQerrorMessage(dbconn));
+               PQfinish(dbconn);
+               dbconn = NULL;
+               exit(1);
+       }
+
+       dbctx->priv = dbconn;
+
+       dbctx->cleanupdb                = pg_cleanupdb;
+       dbctx->starttrans               = pg_starttrans;
+       dbctx->endtrans                 = pg_endtrans;
+       dbctx->fetch_key_id             = pg_fetch_key_id;
+       dbctx->fetch_key_fp             = generic_fetch_key_fp;
+       dbctx->fetch_key_text           = pg_fetch_key_text;
+       dbctx->store_key                = pg_store_key;
+       dbctx->update_keys              = generic_update_keys;
+       dbctx->delete_key               = pg_delete_key;
+       dbctx->getkeysigs               = pg_getkeysigs;
+       dbctx->cached_getkeysigs        = generic_cached_getkeysigs;
+       dbctx->keyid2uid                = pg_keyid2uid;
+       dbctx->getfullkeyid             = generic_getfullkeyid;
+       dbctx->iterate_keys             = pg_iterate_keys;
+
+       return dbctx;
+}
 
 #include "version.h"
 
 /* HACK: We need to stop onak-conf.o requiring this. */
-void *DBFUNCS = NULL;
+void *DBINIT = NULL;
 
 static int keyd_fd = -1;
 static int verbose = 0;
 
        return length;
 }
 
-int list_sigs(struct openpgp_packet_list *sigs, bool html)
+int list_sigs(struct onak_dbctx *dbctx,
+               struct openpgp_packet_list *sigs, bool html)
 {
        char *uid = NULL;
        uint64_t sigid = 0;
 
        while (sigs != NULL) {
                sigid = sig_keyid(sigs->packet);
-               uid = config.dbbackend->keyid2uid(sigid);
+               uid = dbctx->keyid2uid(dbctx, sigid);
                if (sigs->packet->data[0] == 4 &&
                                sigs->packet->data[1] == 0x30) {
                        /* It's a Type 4 sig revocation */
        return 0;
 }
 
-int list_uids(uint64_t keyid, struct openpgp_signedpacket_list *uids,
+int list_uids(struct onak_dbctx *dbctx,
+               uint64_t keyid, struct openpgp_signedpacket_list *uids,
                bool verbose, bool html)
 {
        char buf[1024];
                        }
                }
                if (verbose) {
-                       list_sigs(uids->sigs, html);
+                       list_sigs(dbctx, uids->sigs, html);
                }
                uids = uids->next;
        }
        return 0;
 }
 
-int list_subkeys(struct openpgp_signedpacket_list *subkeys, bool verbose,
+int list_subkeys(struct onak_dbctx *dbctx,
+               struct openpgp_signedpacket_list *subkeys, bool verbose,
                bool html)
 {
        struct tm       *created = NULL;
 
                }
                if (verbose) {
-                       list_sigs(subkeys->sigs, html);
+                       list_sigs(dbctx, subkeys->sigs, html);
                }
                subkeys = subkeys->next;
        }
  *     This function takes a list of OpenPGP public keys and displays an index
  *     of them. Useful for debugging or the keyserver Index function.
  */
-int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
+int key_index(struct onak_dbctx *dbctx,
+               struct openpgp_publickey *keys, bool verbose, bool fingerprint,
                        bool skshash, bool html)
 {
        struct openpgp_signedpacket_list        *curuid = NULL;
                                display_fingerprint(keys);
                        }
                        if (verbose) {
-                               list_sigs(curuid->sigs, html);
+                               list_sigs(dbctx, curuid->sigs, html);
                        }
                        curuid = curuid->next;
                } else {
                        }
                }
 
-               list_uids(keyid, curuid, verbose, html);
+               list_uids(dbctx, keyid, curuid, verbose, html);
                if (verbose) {
-                       list_subkeys(keys->subkeys, verbose, html);
+                       list_subkeys(dbctx, keys->subkeys, verbose, html);
                }
 
                keys = keys->next;
 
 
 #include <stdbool.h>
 
+#include "keydb.h"
 #include "keystructs.h"
 
 /**
  *     This function takes a list of OpenPGP public keys and displays an index
  *     of them. Useful for debugging or the keyserver Index function.
  */
-int key_index(struct openpgp_publickey *keys, bool verbose,
+int key_index(struct onak_dbctx *dbctx,
+               struct openpgp_publickey *keys, bool verbose,
                bool fingerprint, bool skshash, bool html);
 
 /**
 
 #define OP_PHOTO   4
 #define OP_HGET    5
 
-void find_keys(char *search, uint64_t keyid, uint8_t *fp, size_t fpsize,
+void find_keys(struct onak_dbctx *dbctx,
+               char *search, uint64_t keyid, uint8_t *fp, size_t fpsize,
                bool ishex, bool isfp, bool fingerprint, bool skshash,
                bool exact, bool verbose, bool mrhkp)
 {
        int count = 0;
 
        if (ishex) {
-               count = config.dbbackend->fetch_key_id(keyid, &publickey,
+               count = dbctx->fetch_key_id(dbctx, keyid, &publickey,
                                false);
        } else if (isfp) {
-               count = config.dbbackend->fetch_key_fp(fp, fpsize, &publickey,
+               count = dbctx->fetch_key_fp(dbctx, fp, fpsize, &publickey,
                                false);
        } else {
-               count = config.dbbackend->fetch_key_text(search, &publickey);
+               count = dbctx->fetch_key_text(dbctx, search, &publickey);
        }
        if (publickey != NULL) {
                if (mrhkp) {
                        printf("info:1:%d\n", count);
                        mrkey_index(publickey);
                } else {
-                       key_index(publickey, verbose, fingerprint, skshash,
-                               true);
+                       key_index(dbctx, publickey, verbose, fingerprint,
+                               skshash, true);
                }
                free_publickey(publickey);
        } else if (count == 0) {
        struct openpgp_packet_list *list_end = NULL;
        int result;
        struct skshash hash;
+       struct onak_dbctx *dbctx;
 
        params = getcgivars(argc, argv);
        for (i = 0; params != NULL && params[i] != NULL; i += 2) {
                readconfig(NULL);
                initlogthing("lookup", config.logfile);
                catchsignals();
-               config.dbbackend->initdb(false);
+               dbctx = config.dbinit(false);
                switch (op) {
                case OP_GET:
                case OP_HGET:
                        if (op == OP_HGET) {
                                parse_skshash(search, &hash);
-                               result = config.dbbackend->fetch_key_skshash(
+                               result = dbctx->fetch_key_skshash(dbctx,
                                        &hash, &publickey);
                        } else if (ishex) {
-                               result = config.dbbackend->fetch_key_id(keyid,
+                               result = dbctx->fetch_key_id(dbctx, keyid,
                                        &publickey, false);
                        } else if (isfp) {
-                               result = config.dbbackend->fetch_key_fp(fp,
+                               result = dbctx->fetch_key_fp(dbctx, fp,
                                        MAX_FINGERPRINT_LEN, &publickey, false);
                        } else {
-                               result = config.dbbackend->fetch_key_text(
+                               result = dbctx->fetch_key_text(dbctx,
                                        search,
                                        &publickey);
                        }
                        }
                        break;
                case OP_INDEX:
-                       find_keys(search, keyid, fp, MAX_FINGERPRINT_LEN,
+                       find_keys(dbctx, search, keyid, fp, MAX_FINGERPRINT_LEN,
                                        ishex, isfp, fingerprint, skshash,
                                        exact, false, mrhkp);
                        break;
                case OP_VINDEX:
-                       find_keys(search, keyid, fp, MAX_FINGERPRINT_LEN,
+                       find_keys(dbctx, search, keyid, fp, MAX_FINGERPRINT_LEN,
                                        ishex, isfp, fingerprint, skshash,
                                        exact, true, mrhkp);
                        break;
                case OP_PHOTO:
                        if (isfp) {
-                               config.dbbackend->fetch_key_fp(fp,
+                               dbctx->fetch_key_fp(dbctx, fp,
                                        MAX_FINGERPRINT_LEN,
                                        &publickey, false);
                        } else {
-                               config.dbbackend->fetch_key_id(keyid,
+                               dbctx->fetch_key_id(dbctx, keyid,
                                        &publickey, false);
                        }
                        if (publickey != NULL) {
                default:
                        puts("Unknown operation!");
                }
-               config.dbbackend->cleanupdb();
+               dbctx->cleanupdb(dbctx);
                cleanuplogthing();
                cleanupconfig();
        }
 
 #include "onak-conf.h"
 #include "stats.h"
 
-void findmaxpath(unsigned long max)
+void findmaxpath(struct onak_dbctx *dbctx, unsigned long max)
 {
        struct stats_key *from, *to, *tmp;
        struct ll *curkey;
         * My (noodles@earth.li, RSA) key is in the strongly connected set of
         * keys, so we use it as a suitable starting seed.
         */
-       config.dbbackend->cached_getkeysigs(0x94FA372B2DA8B985);
+       dbctx->cached_getkeysigs(dbctx, 0x94FA372B2DA8B985);
 
        /*
         * Loop through the hash examining each key present and finding the
        for (loop = 0; (loop < HASHSIZE) && (distance < max); loop++) {
                curkey = gethashtableentry(loop);
                while (curkey != NULL && distance < max) {
-                       config.dbbackend->cached_getkeysigs(
+                       dbctx->cached_getkeysigs(dbctx,
                                        ((struct stats_key *)
                                        curkey->object)->keyid);
                        initcolour(false);
-                       tmp = furthestkey((struct stats_key *)
+                       tmp = furthestkey(dbctx, (struct stats_key *)
                                                curkey->object);
                        if (tmp->colour > distance) {
                                from = (struct stats_key *)curkey->object;
                        from->keyid,
                        to->keyid,
                        distance);
-       dofindpath(to->keyid, from->keyid, false, 1);
+       dofindpath(dbctx, to->keyid, from->keyid, false, 1);
 }
 
 int main(int argc, char *argv[])
 {
        int optchar;
        char *configfile = NULL;
+       struct onak_dbctx *dbctx;
 
        while ((optchar = getopt(argc, argv, "c:")) != -1 ) {
                switch (optchar) {
 
        readconfig(configfile);
        initlogthing("maxpath", config.logfile);
-       config.dbbackend->initdb(true);
-       inithash();
-       findmaxpath(30);
-       printf("--------\n");
-       findmaxpath(30);
-       destroyhash();
-       config.dbbackend->cleanupdb();
+       dbctx = config.dbinit(true);
+       if (dbctx != NULL) {
+               inithash();
+               findmaxpath(dbctx, 30);
+               printf("--------\n");
+               findmaxpath(dbctx, 30);
+               destroyhash();
+               dbctx->cleanupdb(dbctx);
+       } else {
+               fprintf(stderr, "Couldn't initialize key database.\n");
+       }
        cleanuplogthing();
        cleanupconfig();
        
 
 #include "log.h"
 #include "onak-conf.h"
 
-extern struct dbfuncs DBFUNCS;
+extern struct onak_dbctx *DBINIT(bool readonly);
 
 /*
  *     config - Runtime configuration for onak.
        NULL,                   /* db_backend */
        NULL,                   /* backends_dir */
 
-       &DBFUNCS,               /* Default dbfuncs struct */
+       DBINIT,                 /* Default db initialisation function */
 
        true,                   /* Check packet sig hashes */
 };
 
        /** Directory where backend .so files can be found */
        char *backends_dir;
 
-       /** Pointer to the function table for our loaded DB backend */
-       struct dbfuncs *dbbackend;
+       /** Pointer to the initialisation function for our loaded DB backend */
+       struct onak_dbctx *(*dbinit)(bool);
 
        /** Should we verify signature hashes match? */
        bool check_sighash;
 
 #include "photoid.h"
 #include "version.h"
 
-void find_keys(char *search, uint64_t keyid, uint8_t *fp, bool ishex,
+void find_keys(struct onak_dbctx *dbctx,
+               char *search, uint64_t keyid, uint8_t *fp, bool ishex,
                bool isfp, bool fingerprint, bool skshash, bool exact,
                bool verbose)
 {
        int count = 0;
 
        if (ishex) {
-               count = config.dbbackend->fetch_key_id(keyid, &publickey,
+               count = dbctx->fetch_key_id(dbctx, keyid, &publickey,
                                false);
        } else if (isfp) {
-               count = config.dbbackend->fetch_key_fp(fp, MAX_FINGERPRINT_LEN,
+               count = dbctx->fetch_key_fp(dbctx, fp, MAX_FINGERPRINT_LEN,
                                &publickey, false);
        } else {
-               count = config.dbbackend->fetch_key_text(search, &publickey);
+               count = dbctx->fetch_key_text(dbctx, search, &publickey);
        }
        if (publickey != NULL) {
-               key_index(publickey, verbose, fingerprint, skshash, false);
+               key_index(dbctx, publickey, verbose, fingerprint, skshash,
+                       false);
                free_publickey(publickey);
        } else if (count == 0) {
                puts("Key not found.");
        int                              optchar;
        struct dump_ctx                  dumpstate;
        struct skshash                   hash;
+       struct onak_dbctx               *dbctx;
 
        while ((optchar = getopt(argc, argv, "bc:fsuv")) != -1 ) {
                switch (optchar) {
        if ((argc - optind) < 1) {
                usage();
        } else if (!strcmp("dump", argv[optind])) {
-               config.dbbackend->initdb(true);
+               dbctx = config.dbinit(true);
                dumpstate.count = dumpstate.filenum = 0;
                dumpstate.maxcount = 100000;
                dumpstate.fd = -1;
                dumpstate.filebase = "keydump.%d.pgp";
-               config.dbbackend->iterate_keys(dump_func, &dumpstate);
+               dbctx->iterate_keys(dbctx, dump_func, &dumpstate);
                if (dumpstate.fd != -1) {
                        close(dumpstate.fd);
                        dumpstate.fd = -1;
                }
-               config.dbbackend->cleanupdb();
+               dbctx->cleanupdb(dbctx);
        } else if (!strcmp("add", argv[optind])) {
                if (binary) {
                        result = read_openpgp_stream(stdin_getchar, NULL,
                        logthing(LOGTHING_INFO, "%d keys cleaned.",
                                        result);
 
-                       config.dbbackend->initdb(false);
+                       dbctx = config.dbinit(false);
                        logthing(LOGTHING_NOTICE, "Got %d new keys.",
-                                       config.dbbackend->update_keys(&keys,
+                                       dbctx->update_keys(dbctx, &keys,
                                        false));
                        if (keys != NULL && update) {
                                flatten_publickey(keys,
                                free_packet_list(packets);
                                packets = NULL;
                        }
-                       config.dbbackend->cleanupdb();
+                       dbctx->cleanupdb(dbctx);
                } else {
                        rc = 1;
                        logthing(LOGTHING_NOTICE, "No keys read.");
                                ishex = true;
                        }
                }
-               config.dbbackend->initdb(false);
+               dbctx = config.dbinit(false);
                if (!strcmp("index", argv[optind])) {
-                       find_keys(search, keyid, fp, ishex, isfp,
+                       find_keys(dbctx, search, keyid, fp, ishex, isfp,
                                        fingerprint, skshash,
                                        false, false);
                } else if (!strcmp("vindex", argv[optind])) {
-                       find_keys(search, keyid, fp, ishex, isfp,
+                       find_keys(dbctx, search, keyid, fp, ishex, isfp,
                                        fingerprint, skshash,
                                        false, true);
                } else if (!strcmp("getphoto", argv[optind])) {
                        if (!ishex) {
                                puts("Can't get a key on uid text."
                                        " You must supply a keyid.");
-                       } else if (config.dbbackend->fetch_key_id(keyid, &keys,
+                       } else if (dbctx->fetch_key_id(dbctx, keyid, &keys,
                                        false)) {
                                unsigned char *photo = NULL;
                                size_t         length = 0;
                                puts("Key not found");
                        }
                } else if (!strcmp("delete", argv[optind])) {
-                       config.dbbackend->delete_key(
-                                       config.dbbackend->getfullkeyid(keyid),
+                       dbctx->delete_key(dbctx,
+                                       dbctx->getfullkeyid(dbctx, keyid),
                                        false);
                } else if (!strcmp("get", argv[optind])) {
                        if (!(ishex || isfp)) {
                                        " You must supply a keyid / "
                                        "fingerprint.");
                        } else if ((isfp &&
-                                       config.dbbackend->fetch_key_fp(fp,
+                                       dbctx->fetch_key_fp(dbctx, fp,
                                                MAX_FINGERPRINT_LEN,
                                                &keys, false)) ||
                                        (ishex &&
-                                       config.dbbackend->fetch_key_id(keyid,
+                                       dbctx->fetch_key_id(dbctx, keyid,
                                                &keys, false))) {
                                logthing(LOGTHING_INFO, "Got key.");
                                flatten_publickey(keys,
                } else if (!strcmp("hget", argv[optind])) {
                        if (!parse_skshash(search, &hash)) {
                                puts("Couldn't parse sks hash.");
-                       } else if (config.dbbackend->fetch_key_skshash(&hash,
+                       } else if (dbctx->fetch_key_skshash(dbctx, &hash,
                                        &keys)) {
                                logthing(LOGTHING_INFO, "Got key.");
                                flatten_publickey(keys,
                                puts("Key not found");
                        }
                }
-               config.dbbackend->cleanupdb();
+               dbctx->cleanupdb(dbctx);
        } else {
                usage();
        }
 
 #include "onak-conf.h"
 #include "stats.h"
 
-unsigned long countdegree(struct stats_key *have, bool sigs, int maxdegree)
+unsigned long countdegree(struct onak_dbctx *dbctx,
+               struct stats_key *have, bool sigs, int maxdegree)
 {
        unsigned long     count = 0, curdegree = 0;
        struct ll        *curll, *nextll, *sigll, *tmp;
 
        while (curll != NULL && curdegree <= maxdegree) {
                if (sigs) {
-                       sigll = config.dbbackend->cached_getkeysigs(
+                       sigll = dbctx->cached_getkeysigs(dbctx,
                                ((struct stats_key *)
                                curll->object)->keyid);
                } else {
        return count;
 }
 
-void sixdegrees(uint64_t keyid)
+void sixdegrees(struct onak_dbctx *dbctx, uint64_t keyid)
 {
        struct stats_key *keyinfo;
        int loop;
        long degree;
        char *uid;
 
-       config.dbbackend->cached_getkeysigs(keyid);
+       dbctx->cached_getkeysigs(dbctx, keyid);
 
        if ((keyinfo = findinhash(keyid)) == NULL) {
                printf("Couldn't find key 0x%016" PRIX64 ".\n", keyid);
                return;
        }
 
-       uid = config.dbbackend->keyid2uid(keyinfo->keyid);
+       uid = dbctx->keyid2uid(dbctx, keyinfo->keyid);
        printf("Six degrees for 0x%016" PRIX64 " (%s):\n", keyinfo->keyid,
                        uid);
        free(uid);
         * if it's signed by the key we're looking at.
         */
        initcolour(false);
-       degree = countdegree(keyinfo, true, 7);
+       degree = countdegree(dbctx, keyinfo, true, 7);
 
        puts("\t\tSigned by\t\tSigns");
        for (loop = 1; loop < 7; loop++) {
                initcolour(false);
-               degree = countdegree(keyinfo, true, loop);
+               degree = countdegree(dbctx, keyinfo, true, loop);
                printf("Degree %d:\t%8ld", loop, degree);
 
                initcolour(false);
-               degree = countdegree(keyinfo, false, loop);
+               degree = countdegree(dbctx, keyinfo, false, loop);
                printf("\t\t%8ld\n", degree);
        }
 }
        int optchar;
        char *configfile = NULL;
        uint64_t keyid = 0x2DA8B985;
+       struct onak_dbctx *dbctx;
 
        while ((optchar = getopt(argc, argv, "c:")) != -1 ) {
                switch (optchar) {
 
        readconfig(configfile);
        initlogthing("sixdegrees", config.logfile);
-       config.dbbackend->initdb(true);
-       inithash();
-       sixdegrees(config.dbbackend->getfullkeyid(keyid));
-       destroyhash();
-       config.dbbackend->cleanupdb();
+       dbctx = config.dbinit(true);
+       if (dbctx != NULL) {
+               inithash();
+               sixdegrees(dbctx, dbctx->getfullkeyid(dbctx, keyid));
+               destroyhash();
+               dbctx->cleanupdb(dbctx);
+       } else {
+               fprintf(stderr, "Couldn't initialize key database.\n");
+       }
        cleanuplogthing();
        cleanupconfig();
 
 
  *     key we have. It returns as soon as a path is found or when we run out
  *     of keys; whichever comes sooner.
  */
-unsigned long findpath(struct stats_key *have, struct stats_key *want)
+unsigned long findpath(struct onak_dbctx *dbctx,
+               struct stats_key *have, struct stats_key *want)
 {
        struct ll *keys = NULL;
        struct ll *oldkeys = NULL;
        oldkeys = keys;
 
        while ((!cleanup()) && keys != NULL && have->colour == 0) {
-               sigs = config.dbbackend->cached_getkeysigs(((struct stats_key *)
+               sigs = dbctx->cached_getkeysigs(dbctx, ((struct stats_key *)
                                        keys->object)->keyid);
                while ((!cleanup()) && sigs != NULL && have->colour == 0) {
                        /*
  *     key we have. It returns as soon as a path is found or when we run out
  *     of keys; whichever comes sooner.
  */
-void dofindpath(uint64_t have, uint64_t want, bool html, int count)
+void dofindpath(struct onak_dbctx *dbctx,
+               uint64_t have, uint64_t want, bool html, int count)
 {
        struct stats_key *keyinfoa, *keyinfob, *curkey;
        uint64_t fullhave, fullwant;
        int pathnum;
        char *uid;
 
-       fullhave = config.dbbackend->getfullkeyid(have);
-       fullwant = config.dbbackend->getfullkeyid(want);
+       fullhave = dbctx->getfullkeyid(dbctx, have);
+       fullwant = dbctx->getfullkeyid(dbctx, want);
 
        /*
         * Make sure the keys we have and want are in the cache.
         */
-       (void) config.dbbackend->cached_getkeysigs(fullhave);
-       (void) config.dbbackend->cached_getkeysigs(fullwant);
+       (void) dbctx->cached_getkeysigs(dbctx, fullhave);
+       (void) dbctx->cached_getkeysigs(dbctx, fullwant);
 
        if ((keyinfoa = findinhash(fullhave)) == NULL) {
                printf("Couldn't find key 0x%016" PRIX64 ".\n", have);
                 * Fill the tree info up.
                 */
                initcolour(true);
-               rec = findpath(keyinfoa, keyinfob);
+               rec = findpath(dbctx, keyinfoa, keyinfob);
                keyinfob->parent = 0;
 
                printf("%s%d nodes examined. %ld elements in the hash%s\n",
                                html ? "<BR>" : "");
                        curkey = keyinfoa;
                        while (curkey != NULL && curkey->keyid != 0) {
-                               uid = config.dbbackend->keyid2uid(
+                               uid = dbctx->keyid2uid(dbctx,
                                                curkey->keyid);
                                if (html && uid == NULL) {
                                        printf("<a href=\"lookup?op=get&search="
 
 
 
-struct stats_key *furthestkey(struct stats_key *have)
+struct stats_key *furthestkey(struct onak_dbctx *dbctx, struct stats_key *have)
 {
        unsigned long count = 0;
        unsigned long curdegree = 0;
        curll = lladd(NULL, have);
 
        while (curll != NULL) {
-               sigs = config.dbbackend->cached_getkeysigs(((struct stats_key *)
+               sigs = dbctx->cached_getkeysigs(dbctx, ((struct stats_key *)
                                curll->object)->keyid);
                while (sigs != NULL) {
                        if (((struct stats_key *) sigs->object)->colour == 0) {
 
 #include <inttypes.h>
 #include <stdbool.h>
 
+#include "keydb.h"
 #include "ll.h"
 
 /**
  *     key we have. It returns as soon as a path is found or when we run out
  *     of keys; whichever comes sooner.
  */
-unsigned long findpath(struct stats_key *have, struct stats_key *want);
+unsigned long findpath(struct onak_dbctx *dbctx,
+               struct stats_key *have, struct stats_key *want);
 
 /**
  *     dofindpath - Given 2 keys displays a path between them.
  *     key we have. It returns as soon as a path is found or when we run out
  *     of keys; whichever comes sooner.
  */
-void dofindpath(uint64_t have, uint64_t want, bool html, int count);
+void dofindpath(struct onak_dbctx *dbctx,
+               uint64_t have, uint64_t want, bool html, int count);
 
-struct stats_key *furthestkey(struct stats_key *have);
+struct stats_key *furthestkey(struct onak_dbctx *dbctx, struct stats_key *have);
 
 #endif /* __STATS_H__ */
 
        return newll;
 }
 
-static void output_key(FILE *names, FILE *keys, uint64_t keyid)
+static void output_key(struct onak_dbctx *dbctx,
+               FILE *names, FILE *keys, uint64_t keyid)
 {
-       fprintf(names, "%s\n", config.dbbackend->keyid2uid(keyid));
+       fprintf(names, "%s\n", dbctx->keyid2uid(dbctx, keyid));
        fprintf(keys, "%c%c%c%c", (int) (keyid >> 24) & 0xFF,
                        (int) (keyid >> 16) & 0xFF,
                        (int) (keyid >>  8) & 0xFF,
                        (int) (keyid      ) & 0xFF);
 }
 
-static void wotsap(uint64_t keyid, char *dir)
+static void wotsap(struct onak_dbctx *dbctx, uint64_t keyid, char *dir)
 {
        struct ll *pending, *sigll, *sigsave;
        uint32_t curidx = 0;
        }
        free(tmppath);
 
-       config.dbbackend->cached_getkeysigs(keyid);
+       dbctx->cached_getkeysigs(dbctx, keyid);
        curkey = findinhash(keyid);
        curkey->colour = ++curidx;
        pending = lladd(NULL, curkey);
 
-       output_key(names, keys, curkey->keyid);
+       output_key(dbctx, names, keys, curkey->keyid);
 
        while (pending != NULL) {
                curkey = (struct stats_key *) pending->object;
-               sigll = config.dbbackend->cached_getkeysigs(curkey->keyid);
+               sigll = dbctx->cached_getkeysigs(dbctx, curkey->keyid);
                sigsave = sigll = sortkeyll(sigll);
                sigcount = 0;
                while (sigll != NULL) {
                        addkey = (struct stats_key *) sigll->object;
                        if (addkey->colour == 0 && !addkey->revoked) {
-                               uid = config.dbbackend->keyid2uid(addkey->keyid);
+                               uid = dbctx->keyid2uid(dbctx, addkey->keyid);
                                if (uid != NULL) {
                                        /* Force it to be loaded so we know if it's revoked */
-                                       config.dbbackend->cached_getkeysigs(addkey->keyid);
+                                       dbctx->cached_getkeysigs(dbctx,
+                                                       addkey->keyid);
                                        if (!addkey->revoked) {
                                                addkey->colour = ++curidx;
                                                pending = lladdend(pending, addkey);
-                                               output_key(names, keys, addkey->keyid);
+                                               output_key(dbctx, names, keys,
+                                                       addkey->keyid);
                                        }
                                }
                        }
        int optchar;
        char *configfile = NULL, *dir = NULL;
        uint64_t keyid = 0x2DA8B985;
+       struct onak_dbctx *dbctx;
 
        while ((optchar = getopt(argc, argv, "c:")) != -1 ) {
                switch (optchar) {
 
        readconfig(configfile);
        initlogthing("wotsap", config.logfile);
-       config.dbbackend->initdb(true);
-       inithash();
-       wotsap(config.dbbackend->getfullkeyid(keyid), dir ? dir : ".");
-       destroyhash();
-       config.dbbackend->cleanupdb();
+       dbctx = config.dbinit(true);
+       if (dbctx != NULL) {
+               inithash();
+               wotsap(dbctx, dbctx->getfullkeyid(dbctx, keyid),
+                       dir ? dir : ".");
+               destroyhash();
+               dbctx->cleanupdb(dbctx);
+       } else {
+               fprintf(stderr, "Couldn't initialize key database.\n");
+       }
        cleanuplogthing();
        cleanupconfig();
 }