-------------
GDBM 使用範例
以下我提供了三個完整的程式範例,示範 GDBM 的使用。
在編譯,必須連結 gdbm 這個 library ,如下:
$ gcc -O db_add.c -o db_add -lgdbm
------------------------------------------------
/* db_add.c: storing
written by rock, 1999.11.29
*/
#include <stdlib.h>
#include <stdio.h>
#include <gdbm.h>
#define datum_set(um, buf) { um.dptr = buf; um.dsize = strlen(buf); }
int main(int argc, char *args[]) {
char keyb[256], datab[256], *dbname;
GDBM_FILE dbf;
datum key, data;
if( argc < 2) {
puts("Usage: db_add <dbname>\n");
return 1;
}
dbname = args[1];
if( !(dbf = gdbm_open(dbname, 0, GDBM_WRCREAT, 0644, NULL)) ) {
printf("%s\n", gdbm_strerror(gdbm_errno));
return 1;
}
puts("Input key: ");
gets(keyb);
puts("Input data: ");
gets(datab);
datum_set(key, keyb);
datum_set(data, datab);
if( gdbm_store(dbf, key, data, GDBM_INSERT) ) {
printf("%s\nRecord may be exist.\n", gdbm_strerror(gdbm_errno));
gdbm_close(dbf);
return 1;
}
puts("Storing record successed.\n");
gdbm_close(dbf);
return 0;
}
------------------------------------------------
/* db_ls.c: retrieval
written by rock, 1999.11.29
*/
#include <stdlib.h>
#include <stdio.h>
#include <gdbm.h>
int main(int argc, char *args[]) {
GDBM_FILE dbf;
datum key, next, data;
int n = 1;
char *dbname;
if( argc < 2) {
puts("Usage: db_ls <dbname>\n");
return 1;
}
dbname = args[1];
dbf = gdbm_open(dbname, 0, GDBM_READER, 0, NULL);
if(!dbf) {
printf("%s\n", gdbm_strerror(gdbm_errno));
return 1;
}
key = gdbm_firstkey(dbf);
while( key.dptr ) {
data = gdbm_fetch(dbf, key);
printf("(%d) %s:\t%s\n", n++, key.dptr, data.dptr);
next = gdbm_nextkey(dbf, key);
free(key.dptr);
key = next;
}
gdbm_close(dbf);
return 0;
}
------------------------------------------------
/* db_rm.c: deletion
written by rock, 1999.11.29
*/
#include <stdlib.h>
#include <stdio.h>
#include <gdbm.h>
int main(int argc, char *args[]) {
GDBM_FILE dbf;
char keyb[256], *dbname;
datum key;
if( argc < 2) {
puts("Usage: db_rm <dbname>\n");
return 1;
}
dbname = args[1];
dbf = gdbm_open(dbname, 0, GDBM_WRITER, 0, NULL);
if( !dbf ) {
printf("%s\n", gdbm_strerror(gdbm_errno));
return 1;
}
puts("Input key: ");
gets(keyb);
key.dptr = keyb; key.dsize = strlen(keyb);
if(gdbm_delete(dbf, key)) {
printf("%s\n", gdbm_strerror(gdbm_errno));
gdbm_close(dbf);
return 1;
}
puts("Removing record successed\n");
gdbm_close(dbf);
return 0;
}
------------------------------------------------
使用結果示範如下:
------------------------------------------------
$ db_add
Usage: db_add <dbname>
$ db_add email_list.db
Input key:
rock
Input data:
shirock@residence.educities.edu.tw, 847-1023
Storing record successed.
$ db_ls email_list.db
(1) rock: shirock@residence.educities.edu.tw, 847-1023
$ db_rm email_list.db
Input key:
abc
Item not found
$ db_rm email_list.db
Input key:
rock
Removing record successed
------------------------------------------------
還有一個使用上的問題是,當你的程式可能運作在多人同時操作的環境時, GDBM 在無法
開啟時,不擱置立即返回的特色,可能會造成程式設計上的困擾。一般你需要再加上一個
防衛措施,故且稱為衛兵,在開啟資料庫前,先通過這個衛兵的檢查,如果你可以立即取
得資料庫的使用權,再呼叫 gdbm_open() 開啟資料庫。 若無法立即取得,則由衛兵將此
工作擱置下來。
這個衛兵需要具有共用、互斥的防衛機制,一般會透過 semaphore (信號) 或是 locking
(檔案鎖定) 來實作。
檔案鎖定的方式,則是另外建立一個檔案,就稱為衛兵好了,當欲成為資料庫的 reader
時,先開啟這個衛兵,然後以 SHLOCK (共享鎖定) 的方式鎖上衛兵,若目前無法上鎖,
系統就會將工作自動擱置下來。若欲成為資料庫的 writer ,則對此衛兵以 EXLOCK (互
斥鎖定) 的方式上鎖。
在 BSD 上提供的檔案鎖定函數叫 flock() ,在 SYSV 上提供的叫 lockf() ,但我強烈
建議使用 POSIX 所規範的 fcntl() 上鎖方式,此方式具有普遍性及一致性。