Files
ldb/kvs_array.c
1iaan 3cc97b9454 实现全量持久化:save操作落盘,启动时读取到内存
增量持久化:执行修改操作时将cmd追加到log中,启动时逐条取出顺序执行
2026-01-07 18:43:28 +08:00

411 lines
9.6 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 <arpa/inet.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);
}
}
#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
*/
int kvs_array_set(kvs_array_t *inst, char *key, char *value) {
if (inst == NULL || key == NULL || value == NULL) return -1;
if (inst->total == KVS_ARRAY_SIZE) return -1;
char *str = kvs_array_get(inst, key);
if (str) {
return 1; //
}
char *kcopy = kvs_malloc(strlen(key) + 1);
if (kcopy == NULL) return -2;
memset(kcopy, 0, strlen(key) + 1);
strncpy(kcopy, key, strlen(key));
char *kvalue = kvs_malloc(strlen(value) + 1);
if (kvalue == NULL) return -2;
memset(kvalue, 0, strlen(value) + 1);
strncpy(kvalue, value, strlen(value));
int i = 0;
for (i = 0;i < inst->total;i ++) {
if (inst->table[i].key == NULL) {
inst->table[i].key = kcopy;
inst->table[i].value = kvalue;
inst->total ++;
return 0;
}
}
if (i == inst->total && i < KVS_ARRAY_SIZE) {
inst->table[i].key = kcopy;
inst->table[i].value = kvalue;
inst->total ++;
}
return 0;
}
char* kvs_array_get(kvs_array_t *inst, char *key) {
if (inst == NULL || key == NULL) return NULL;
int i = 0;
for (i = 0;i < inst->total;i ++) {
if (inst->table[i].key == NULL) {
continue;
}
if (strcmp(inst->table[i].key, key) == 0) {
return inst->table[i].value;
}
}
return NULL;
}
/*
* @return < 0, error; =0, success; >0, no exist
*/
int kvs_array_del(kvs_array_t *inst, char *key) {
if (inst == NULL || key == NULL) return -1;
int i = 0;
for (i = 0;i < inst->total;i ++) {
if (strcmp(inst->table[i].key, key) == 0) {
kvs_free(inst->table[i].key);
inst->table[i].key = NULL;
kvs_free(inst->table[i].value);
inst->table[i].value = NULL;
// error: > 1024
if (inst->total-1 == i) {
inst->total --;
}
return 0;
}
}
return i;
}
/*
* @return : < 0, error; =0, success; >0, no exist
*/
int kvs_array_mod(kvs_array_t *inst, char *key, char *value) {
if (inst == NULL || key == NULL || value == NULL) return -1;
// error: > 1024
if (inst->total == 0) {
return KVS_ARRAY_SIZE;
}
int i = 0;
for (i = 0;i < inst->total;i ++) {
if (inst->table[i].key == NULL) {
continue;
}
if (strcmp(inst->table[i].key, key) == 0) {
kvs_free(inst->table[i].value);
char *kvalue = kvs_malloc(strlen(value) + 1);
if (kvalue == NULL) return -2;
memset(kvalue, 0, strlen(value) + 1);
strncpy(kvalue, value, strlen(value));
inst->table[i].value = kvalue;
return 0;
}
}
return i;
}
/*
* @return 0: exist, 1: no exist
*/
int kvs_array_exist(kvs_array_t *inst, char *key) {
if (!inst || !key) return -1;
char *str = kvs_array_get(inst, key);
if (!str) {
return 1; //
}
return 0;
}
#endif