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

301 lines
6.7 KiB
C
Executable File
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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include "kvstore.h"
// Key, Value -->
// Modify
kvs_hash_t global_hash;
//Connection
// 'C' + 'o' + 'n'
static int _hash(const void *key, uint32_t key_len, int size) {
if (!key || size <= 0) return -1;
const uint8_t *p = (const uint8_t *)key;
uint32_t sum = 0;
for (uint32_t i = 0; i < key_len; i++) {
sum += p[i];
}
return sum % size;
}
static int _key_equal(const hashnode_t *node, const void *key, uint32_t key_len) {
if (!node || !key) return 0;
if (!node->key) return 0;
if (node->key_len != key_len) return 0;
return memcmp(node->key, key, key_len) == 0;
}
static hashnode_t *_create_node(const void *key, uint32_t key_len,
const void *value, uint32_t value_len) {
hashnode_t *node = (hashnode_t*)kvs_malloc(sizeof(hashnode_t));
if (!node) return NULL;
memset(node, 0, sizeof(*node));
if (key_len > 0) {
node->key = (uint8_t*)kvs_malloc(key_len);
if (!node->key) { kvs_free(node); return NULL; }
memcpy(node->key, key, key_len);
node->key_len = key_len;
}
if (value_len > 0) {
node->value = (uint8_t*)kvs_malloc(value_len);
if (!node->value) {
kvs_free(node->key);
kvs_free(node);
return NULL;
}
memcpy(node->value, value, value_len);
node->value_len = value_len;
} else {
node->value = NULL;
node->value_len = 0;
}
node->next = NULL;
return node;
}
//
int kvs_hash_create(kvs_hash_t *hash) {
if (!hash) return -1;
hash->nodes = (hashnode_t**)kvs_malloc(sizeof(hashnode_t*) * MAX_TABLE_SIZE);
if (!hash->nodes) return -1;
memset(hash->nodes, 0, sizeof(hashnode_t*) * MAX_TABLE_SIZE);
hash->max_slots = MAX_TABLE_SIZE;
hash->count = 0;
return 0;
}
//
void kvs_hash_destroy(kvs_hash_t *hash) {
if (!hash || !hash->nodes) return;
for (int i = 0; i < hash->max_slots; i++) {
hashnode_t *node = hash->nodes[i];
while (node != NULL) {
hashnode_t *tmp = node;
node = node->next;
if (tmp->key) kvs_free(tmp->key);
if (tmp->value) kvs_free(tmp->value);
kvs_free(tmp);
}
hash->nodes[i] = NULL;
}
kvs_free(hash->nodes);
hash->nodes = NULL;
hash->max_slots = 0;
hash->count = 0;
}
// 5 + 2
// mp
/*
* @return: <0 error; =0 success; >0 exist
*/
int kvs_hash_set_bin(kvs_hash_t *hash, const void *key, uint32_t key_len, const void *value, uint32_t value_len) {
if (!hash || !hash->nodes || !key || key_len == 0 || !value) return -1;
int idx = _hash(key, key_len, MAX_TABLE_SIZE);
if (idx < 0) return -1;
hashnode_t *node = hash->nodes[idx];
while (node != NULL) {
if (_key_equal(node, key, key_len)) { // exist
return 1;
}
node = node->next;
}
hashnode_t *new_node = _create_node(key, key_len, value, value_len);
if (!new_node) return -2;
new_node->next = hash->nodes[idx];
hash->nodes[idx] = new_node;
hash->count ++;
return 0;
}
/*
* get 返回value 指针(由 hash 持有),并通过 out_value_len 返回长度
*/
void *kvs_hash_get_bin(kvs_hash_t *hash, const void *key, uint32_t key_len, uint32_t *out_value_len) {
if (!hash || !hash->nodes || !key || key_len == 0 || !out_value_len) return NULL;
*out_value_len = 0;
int idx = _hash(key, key_len, MAX_TABLE_SIZE);
if (idx < 0) return NULL;
hashnode_t *node = hash->nodes[idx];
while (node != NULL) {
if (_key_equal(node, key, key_len)) {
*out_value_len = node->value_len;
return node->value;
}
node = node->next;
}
return NULL;
}
/*
* @return <0 error; =0 success; >0 no exist
*/
int kvs_hash_mod_bin(kvs_hash_t *hash, const void *key, uint32_t key_len, const void *value, uint32_t value_len) {
if (!hash || !hash->nodes || !key || key_len == 0 || !value) return -1;
int idx = _hash(key, key_len, MAX_TABLE_SIZE);
if (idx < 0) return -1;
hashnode_t *node = hash->nodes[idx];
while (node != NULL) {
if (_key_equal(node, key, key_len)) {
break;
}
node = node->next;
}
if (node == NULL) {
return 1;
}
// node -->
if (node->value) kvs_free(node->value);
node->value = NULL;
node->value_len = 0;
if (value_len > 0) {
uint8_t *vcopy = (uint8_t*)kvs_malloc(value_len);
if (!vcopy) return -2;
memcpy(vcopy, value, value_len);
node->value = vcopy;
node->value_len = value_len;
}
return 0;
}
int kvs_hash_count(kvs_hash_t *hash) {
return hash->count;
}
/*
* @return 0 success; <0 error/noexist
*/
int kvs_hash_del_bin(kvs_hash_t *hash, const void *key, uint32_t key_len) {
if (!hash || !key || key_len == 0) return -2;
int idx = _hash(key, key_len, MAX_TABLE_SIZE);
if (idx < 0) return -2;
hashnode_t *head = hash->nodes[idx];
if (head == NULL) return -1; // noexist
// head node
if (_key_equal(head, key, key_len)) {
hashnode_t *tmp = head->next;
hash->nodes[idx] = tmp;
if (head->key) kvs_free(head->key);
if (head->value) kvs_free(head->value);
kvs_free(head);
hash->count --;
return 0;
}
hashnode_t *cur = head;
while (cur->next != NULL) {
if (_key_equal(cur->next, key, key_len)) break; // search node
cur = cur->next;
}
if (cur->next == NULL) {
return -1;
}
hashnode_t *tmp = cur->next;
cur->next = tmp->next;
if (tmp->key) kvs_free(tmp->key);
if (tmp->value) kvs_free(tmp->value);
kvs_free(tmp);
hash->count --;
return 0;
}
/*
* @return 0 exist, 1 no exist
*/
int kvs_hash_exist_bin(kvs_hash_t *hash, const void *key, uint32_t key_len) {
uint32_t vlen = 0;
void *value = kvs_hash_get_bin(hash, key, key_len, &vlen);
return value ? 0 : 1;
}
#if 0
int main() {
kvs_hash_create(&hash);
kvs_hash_set(&hash, "Teacher1", "King");
kvs_hash_set(&hash, "Teacher2", "Darren");
kvs_hash_set(&hash, "Teacher3", "Mark");
kvs_hash_set(&hash, "Teacher4", "Vico");
kvs_hash_set(&hash, "Teacher5", "Nick");
char *value1 = kvs_hash_get(&hash, "Teacher1");
printf("Teacher1 : %s\n", value1);
int ret = kvs_hash_mod(&hash, "Teacher1", "King1");
printf("mode Teacher1 ret : %d\n", ret);
char *value2 = kvs_hash_get(&hash, "Teacher1");
printf("Teacher2 : %s\n", value1);
ret = kvs_hash_del(&hash, "Teacher1");
printf("delete Teacher1 ret : %d\n", ret);
ret = kvs_hash_exist(&hash, "Teacher1");
printf("Exist Teacher1 ret : %d\n", ret);
kvs_hash_destroy(&hash);
return 0;
}
#endif