tdb: 一个简单的数据库,源码:http://sourceforge.net/projects/tdb/
文档:http://tdb.samba.org/
SAMBA后端的一个数据库;基于gdbm数据库。
/* 打开数据库时返回的一个数据库上下文结构 */
typedef struct tdb_context {
char *name; /* 数据库名 */
void *map_ptr; /* where it is currently mapped */
int fd; /* open file descriptor for the database */
tdb_len map_size; /* how much space has been mapped */
int read_only; /* opened read-only */
struct tdb_lock_type *locked; /* array of chain locks */
enum TDB_ERROR ecode; /* error code for last tdb error */
struct tdb_header header; /* a cached copy of the header */
u32 flags; /* the flags passed to tdb_open */
u32 *lockedkeys; /* array of locked keys: first is #keys */
struct tdb_traverse_lock travlocks; /* current traversal locks */
struct tdb_context *next; /* all tdbs to avoid multiple opens */
dev_t device; /* uniquely identifies this tdb */
ino_t inode; /* uniquely identifies this tdb */
void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...); /* logging function */
int open_flags; /* flags used in the open - needed by reopen */
} TDB_CONTEXT;
表项元数类型:
typedef struct {
char *dptr;
size_t dsize;
} TDB_DATA;
打开数据库,如果有必要创建它:
TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode)
hash_size: 哈希值大小为顾问,使用零为默认值。
open_flags , mode : 该open_flags和模式都直接传递给open调用的数据库上文件中。
tdb_flags:
TDB_CLEAR_IF_FIRST - 清除数据库,如果我们是唯一一个打开它的
TDB_INTERNAL - 不使用文件,数据存储在内存。此时文件名被忽略。
TDB_NOLOCK - 不用锁
TDB_NOMMAP - 不用mmap
TDB_CONVERT - 在本机端的创建一个数据库
返回TDB数据库的当前错误状态:
enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb);
返回数据库错误状态的描述字符串:
const char *tdb_errorstr(TDB_CONTEXT *tdb);
关闭数据库:
int tdb_close(TDB_CONTEXT *tdb);
int tdb_update(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf);
更新数据库中一项: 只有键存在,且新的数据大小< =旧的数据大小。
失败时返回-1。
TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key);
提取数据库中给定key的值,出错时返回值为空指针,调用者必须释放所产生的数据。
int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key);
检查数据库中是否存在某个关健值,该键被发现则返回1 ,如果没有找到,则返回0;
int tdb_traverse(TDB_CONTEXT *tdb,
int (*fn)(TDB_CONTEXT *tdb,TDB_DATA key, TDB_DATA dbuf, void *state),
void *state);
遍历整个数据库 - 对每个元素都调用传入的fn函数
返回-1错误或记录的条目数
如果fn为NULL,则不调用
当fn返回一个非零值时,停止遍历
TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb);
在数据库中找到的第一个条目,并返回它的关键
调用者必须释放返回的数据
TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key);
在数据库中查找下一个条目,返回它的关键
调用者必须释放返回的数据
int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key);
用给定的关健值来删除数据库中的对应的条目。
int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
向数据库中存储一个新条目,如果key对应的条目存在,就替换掉
flag == TDB_INSERT 则不覆盖现有条目
flag == TDB_MODIFY 就不创建一个新条目
成功返回0, -1失败。
int tdb_lockall(TDB_CONTEXT *tdb);
锁定数据库。如果我们已经锁上,它什么也不做。
int tdb_unlockall(TDB_CONTEXT * TDB);
解锁数据库
int tdb_lockchain(TDB_CONTEXT *tdb, TDB_DATA key);
锁定一个散列链。这是为了可用于减少锁定争 - 它不能保证多少条记录将被锁定.
int tdb_unlockchain(TDB_CONTEXT *tdb, TDB_DATA key);
解锁一个散列链
例:
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> #include <tdb.h> void print_data(TDB_DATA d){ unsigned char *p=d.dptr; /* printf("%s\n",p); */ int len = d.dsize; while (len--) { if (isprint(*p) && !strchr("\"\\", *p)) { fputc(*p, stdout); } else { printf("\\%02X", *p); } p++; } } static int mypaser(TDB_CONTEXT*tdb,TDB_DATA key,TDB_DATA dbuf,void *state){ printf("{\n"); printf("key=\""); print_data(key); printf("\"\n"); printf("value=\""); print_data(dbuf); printf("\"\n"); printf("}\n"); return 0; } int main(int argc,char*argv[]){ TDB_CONTEXT *fd; if(argc!=2){ printf("usage:tdbedit filename!\n"); return -1; } fd=tdb_open(argv[1],0,0,O_RDONLY,0); if(!fd){ printf("failed to open %s !\n",argv[1]); return -1; } tdb_traverse(fd,mypaser,NULL); return 0; }