Berkeley DB (BDB) C语言简单示例

来源:互联网 发布:软件配置文件用途 编辑:程序博客网 时间:2024/06/04 20:16
Berkeley DB 是嵌入式数据库系统,简单,高效。
虽然使用上个人感觉没有sqllite那么简单方便,但是从效率上来说sqllite是无法和BDB相比的。
BDB根据使用者的设置可以设置成tree型,queue型等,每种有每种不同的特点和优势。
深入研究的同学可去官网研究手册,本文仅是给入门者一个简单的hello world介绍。
本文的程序是从几年前代码里抽出来的,具体新版本是否有新函数代替是否有建议废弃的函数没有调查过,事先声明。
例子
main.c
/*** @file tt_bdb.c* @brief Simple example of BDB (QUEUE type)* @author cjx* @version * @date */#include <string.h>#include <stdlib.h>#include "tt_bdb.h"#define COMMAND_MAX_SIZE     256#define DB_FILENAME_MAX_SIZE 256#define DB_NAME "my_db"DB_ENV *myEnv;     /* Env structure handle */DB *dbp;inline void init_DBT(DBT *key, DBT *data){    memset(key, 0, sizeof(DBT));    memset(data, 0, sizeof(DBT));}   /*** @brief Set the env content** @return OK:0 / NG:other*/static int init_bdb_env(const char *db_path){    int ret = db_env_create(&myEnv, 0);    if (ret != 0) {        return 1;    }    u_int32_t g = 0;                // The size of the cache is set to gbytes gigabytes plus bytes    u_int32_t b = 32 * 1024;        // The size of the cache is set to gbytes gigabytes plus bytes    int n = 1;                      // The ncache parameter is the number of caches to create    if (myEnv->set_cachesize(myEnv, g, b, n) != 0) {        return 1;    }    u_int32_t env_flags = DB_CREATE|DB_INIT_MPOOL|DB_INIT_TXN|DB_REGISTER|DB_RECOVER;    if (myEnv->open(myEnv, db_path, env_flags, 0) != 0) {        return 1;    }    if (myEnv->get_cachesize(myEnv, &g, &b, &n) == 0) {        printf(" g: %d, b: %d, n: %d\n", g, b, n);    } else {        return 1;    }    return 0;}/*** @brief Init DB handle** @param db_filename** @return OK:0/NG:other*/static int init_bdb_db(const char *db_filename){    if (db_create(&dbp, myEnv, 0) != 0)         return 1;    u_int32_t flags;    flags = DB_CREATE ;    if ( dbp->set_re_len(dbp, sizeof(task_t)) != 0      || dbp->set_re_pad(dbp, (int)0x00)      != 0      || dbp->set_q_extentsize(dbp, 4096)     != 0 ) {        return 1;    }    if (dbp->open(dbp, NULL, db_filename, NULL, DB_QUEUE , flags, 0) != 0) {        return 1;    }    return 0;}int init_bdb(const char *path) {    char command[COMMAND_MAX_SIZE] = {0};    snprintf(command, COMMAND_MAX_SIZE - 1, "mkdir -p %s/db", path);    system(command);    char db_path[256] = {0};    snprintf(db_path, 255, "%s/db", path);    char filename[DB_FILENAME_MAX_SIZE] = {0};    snprintf(filename, DB_FILENAME_MAX_SIZE - 1, "%s/db/%s.db", path, DB_NAME);    // Real start of initializing BDB.    if (init_bdb_env(db_path) != 0) {        return 1;    }    if (init_bdb_db(filename) != 0) {        return 1;    }    return 0;}void put_bdb_task(){    int length, ret;    DBT key, data;    task_t task;    task.id = 12;   // just a example    length  = sizeof(int);    init_DBT(&key, &data);    key.size    = length;    data.data   = &(task);    data.size   = sizeof(task_t);    ret = dbp->put(dbp, NULL, &key, &data, DB_APPEND);}void get_bdb_task(){    int length, ret;    DBT key, data;    task_t task;    init_DBT(&key, &data);    key.size    = length;    data.data   = &(task);    data.size   = sizeof(task_t);    // I use cursor to get the data in this example.    // U can chose other way to get it as U need.    // dbp->get() and DB_CONSUME flag is a intresting way for QUEUE type.    DBC *cursor;        ret = dbp->cursor(dbp, NULL, &cursor, 0);    if (ret != 0) {        printf("ERROR: %s\n",db_strerror(ret));        return;    }    if ((ret = cursor->get(cursor, &key, &data, DB_NEXT)) == 0) {        int real_data = *(int*)data.data;        printf("get the data:%d\n", real_data);        cursor->del(cursor, 0);    }}

tt_bdb.c
/*** @file tt_bdb.c* @brief Simple example of BDB (QUEUE type)* @author cjx* @version * @date */#include <string.h>#include <stdlib.h>#include "tt_bdb.h"#define COMMAND_MAX_SIZE     256#define DB_FILENAME_MAX_SIZE 256#define DB_NAME "my_db"DB_ENV *myEnv;     /* Env structure handle */DB *dbp;inline void init_DBT(DBT *key, DBT *data){    memset(key, 0, sizeof(DBT));    memset(data, 0, sizeof(DBT));}   /*** @brief Set the env content** @return OK:0 / NG:other*/static int init_bdb_env(const char *db_path){    int ret = db_env_create(&myEnv, 0);    if (ret != 0) {        return 1;    }    u_int32_t g = 0;                // The size of the cache is set to gbytes gigabytes plus bytes    u_int32_t b = 32 * 1024;        // The size of the cache is set to gbytes gigabytes plus bytes    int n = 1;                      // The ncache parameter is the number of caches to create    if (myEnv->set_cachesize(myEnv, g, b, n) != 0) {        return 1;    }    u_int32_t env_flags = DB_CREATE|DB_INIT_MPOOL|DB_INIT_TXN|DB_REGISTER|DB_RECOVER;    if (myEnv->open(myEnv, db_path, env_flags, 0) != 0) {        return 1;    }    if (myEnv->get_cachesize(myEnv, &g, &b, &n) == 0) {        printf(" g: %d, b: %d, n: %d\n", g, b, n);    } else {        return 1;    }    return 0;}/*** @brief Init DB handle** @param db_filename** @return OK:0/NG:other*/static int init_bdb_db(const char *db_filename){    if (db_create(&dbp, myEnv, 0) != 0)         return 1;    u_int32_t flags;    flags = DB_CREATE ;    if ( dbp->set_re_len(dbp, sizeof(task_t)) != 0      || dbp->set_re_pad(dbp, (int)0x00)      != 0      || dbp->set_q_extentsize(dbp, 4096)     != 0 ) {        return 1;    }    if (dbp->open(dbp, NULL, db_filename, NULL, DB_QUEUE , flags, 0) != 0) {        return 1;    }    return 0;}int init_bdb(const char *path) {    char command[COMMAND_MAX_SIZE] = {0};    snprintf(command, COMMAND_MAX_SIZE - 1, "mkdir -p %s/db", path);    system(command);    char db_path[256] = {0};    snprintf(db_path, 255, "%s/db", path);    char filename[DB_FILENAME_MAX_SIZE] = {0};    snprintf(filename, DB_FILENAME_MAX_SIZE - 1, "%s/db/%s.db", path, DB_NAME);    // Real start of initializing BDB.    if (init_bdb_env(db_path) != 0) {        return 1;    }    if (init_bdb_db(filename) != 0) {        return 1;    }    return 0;}void put_bdb_task(){    int length, ret;    DBT key, data;    task_t task;    task.id = 12;   // just a example    length  = sizeof(int);    init_DBT(&key, &data);    key.size    = length;    data.data   = &(task);    data.size   = sizeof(task_t);    ret = dbp->put(dbp, NULL, &key, &data, DB_APPEND);}void get_bdb_task(){    int length, ret;    DBT key, data;    task_t task;    init_DBT(&key, &data);    key.size    = length;    data.data   = &(task);    data.size   = sizeof(task_t);    // I use cursor to get the data in this example.    // U can chose other way to get it as U need.    // dbp->get() and DB_CONSUME flag is a intresting way for QUEUE type.    DBC *cursor;        ret = dbp->cursor(dbp, NULL, &cursor, 0);    if (ret != 0) {        printf("ERROR: %s\n",db_strerror(ret));        return;    }    if ((ret = cursor->get(cursor, &key, &data, DB_NEXT)) == 0) {        int real_data = *(int*)data.data;        printf("get the data:%d\n", real_data);        cursor->del(cursor, 0);    }}
tt_bdb.h
#ifndef TT_BDB_H_#define TT_BDB_H_#include "db.h"typedef struct task {    int id;    /* sth U want to store */} task_t;int init_bdb(const char *db_path);void put_bdb_task();void get_bdb_task();#endif
编译:
gcc -o simple -Wall -Wno-format -g -DDEBUG  -I.  tt_bdb.c main.c  -I./include -L./lib  -ldb  -lpthread

有需求则增加说明或注释。无需求就放这了,貌似用这个的人也不是很多。