简介
使用hash算法可以提高数据的查询效率。若结构中存在和关键字K相等的记录,则必定在f(K)的存储位置上。由此,不需比较便可直接取得所查记录。称这个对应关系f为散列函数(Hash function),按这个事先建立的表为散列表。
使用
结构体关联hash表
struct disable_list {
OMAPI_OBJECT_PREAMBLE;
struct hardware hw_address; /* Its physical address. */
};
1、dhcpd.h文件中重定义一个hash表的类型
typedef struct hash_table disable_list_hash_t;
2、dhcpd.h文件中声明hash函数
HASH_FUNCTIONS_DECL (disableList, const unsigned char *, struct disable_list, disable_list_hash_t)
宏定义如下:
#define HASH_FUNCTIONS_DECL(name, bufarg, type, hashtype) \
void name##_hash_add (hashtype *, bufarg, unsigned, type *, \
const char *, int); \
void name##_hash_delete (hashtype *, bufarg, unsigned, \
const char *, int); \
int name##_hash_lookup (type **, hashtype *, bufarg, unsigned, \
const char *, int); \
unsigned char * name##_hash_report(hashtype *); \
int name##_hash_foreach (hashtype *, hash_foreach_func); \
int name##_new_hash (hashtype **, unsigned, const char *, int); \
void name##_free_hash_table (hashtype **, const char *, int);
3、dhcpd.h声明内存申请操作的函数
OMAPI_OBJECT_ALLOC_DECL (disableList, struct disable_list, dhcp_type_disable_list)
宏定义如下:
#define OMAPI_OBJECT_ALLOC_DECL(name, stype, type) \
isc_result_t name##_allocate (stype **p, const char *file, int line); \
isc_result_t name##_reference (stype **pptr, stype *ptr, \
const char *file, int line); \
isc_result_t name##_dereference (stype **ptr, const char *file, int line);
4、dhcpd.h、dhcpd.cpp中声明和定义omapi_object_type_t结构中函数
isc_result_t dhcp_disableList_set_value (omapi_object_t *h, omapi_object_t *id,
omapi_data_string_t *name,
omapi_typed_data_t *value);
isc_result_t dhcp_disableList_get_value (omapi_object_t *h, omapi_object_t *id,
omapi_data_string_t *name,
omapi_value_t **value);
isc_result_t dhcp_disableList_destroy (omapi_object_t *h, const char *file, int line);
isc_result_t dhcp_disableList_lookup (omapi_object_t **lp,
omapi_object_t *id, omapi_object_t *ref);
isc_result_t dhcp_disableList_signal_handler (omapi_object_t *h,
const char *name, va_list ap);
isc_result_t dhcp_disableList_stuff_values (omapi_object_t *c, omapi_object_t *id,
omapi_object_t *h);
isc_result_t dhcp_disableList_create (omapi_object_t **lp,
omapi_object_t *id);
isc_result_t dhcp_disableList_remove (omapi_object_t *lp,
omapi_object_t *id);
5、dhcpd.h中声明hash表disable_list_hw_addr_hash
extern disable_list_hash_t *disable_list_hw_addr_hash;
6、mdb.c文件中定义hash表
disable_list_hash_t *disable_list_hw_addr_hash;
7、salloc.c文件中定义omapi对象申请的接口
extern omapi_object_type_t *dhcp_type_disable_list;
OMAPI_OBJECT_ALLOC (disableList, struct disable_list, dhcp_type_disable_list)
宏定义如下:
#define OMAPI_OBJECT_ALLOC(name, stype, type) \
isc_result_t name##_allocate (stype **p, const char *file, int line) \
{ \
return omapi_object_allocate ((omapi_object_t **)p, \
type, 0, file, line); \
} \
\
isc_result_t name##_reference (stype **pptr, stype *ptr, \
const char *file, int line) \
{ \
return omapi_object_reference ((omapi_object_t **)pptr, \
(omapi_object_t *)ptr, file, line); \
} \
\
isc_result_t name##_dereference (stype **ptr, const char *file, int line) \
{ \
return omapi_object_dereference ((omapi_object_t **)ptr, file, line); \
}
8、mdb.c文件中hash函数的定义
HASH_FUNCTIONS (disableList, const unsigned char *, struct disable_list, disable_list_hash_t,
disableList_reference, disableList_dereference, do_string_hash)
9、omapi.c文件中声明对象类型和注册
omapi_object_type_t *dhcp_type_disable_list;
status = omapi_object_type_register (&dhcp_type_disable_list,
"disableList",
dhcp_disableList_set_value,
dhcp_disableList_get_value,
dhcp_disableList_destroy,
dhcp_disableList_signal_handler,
dhcp_disableList_stuff_values,
dhcp_disableList_lookup,
dhcp_disableList_create,
dhcp_disableList_remove, 0, 0, 0,
sizeof (struct disable_list),
0, RC_MISC);
if (status != ISC_R_SUCCESS)
log_fatal ("Can't register disalbeList object type: %s",
isc_result_totext (status));
测试
使用ATF架添加测试用例
void disable_list_hash_test() {
printf("Enter disable_list_hash_test.\n");
dhcp_db_objects_setup ();
dhcp_common_objects_setup ();
struct disable_list *list = 0;
struct disable_list *check = 0;
struct hardware hw_addr;
memset(&hw_addr, 0x00, sizeof(hw_addr));
hw_addr.hlen = sizeof(hw_addr.hbuf);
u_int8_t mac[] = {"00:0c:29:5e:1e:67"};
memcpy(hw_addr.hbuf, mac, sizeof(mac));
ATF_CHECK_MSG(disableList_allocate(&list, MDL) == ISC_R_SUCCESS,
"Failed to allocate list");
memcpy(&list->hw_address, &hw_addr, sizeof(hw_addr));
ATF_CHECK_MSG(list->refcnt == 1, "Invalid refcnt for list");
ATF_CHECK_MSG(disableList_new_hash(&disable_list_hw_addr_hash, HOST_HASH_SIZE, MDL) != 0,
"Unable to create new hash");
ATF_CHECK_MSG(disableList_hash_lookup(&check, disable_list_hw_addr_hash, hw_addr.hbuf,
hw_addr.hlen, MDL) == 0,
"disable list is not supposed to be in the uid_hash.");
disableList_hash_add(disable_list_hw_addr_hash, hw_addr.hbuf, hw_addr.hlen, list, MDL);
ATF_CHECK_MSG(list->refcnt == 2, "Invalid refcnt for list");
ATF_CHECK_MSG(disableList_hash_lookup(&check, disable_list_hw_addr_hash, hw_addr.hbuf,
hw_addr.hlen, MDL),
"disable list is not supposed to be in the uid_hash.");
ATF_CHECK_MSG(list->refcnt == 3, "Invalid refcnt for list");
printf("hw len:%d.\n", check->hw_address.hlen);
printf("hw addr:%s.\n", check->hw_address.hbuf);
disableList_hash_delete(disable_list_hw_addr_hash, hw_addr.hbuf, hw_addr.hlen, MDL);
ATF_CHECK_MSG(list->refcnt == 2, "Invalid refcnt for list");
disableList_dereference(&check, MDL); /* we don't need it now */
disableList_dereference(&list, MDL); /* we don't need it now */
if (list == 0) {
printf("success.\n");
}
}