简单ttl懒删除支持
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
#include "kvs_rw_tools.h"
|
||||
#include "memory/alloc_dispatch.h"
|
||||
#include "diskuring/diskuring.h"
|
||||
#include <endian.h>
|
||||
|
||||
/* ============================================================================
|
||||
* 内存布局说明:
|
||||
@@ -31,6 +32,10 @@ static inline uint8_t* rbtree_node_get_key(rbtree_node *node) {
|
||||
return (uint8_t *)node + sizeof(rbtree_node_fixed);
|
||||
}
|
||||
|
||||
const uint8_t *kvs_rbtree_node_key_ptr(const rbtree_node *node) {
|
||||
return node ? (const uint8_t *)rbtree_node_get_key((rbtree_node *)node) : NULL;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 辅助函数:获取节点内的value指针
|
||||
// ============================================================================
|
||||
@@ -39,6 +44,10 @@ static inline uint8_t* rbtree_node_get_value(rbtree_node *node) {
|
||||
return (uint8_t *)node + sizeof(rbtree_node_fixed) + node->key_len;
|
||||
}
|
||||
|
||||
const uint8_t *kvs_rbtree_node_value_ptr(const rbtree_node *node) {
|
||||
return node ? (const uint8_t *)rbtree_node_get_value((rbtree_node *)node) : NULL;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 原始比较函数(保持不变)
|
||||
// ============================================================================
|
||||
@@ -383,6 +392,27 @@ rbtree_node *rbtree_search(rbtree *T, const uint8_t *key, uint32_t keylen) {
|
||||
return T->nil;
|
||||
}
|
||||
|
||||
rbtree_node *rbtree_search_with_visit(rbtree *T, const uint8_t *key, uint32_t keylen,
|
||||
kvs_rbtree_visit_cb cb, void *arg) {
|
||||
rbtree_node *node;
|
||||
|
||||
if (!T) return NULL;
|
||||
|
||||
node = T->root;
|
||||
while (node != T->nil) {
|
||||
if (cb && cb(node, arg) != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t *node_key = rbtree_node_get_key(node);
|
||||
int c = kvs_keycmp(key, keylen, node_key, node->key_len);
|
||||
if (c < 0) node = node->left;
|
||||
else if (c > 0) node = node->right;
|
||||
else return node;
|
||||
}
|
||||
return T->nil;
|
||||
}
|
||||
|
||||
|
||||
void rbtree_traversal(rbtree *T, rbtree_node *node) {
|
||||
if (node != T->nil) {
|
||||
@@ -412,6 +442,7 @@ int kvs_rbtree_create(kvs_rbtree_t *inst) {
|
||||
|
||||
inst->nil->color = BLACK;
|
||||
inst->nil->left = inst->nil->right = inst->nil->parent = inst->nil;
|
||||
inst->nil->expire_at_ms = 0;
|
||||
inst->nil->key_len = 0;
|
||||
inst->nil->value_len = 0;
|
||||
inst->root = inst->nil;
|
||||
@@ -448,6 +479,11 @@ void kvs_rbtree_destroy(kvs_rbtree_t *inst) {
|
||||
* @return: <0 error; 0 success; 1 exist
|
||||
*/
|
||||
int kvs_rbtree_set(kvs_rbtree_t *inst, const void *key, uint32_t key_len, const void *value, uint32_t value_len) {
|
||||
return kvs_rbtree_set_ex(inst, key, key_len, value, value_len, 0);
|
||||
}
|
||||
|
||||
int kvs_rbtree_set_ex(kvs_rbtree_t *inst, const void *key, uint32_t key_len,
|
||||
const void *value, uint32_t value_len, uint64_t expire_at_ms) {
|
||||
if (!inst || !key || !value) return -1;
|
||||
|
||||
// 1. 查找键是否已存在
|
||||
@@ -467,6 +503,7 @@ int kvs_rbtree_set(kvs_rbtree_t *inst, const void *key, uint32_t key_len, const
|
||||
new_node->right = existing->right;
|
||||
new_node->left = existing->left;
|
||||
new_node->parent = existing->parent;
|
||||
new_node->expire_at_ms = expire_at_ms;
|
||||
new_node->key_len = key_len;
|
||||
new_node->value_len = value_len;
|
||||
|
||||
@@ -500,6 +537,7 @@ int kvs_rbtree_set(kvs_rbtree_t *inst, const void *key, uint32_t key_len, const
|
||||
// 大小相同,直接更新值
|
||||
uint8_t *val = rbtree_node_get_value(existing);
|
||||
if (value_len > 0) memcpy(val, value, value_len);
|
||||
existing->expire_at_ms = expire_at_ms;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -513,6 +551,7 @@ int kvs_rbtree_set(kvs_rbtree_t *inst, const void *key, uint32_t key_len, const
|
||||
|
||||
node->key_len = key_len;
|
||||
node->value_len = value_len;
|
||||
node->expire_at_ms = expire_at_ms;
|
||||
|
||||
uint8_t *node_key = rbtree_node_get_key(node);
|
||||
uint8_t *node_val = rbtree_node_get_value(node);
|
||||
@@ -592,6 +631,7 @@ int kvs_rbtree_mod(kvs_rbtree_t *inst, const void *key, uint32_t key_len, const
|
||||
new_node->left = node->left;
|
||||
new_node->right = node->right;
|
||||
new_node->parent = node->parent;
|
||||
new_node->expire_at_ms = node->expire_at_ms;
|
||||
new_node->key_len = node->key_len;
|
||||
new_node->value_len = value_len;
|
||||
|
||||
@@ -645,9 +685,10 @@ static int kvs_rbtree_save_node(iouring_ctx_t *uring, int fd, off_t *current_off
|
||||
|
||||
uint32_t klen = htonl(node->key_len);
|
||||
uint32_t vlen = htonl(node->value_len);
|
||||
uint64_t expire_at_ms = htobe64(node->expire_at_ms);
|
||||
|
||||
void *bufs[4];
|
||||
size_t lens[4];
|
||||
void *bufs[5];
|
||||
size_t lens[5];
|
||||
int count = 0;
|
||||
|
||||
bufs[count] = &klen;
|
||||
@@ -658,6 +699,10 @@ static int kvs_rbtree_save_node(iouring_ctx_t *uring, int fd, off_t *current_off
|
||||
lens[count] = sizeof(vlen);
|
||||
count++;
|
||||
|
||||
bufs[count] = &expire_at_ms;
|
||||
lens[count] = sizeof(expire_at_ms);
|
||||
count++;
|
||||
|
||||
uint8_t *node_key = rbtree_node_get_key(node);
|
||||
if (node->key_len > 0) {
|
||||
bufs[count] = node_key;
|
||||
@@ -718,12 +763,25 @@ int kvs_rbtree_load(kvs_rbtree_t *inst, const char* filename){
|
||||
|
||||
for (;;) {
|
||||
uint32_t klen_n = 0, vlen_n = 0;
|
||||
uint64_t expire_at_ms_n = 0;
|
||||
size_t r = fread(&klen_n, 1, sizeof(klen_n), fp);
|
||||
|
||||
if (r == 0) {
|
||||
if (feof(fp)) {
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
fclose(fp);
|
||||
return -3;
|
||||
}
|
||||
if (r != sizeof(klen_n)) { fclose(fp); return -3; }
|
||||
|
||||
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; }
|
||||
if (kvs_read_file(fp, &expire_at_ms_n, sizeof(expire_at_ms_n)) < 0) { fclose(fp); return -3; }
|
||||
|
||||
uint32_t klen = ntohl(klen_n);
|
||||
uint32_t vlen = ntohl(vlen_n);
|
||||
uint64_t expire_at_ms = be64toh(expire_at_ms_n);
|
||||
|
||||
if (klen == 0) { fclose(fp); return -3; }
|
||||
|
||||
@@ -735,6 +793,7 @@ int kvs_rbtree_load(kvs_rbtree_t *inst, const char* filename){
|
||||
memset(node, 0, node_size);
|
||||
node->key_len = klen;
|
||||
node->value_len = vlen;
|
||||
node->expire_at_ms = expire_at_ms;
|
||||
|
||||
uint8_t *keybuf = rbtree_node_get_key(node);
|
||||
if (kvs_read_file(fp, keybuf, (size_t)klen) < 0) {
|
||||
@@ -753,6 +812,11 @@ int kvs_rbtree_load(kvs_rbtree_t *inst, const char* filename){
|
||||
}
|
||||
}
|
||||
|
||||
if (node->expire_at_ms != 0 && node->expire_at_ms <= kvs_now_ms()) {
|
||||
kvs_free(node);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 使用原生 rbtree_insert 而非 kvs_rbtree_set
|
||||
// 因为 kvs_rbtree_set 会重新分配节点
|
||||
if (rbtree_insert(inst, node) < 0) {
|
||||
@@ -764,4 +828,4 @@ int kvs_rbtree_load(kvs_rbtree_t *inst, const char* filename){
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user