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

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

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

猜你喜欢

转载自blog.csdn.net/irwin_chen/article/details/8863813
BDB