1. 打开Duplicate keys的功能。在ham_create_ex or ham_env_create_db中将flags参数设置为HAM_ENABLE_DUPLICATES。
ham_create_ex(db, "test.db", HAM_ENABLE_DUPLICATES, 0664, 0)
2. 插入重复数据。在调用ham_insert or ham_cursor_insert时将flags参数设置为HAM_DUPLICATE。通过ham_cursor_insert可以改变插入数据的顺序,如HAM_DUPLICATE_INSERT_BEFORE, HAM_DUPLICATE_INSERT_AFTER, HAM_DUPLICATE_INSERT_FIRST or HAM_DUPLICATE_INSERT_LAST,ham_insert的缺省行为是HAM_DUPLICATE_INSERT_LAST。
3. 遍历重复keys。ham_find(总是返回重复key的第一条记录),然后再通过ham_cursor_move函数进行duplicate keys的遍历,HAM_SKIP_DUPLICATES标志将跳过后面的重复键,HAM_ONLY_DUPLICATES标志将只是遍历重复键。
4. 替换重复keys,ham_cursor_overwrite或者ham_insert函数的flags参数设置为HAM_OVERWRITE。
5. 获取重复键的数量,ham_cursor_get_duplicate_count,对于非重复键,该函数返回1,否则返回重复键的记录数。
6. 删除重复键,ham_erase将删除该重复键的所有记录,ham_cursor_erase只是删除当前cursor指向的记录。
7. 给重复键排序,在创建数据库的时候同时指定这两个flags,HAM_SORT_DUPLICATES | HAM_ENABLE_DUPLICATES。
同时安装一下回调函数
typedef int HAM_CALLCONV (*ham_duplicate_compare_func_t)(ham_db_t *db,const ham_u8_t *lhs, ham_size_t lhs_length,const ham_u8_t *rhs, ham_size_t rhs_length);
以下函数为回调函数安装函数。
ham_status_t ham_set_duplicate_compare_func(ham_db_t *db, ham_duplicate_compare_func_t foo);
事物:
1. 同一数据库在同一时刻只能存在同一个事物,包括隐性事物也不能和显示事物同时存在,以下函数为隐性事物ham_insert, ham_find, ham_erase, ham_cursor_create和ham_env_erase_db。
2. 在ENV或者DB中打开事物功能,在创建环境或者数据库的时候将flag参数设置为HAM_ENABLE_TRANSACTIONS。如下:
ham_env_create_ex(env, "test.db", HAM_ENABLE_TRANSACTIONS, 0644, 0)
3. 开始一个新事物:ham_status_t ham_txn_begin(ham_txn_t **txn, ham_db_t *db, ham_u32_t flags)
4. 应用事物:以下四个函数可以和事物一起使用。
* ham_insert
* ham_erase
* ham_find
* ham_cursor_create
注意:ham_cursor_create函数创建的游标将和attached的事物共享相同的生命周期,因此在commit或者abort事物之前,必须先close游标。
5. 提交和放弃
ham_status_t ham_txn_commit(ham_txn_t *txn, ham_u32_t flags)
ham_status_t ham_txn_abort(ham_txn_t *txn, ham_u32_t flags)
数据操作和游标
1. 设置自定义比较函数。
static int my_int_compare(ham_db_t *db, ham_u8_t *lhs, ham_size_t lhs_size, ham_u8_t *rhs, ham_size_t rhs_size) {
int nlhs=*(int *)lhs;
int nrhs=*(int *)rhs;
if (nlhs<nrhs) return -1;
if (nrhs>nlhs) return +1;
return 0;
}
int main(int argc, char **argv)
{
ham_status_t st;
ham_db_t *db;
if ((st=ham_new(&db))!=HAM_SUCCESS) {
printf("ham_new failed: %d (%s)\n", st, ham_strerror(st));
exit(-1);
}
if ((st=ham_set_compare_func(db, my_int_compare))!=HAM_SUCCESS) {
printf("ham_set_compare_func failed: %d (%s)\n", st, ham_strerror(st));
exit(-1);
}
if ((st=ham_create_ex(db, "test.db", 0, 0664))!=HAM_SUCCESS) {
printf("ham_create_ex failed: %d (%s)\n", st, ham_strerror(st));
exit(-1);
}
// ...
}
2. ham_insert,插入数据。 当flags参数设置为HAM_DUPLICATE时,如果该key已经存在,则插入重复键。flags为HAM_OVERWRITE时,如果该key已经存在则覆盖它。flags如果没有被指定,当key重复时,insert操作将报错。注意,insert之前需要将key和value这两个结构体先初始化为0.
void example_of_insert() {
ham_key_t key;
ham_record_t record;
memset(&key, 0, sizeof(key));
memset(&record, 0, sizeof(record));
.
key.data="color";
key.size=strlen(key.data)+1; /* +1 for the terminating zero-byte */
record.data="green";
record.size=strlen(record.data)+1; /* +1 for the terminating zero-byte */
.
if ((st=ham_insert(db, NULL, &key, &record, 0))!=HAM_SUCCESS) {
printf("ham_insert failed: %d (%s)\n", st, ham_strerror(st));
exit(-1);
}
}
3. ham_find,查找数据。基于指定的key查找。
void example_of_find() {
ham_status_t st;
ham_key_t key;
ham_record_t record;
memset(&key, 0, sizeof(key));
memset(&record, 0, sizeof(record));
key.data="color";
key.size=strlen(key.data)+1; /* +1 for the terminating zero-byte */
.
if ((st=ham_find(db, NULL, &key, &record, 0))!=HAM_SUCCESS) {
printf("ham_find failed: %d (%s)\n", st, ham_strerror(st));
exit(-1);
}
}
注意:这里的record.data的内存空间是由hamsterdb内部分配,因此只要在调用任何hamsterdb的任何函数,该数据可能会被覆盖,如果打算自行分配内存,如下:
memset(&record, 0, sizeof(record));
record.flags=HAM_RECORD_USER_ALLOC;
record.data=malloc(6);
.
if ((st=ham_find(db, NULL, &key, &record, 0))!=HAM_SUCCESS) {
// ...
}
这里内存分配是否可以容纳所有record数据,需要自行判断。
4. hamsterdb可以读取和替换已存在record的partial data。
5. hamsterdb针对ham_find or ham_cursor_find两个函数都提供了近似查找的flag,如ham_find(db, NULL, &key, &record, HAM_FIND_NEAR_MATCH)。
* HAM_FIND_EXACT_MATCH: This is the default setting. If exactly this key exists then the record of this key will be returned.
* HAM_FIND_LT_MATCH ‘find’ flag ‘Less Than’: retrieves the last record with a key which is less than the specified key.
* HAM_FIND_GT_MATCH ‘find’ flag ‘Greater Than’: retrieves the first record with a key which is greater than the specified key.
* HAM_FIND_LEQ_MATCH ‘find’ flag ‘Less or EQual’: retrieves the last record with a key which is less or equal than the specified key.
* HAM_FIND_GEQ_MATCH ‘find’ flag ‘Greater or Equal’: retrieves the first record with a key which is greater or equal than the specified key.
* HAM_FIND_NEAR_MATCH ‘find’ flag ‘Any Near Or Equal’: retrieves the record which’ key matches the specified key and when such a key is not available hamsterdb will retrieve either the last record which’ key is less than the specified key or the first record which’ key is larger than the specified key, whichever of these records is located first.
6. 游标操作相关的函数:
1) ham_status_t ham_cursor_create(ham_db_t *db, ham_txn_t *txn, ham_u32_t flags, ham_cursor_t **cursor);
2) ham_status_t ham_cursor_move(ham_cursor_t *cursor, ham_key_t *key, ham_record_t *record, ham_u32_t flags);
3) ham_status_t ham_cursor_insert(ham_cursor_t *cursor, ham_key_t *key, ham_record_t *record, ham_u32_t flags);
4) ham_status_t ham_cursor_find(ham_cursor_t *cursor, ham_key_t *key, ham_u32_t flags);
5) ham_status_t ham_cursor_overwrite(ham_cursor_t *cursor, ham_record_t *record, ham_u32_t flags);
6) ham_status_t ham_cursor_erase(ham_cursor_t *cursor, ham_u32_t flags);
7) ham_status_t ham_cursor_clone(ham_cursor_t *src, ham_cursor_t **dest);
8) ham_status_t ham_cursor_close(ham_cursor_t *cursor);
7. hamsterdb关闭:
1) ham_status_t ham_close(ham_db_t *db, ham_u32_t flags); 该函数只是关闭数据库,可以重新打开。
2) ham_status_t ham_delete(ham_db_t *db); 该函数将删除ham_new创建的数据库句柄,以防止内存泄露。