rbtree和hash的全量持久化操作。rbtree的二进制安全。

粗略测试。
This commit is contained in:
2026-01-08 21:42:20 +08:00
parent de21fe94ec
commit 4b4e06b33d
16 changed files with 1997 additions and 1450 deletions

View File

@@ -38,224 +38,7 @@ void kvs_array_destroy(kvs_array_t *inst) {
}
#if BIN_SAFE
/**
* return: ==-2 not exist, == -1 error, >= 0 exist idx
*/
int kvs_array_find_index(kvs_array_t *inst, const void *key, uint32_t key_len) {
if (!inst || !inst->table || !key) return -1;
for (int i = 0; i < inst->total; i++) {
kvs_array_item_t *it = &inst->table[i];
if (!it->key) continue;
if (it->key_len == key_len && memcmp(it->key, key, key_len) == 0) {
return i;
}
}
return -2; // not found
}
/*
* return: <0 error; 0 success; 1 exist
*/
int kvs_array_set_bin(kvs_array_t *inst,
const void *key, uint32_t key_len,
const void *value, uint32_t value_len) {
if (!inst || !inst->table || !key || key_len == 0 || !value) return -1;
if (inst->total >= KVS_ARRAY_SIZE) return -1;
int idx = kvs_array_find_index(inst, key, key_len);
// -2 not exist
if (idx >= 0) return 1; // exist
if (idx == -1) return -1; // error
uint8_t *kcopy = (uint8_t *)kvs_malloc(key_len);
if (!kcopy) return -2;
memcpy(kcopy, key, key_len);
uint8_t *vcopy = NULL;
if (value_len > 0) {
vcopy = (uint8_t *)kvs_malloc(value_len);
if (!vcopy) {
kvs_free(kcopy);
return -2;
}
memcpy(vcopy, value, value_len);
} else {
// 允许空 value长度0value 指针置 NULL
vcopy = NULL;
}
int i = 0;
for (i = 0;i < inst->total;i ++) {
if (inst->table[i].key == NULL) {
inst->table[i].key = kcopy;
inst->table[i].key_len = key_len;
inst->table[i].value = vcopy;
inst->table[i].value_len = value_len;
inst->total ++;
return 0;
}
}
if (i == inst->total && i < KVS_ARRAY_SIZE) {
inst->table[i].key = kcopy;
inst->table[i].key_len = key_len;
inst->table[i].value = vcopy;
inst->table[i].value_len = value_len;
inst->total ++;
}
return 0;
}
void *kvs_array_get_bin(kvs_array_t *inst, const void *key, uint32_t key_len, uint32_t *out_value_len) {
if (out_value_len) *out_value_len = 0;
if (!inst || !inst->table || !key || key_len == 0) return NULL;
int idx = kvs_array_find_index(inst, key, key_len);
if (idx < 0) return NULL;
kvs_array_item_t *it = &inst->table[idx];
if (out_value_len) *out_value_len = it->value_len;
return it->value; // 注意:由 store 持有
}
int kvs_array_del_bin(kvs_array_t *inst, const void *key, uint32_t key_len) {
if (!inst || !inst->table || !key || key_len == 0) return -1;
int idx = kvs_array_find_index(inst, key, key_len);
if (idx == -2) return 1; // not exist
if (idx < 0) return -1;
kvs_array_item_t *it = &inst->table[idx];
if (it->key) kvs_free(it->key);
if (it->value) kvs_free(it->value);
// 用末尾元素填洞,保证 total 连续,避免 “total 只增不减” 问题
int last = inst->total - 1;
if (idx != last) {
inst->table[idx] = inst->table[last];
}
// 清理末尾(已被移动或删除)
memset(&inst->table[last], 0, sizeof(kvs_array_item_t));
inst->total--;
return 0;
}
int kvs_array_mod_bin(kvs_array_t *inst,
const void *key, uint32_t key_len,
const void *value, uint32_t value_len) {
if (!inst || !inst->table || !key || key_len == 0 || !value) return -1;
int idx = kvs_array_find_index(inst, key, key_len);
if (idx == -2) return 1; // not exist
if (idx < 0) return -1;
kvs_array_item_t *it = &inst->table[idx];
uint8_t *vcopy = NULL;
if (value_len > 0) {
vcopy = (uint8_t *)kvs_malloc(value_len);
if (!vcopy) return -2;
memcpy(vcopy, value, value_len);
} else {
vcopy = NULL;
}
if (it->value) kvs_free(it->value);
it->value = vcopy;
it->value_len = value_len;
return 0;
}
int kvs_array_exist_bin(kvs_array_t *inst, const void *key, uint32_t key_len) {
if (!inst || !inst->table || !key || key_len == 0) return -1;
int idx = kvs_array_find_index(inst, key, key_len);
return (idx >= 0) ? 0 : 1;
}
// return: 0 success, <0 error
int kvs_array_save(kvs_array_t *inst, const char* filename){
if(!inst || !filename) return -1;
FILE *fp = fopen(filename, "wb");
if(!fp) return -2;
for(int i = 0;i < inst->total; ++ i){
kvs_array_item_t *it = &inst->table[i];
if(!it->key || it->key_len == 0) continue; // 跳过空槽
if(it->value_len > 0 && !it->value) { fclose(fp); return -3; }
uint32_t klen = htonl(it->key_len);
uint32_t vlen = htonl(it->value_len);
if (kvs_write_file(fp, &klen, 4) < 0) { fclose(fp); return -4; }
if (kvs_write_file(fp, &vlen, 4) < 0) { fclose(fp); return -4; }
if (kvs_write_file(fp, it->key, it->key_len) < 0) { fclose(fp); return -4; }
if (it->value_len > 0) {
if (kvs_write_file(fp, it->value, it->value_len) < 0) { fclose(fp); return -4; }
}
}
fclose(fp);
return 0;
}
int kvs_array_load(kvs_array_t *inst, const char* filename) {
if (!inst || !filename) return -1;
if (!inst->table) return -1;
FILE *fp = fopen(filename, "rb");
if (!fp) return -2;
int idx = 0;
while(1){
uint32_t klen = 0, vlen = 0;
if (kvs_read_file(fp, &klen, 4) < 0) { fclose(fp); return -3; }
if (kvs_read_file(fp, &vlen, 4) < 0) { fclose(fp); return -3; }
klen = ntohl(klen);
vlen = ntohl(vlen);
if (klen == 0) { fclose(fp); return -3; }
kvs_array_item_t *it = &inst->table[idx];
memset(it, 0, sizeof(*it));
it->key = (uint8_t *)kvs_malloc(klen);
if (!it->key) { fclose(fp); return -3; }
it->key_len = klen;
if (kvs_read_file(fp, it->key, klen) < 0) { fclose(fp); return -3; }
if (vlen > 0) {
it->value = (uint8_t *)kvs_malloc(vlen);
if (!it->value) { fclose(fp); return -4; }
it->value_len = vlen;
if (kvs_read_file(fp, it->value, vlen) < 0) { fclose(fp); return -3; }
} else {
it->value = NULL;
it->value_len = 0;
}
inst->total ++;
idx++;
if(idx >= KVS_ARRAY_SIZE){ break; }
}
fclose(fp);
return 0;
}
#else
/*
* @return: <0, error; =0, success; >0, exist
*/
@@ -406,6 +189,3 @@ int kvs_array_exist(kvs_array_t *inst, char *key) {
}
return 0;
}
#endif