简单ttl懒删除支持
This commit is contained in:
116
kvstore.c
116
kvstore.c
@@ -17,9 +17,10 @@
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <libxml/parser.h>
|
||||
#include <limits.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <libxml/parser.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
|
||||
#define TIME_COLLECT 0
|
||||
|
||||
@@ -33,7 +34,16 @@ unsigned long long global_seq;
|
||||
|
||||
extern int global_oplog_fd;
|
||||
|
||||
replica_shm_t g_rep_shm;
|
||||
replica_shm_t g_rep_shm;
|
||||
|
||||
typedef struct ttl_delete_task_s {
|
||||
struct ttl_delete_task_s *next;
|
||||
uint8_t *key;
|
||||
uint32_t key_len;
|
||||
} ttl_delete_task_t;
|
||||
|
||||
static ttl_delete_task_t *g_ttl_delete_head = NULL;
|
||||
static ttl_delete_task_t *g_ttl_delete_tail = NULL;
|
||||
|
||||
__attribute__((noinline))
|
||||
void __completed_cmd(const uint8_t *cmd, size_t len, unsigned long long seq){
|
||||
@@ -45,13 +55,80 @@ void __completed_cmd(const uint8_t *cmd, size_t len, unsigned long long seq){
|
||||
#define TIME_SUB_MS(tv1, tv2) ((tv1.tv_sec - tv2.tv_sec) * 1000 + (tv1.tv_usec - tv2.tv_usec) / 1000)
|
||||
#define TIME_SUB_US(tv1, tv2) ((tv1.tv_sec - tv2.tv_sec) * 1000000 + (tv1.tv_usec - tv2.tv_usec))
|
||||
|
||||
static int checked_size_add(size_t a, size_t b, size_t *out) {
|
||||
static int checked_size_add(size_t a, size_t b, size_t *out) {
|
||||
if (!out || a > SIZE_MAX - b) {
|
||||
return -1;
|
||||
}
|
||||
*out = a + b;
|
||||
return 0;
|
||||
}
|
||||
*out = a + b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t kvs_now_ms(void) {
|
||||
struct timespec ts;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
return (uint64_t)ts.tv_sec * 1000ULL + (uint64_t)ts.tv_nsec / 1000000ULL;
|
||||
}
|
||||
|
||||
int ttl_delete_schedule(const void *key, uint32_t key_len) {
|
||||
ttl_delete_task_t *task;
|
||||
|
||||
if (!key || key_len == 0) return -1;
|
||||
|
||||
task = (ttl_delete_task_t *)kvs_malloc(sizeof(*task));
|
||||
if (!task) return -1;
|
||||
memset(task, 0, sizeof(*task));
|
||||
|
||||
task->key = (uint8_t *)kvs_malloc(key_len);
|
||||
if (!task->key) {
|
||||
kvs_free(task);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(task->key, key, key_len);
|
||||
task->key_len = key_len;
|
||||
|
||||
if (g_ttl_delete_tail) {
|
||||
g_ttl_delete_tail->next = task;
|
||||
} else {
|
||||
g_ttl_delete_head = task;
|
||||
}
|
||||
g_ttl_delete_tail = task;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ttl_delete_drain(int budget) {
|
||||
int drained = 0;
|
||||
|
||||
#if !ENABLE_RBTREE
|
||||
(void)budget;
|
||||
return 0;
|
||||
#else
|
||||
while (budget > 0 && g_ttl_delete_head) {
|
||||
ttl_delete_task_t *task = g_ttl_delete_head;
|
||||
rbtree_node *node;
|
||||
|
||||
g_ttl_delete_head = task->next;
|
||||
if (!g_ttl_delete_head) {
|
||||
g_ttl_delete_tail = NULL;
|
||||
}
|
||||
|
||||
node = rbtree_search(&global_rbtree, task->key, task->key_len);
|
||||
if (node != global_rbtree.nil &&
|
||||
node->expire_at_ms != 0 &&
|
||||
node->expire_at_ms <= kvs_now_ms()) {
|
||||
(void)kvs_rbtree_del(&global_rbtree, task->key, task->key_len);
|
||||
}
|
||||
|
||||
kvs_free(task->key);
|
||||
kvs_free(task);
|
||||
drained++;
|
||||
budget--;
|
||||
}
|
||||
|
||||
return drained;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int resp_value_encoded_len(const resp_value_t *v, size_t *out_len) {
|
||||
size_t len = 0;
|
||||
@@ -138,11 +215,12 @@ static int is_update_cmd(const resp_cmd_t *cmd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
c0 = &cmd->argv[0];
|
||||
return ascii_casecmp(c0->ptr, c0->len, "SET") == 0 ||
|
||||
ascii_casecmp(c0->ptr, c0->len, "DEL") == 0 ||
|
||||
ascii_casecmp(c0->ptr, c0->len, "MOD") == 0 ||
|
||||
ascii_casecmp(c0->ptr, c0->len, "RSET") == 0 ||
|
||||
c0 = &cmd->argv[0];
|
||||
return ascii_casecmp(c0->ptr, c0->len, "SET") == 0 ||
|
||||
ascii_casecmp(c0->ptr, c0->len, "DEL") == 0 ||
|
||||
ascii_casecmp(c0->ptr, c0->len, "SETEX") == 0 ||
|
||||
ascii_casecmp(c0->ptr, c0->len, "MOD") == 0 ||
|
||||
ascii_casecmp(c0->ptr, c0->len, "RSET") == 0 ||
|
||||
ascii_casecmp(c0->ptr, c0->len, "RDEL") == 0 ||
|
||||
ascii_casecmp(c0->ptr, c0->len, "RMOD") == 0 ||
|
||||
ascii_casecmp(c0->ptr, c0->len, "HSET") == 0 ||
|
||||
@@ -420,11 +498,13 @@ int init_config(AppConfig *cfg){
|
||||
printf("|—— Persist-rbtree : %s\n", cfg->rbtree_file);
|
||||
printf("|—— Persist-hash : %s\n", cfg->hash_file);
|
||||
|
||||
printf("Log level : %s\n", log_level_to_string(cfg->log_level));
|
||||
printf("Memory : \n");
|
||||
printf("|——Allocator : %s\n", allocator_to_string(cfg->allocator));
|
||||
printf("|——MemLeakDetectMode : %s\n", leakage_to_string(cfg->leak_mode));
|
||||
printf("=============== Config ===============\n");
|
||||
printf("Log level : %s\n", log_level_to_string(cfg->log_level));
|
||||
printf("Memory : \n");
|
||||
printf("|——Allocator : %s\n", allocator_to_string(cfg->allocator));
|
||||
printf("|——MemLeakDetectMode : %s\n", leakage_to_string(cfg->leak_mode));
|
||||
printf("Redis-Compat\t\t: \n");
|
||||
printf("|——Auth Password\t: %s\n", cfg->redis_auth_password[0] ? "[configured]" : "[empty]");
|
||||
printf("=============== Config ===============\n");
|
||||
|
||||
xmlCleanupParser();
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user