文件中的空间是以gdbm_file_header.block_size进行分配的,如果有一些小的文件空间,则用多个avail_elem进行管理。
typedef struct {
int av_size; /*大小*/
off_t av_adr; /*文件中的偏移量*/
}avail_elem;
typedef struct {
int size; /*一个block中的avail_elem总数目*/
int count; /*表中的有效的元素计数*/
off_tnext_block; /*下一个可用块的地址*/
avail_elemav_table[1]; /*数组*/
}avail_block;
上面的next_block会形成一个链表,有大量的avail_elem,则push_avail_block,把一部分压入到链表中,如果只有少量的avail_elem,则pop_avail_block,则弹出一个,合并到当前的avail_block.av_table中。
typedef struct {
int header_magic; /*文件的版本信息*/
int block_size; /*最佳的块大小 */
off_t dir; /* hash directory table在文件中偏移量*/
int dir_size; /* hash directory table的大小*/
int dir_bits; /*dir_size用二进制表示,最高位1的位置*/
int bucket_size; /*一个hash bucket的大小*/
int bucket_elems; /*一个hash bucket中元素数目*/
off_tnext_block; /*下一个未分配块的偏移量(总是文件的尾部)*/
avail_blockavail; /*这个结构体必须放在后面,因为后面会有一个数组*/
} gdbm_file_header;
gdbm_file_header结构体中的dir,dir_size,dir_bits三个成员用来描述hash directory table在文件中的保存情况,如果dir_size为8,则dir_bits为3。gdbm_file_header总是存在于文件的开始外;dir的位置不确定,因为dir_size的大小会随着内容的增多,而不断的增长;hash_bucket之间也很可能是不连续的,一个hash_bucket总是占有block_size的大小。dir实际上是一棵有点类似二叉树,在hash的时候会用上。一种可能的文件保存情况如下。
在gdbm中对文件空间进行管理,对于falloc.c文件提供的两个函数接口分别为:
off_t_gdbm_alloc(GDBM_FILE dbf, int num_bytes);
void _gdbm_free(GDBM_FILEdbf, off_t file_adr, int num_butes);
在_gdbm_alloc查找num_bytes大小的空间时。有三处管理着可用的文件空间,第一处是在hash_bucket.bucket_avail[]中;第二处是在gdbm_file_header.avail.av_table[],且是空间大小是升序的,以及gdbm_file_header.avail.next_block,形成一个链表;第三处是在gdbm_file_header.next_block中,总是指向未管理的空间尾部,请求的顺序也这样进行的。