Files
ldb/kvs_array_bin.c

301 lines
7.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "kvstore.h"
#include "kvs_rw_tools.h"
#include "memory/alloc_dispatch.h"
#include "diskuring/diskuring.h"
// singleton
kvs_array_t global_array = {0};
int kvs_array_create(kvs_array_t *inst) {
if (!inst) return -1;
if (inst->table) {
printf("table has alloc\n");
return -1;
}
inst->table = kvs_malloc(KVS_ARRAY_SIZE * sizeof(kvs_array_item_t));
if (!inst->table) {
return -1;
}
memset(inst->table, 0, (size_t)KVS_ARRAY_SIZE * sizeof(kvs_array_item_t));
inst->total = 0;
return 0;
}
void kvs_array_destroy(kvs_array_t *inst) {
if (!inst) return ;
if (inst->table) {
kvs_free(inst->table);
}
}
/**
* 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;
}
/*
* @return: NULL notexist, NOTNULL exist。out_value_len 是长度。
*/
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 持有
}
/*
* @return <0 error; =0 success; >0 no exist
*/
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;
}
/*
* @return < 0 error; =0 success; >0 no exist
*/
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;
}
/*
* @return =0 exist, =1 no exist
*/
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(iouring_ctx_t *uring, kvs_array_t *inst, const char* filename){
if(!uring || !inst || !filename) return -1;
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if(fd < 0) return -2;
off_t current_off = 0;
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) { close(fd); return -3; }
uint32_t klen = htonl(it->key_len);
uint32_t vlen = htonl(it->value_len);
void *bufs[4];
size_t lens[4];
int count = 0;
bufs[count] = &klen;
lens[count] = sizeof(klen);
count++;
bufs[count] = &vlen;
lens[count] = sizeof(vlen);
count++;
if (it->key_len > 0){
bufs[count] = it->key;
lens[count] = it->key_len;
count++;
}
if (it->value_len > 0) {
bufs[count] = it->value;
lens[count] = it->value_len;
count++;
}
size_t total = 0;
for (int i = 0; i < count; i++) total += lens[i];
task_t *t = submit_write(uring, fd, bufs, lens, count, current_off);
if (!t) { close(fd); return -4; }
// int res = task_wait(t);
// task_destroy(t);
// if (res < 0) {
// close(fd);
// return -5;
// }
current_off += (off_t) total;
}
close(fd);
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_n = 0, vlen_n = 0;
if (kvs_read_file(fp, &klen_n, 4) < 0) { fclose(fp); return -3; }
if (kvs_read_file(fp, &vlen_n, 4) < 0) { fclose(fp); return -3; }
uint32_t klen = ntohl(klen_n);
uint32_t vlen = ntohl(vlen_n);
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;
}