Chinaunix首页 | 论坛 | 博客
  • 博客访问: 858164
  • 博文数量: 150
  • 博客积分: 5123
  • 博客等级: 大校
  • 技术积分: 1478
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-06 10:03
文章分类

全部博文(150)

文章存档

2011年(2)

2010年(139)

2009年(9)

分类: 数据库开发技术

2010-09-22 21:33:00

GDBM/NDBM使用介绍 

GDBM - GNU database manager,一套简单的资料库管理函数。 

gdbm 的常见版本是1.73 ,在大部份的FreeBSD, Linux 系统中皆已提供,若未提供, 
则可利用搜寻引擎寻找gdbm-1.7.3.tar.gz 或gdbm-1.8.0.tar.gz 并下载,利用 
configure 指令即可轻松安装。 

在安装时,可以选择是否一并安装dbm 及ndbm 的相容介面。 

dbm 是UNIX 上一套古老的常见资料库处理介面,而ndbm 则是改良dbm 缺失而设计的, 
两者的介面差异颇大。 

gdbm 则是根据ndbm 的介面设计的,两者间非常相似, ndbm 的函数名称皆以dbm_ 开头, 
而gdbm 为了加以区别,则以gdbm_ 开头,除此之外,皆可对应。 

gdbm 所提供的资料库管理介面,与ndbm 非常相似,因此gdbm 的说明,也可以适用于 
ndbm 上。 

可用两种方式判断有无安装 gdbm : 
1.查询有无 gdbm 的 manpage 
  
$ man gdbm 
2.查询有无 gdbm 的 library 
  
$ ls /usr/lib/libgdbm* 

gdbm 提供一套管理key/data 类型的资料库的函数,其特征是资料库中,每笔记录都有 
一个唯一的键值。 

这种key/data 格式的资料档案其实很常见,例如: 
-------------------------------------------- 
rock: 983-1231, rock@isu.edu.tw 
xyz: 931-4321, xyz@touc.edu.tw 
-------------------------------------------- 
一个键值,一个记录内容。 

在使用gdbm 前,通常我们会用循序档来存放这类的资料,一笔一行或一区块,一
笔一笔的存下来,这样的好处是: 
1.修改方便 
  
可以用一般的文字编辑工具增修资料,不用另行设计。 
2.节省空间 
  
有多少资料就用多少空间,不像用struct 的随机档,不论资料量多少,所有 
  
记录都占同样的空间。 

但其缺点有: 
1.管理不便 
  
当记录数达数百、甚至数万笔时,继续用这种方式管理,可是件令人痛苦的事。 
2.使用负担大 
  
资料搜寻费时,所有资料都必须从头开始找,在增修资料时也很费功夫,当资料 
  
量大、使用率高时,会对系统造成负担。 

而gdbm 则是针对此缺点提出的一个解决方案,其利用hash 表存放键值,大幅节省 
搜寻时间,同时仍允许记录采用浮动长度,在时间及空间两者中取得平衡。 

其hash 表是用可扩充式hash 表演算法,会视需要自动扩充hash 表,不需担心 
hash 表的大小。 

gdbm 将资料库管理动作分成三个: 
1.storing 储存 
2.retrieval 撷取 
3.deletion 删除 

加上开启资料库及走访(visiting)的动作,提供七个主要的函数。 

再加上一个存放上述函数呼叫错误状态值的变数gdbm_errno 。 

其 prototype 如下: 
================================================= 
#include  

typedef struct { 
        
char *dptr; 
        
int dsize; 
} datum; 

extern gdbm_error gdbm_errno; 

GDBM_FILE gdbm_open (name, block_size, read_write, mode, fatal_func); 
char * name; 
int block_size, read_write, mode; 
void (*fatal_func) (); 

void gdbm_close (dbf); 
GDBM_FILE dbf; 

int gdbm_store (dbf, key, content, flag); 
GDBM_FILE dbf; 
datum key, content; 
int flag; 

datum gdbm_fetch (dbf, key); 
GDBM_FILE dbf; 
datum key; 

int gdbm_delete (dbf, key); 
GDBM_FILE dbf; 
datum key; 

datum gdbm_firstkey (dbf); 
GDBM_FILE dbf; 

datum gdbm_nextkey (dbf, key); 
GDBM_FILE dbf; 
datum key; 
================================================= 

datum 是用来表示记录键值及记录内容的structure 。 

1.gdbm_open() 
  
开启资料库。 

  
gdbm 将开启者分成reader 及writer ,在同一时间内可以有多个reader , 
  
但一次只能有一个 writer 。当指定的资料库有reader 在使用时,其他人就无 
  
法成为writer ,当有writer 在使用时,其他人就无法成为reader 或writer。 

  
GDBM_FILE 是传回给开启者的 handle 值。 

  
name 是资料库的档案名称,此档案是完整的, gdbm 不会添加其他字眼上去。 
  
而gdbm 也就只会建立这一个资料库档案,不会另外再建索引档或关连档。 

  
block_size 在建立资料库时指定,指示gdbm 以多大的记忆体区块来读写磁碟资 
  
料,此值最小是512 (bytes) ,但不妨指定0 ,由gdbm 自行根据档案系统的状 
  
态决定。 

  
read_write 在指示开启者的开启型式,可指定的有四: 
  
GDBM_READER 成为 reader 
  
GDBM_WRITER 成为 writer 
  
GDBM_WRCREAT 成为writer ,若资料库不存在则建立之 
  
GDBM_NEWDB 成为writer ,并建立新的资料库,不论是否存在旧资料库 

  
若欲成为writer ,则可以再附带一个设定值GDBM_FAST ,指示gdbm 在写入资 
  
料时,不要马上进行与磁碟内容的同步化动作。 
  
此行为在 gdbm 1.8 后,为预设动作。 

  
mode 在指示建立资料库时,档案的属性,其意义同chmod() 。 
  
一般设为0644 (rw-r--r--),若没有建立资料库的动作,则指定0 即可。 

  
Fatal_func 为函数指标,当开启资料库,发现一个错误时,就呼叫该函数, 
  
一般皆设为NULL ,由gdbm 自行以预设动作处理。 

  
当gdbm 无法成为reader 或writer 时,会立即返回,而不会自动搁置, 
  
此时gdbm_open() 传回NULL ,可由gdbm_errno 得知错误状态码。 

  
范例: 
  
--------------------------------------- 
  
GDBM_FILE dbf; 
  
dbf = gdbm_open("mydata.db", 0, GDBM_READER, 0, NULL); 
  
if( dbf == NULL ) { 
    
printf("Can not open database\n, %s\n", gdbm_strerror(gdbm_errno) ); 
  

  
--------------------------------------- 


2.gdbm_close() 
  
关闭资料库,不会有错误传回。 

  
范例: 
  
--------------------------------------- 
  
gdbm_close(dbf); 
  
--------------------------------------- 

3.gdbm_store() 
  
储存记录。 

  
将记录键值及记录内容存入资料库中,存入动作分为增加及替代,在flag 中指定, 
  
其值有二: 
  
GDBM_INSERT 增加一笔新记录,若键值已存在,则储存动作失败。 
  
GDBM_REPLACE 替代记录内容。 

  
其传回值有三: 
  
-1 无法储存。 
  
0 储存成功。 
  
1 当使用GDBM_INSERT 时,键值已存在,无法储存。 

  
范例: 
  
--------------------------------------- 
  
char keybuf[256], databuf[256]; 
  
datum key, data; 

  
gets(keybuf); 
  
gets(databuf); 

  
key.dptr = keybuf; key.dsize = strlen(keybuf); 
  
data.dptr = databuf; data.dsize = strlen(databuf); 

  
rc = gdbm_store(dbf, key, data, GDBM_INSERT); 
  
if( rc != 0 ) { 
    
printf("Can not store record\n, %s\n", gdbm_strerror(gdbm_errno) ); 
  

  
--------------------------------------- 

  
注意,这里示范的是资料键值及内容都是一般文字,如果键值及内容中,包 
  
含'\0' 时,就不能用strlen() 去计算size 了。 

4.gdbm_fetch() 
  
根据指定键值撷取记录。 

  
传回记录的内容,要注意的是,记录内容的空间是由gdbm 以malloc() 配置的, 
  
但gdbm 不会自动释放,故当你不再使用该资料时,记得将其释放。 

  
若记录内容指向 NULL ,表无此记录。 

  
范例: 
  
--------------------------------------- 
  
char keybuf[256]; 
  
datum key, data; 

  
gets(keybuf); 
  
key.dptr = keybuf; key.dsize = strlen(keybuf); 

  
data = gdbm_fetch(dbf, key); 
  
if( data.dptr == NULL ) { 
    
puts("Record not found!\n"); 
  

  
else { 
    
printf("Record found (%d): %s", data.dsize, data.dptr); 
    
free(data.dptr); 
  

  
--------------------------------------- 

  
若你只是单纯地想查询键值是否已存在于资料库,而不想撷取资料内容时,可以使 
  
用gdbm_exists(dbf, key) ,其传回非零值(true)时,表示键值存在。 

5.gdbm_delete() 
  
根据指定键值移除记录。 

  
传回0 表示成功删除, -1 表示删除失败。 

  
范例: 
  
--------------------------------------- 
  
char keybuf[256]; 
  
datum key; 

  
gets(keybuf); 
  
key.dptr = keybuf; key.dsize = strlen(keybuf); 

  
rc = gdbm_delete(dbf, key); 
  
if( rc != 0 ) 
    
printf("Record can not delete.\n %s", gdbm_strerror(gdbm_errno)); 
  
--------------------------------------- 

6.gdbm_firstkey() / gdbm_nextkey() 
  
走访资料库。 

  
根据hash 表走访资料库,由于其并非根据资料存入顺序或键值的排序走访,因此
  
走访结果并无次序,但可以保证的是,每笔记录都会被走访一次,不会遗漏。 

  
key.dptr 是由gdbm 以malloc() 配置的,但gdbm 不会自动释放,故当你走访完 
  
毕时,记得将其释放。 

  
当key.dptr 指向NULL 时,表示走访完毕。 

  
注意,当你在走访资料库时,不要增加或删除任何记录,因为这将改变hash 表的
  
内容,造成其走访时的遗漏。 

  
范例: 
  
--------------------------------------- 
  
datum key, nextkey; 
  
int n = 1; 

  
puts("Key list:\n"); 
  
key = gdbm_firstkey(dbf); 
  
while( key.dptr != NULL ) { 
    
printf("%d: %s", n, key.dptr); 
    
n++; 
    
nextkey = gdbm_nextkey(dbf, key); 
    
free(key.dptr); 
    
key = nextkey; 
  

  
--------------------------------------- 

7.gdbm_reorganize() 
  
重整资料库。 

  
这个函数使用时,请再三斟酌,不要常使用。 

  
随着资料库的增删,时间一久,资料库中,就会留下许多未被使用的空隙,此时可 
  
呼叫gdbm_reorganize(dbf) 进行资料库的重整,去除那些空隙,适度缩减资料库 
  
档案的大小。 

  
除非呼叫gdbm_reorganize() ,否则gdbm 不会缩减资料库档案的长度,但是gdbm 
  
也不是一直往后增加资料,当旧有资料被删除时, gdbm 会尽然重复使用那些空下来 
  
的空间。 

附注: 

1.参考文件 GDBM(3), gdbm.h 
  
详细说明请参阅此 manpage 。 
  
$ man gdbm 

2.在本文中,一共提到了十个gdbm 函数及一个gdbm 变数: 
  
gdbm_open() 
  
gdbm_close() 
  
gdbm_store() 
  
gdbm_fetch() 
  
gdbm_delete() 
  
gdbm_firstkey() 
  
gdbm_nextkey() 
  
gdbm_exists() 
  
gdbm_reorganize() 
  
gdbm_strerror() 
  
gdbm_errno 

  
reader 无法使用gdbm_store(), gdbm_delete() 及gdbm_reorganize() 。
阅读(16057) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-09-26 15:45:07

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com