使用BDB
前段时间准备将以前程序里的gdbm替换成bdb,所以写了一些代码,如何使用bdb,现在将代码贴出来:
#ifndef EYOU_DBT_H #define EYOU_DBT_H
#include <db.h>
/* Set all fields of DBT to zero. Return DBT. */ DBT *affirm_clear_dbt (DBT *dbt);
/* Set DBT to retrieve no data. This is useful when you're just probing the table to see if an entry exists, or to find a key, but don't care what the value is. Return DBT. */ DBT *affirm_nodata_dbt (DBT *dbt);
/* Set DBT to refer to the SIZE bytes at DATA. Return DBT. */ DBT *affirm_set_dbt (DBT *dbt, const void *data, u_int32_t size);
void init_DBT(DBT *key, DBT *data);
#endif /* EYOU_DBT_H */ |
dbt.h
/* * bdb_error.h : interface to routines for returning Berkeley DB errors */
#ifndef EYOU_BDB_ERR_H #define EYOU_BDB_ERR_H
#include <db.h>
#ifdef __cplusplus extern "C" { #endif /* __cplusplus */
#define BDB_ERR(expr) / do { / int db_err__temp = (expr); / if (db_err__temp) / return db_err__temp; / } while (0)
#ifdef __cplusplus } #endif /* __cplusplus */
#endif /* EYOU_BDB_ERR_H */ |
bdb_error.h
Bdb_compat.h 主要是同时可以在不同版本的bdb中使用,因为open函数参数一样
#ifndef EYOU_BDB_COMPAT_H #define EYOU_BDB_COMPAT_H
#include <db.h>
/* BDB 4.1 introduced the DB_AUTO_COMMIT flag. Older versions can just use 0 instead. */ #ifdef DB_AUTO_COMMIT #define AFFIRM_BDB_AUTO_COMMIT (DB_AUTO_COMMIT) #else #define AFFIRM_BDB_AUTO_COMMIT (0) #endif
/* DB_INCOMPLETE is obsolete in BDB 4.1. */ #ifdef DB_INCOMPLETE #define AFFIRM_BDB_HAS_DB_INCOMPLETE 1 #else #define AFFIRM_BDB_HAS_DB_INCOMPLETE 0 #endif
/* In BDB 4.3, "buffer too small" errors come back with DB_BUFFER_SMALL (instead of ENOMEM, which is now fatal). */ #ifdef DB_BUFFER_SMALL #define AFFIRM_BDB_DB_BUFFER_SMALL DB_BUFFER_SMALL #else #define AFFIRM_BDB_DB_BUFFER_SMALL ENOMEM #endif
/* BDB 4.4 introdiced the DB_REGISTER flag for DBEnv::open that allows for automatic recovery of the databases after a program crash. */ #ifdef DB_REGISTER #define AFFIRM_BDB_AUTO_RECOVER (DB_REGISTER | DB_RECOVER) #else #define AFFIRM_BDB_AUTO_RECOVER (0) #endif
/* Parameter lists */
/* In BDB 4.1, DB->open takes a transaction parameter. We'll ignore it when building with 4.0. */ #if (DB_VERSION_MAJOR > 4) / || (DB_VERSION_MAJOR == 4) && (DB_VERSION_MINOR >= 1) #define AFFIRM_BDB_OPEN_PARAMS(env,txn) (env), (txn) #else #define AFFIRM_BDB_OPEN_PARAMS(env,txn) (env) #endif
/* In BDB 4.3, the error gatherer function grew a new DBENV parameter, and the MSG parameter's type changed. */ #if (DB_VERSION_MAJOR > 4) / || (DB_VERSION_MAJOR == 4) && (DB_VERSION_MINOR >= 3) /* Prevents most compilers from whining about unused parameters. */ #define AFFIRM_BDB_ERROR_GATHERER_IGNORE(varname) ((void)(varname)) #else #define bdb_error_gatherer(param1, param2, param3) / bdb_error_gatherer (param2, char *msg) #define AFFIRM_BDB_ERROR_GATHERER_IGNORE(varname) ((void)0) #endif
/* Before calling db_create, we must check that the version of the BDB libraries we're linking with is the same as the one we compiled against, because the DB->open call is not binary compatible between BDB 4.0 and 4.1. This function returns DB_OLD_VERSION if the compile-time and run-time versions of BDB don't match. */ int affirm_bdb_check_version (void);
#endif /* EYOU_BDB_COMPAT_H */ |
bdb_compat.h
#ifndef EYOU_AFFIRM_TABLE_H #define EYOU_AFFIRM_TABLE_H
#include <db.h>
int bdb_open(DB** dbp, char *db_name); int bdb_get(DB* dbp, DBT* key, DBT* data, char* db_name); int bdb_put(DB* dbp, DBT* key, DBT* data, char* db_name); int bdb_del(DB* dbp, DBT* key, char* db_name);
#endif /* EYOU_AFFIRM_TABLE_H */ |
affirm_table.h
#include <stdlib.h> #include <string.h> #include <stdio.h>
#include "dbt.h"
void init_DBT(DBT *key, DBT *data) { if (key != NULL) memset (key, 0, sizeof(DBT));
if (data != NULL) memset (data, 0, sizeof(DBT)); }
DBT * affirm_clear_dbt (DBT *dbt) { memset (dbt, 0, sizeof (*dbt));
return dbt; }
DBT *affirm_nodata_dbt (DBT *dbt) { affirm_clear_dbt (dbt);
/* A `nodata' dbt is one which retrieves zero bytes from offset zero, and stores them in a zero-byte buffer in user-allocated memory. */ dbt->flags |= (DB_DBT_USERMEM | DB_DBT_PARTIAL); dbt->doff = dbt->dlen = 0;
return dbt; }
DBT * affirm_set_dbt (DBT *dbt, const void *data, unsigned int size) { affirm_clear_dbt (dbt);
dbt->data = (void *) data; dbt->size = size;
return dbt; }
|
dbt.c
/* bdb_compat.c --- Compatibility wrapper for different BDB versions. * */ #include <db.h>
#include "bdb_compat.h"
int affirm_bdb_check_version (void) { int major, minor;
db_version(&major, &minor, NULL); if (major != DB_VERSION_MAJOR || minor != DB_VERSION_MINOR) return DB_OLD_VERSION; return 0; } |
bdb_compat.c
#include <string.h> #include <unistd.h>
#include "affirm_table.h" #include "bdb_compat.h" #include "dbt.h" #include "bdb_error.h"
int bdb_open(DB** dbp, char *db_name) { DB *dbtmp;
if (db_name == NULL) { return -1; }
BDB_ERR(affirm_bdb_check_version()); BDB_ERR(db_create(&dbtmp, NULL, 0)); BDB_ERR(dbtmp->open(AFFIRM_BDB_OPEN_PARAMS(dbtmp, NULL), db_name, NULL, DB_BTREE, DB_CREATE /*| AFFIRM_BDB_AUTO_COMMIT*/, 0666));
*dbp = dbtmp; return 0; }
int bdb_get(DB* dbp, DBT* key, DBT* data, char* db_name) { int db_flag = 0; DB* dbtmp = NULL;
if (key == NULL) { return -1; }
if (dbp == NULL) { int ret; if (db_name == NULL) { return -1; }
if ((ret = bdb_open(&dbtmp, db_name)) != 0) return ret; } else { dbtmp = dbp; db_flag = 1; }
BDB_ERR(dbtmp->get(dbtmp, NULL, key, data, 0));
if (0 == db_flag) { BDB_ERR(dbtmp->close(dbtmp, 0)); }
return 0; }
int bdb_put(DB* dbp, DBT* key, DBT* data, char *db_name) { int db_flag = 0; DB* dbtmp = NULL;
if (key == NULL || data == NULL) { return -1; }
if (dbp == NULL) { int ret;
if (db_name == NULL) { return -1; }
if ((ret = bdb_open(&dbtmp, db_name)) != 0) return ret; } else { dbtmp = dbp; db_flag = 1; }
BDB_ERR(dbtmp->put(dbtmp, NULL, key, data, 0)); BDB_ERR(dbtmp->sync(dbtmp, 0));
if (0 == db_flag) { BDB_ERR(dbtmp->close(dbtmp, 0)); }
return 0; }
int bdb_del(DB* dbp, DBT* key, char* db_name) { int db_flag = 0; DB* dbtmp = NULL;
if (key == NULL) { return -1; }
if (dbp == NULL) { int ret;
if (db_name == NULL) { return -1; }
if ((ret = bdb_open(&dbtmp, db_name)) != 0) return ret; } else { dbtmp = dbp; db_flag = 1; }
BDB_ERR(dbtmp-> del (dbtmp, NULL, key, 0));
if (0 == db_flag) { BDB_ERR(dbtmp->close(dbtmp, 0)); }
return 0; } |
affirm_table.c
#include <stdio.h> #include <string.h> #include <db.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h>
#include "affirm_table.h" #include "bdb_compat.h" #include "dbt.h" #include "bdb_error.h"
#define AFFIRM_BDB_FILE "/tmp/aftest.db"
void get_func(int i) { int ret; DBT key, data; memset (&data, 0, sizeof(DBT)); ret = bdb_get(NULL, affirm_set_dbt(&key, (void*)&i, sizeof(int)), &data, AFFIRM_BDB_FILE);
if (ret ==0 ) printf("get :key = %d, data = %d/n", i, *(int*)data.data); }
void put_func() { int i,r; DBT key, data; i = 4; r = bdb_put(NULL, affirm_set_dbt(&key, &i, sizeof(int)), affirm_set_dbt(&data, &i, sizeof(int)), AFFIRM_BDB_FILE); printf("put: key=%d, data=%d, ret=%d/n", *(int*)key.data, *(int*)data.data, r); }
int main() { DB *dbp; DBT key, data; int i = 0; int ret; pid_t pid;
#if 0 i++; memset(&key, 0, sizeof(DBT)); memset(&data, 0, sizeof(DBT)); key.data = &i; key.size = sizeof(int); data.data = &i; data.size = sizeof(int); #endif
unlink(AFFIRM_BDB_FILE); #if 0 ret = bdb_open(&dbp, AFFIRM_BDB_FILE); if (ret != 0) { printf("open error! ret = %d/n", ret); return -1; } #endif
pid = fork();
if (pid == 0) { int r; i = 0;
i++; r = bdb_put(NULL, affirm_set_dbt(&key, &i, sizeof(int)), affirm_set_dbt(&data, &i, sizeof(int)), AFFIRM_BDB_FILE); printf("key=%d, data=%d, ret=%d/n", *(int*)key.data, *(int*)data.data, r);
i++; r = bdb_put(NULL, affirm_set_dbt(&key, &i, sizeof(int)), affirm_set_dbt(&data, &i, sizeof(int)), AFFIRM_BDB_FILE); printf("key=%d, data=%d, ret=%d/n", *(int*)key.data, *(int*)data.data, r);
i++; r = bdb_put(NULL, affirm_set_dbt(&key, &i, sizeof(int)), affirm_set_dbt(&data, &i, sizeof(int)), AFFIRM_BDB_FILE); printf("key=%d, data=%d, ret=%d/n", *(int*)key.data, *(int*)data.data, r);
#if 0 ret = bdb_get(NULL, affirm_set_dbt(&key, (void*)&i, sizeof(int)), &data, AFFIRM_BDB_FILE); printf("ret = %d/n", ret);
if (ret ==0 ) printf("key = 3, data = %d/n", *(int*)data.data); #endif exit (0); }
printf("wait .../n"); waitpid(pid, NULL, 0); printf("wait return/n");
pid = fork(); if (pid == 0) { i = 3; memset (&data, 0, sizeof(DBT)); ret = bdb_get(NULL, affirm_set_dbt(&key, (void*)&i, sizeof(int)), &data, AFFIRM_BDB_FILE); printf("ret = %d/n", ret);
if (ret ==0 ) printf("key = 3, data = %d/n", *(int*)data.data);
exit (0); } printf("wait .../n"); waitpid(pid, NULL, 0); printf("wait return/n");
i = 3; memset (&data, 0, sizeof(DBT)); ret = bdb_get(NULL, affirm_set_dbt(&key, (void*)&i, sizeof(int)), &data, AFFIRM_BDB_FILE); printf("ret = %d/n", ret);
if (ret ==0 ) printf("key = 3, data = %d/n", *(int*)data.data);
get_func(2); put_func(); get_func(4);
return 0; } |
test.c
BIN = bdbtest OBJS = affirm_table.o bdb_compat.o dbt.o test.o CC = gcc -Wall INSTALL = /usr/bin/install -c TARGET = /var/eyouipb
.c.o: $(CC) -c $*.c
all: $(BIN)
$(BIN): $(OBJS) $(CC) -o $(BIN) $(OBJS) -ldb
clean: rm -rf $(OBJS) $(BIN)
install: install_affirm_daemon
install_affirm_daemon: $(INSTALL) $(BIN) $(TARGET)/sbin |
Makefile