GDBM 使用 C 語言範例 來源:石頭閒語
-------------
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() 上鎖方式,此方式具有普遍性及一致性。

小恐龍工作坊 提供