引
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
有需求则增加说明或注释。无需求就放这了,貌似用这个的人也不是很多。