From 4b4e06b33db3bce5041e18fd3f2fbed85535a347 Mon Sep 17 00:00:00 2001 From: 1iaan Date: Thu, 8 Jan 2026 21:42:20 +0800 Subject: [PATCH] =?UTF-8?q?rbtree=E5=92=8Chash=E7=9A=84=E5=85=A8=E9=87=8F?= =?UTF-8?q?=E6=8C=81=E4=B9=85=E5=8C=96=E6=93=8D=E4=BD=9C=E3=80=82rbtree?= =?UTF-8?q?=E7=9A=84=E4=BA=8C=E8=BF=9B=E5=88=B6=E5=AE=89=E5=85=A8=E3=80=82?= =?UTF-8?q?=20=E7=B2=97=E7=95=A5=E6=B5=8B=E8=AF=95=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + Makefile | 2 +- kvs_array.c | 220 ------------- kvs_array_bin.c | 267 +++++++++++++++ kvs_cmd_log.c | 100 ++++++ kvs_hash_bin.c | 110 +++++-- kvs_rbtree.c | 798 ++++++++++++++++++++++----------------------- kvs_rbtree_bin.c | 568 ++++++++++++++++++++++++++++++++ kvs_rw_tools.c | 495 +++------------------------- kvs_rw_tools.h | 10 +- kvstore.c | 531 ++++++++++++++++++------------ kvstore.h | 55 +++- reactor.c | 2 +- test/test_client.c | 12 +- test/test_client.h | 13 +- test/testcase.c | 263 +++++++++------ 16 files changed, 1997 insertions(+), 1450 deletions(-) create mode 100644 kvs_array_bin.c create mode 100644 kvs_cmd_log.c create mode 100644 kvs_rbtree_bin.c diff --git a/.gitignore b/.gitignore index 2519e0b..37911d4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ NtyCo/ .vscode/ *.db +*.copy proactor copy.c ntyco copy.c diff --git a/Makefile b/Makefile index 789e60b..7afef91 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CC = gcc FLAGS = -I ./NtyCo/core/ -L ./NtyCo/ -lntyco -lpthread -luring -ldl # SRCS = kvstore.c ntyco.c proactor.c reactor.c kvs_array.c kvs_rbtree.c kvs_hash.c kvs_rw_tools.c -SRCS = kvstore.c ntyco.c proactor.c reactor.c kvs_array.c kvs_rbtree.c kvs_hash_bin.c kvs_rw_tools.c +SRCS = kvstore.c ntyco.c proactor.c reactor.c kvs_array_bin.c kvs_rbtree_bin.c kvs_hash_bin.c kvs_rw_tools.c kvs_cmd_log.c TESTCASE_SRCS = testcase.c TARGET = kvstore SUBDIR = ./NtyCo/ diff --git a/kvs_array.c b/kvs_array.c index cab6998..eb1ed96 100644 --- a/kvs_array.c +++ b/kvs_array.c @@ -38,224 +38,7 @@ void kvs_array_destroy(kvs_array_t *inst) { } -#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(长度0),value 指针置 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 */ @@ -406,6 +189,3 @@ int kvs_array_exist(kvs_array_t *inst, char *key) { } return 0; } - - -#endif \ No newline at end of file diff --git a/kvs_array_bin.c b/kvs_array_bin.c new file mode 100644 index 0000000..5c3a5bc --- /dev/null +++ b/kvs_array_bin.c @@ -0,0 +1,267 @@ + + +#include "kvstore.h" +#include "kvs_rw_tools.h" +#include + + +// 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(长度0),value 指针置 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 + */ +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(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_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; +} diff --git a/kvs_cmd_log.c b/kvs_cmd_log.c new file mode 100644 index 0000000..ba12bd7 --- /dev/null +++ b/kvs_cmd_log.c @@ -0,0 +1,100 @@ +#include "kvstore.h" +#include "kvs_rw_tools.h" +#include +#include +#include + +int init_cmd_log(const char *file, int *logfd){ + if(!file) return -1; + int fd = open(file, O_RDWR | O_CREAT | O_APPEND, 0644); + if(fd < 0) return -2; + + *logfd = fd; + return 0; +} + +int destroy_cmd_log(int logfd){ + close(logfd); + return 0; +} + + + +int kvs_save_cmd_to_logfile(const uint8_t *cmd, size_t len, int logfd){ + if (logfd < 0 || !cmd || len == 0) + return -1; + + if (len > UINT32_MAX) + return -2; + + uint32_t nlen = htonl((uint32_t)len); + + if (write_full(logfd, &nlen, sizeof(nlen)) < 0) + return -3; + + if (write_full(logfd, cmd, len) < 0) + return -4; + + if (fsync(logfd) < 0) + return -5; + + return 0; +} + +int kvs_replay_log(const char *logfile, int logfd){ + if (!logfile|| logfd<0) return -1; + + for (;;) { + uint32_t nlen = 0; + + int hr = read_full(logfd, &nlen, sizeof(nlen)); + if (hr == 0) break; /* EOF:正常结束 */ + if (hr < 0) { return -2; } /* 半截头 */ + + uint32_t len = ntohl(nlen); + if (len == 0) { return -3; } + + uint8_t *cmd = (uint8_t *)kvs_malloc(len); + if (!cmd) { return -5; } + + int pr = read_full(logfd, cmd, len); + if (pr <= 0) { /* 半截 payload */ + kvs_free(cmd); + return -6; + } + + kvs_req_t req; + memset(&req, 0, sizeof(req)); + + int clen = kvs_parse_one_cmd(cmd, (int)len, &req); + if (clen <= 0 || clen != (int)len) { + kvs_free_request(&req); + kvs_free(cmd); + return -7; + } + + kvs_rsp_t rsp; + memset(&rsp, 0, sizeof(rsp)); + + if (kvs_execute_one_cmd(&req, &rsp) < 0) { + kvs_free_request(&req); + kvs_free(cmd); + return -8; + } + + kvs_free_request(&req); + kvs_free(cmd); + } + + return 0; +} + +/** + * clear log file not close + */ +int ksv_clear_log(int logfd){ + if(logfd < 0) return -1; + ftruncate(logfd, 0); + lseek(logfd, 0, SEEK_SET); + return 0; +} \ No newline at end of file diff --git a/kvs_hash_bin.c b/kvs_hash_bin.c index fe006c8..7334614 100755 --- a/kvs_hash_bin.c +++ b/kvs_hash_bin.c @@ -8,7 +8,8 @@ #include "kvstore.h" - +#include "kvs_rw_tools.h" +#include // Key, Value --> // Modify @@ -114,7 +115,7 @@ void kvs_hash_destroy(kvs_hash_t *hash) { * @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; + if (!hash || !hash->nodes || !key || key_len == 0) return -1; int idx = _hash(key, key_len, MAX_TABLE_SIZE); if (idx < 0) return -1; @@ -208,16 +209,16 @@ int kvs_hash_count(kvs_hash_t *hash) { } /* - * @return 0 success; <0 error/noexist + * @return < 0, error; =0, success; >0, no exist */ int kvs_hash_del_bin(kvs_hash_t *hash, const void *key, uint32_t key_len) { - if (!hash || !key || key_len == 0) return -2; + if (!hash || !key || key_len == 0) return -1; int idx = _hash(key, key_len, MAX_TABLE_SIZE); - if (idx < 0) return -2; + if (idx < 0) return -1; hashnode_t *head = hash->nodes[idx]; - if (head == NULL) return -1; // noexist + if (head == NULL) return 1; // noexist // head node if (_key_equal(head, key, key_len)) { @@ -241,7 +242,7 @@ int kvs_hash_del_bin(kvs_hash_t *hash, const void *key, uint32_t key_len) { if (cur->next == NULL) { - return -1; + return 1; } hashnode_t *tmp = cur->next; @@ -264,37 +265,86 @@ int kvs_hash_exist_bin(kvs_hash_t *hash, const void *key, uint32_t key_len) { return value ? 0 : 1; } -#if 0 -int main() { +// 0 suc, <0 error +int kvs_hash_save(kvs_hash_t *inst, const char* filename){ + if(!inst || !filename) return -1; + FILE *fp = fopen(filename, "wb"); + if(!fp) return -2; - 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"); + for(int i = 0;i < inst->max_slots; ++ i){ + for (hashnode_t *n = inst->nodes[i]; n != NULL; n = n->next) { + if (!n->key || n->key_len == 0) continue; + if (n->value_len > 0 && !n->value) { fclose(fp); return -3; } + - char *value1 = kvs_hash_get(&hash, "Teacher1"); - printf("Teacher1 : %s\n", value1); + uint32_t klen = htonl((uint32_t)n->key_len); + uint32_t vlen = htonl((uint32_t)n->value_len); - 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); + if (kvs_write_file(fp, &klen, 4) < 0) { fclose(fp); return -4; } + if (kvs_write_file(fp, &vlen, 4) < 0) { fclose(fp); return -4; } - 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); + if (kvs_write_file(fp, n->key, n->key_len) < 0) { fclose(fp); return -4; } + if (n->value_len > 0) { + if (kvs_write_file(fp, n->value, n->value_len) < 0) { fclose(fp); return -4; } + } + } + } + fclose(fp); return 0; } -#endif +int kvs_hash_load(kvs_hash_t *inst, const char* filename){ + if (!inst || !filename) return -1; + if (!inst->nodes || inst->max_slots <= 0) return -1; + FILE *fp = fopen(filename, "rb"); + if (!fp) return -2; + 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; } + + uint8_t *keybuf = (uint8_t*)kvs_malloc((size_t)klen); + if (!keybuf) { fclose(fp); return -4; } + if (kvs_read_file(fp, keybuf, (size_t)klen) < 0) { + kvs_free(keybuf); + fclose(fp); + return -3; + } + uint8_t *valbuf = NULL; + if (vlen > 0) { + valbuf = (uint8_t*)kvs_malloc((size_t)vlen); + if (!valbuf) { + kvs_free(keybuf); + fclose(fp); + return -4; + } + if (kvs_read_file(fp, valbuf, (size_t)vlen) < 0) { + kvs_free(valbuf); + kvs_free(keybuf); + fclose(fp); + return -3; + } + } + + int rc = kvs_hash_set_bin(inst, keybuf, klen, valbuf, vlen); + kvs_free(keybuf); + if (vlen > 0) kvs_free(valbuf); + + if (rc < 0) { // error + fclose(fp); + return -5; + } + } + fclose(fp); + return 0; +} \ No newline at end of file diff --git a/kvs_rbtree.c b/kvs_rbtree.c index ac47a7c..48ca1c1 100755 --- a/kvs_rbtree.c +++ b/kvs_rbtree.c @@ -1,553 +1,553 @@ -#include -#include -#include +// #include +// #include +// #include -#include "kvstore.h" +// #include "kvstore.h" -rbtree_node *rbtree_mini(rbtree *T, rbtree_node *x) { - while (x->left != T->nil) { - x = x->left; - } - return x; -} +// rbtree_node *rbtree_mini(rbtree *T, rbtree_node *x) { +// while (x->left != T->nil) { +// x = x->left; +// } +// return x; +// } -rbtree_node *rbtree_maxi(rbtree *T, rbtree_node *x) { - while (x->right != T->nil) { - x = x->right; - } - return x; -} +// rbtree_node *rbtree_maxi(rbtree *T, rbtree_node *x) { +// while (x->right != T->nil) { +// x = x->right; +// } +// return x; +// } -rbtree_node *rbtree_successor(rbtree *T, rbtree_node *x) { - rbtree_node *y = x->parent; +// rbtree_node *rbtree_successor(rbtree *T, rbtree_node *x) { +// rbtree_node *y = x->parent; - if (x->right != T->nil) { - return rbtree_mini(T, x->right); - } +// if (x->right != T->nil) { +// return rbtree_mini(T, x->right); +// } - while ((y != T->nil) && (x == y->right)) { - x = y; - y = y->parent; - } - return y; -} +// while ((y != T->nil) && (x == y->right)) { +// x = y; +// y = y->parent; +// } +// return y; +// } -void rbtree_left_rotate(rbtree *T, rbtree_node *x) { +// void rbtree_left_rotate(rbtree *T, rbtree_node *x) { - rbtree_node *y = x->right; // x --> y , y --> x, right --> left, left --> right +// rbtree_node *y = x->right; // x --> y , y --> x, right --> left, left --> right - x->right = y->left; //1 1 - if (y->left != T->nil) { //1 2 - y->left->parent = x; - } +// x->right = y->left; //1 1 +// if (y->left != T->nil) { //1 2 +// y->left->parent = x; +// } - y->parent = x->parent; //1 3 - if (x->parent == T->nil) { //1 4 - T->root = y; - } else if (x == x->parent->left) { - x->parent->left = y; - } else { - x->parent->right = y; - } +// y->parent = x->parent; //1 3 +// if (x->parent == T->nil) { //1 4 +// T->root = y; +// } else if (x == x->parent->left) { +// x->parent->left = y; +// } else { +// x->parent->right = y; +// } - y->left = x; //1 5 - x->parent = y; //1 6 -} +// y->left = x; //1 5 +// x->parent = y; //1 6 +// } -void rbtree_right_rotate(rbtree *T, rbtree_node *y) { +// void rbtree_right_rotate(rbtree *T, rbtree_node *y) { - rbtree_node *x = y->left; +// rbtree_node *x = y->left; - y->left = x->right; - if (x->right != T->nil) { - x->right->parent = y; - } +// y->left = x->right; +// if (x->right != T->nil) { +// x->right->parent = y; +// } - x->parent = y->parent; - if (y->parent == T->nil) { - T->root = x; - } else if (y == y->parent->right) { - y->parent->right = x; - } else { - y->parent->left = x; - } +// x->parent = y->parent; +// if (y->parent == T->nil) { +// T->root = x; +// } else if (y == y->parent->right) { +// y->parent->right = x; +// } else { +// y->parent->left = x; +// } - x->right = y; - y->parent = x; -} +// x->right = y; +// y->parent = x; +// } -void rbtree_insert_fixup(rbtree *T, rbtree_node *z) { +// void rbtree_insert_fixup(rbtree *T, rbtree_node *z) { - while (z->parent->color == RED) { //z ---> RED - if (z->parent == z->parent->parent->left) { - rbtree_node *y = z->parent->parent->right; - if (y->color == RED) { - z->parent->color = BLACK; - y->color = BLACK; - z->parent->parent->color = RED; +// while (z->parent->color == RED) { //z ---> RED +// if (z->parent == z->parent->parent->left) { +// rbtree_node *y = z->parent->parent->right; +// if (y->color == RED) { +// z->parent->color = BLACK; +// y->color = BLACK; +// z->parent->parent->color = RED; - z = z->parent->parent; //z --> RED - } else { +// z = z->parent->parent; //z --> RED +// } else { - if (z == z->parent->right) { - z = z->parent; - rbtree_left_rotate(T, z); - } +// if (z == z->parent->right) { +// z = z->parent; +// rbtree_left_rotate(T, z); +// } - z->parent->color = BLACK; - z->parent->parent->color = RED; - rbtree_right_rotate(T, z->parent->parent); - } - }else { - rbtree_node *y = z->parent->parent->left; - if (y->color == RED) { - z->parent->color = BLACK; - y->color = BLACK; - z->parent->parent->color = RED; +// z->parent->color = BLACK; +// z->parent->parent->color = RED; +// rbtree_right_rotate(T, z->parent->parent); +// } +// }else { +// rbtree_node *y = z->parent->parent->left; +// if (y->color == RED) { +// z->parent->color = BLACK; +// y->color = BLACK; +// z->parent->parent->color = RED; - z = z->parent->parent; //z --> RED - } else { - if (z == z->parent->left) { - z = z->parent; - rbtree_right_rotate(T, z); - } +// z = z->parent->parent; //z --> RED +// } else { +// if (z == z->parent->left) { +// z = z->parent; +// rbtree_right_rotate(T, z); +// } - z->parent->color = BLACK; - z->parent->parent->color = RED; - rbtree_left_rotate(T, z->parent->parent); - } - } +// z->parent->color = BLACK; +// z->parent->parent->color = RED; +// rbtree_left_rotate(T, z->parent->parent); +// } +// } - } +// } - T->root->color = BLACK; -} +// T->root->color = BLACK; +// } -void rbtree_insert(rbtree *T, rbtree_node *z) { +// void rbtree_insert(rbtree *T, rbtree_node *z) { - rbtree_node *y = T->nil; - rbtree_node *x = T->root; +// rbtree_node *y = T->nil; +// rbtree_node *x = T->root; - while (x != T->nil) { - y = x; -#if ENABLE_KEY_CHAR +// while (x != T->nil) { +// y = x; +// #if ENABLE_KEY_CHAR - if (strcmp(z->key, x->key) < 0) { - x = x->left; - } else if (strcmp(z->key, x->key) > 0) { - x = x->right; - } else { - return ; - } +// if (strcmp(z->key, x->key) < 0) { +// x = x->left; +// } else if (strcmp(z->key, x->key) > 0) { +// x = x->right; +// } else { +// return ; +// } -#else - if (z->key < x->key) { - x = x->left; - } else if (z->key > x->key) { - x = x->right; - } else { //Exist - return ; - } -#endif - } +// #else +// if (z->key < x->key) { +// x = x->left; +// } else if (z->key > x->key) { +// x = x->right; +// } else { //Exist +// return ; +// } +// #endif +// } - z->parent = y; - if (y == T->nil) { - T->root = z; -#if ENABLE_KEY_CHAR - } else if (strcmp(z->key, y->key) < 0) { -#else - } else if (z->key < y->key) { -#endif - y->left = z; - } else { - y->right = z; - } +// z->parent = y; +// if (y == T->nil) { +// T->root = z; +// #if ENABLE_KEY_CHAR +// } else if (strcmp(z->key, y->key) < 0) { +// #else +// } else if (z->key < y->key) { +// #endif +// y->left = z; +// } else { +// y->right = z; +// } - z->left = T->nil; - z->right = T->nil; - z->color = RED; +// z->left = T->nil; +// z->right = T->nil; +// z->color = RED; - rbtree_insert_fixup(T, z); -} +// rbtree_insert_fixup(T, z); +// } -void rbtree_delete_fixup(rbtree *T, rbtree_node *x) { +// void rbtree_delete_fixup(rbtree *T, rbtree_node *x) { - while ((x != T->root) && (x->color == BLACK)) { - if (x == x->parent->left) { +// while ((x != T->root) && (x->color == BLACK)) { +// if (x == x->parent->left) { - rbtree_node *w= x->parent->right; - if (w->color == RED) { - w->color = BLACK; - x->parent->color = RED; +// rbtree_node *w= x->parent->right; +// if (w->color == RED) { +// w->color = BLACK; +// x->parent->color = RED; - rbtree_left_rotate(T, x->parent); - w = x->parent->right; - } +// rbtree_left_rotate(T, x->parent); +// w = x->parent->right; +// } - if ((w->left->color == BLACK) && (w->right->color == BLACK)) { - w->color = RED; - x = x->parent; - } else { +// if ((w->left->color == BLACK) && (w->right->color == BLACK)) { +// w->color = RED; +// x = x->parent; +// } else { - if (w->right->color == BLACK) { - w->left->color = BLACK; - w->color = RED; - rbtree_right_rotate(T, w); - w = x->parent->right; - } +// if (w->right->color == BLACK) { +// w->left->color = BLACK; +// w->color = RED; +// rbtree_right_rotate(T, w); +// w = x->parent->right; +// } - w->color = x->parent->color; - x->parent->color = BLACK; - w->right->color = BLACK; - rbtree_left_rotate(T, x->parent); +// w->color = x->parent->color; +// x->parent->color = BLACK; +// w->right->color = BLACK; +// rbtree_left_rotate(T, x->parent); - x = T->root; - } +// x = T->root; +// } - } else { +// } else { - rbtree_node *w = x->parent->left; - if (w->color == RED) { - w->color = BLACK; - x->parent->color = RED; - rbtree_right_rotate(T, x->parent); - w = x->parent->left; - } +// rbtree_node *w = x->parent->left; +// if (w->color == RED) { +// w->color = BLACK; +// x->parent->color = RED; +// rbtree_right_rotate(T, x->parent); +// w = x->parent->left; +// } - if ((w->left->color == BLACK) && (w->right->color == BLACK)) { - w->color = RED; - x = x->parent; - } else { +// if ((w->left->color == BLACK) && (w->right->color == BLACK)) { +// w->color = RED; +// x = x->parent; +// } else { - if (w->left->color == BLACK) { - w->right->color = BLACK; - w->color = RED; - rbtree_left_rotate(T, w); - w = x->parent->left; - } +// if (w->left->color == BLACK) { +// w->right->color = BLACK; +// w->color = RED; +// rbtree_left_rotate(T, w); +// w = x->parent->left; +// } - w->color = x->parent->color; - x->parent->color = BLACK; - w->left->color = BLACK; - rbtree_right_rotate(T, x->parent); +// w->color = x->parent->color; +// x->parent->color = BLACK; +// w->left->color = BLACK; +// rbtree_right_rotate(T, x->parent); - x = T->root; - } +// x = T->root; +// } - } - } +// } +// } - x->color = BLACK; -} +// x->color = BLACK; +// } -rbtree_node *rbtree_delete(rbtree *T, rbtree_node *z) { +// rbtree_node *rbtree_delete(rbtree *T, rbtree_node *z) { - rbtree_node *y = T->nil; - rbtree_node *x = T->nil; +// rbtree_node *y = T->nil; +// rbtree_node *x = T->nil; - if ((z->left == T->nil) || (z->right == T->nil)) { - y = z; - } else { - y = rbtree_successor(T, z); - } +// if ((z->left == T->nil) || (z->right == T->nil)) { +// y = z; +// } else { +// y = rbtree_successor(T, z); +// } - if (y->left != T->nil) { - x = y->left; - } else if (y->right != T->nil) { - x = y->right; - } +// if (y->left != T->nil) { +// x = y->left; +// } else if (y->right != T->nil) { +// x = y->right; +// } - x->parent = y->parent; - if (y->parent == T->nil) { - T->root = x; - } else if (y == y->parent->left) { - y->parent->left = x; - } else { - y->parent->right = x; - } +// x->parent = y->parent; +// if (y->parent == T->nil) { +// T->root = x; +// } else if (y == y->parent->left) { +// y->parent->left = x; +// } else { +// y->parent->right = x; +// } - if (y != z) { -#if ENABLE_KEY_CHAR +// if (y != z) { +// #if ENABLE_KEY_CHAR - void *tmp = z->key; - z->key = y->key; - y->key = tmp; +// void *tmp = z->key; +// z->key = y->key; +// y->key = tmp; - tmp = z->value; - z->value= y->value; - y->value = tmp; +// tmp = z->value; +// z->value= y->value; +// y->value = tmp; -#else - z->key = y->key; - z->value = y->value; -#endif - } +// #else +// z->key = y->key; +// z->value = y->value; +// #endif +// } - if (y->color == BLACK) { - rbtree_delete_fixup(T, x); - } +// if (y->color == BLACK) { +// rbtree_delete_fixup(T, x); +// } - return y; -} +// return y; +// } -rbtree_node *rbtree_search(rbtree *T, KEY_TYPE key) { +// rbtree_node *rbtree_search(rbtree *T, KEY_TYPE key) { - rbtree_node *node = T->root; - while (node != T->nil) { -#if ENABLE_KEY_CHAR +// rbtree_node *node = T->root; +// while (node != T->nil) { +// #if ENABLE_KEY_CHAR - if (strcmp(key, node->key) < 0) { - node = node->left; - } else if (strcmp(key, node->key) > 0) { - node = node->right; - } else { - return node; - } +// if (strcmp(key, node->key) < 0) { +// node = node->left; +// } else if (strcmp(key, node->key) > 0) { +// node = node->right; +// } else { +// return node; +// } -#else - if (key < node->key) { - node = node->left; - } else if (key > node->key) { - node = node->right; - } else { - return node; - } -#endif - } - return T->nil; -} +// #else +// if (key < node->key) { +// node = node->left; +// } else if (key > node->key) { +// node = node->right; +// } else { +// return node; +// } +// #endif +// } +// return T->nil; +// } -void rbtree_traversal(rbtree *T, rbtree_node *node) { - if (node != T->nil) { - rbtree_traversal(T, node->left); -#if ENABLE_KEY_CHAR - printf("key:%s, value:%s\n", node->key, (char *)node->value); -#else - printf("key:%d, color:%d\n", node->key, node->color); -#endif - rbtree_traversal(T, node->right); - } -} +// void rbtree_traversal(rbtree *T, rbtree_node *node) { +// if (node != T->nil) { +// rbtree_traversal(T, node->left); +// #if ENABLE_KEY_CHAR +// printf("key:%s, value:%s\n", node->key, (char *)node->value); +// #else +// printf("key:%d, color:%d\n", node->key, node->color); +// #endif +// rbtree_traversal(T, node->right); +// } +// } -#if 0 +// #if 0 -int main() { +// int main() { -#if ENABLE_KEY_CHAR +// #if ENABLE_KEY_CHAR - char* keyArray[10] = {"King", "Darren", "Mark", "Vico", "Nick", "qiuxiang", "youzi", "taozi", "123", "234"}; - char* valueArray[10] = {"1King", "2Darren", "3Mark", "4Vico", "5Nick", "6qiuxiang", "7youzi", "8taozi", "9123", "10234"}; +// char* keyArray[10] = {"King", "Darren", "Mark", "Vico", "Nick", "qiuxiang", "youzi", "taozi", "123", "234"}; +// char* valueArray[10] = {"1King", "2Darren", "3Mark", "4Vico", "5Nick", "6qiuxiang", "7youzi", "8taozi", "9123", "10234"}; - rbtree *T = (rbtree *)malloc(sizeof(rbtree)); - if (T == NULL) { - printf("malloc failed\n"); - return -1; - } +// rbtree *T = (rbtree *)malloc(sizeof(rbtree)); +// if (T == NULL) { +// printf("malloc failed\n"); +// return -1; +// } - T->nil = (rbtree_node*)malloc(sizeof(rbtree_node)); - T->nil->color = BLACK; - T->root = T->nil; +// T->nil = (rbtree_node*)malloc(sizeof(rbtree_node)); +// T->nil->color = BLACK; +// T->root = T->nil; - rbtree_node *node = T->nil; - int i = 0; - for (i = 0;i < 10;i ++) { - node = (rbtree_node*)malloc(sizeof(rbtree_node)); +// rbtree_node *node = T->nil; +// int i = 0; +// for (i = 0;i < 10;i ++) { +// node = (rbtree_node*)malloc(sizeof(rbtree_node)); - node->key = malloc(strlen(keyArray[i]) + 1); - memset(node->key, 0, strlen(keyArray[i]) + 1); - strcpy(node->key, keyArray[i]); +// node->key = malloc(strlen(keyArray[i]) + 1); +// memset(node->key, 0, strlen(keyArray[i]) + 1); +// strcpy(node->key, keyArray[i]); - node->value = malloc(strlen(valueArray[i]) + 1); - memset(node->value, 0, strlen(valueArray[i]) + 1); - strcpy(node->value, valueArray[i]); +// node->value = malloc(strlen(valueArray[i]) + 1); +// memset(node->value, 0, strlen(valueArray[i]) + 1); +// strcpy(node->value, valueArray[i]); - rbtree_insert(T, node); +// rbtree_insert(T, node); - } +// } - rbtree_traversal(T, T->root); - printf("----------------------------------------\n"); +// rbtree_traversal(T, T->root); +// printf("----------------------------------------\n"); - for (i = 0;i < 10;i ++) { +// for (i = 0;i < 10;i ++) { - rbtree_node *node = rbtree_search(T, keyArray[i]); - rbtree_node *cur = rbtree_delete(T, node); - free(cur); +// rbtree_node *node = rbtree_search(T, keyArray[i]); +// rbtree_node *cur = rbtree_delete(T, node); +// free(cur); - rbtree_traversal(T, T->root); - printf("----------------------------------------\n"); - } +// rbtree_traversal(T, T->root); +// printf("----------------------------------------\n"); +// } -#else +// #else - int keyArray[20] = {24,25,13,35,23, 26,67,47,38,98, 20,19,17,49,12, 21,9,18,14,15}; +// int keyArray[20] = {24,25,13,35,23, 26,67,47,38,98, 20,19,17,49,12, 21,9,18,14,15}; - rbtree *T = (rbtree *)malloc(sizeof(rbtree)); - if (T == NULL) { - printf("malloc failed\n"); - return -1; - } +// rbtree *T = (rbtree *)malloc(sizeof(rbtree)); +// if (T == NULL) { +// printf("malloc failed\n"); +// return -1; +// } - T->nil = (rbtree_node*)malloc(sizeof(rbtree_node)); - T->nil->color = BLACK; - T->root = T->nil; +// T->nil = (rbtree_node*)malloc(sizeof(rbtree_node)); +// T->nil->color = BLACK; +// T->root = T->nil; - rbtree_node *node = T->nil; - int i = 0; - for (i = 0;i < 20;i ++) { - node = (rbtree_node*)malloc(sizeof(rbtree_node)); - node->key = keyArray[i]; - node->value = NULL; +// rbtree_node *node = T->nil; +// int i = 0; +// for (i = 0;i < 20;i ++) { +// node = (rbtree_node*)malloc(sizeof(rbtree_node)); +// node->key = keyArray[i]; +// node->value = NULL; - rbtree_insert(T, node); +// rbtree_insert(T, node); - } +// } - rbtree_traversal(T, T->root); - printf("----------------------------------------\n"); +// rbtree_traversal(T, T->root); +// printf("----------------------------------------\n"); - for (i = 0;i < 20;i ++) { +// for (i = 0;i < 20;i ++) { - rbtree_node *node = rbtree_search(T, keyArray[i]); - rbtree_node *cur = rbtree_delete(T, node); - free(cur); +// rbtree_node *node = rbtree_search(T, keyArray[i]); +// rbtree_node *cur = rbtree_delete(T, node); +// free(cur); - rbtree_traversal(T, T->root); - printf("----------------------------------------\n"); - } -#endif +// rbtree_traversal(T, T->root); +// printf("----------------------------------------\n"); +// } +// #endif -} +// } -#endif +// #endif -typedef struct _rbtree kvs_rbtree_t; +// typedef struct _rbtree kvs_rbtree_t; -kvs_rbtree_t global_rbtree; +// kvs_rbtree_t global_rbtree; -// 5 + 2 -int kvs_rbtree_create(kvs_rbtree_t *inst) { +// // 5 + 2 +// int kvs_rbtree_create(kvs_rbtree_t *inst) { - if (inst == NULL) return 1; +// if (inst == NULL) return 1; - inst->nil = (rbtree_node*)kvs_malloc(sizeof(rbtree_node)); - inst->nil->color = BLACK; - inst->root = inst->nil; +// inst->nil = (rbtree_node*)kvs_malloc(sizeof(rbtree_node)); +// inst->nil->color = BLACK; +// inst->root = inst->nil; - return 0; +// return 0; -} +// } -void kvs_rbtree_destroy(kvs_rbtree_t *inst) { +// void kvs_rbtree_destroy(kvs_rbtree_t *inst) { - if (inst == NULL) return ; +// if (inst == NULL) return ; - rbtree_node *node = NULL; +// rbtree_node *node = NULL; - while (!(node = inst->root)) { +// while (!(node = inst->root)) { - rbtree_node *mini = rbtree_mini(inst, node); +// rbtree_node *mini = rbtree_mini(inst, node); - rbtree_node *cur = rbtree_delete(inst, mini); - kvs_free(cur); +// rbtree_node *cur = rbtree_delete(inst, mini); +// kvs_free(cur); - } +// } - kvs_free(inst->nil); +// kvs_free(inst->nil); - return ; +// return ; -} +// } -int kvs_rbtree_set(kvs_rbtree_t *inst, char *key, char *value) { +// int kvs_rbtree_set(kvs_rbtree_t *inst, char *key, char *value) { - if (!inst || !key || !value) return -1; +// if (!inst || !key || !value) return -1; - rbtree_node *node = (rbtree_node*)kvs_malloc(sizeof(rbtree_node)); +// rbtree_node *node = (rbtree_node*)kvs_malloc(sizeof(rbtree_node)); - node->key = kvs_malloc(strlen(key) + 1); - if (!node->key) return -2; - memset(node->key, 0, strlen(key) + 1); - strcpy(node->key, key); +// node->key = kvs_malloc(strlen(key) + 1); +// if (!node->key) return -2; +// memset(node->key, 0, strlen(key) + 1); +// strcpy(node->key, key); - node->value = kvs_malloc(strlen(value) + 1); - if (!node->value) return -2; - memset(node->value, 0, strlen(value) + 1); - strcpy(node->value, value); +// node->value = kvs_malloc(strlen(value) + 1); +// if (!node->value) return -2; +// memset(node->value, 0, strlen(value) + 1); +// strcpy(node->value, value); - rbtree_insert(inst, node); +// rbtree_insert(inst, node); - return 0; -} +// return 0; +// } -char* kvs_rbtree_get(kvs_rbtree_t *inst, char *key) { +// char* kvs_rbtree_get(kvs_rbtree_t *inst, char *key) { - if (!inst || !key) return NULL; - rbtree_node *node = rbtree_search(inst, key); - if (!node) return NULL; // no exist - if (node == inst->nil) return NULL; +// if (!inst || !key) return NULL; +// rbtree_node *node = rbtree_search(inst, key); +// if (!node) return NULL; // no exist +// if (node == inst->nil) return NULL; - return node->value; +// return node->value; -} +// } -int kvs_rbtree_del(kvs_rbtree_t *inst, char *key) { +// int kvs_rbtree_del(kvs_rbtree_t *inst, char *key) { - if (!inst || !key) return -1; +// if (!inst || !key) return -1; - rbtree_node *node = rbtree_search(inst, key); - if (!node) return 1; // no exist +// rbtree_node *node = rbtree_search(inst, key); +// if (!node) return 1; // no exist - rbtree_node *cur = rbtree_delete(inst, node); - free(cur); +// rbtree_node *cur = rbtree_delete(inst, node); +// free(cur); - return 0; -} +// return 0; +// } -int kvs_rbtree_mod(kvs_rbtree_t *inst, char *key, char *value) { +// int kvs_rbtree_mod(kvs_rbtree_t *inst, char *key, char *value) { - if (!inst || !key || !value) return -1; +// if (!inst || !key || !value) return -1; - rbtree_node *node = rbtree_search(inst, key); - if (!node) return 1; // no exist - if (node == inst->nil) return 1; +// rbtree_node *node = rbtree_search(inst, key); +// if (!node) return 1; // no exist +// if (node == inst->nil) return 1; - kvs_free(node->value); +// kvs_free(node->value); - node->value = kvs_malloc(strlen(value) + 1); - if (!node->value) return -2; +// node->value = kvs_malloc(strlen(value) + 1); +// if (!node->value) return -2; - memset(node->value, 0, strlen(value) + 1); - strcpy(node->value, value); +// memset(node->value, 0, strlen(value) + 1); +// strcpy(node->value, value); - return 0; +// return 0; -} +// } -int kvs_rbtree_exist(kvs_rbtree_t *inst, char *key) { +// int kvs_rbtree_exist(kvs_rbtree_t *inst, char *key) { - if (!inst || !key) return -1; +// if (!inst || !key) return -1; - rbtree_node *node = rbtree_search(inst, key); - if (!node) return 1; // no exist - if (node == inst->nil) return 1; +// rbtree_node *node = rbtree_search(inst, key); +// if (!node) return 1; // no exist +// if (node == inst->nil) return 1; - return 0; -} +// return 0; +// } diff --git a/kvs_rbtree_bin.c b/kvs_rbtree_bin.c new file mode 100644 index 0000000..8546b7e --- /dev/null +++ b/kvs_rbtree_bin.c @@ -0,0 +1,568 @@ + + + +#include +#include +#include + + +#include "kvstore.h" +#include "kvs_rw_tools.h" +#include + +int kvs_keycmp(const uint8_t *a, uint32_t alen, + const uint8_t *b, uint32_t blen) { + uint32_t min = (alen < blen) ? alen : blen; + int r = 0; + if (min > 0) { + r = memcmp(a, b, min); + if (r != 0) return r; + } + // 前缀相同,则短的更小 + if (alen < blen) return -1; + if (alen > blen) return 1; + return 0; +} + +rbtree_node *rbtree_mini(rbtree *T, rbtree_node *x) { + while (x->left != T->nil) { + x = x->left; + } + return x; +} + +rbtree_node *rbtree_maxi(rbtree *T, rbtree_node *x) { + while (x->right != T->nil) { + x = x->right; + } + return x; +} + +rbtree_node *rbtree_successor(rbtree *T, rbtree_node *x) { + rbtree_node *y = x->parent; + + if (x->right != T->nil) { + return rbtree_mini(T, x->right); + } + + while ((y != T->nil) && (x == y->right)) { + x = y; + y = y->parent; + } + return y; +} + + +void rbtree_left_rotate(rbtree *T, rbtree_node *x) { + + rbtree_node *y = x->right; // x --> y , y --> x, right --> left, left --> right + + x->right = y->left; //1 1 + if (y->left != T->nil) { //1 2 + y->left->parent = x; + } + + y->parent = x->parent; //1 3 + if (x->parent == T->nil) { //1 4 + T->root = y; + } else if (x == x->parent->left) { + x->parent->left = y; + } else { + x->parent->right = y; + } + + y->left = x; //1 5 + x->parent = y; //1 6 +} + + +void rbtree_right_rotate(rbtree *T, rbtree_node *y) { + + rbtree_node *x = y->left; + + y->left = x->right; + if (x->right != T->nil) { + x->right->parent = y; + } + + x->parent = y->parent; + if (y->parent == T->nil) { + T->root = x; + } else if (y == y->parent->right) { + y->parent->right = x; + } else { + y->parent->left = x; + } + + x->right = y; + y->parent = x; +} + +void rbtree_insert_fixup(rbtree *T, rbtree_node *z) { + + while (z->parent->color == RED) { //z ---> RED + if (z->parent == z->parent->parent->left) { + rbtree_node *y = z->parent->parent->right; + if (y->color == RED) { + z->parent->color = BLACK; + y->color = BLACK; + z->parent->parent->color = RED; + + z = z->parent->parent; //z --> RED + } else { + + if (z == z->parent->right) { + z = z->parent; + rbtree_left_rotate(T, z); + } + + z->parent->color = BLACK; + z->parent->parent->color = RED; + rbtree_right_rotate(T, z->parent->parent); + } + }else { + rbtree_node *y = z->parent->parent->left; + if (y->color == RED) { + z->parent->color = BLACK; + y->color = BLACK; + z->parent->parent->color = RED; + + z = z->parent->parent; //z --> RED + } else { + if (z == z->parent->left) { + z = z->parent; + rbtree_right_rotate(T, z); + } + + z->parent->color = BLACK; + z->parent->parent->color = RED; + rbtree_left_rotate(T, z->parent->parent); + } + } + + } + + T->root->color = BLACK; +} + + +int rbtree_insert(rbtree *T, rbtree_node *z) { + + rbtree_node *y = T->nil; + rbtree_node *x = T->root; + + while (x != T->nil) { + y = x; + + int c = kvs_keycmp(z->key, z->key_len, x->key, x->key_len); + if (c < 0) { + x = x->left; + } else if (c > 0) { + x = x->right; + } else { + return -1; + } + + } + + z->parent = y; + if (y == T->nil) { + T->root = z; + + }else{ + int c = kvs_keycmp(z->key, z->key_len, y->key, y->key_len); + if (c < 0) y->left = z; + else y->right = z; + } + z->left = T->nil; + z->right = T->nil; + z->color = RED; + + rbtree_insert_fixup(T, z); + return 0; +} + +void rbtree_delete_fixup(rbtree *T, rbtree_node *x) { + + while ((x != T->root) && (x->color == BLACK)) { + if (x == x->parent->left) { + + rbtree_node *w= x->parent->right; + if (w->color == RED) { + w->color = BLACK; + x->parent->color = RED; + + rbtree_left_rotate(T, x->parent); + w = x->parent->right; + } + + if ((w->left->color == BLACK) && (w->right->color == BLACK)) { + w->color = RED; + x = x->parent; + } else { + + if (w->right->color == BLACK) { + w->left->color = BLACK; + w->color = RED; + rbtree_right_rotate(T, w); + w = x->parent->right; + } + + w->color = x->parent->color; + x->parent->color = BLACK; + w->right->color = BLACK; + rbtree_left_rotate(T, x->parent); + + x = T->root; + } + + } else { + + rbtree_node *w = x->parent->left; + if (w->color == RED) { + w->color = BLACK; + x->parent->color = RED; + rbtree_right_rotate(T, x->parent); + w = x->parent->left; + } + + if ((w->left->color == BLACK) && (w->right->color == BLACK)) { + w->color = RED; + x = x->parent; + } else { + + if (w->left->color == BLACK) { + w->right->color = BLACK; + w->color = RED; + rbtree_left_rotate(T, w); + w = x->parent->left; + } + + w->color = x->parent->color; + x->parent->color = BLACK; + w->left->color = BLACK; + rbtree_right_rotate(T, x->parent); + + x = T->root; + } + + } + } + + x->color = BLACK; +} + +rbtree_node *rbtree_delete(rbtree *T, rbtree_node *z) { + + rbtree_node *y = T->nil; + rbtree_node *x = T->nil; + + if ((z->left == T->nil) || (z->right == T->nil)) { + y = z; + } else { + y = rbtree_successor(T, z); + } + + if (y->left != T->nil) { + x = y->left; + } else if (y->right != T->nil) { + x = y->right; + } + + x->parent = y->parent; + if (y->parent == T->nil) { + T->root = x; + } else if (y == y->parent->left) { + y->parent->left = x; + } else { + y->parent->right = x; + } + + if (y != z) { + uint8_t *ktmp = z->key; z->key = y->key; y->key = ktmp; + uint32_t ltmp = z->key_len; z->key_len = y->key_len; y->key_len = ltmp; + + uint8_t *vtmp = z->value; z->value = y->value; y->value = vtmp; + uint32_t tlen = z->value_len; z->value_len = y->value_len; y->value_len = tlen; + } + + if (y->color == BLACK) { + rbtree_delete_fixup(T, x); + } + + return y; +} + +rbtree_node *rbtree_search(rbtree *T, KEY_TYPE* key, uint32_t keylen) { + + rbtree_node *node = T->root; + while (node != T->nil) { + 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) { + rbtree_traversal(T, node->left); + + printf("key:%s, color:%d\n", (char*)node->key, node->color); + rbtree_traversal(T, node->right); + } +} + + +typedef struct _rbtree kvs_rbtree_t; + +kvs_rbtree_t global_rbtree; + +// 5 + 2 +int kvs_rbtree_create(kvs_rbtree_t *inst) { + + if (inst == NULL) return 1; + + inst->nil = (rbtree_node*)kvs_malloc(sizeof(rbtree_node)); + if (!inst->nil) return 2; + + inst->nil->color = BLACK; + inst->nil->left = inst->nil->right = inst->nil->parent = inst->nil; + inst->root = inst->nil; + + return 0; + +} + +void kvs_rbtree_destroy(kvs_rbtree_t *inst) { + + if (inst == NULL) return ; + + rbtree_node *node = NULL; + + while (inst->root != inst->nil) { + + rbtree_node *mini = rbtree_mini(inst, node); + + rbtree_node *cur = rbtree_delete(inst, mini); + if (cur != inst->nil) { + if (cur->key) kvs_free(cur->key); + if (cur->value) kvs_free(cur->value); + kvs_free(cur); + } + + } + + kvs_free(inst->nil); + inst->nil = NULL; + inst->root = NULL; + return ; + +} + +/* + * 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) { + + if (!inst || !key || !value) return -1; + + rbtree_node *node = (rbtree_node*)kvs_malloc(sizeof(rbtree_node)); + if (!node) return -2; + memset(node, 0, sizeof(*node)); + + node->key = (uint8_t*)kvs_malloc(key_len); + if (!node->key) { + kvs_free(node);return -2; + } + memcpy(node->key, key, key_len); + node->key_len = key_len; + + node->value = (uint8_t*)kvs_malloc(value_len); + if (!node->value) { kvs_free(node->key); kvs_free(node); return -2; } + if (value_len) memcpy(node->value, value, value_len); + node->value_len = value_len; + + if(rbtree_insert(inst, node) < 0){ + kvs_free(node->value); + kvs_free(node->key); + kvs_free(node); + return 1; + } + + return 0; +} + + +/* + * @return: NULL notexist, NOTNULL exist + */ +void* kvs_rbtree_get(kvs_rbtree_t *inst, const void *key, uint32_t key_len, uint32_t *out_valuelen) { + if (!inst || !key || key_len == 0 || !out_valuelen) return NULL; + + rbtree_node *node = rbtree_search(inst, (uint8_t *)key, key_len); + if (!node) return NULL; // no exist + if (node == inst->nil) return NULL; + + *out_valuelen = node->value_len; + return node->value; +} + +/* + * @return < 0, error; =0, success; >0, no exist + */ +int kvs_rbtree_del(rbtree *inst, const void *key, uint32_t key_len) { + + if (!inst || !key || key_len == 0) return -1; + + rbtree_node *node = rbtree_search(inst, (uint8_t *)key, key_len); + if (!node) return 1; // no exist + if (node == inst->nil) return 1; + + rbtree_node *cur = rbtree_delete(inst, node); + if (cur != inst->nil) { + if (cur->key) kvs_free(cur->key); + if (cur->value) kvs_free(cur->value); + kvs_free(cur); + } + + return 0; +} + +/* + * @return : < 0, error; =0, success; >0, no exist + */ + +int kvs_rbtree_mod(kvs_rbtree_t *inst, const void *key, uint32_t key_len, const void *value, uint32_t value_len) { + + if (!inst || !key || key_len==0 || !value) return -1; + + rbtree_node *node = rbtree_search(inst, (uint8_t *)key, key_len); + if (!node) return 1; // no exist + if (node == inst->nil) return 1; + + if (node->value) kvs_free(node->value); + + node->value = (uint8_t*)kvs_malloc(value_len); + if (!node->value) { node->value_len = 0; return -2; } + + if (value_len) memcpy(node->value, value, value_len); + node->value_len = value_len; + + return 0; + +} + +/* + * @return 0: exist, 1: no exist + */ +int kvs_rbtree_exist(kvs_rbtree_t *inst, const void *key, uint32_t key_len) { + + if (!inst || !key || key_len == 0) return -1; + + rbtree_node *node = rbtree_search(inst, (uint8_t*)key, key_len); + if (!node) return 1; // no exist + if (node == inst->nil) return 1; + + return 0; +} + +static int kvs_rbtree_save_node(FILE *fp, kvs_rbtree_t *inst, rbtree_node *node) { + if (!fp || !inst || !node) return -1; + if (node == inst->nil) return 0; + + int rc = 0; + + rc = kvs_rbtree_save_node(fp, inst, node->left); + if (rc < 0) return rc; + + uint32_t klen_n = htonl(node->key_len); + uint32_t vlen_n = htonl(node->value_len); + + if (kvs_write_file(fp, &klen_n, sizeof(klen_n)) < 0) return -1; + if (kvs_write_file(fp, &vlen_n, sizeof(vlen_n)) < 0) return -1; + + if (node->key_len) { + if (!node->key) return -1; + if (kvs_write_file(fp, node->key, node->key_len) < 0) return -1; + } + if (node->value_len) { + if (!node->value) return -1; + if (kvs_write_file(fp, node->value, node->value_len) < 0) return -1; + } + + rc = kvs_rbtree_save_node(fp, inst, node->right); + if (rc < 0) return rc; + + return 0; +} + +// 0 success, <0 error +int kvs_rbtree_save(kvs_rbtree_t *inst, const char* filename){ + if (!inst || !filename) return -1; + + FILE *fp = fopen(filename, "wb"); + if (!fp) return -2; + + int rc = kvs_rbtree_save_node(fp, inst, inst->root); + + if (fflush(fp) != 0) rc = -3; + + fclose(fp); + return rc; +} + +int kvs_rbtree_load(kvs_rbtree_t *inst, const char* filename){ + if (!inst || !filename) return -1; + + FILE *fp = fopen(filename, "rb"); + if (!fp) return -2; + + for (;;) { + 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; } + uint8_t *keybuf = (uint8_t*)kvs_malloc((size_t)klen); + if (!keybuf) { fclose(fp); return -4; } + if (kvs_read_file(fp, keybuf, (size_t)klen) < 0) { + kvs_free(keybuf); + fclose(fp); + return -3; + } + + uint8_t *valbuf = NULL; + if (vlen > 0) { + valbuf = (uint8_t*)kvs_malloc((size_t)vlen); + if (!valbuf) { + kvs_free(keybuf); + fclose(fp); + return -4; + } + if (kvs_read_file(fp, valbuf, (size_t)vlen) < 0) { + kvs_free(valbuf); + kvs_free(keybuf); + fclose(fp); + return -3; + } + } + + int rc = kvs_rbtree_set(inst, keybuf, klen, valbuf, vlen); + if (vlen > 0) kvs_free(valbuf); + + if (rc < 0) { // error + fclose(fp); + return -5; + } + } + + fclose(fp); + return 0; +} \ No newline at end of file diff --git a/kvs_rw_tools.c b/kvs_rw_tools.c index 227ac4f..6364f68 100644 --- a/kvs_rw_tools.c +++ b/kvs_rw_tools.c @@ -17,6 +17,49 @@ extern kvs_hash_t global_hash; extern int global_cmd_log_fd; +#include +int write_full(int fd, const void *buf, size_t len) +{ + const uint8_t *p = buf; + + while (len > 0) { + ssize_t n = write(fd, p, len); + if (n < 0) { + if (errno == EINTR) + continue; + return -1; + } + p += n; + len -= n; + } + return 0; +} + +// 1 read n suc, 0 eof, -1 error +int read_full(int fd, void *buf, size_t n) +{ + uint8_t *p = (uint8_t *)buf; + size_t got = 0; + + while (got < n) { + ssize_t r = read(fd, p + got, n - got); + if (r > 0) { + got += (size_t)r; + continue; + } + if (r == 0) { + return (got == 0) ? 0 : -1; + } + /* r < 0 */ + if (errno == EINTR) { + continue; + } + return -1; + } + + return 1; +} + // 0 suc, -1 err int kvs_need(const uint8_t *p, const uint8_t *end, size_t n) { return (p + n <= end) ? 0 : -1; @@ -101,455 +144,3 @@ int kvs_read_file(FILE *fp, void *buf, size_t n){ } return 0; } - - -// return: -1 fail, 0 half, >0 consumed -int kvs_parse_one_cmd(const uint8_t *request, int request_length, kvs_req_t *req_out){ - if (!request || request_length <= 0 || !req_out) return -1; - - req_out->op = 0; - req_out->argc = 0; - req_out->args = NULL; - - const uint8_t *p = request; - const uint8_t *end = request + (size_t)request_length; - - // OP + ARGC - if (kvs_need(p, end, 2)) { - return 0; // NEED_MORE - } - - uint8_t op = 0, argc = 0; - if (kvs_read_u8(&p, end, &op) < 0) return -1; - if (kvs_read_u8(&p, end, &argc) < 0) return -1; - - if (argc > KVS_MAX_ARGC) return -1; - - // 先扫描一遍确认整条命令数据都在 buffer 里 - const uint8_t *scan = p; - uint32_t lens[KVS_MAX_ARGC]; - if (argc > 0) { - for (uint8_t i = 0; i < argc; i++) { - if (kvs_need(scan, end, 4)) { - return 0; // NEED_MORE - } - uint32_t alen = 0; - if (kvs_read_u32(&scan, end, &alen) < 0) return -1; - - // 防御:单个参数长度限制 - if (alen > KVS_MAX_ARGLEN) return -1; - - // 防御:scan + alen 越界 / 半包 - if (kvs_need(scan, end, (size_t)alen)) { - return 0; // NEED_MORE - } - lens[i] = alen; - scan += alen; - } - } - - size_t total_len = (size_t)(scan - request); - if (total_len > KVS_MAX_CMD_BYTES) return -1; - - req_out->op = op; - req_out->argc = argc; - - if (argc == 0) { - return (int)total_len; - } - - kvs_arg_t *args = (kvs_arg_t *)kvs_malloc((size_t)argc * sizeof(kvs_arg_t)); - if (!args) { - kvs_free_request(req_out); - return -1; - } - memset(args, 0, (size_t)argc * sizeof(kvs_arg_t)); - - for (uint8_t i = 0; i < argc; i++) { - uint32_t alen = 0; - if (kvs_read_u32(&p, end, &alen) < 0) { - kvs_free(args); - kvs_free_request(req_out); - return -1; - } - - // alen 与 lens[i] 应当一致(扫描时读过),不一致说明解析器/输入异常 - if (alen != lens[i]) { - kvs_free(args); - kvs_free_request(req_out); - return -1; - } - - args[i].len = alen; - args[i].data = p; // 直接指向输入 buffer(零拷贝) - p += alen; - } - - - req_out->args = args; - - return (int)(p - request); -} - -void kvs_free_request(kvs_req_t *req) { - if (!req) return; - if (req->args) { - kvs_free(req->args); - req->args = NULL; - } - req->op = 0; - req->argc = 0; -} - -/** - * 输入:req - * 输出:rsp - * 返回:-1 失败,参数错误,0 成功 - */ - int kvs_execute_one_cmd(const kvs_req_t *req, kvs_rsp_t *rsp_out) { - if(!req || !rsp_out) return -1; - rsp_out->op = req->op; - rsp_out->status = KVS_STATUS_ERROR; - rsp_out->data = NULL; - rsp_out->dlen = 0; - - int argc = req->argc; - int op = req->op; - kvs_arg_t *argv = req->args; - - uint32_t key_len = 0; - const void *key = NULL; - uint32_t value_len = 0; - const void *val = NULL; - - if(argc == 1){ - key_len = argv[0].len; - key = argv[0].data; - }else if(argc == 2){ - key_len = argv[0].len; - key = argv[0].data; - value_len = argv[1].len; - val = argv[1].data; - } - - // 基本参数校验(按你原有命令语义) - switch (op) { - case KVS_CMD_SET: - case KVS_CMD_MOD: - case KVS_CMD_RSET: - case KVS_CMD_RMOD: - case KVS_CMD_HSET: - case KVS_CMD_HMOD: - if (argc != 2 || !key || !val) { rsp_out->status = KVS_STATUS_BADREQ; return -1; } - break; - case KVS_CMD_GET: - case KVS_CMD_DEL: - case KVS_CMD_EXIST: - case KVS_CMD_RGET: - case KVS_CMD_RDEL: - case KVS_CMD_REXIST: - case KVS_CMD_HGET: - case KVS_CMD_HDEL: - case KVS_CMD_HEXIST: - if (argc != 1 || !key) { rsp_out->status = KVS_STATUS_BADREQ; return -1; } - break; - case KVS_CMD_SAVE: - if(argc != 0) { rsp_out->status = KVS_STATUS_BADREQ; return -1; } - break; - default: - rsp_out->status = KVS_STATUS_BADREQ; - return -1; - } - - int ret = 0; - const char *result = NULL; - - switch (op) { -#if ENABLE_ARRAY - case KVS_CMD_SET: - ret = kvs_array_set_bin(&global_array, key, key_len, val, value_len); - if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; - else if (ret == 0) rsp_out->status = KVS_STATUS_OK; - else rsp_out->status = KVS_STATUS_EXIST; - return 0; - - case KVS_CMD_GET: - result = kvs_array_get_bin(&global_array, key, key_len, &value_len); - if (!result) { rsp_out->status = KVS_STATUS_NO_EXIST; return 0; } - rsp_out->status = KVS_STATUS_OK; - rsp_out->data = result; - rsp_out->dlen = (uint32_t)value_len; - return 0; - - case KVS_CMD_DEL: - ret = kvs_array_del_bin(&global_array, key, key_len); - if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; - else if (ret == 0) rsp_out->status = KVS_STATUS_OK; - else rsp_out->status = KVS_STATUS_NO_EXIST; - return 0; - - case KVS_CMD_MOD: - ret = kvs_array_mod_bin(&global_array, key, key_len, val, value_len); - if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; - else if (ret == 0) rsp_out->status = KVS_STATUS_OK; - else rsp_out->status = KVS_STATUS_NO_EXIST; - return 0; - - case KVS_CMD_EXIST: - ret = kvs_array_exist_bin(&global_array, key, key_len); - rsp_out->status = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST; - return 0; -#endif - -#if ENABLE_RBTREE - case KVS_CMD_RSET: - ret = kvs_rbtree_set(&global_rbtree, (char*)key, (char*)val); - if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; - else if (ret == 0) rsp_out->status = KVS_STATUS_OK; - else rsp_out->status = KVS_STATUS_EXIST; - return 0; - - case KVS_CMD_RGET: - result = kvs_rbtree_get(&global_rbtree, (char*)key); - if (!result) { rsp_out->status = KVS_STATUS_NO_EXIST; return 0; } - rsp_out->status = KVS_STATUS_OK; - rsp_out->data = result; - rsp_out->dlen = (uint32_t)strlen(result); - return 0; - - case KVS_CMD_RDEL: - ret = kvs_rbtree_del(&global_rbtree, (char*)key); - if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; - else if (ret == 0) rsp_out->status = KVS_STATUS_OK; - else rsp_out->status = KVS_STATUS_NO_EXIST; - return 0; - - case KVS_CMD_RMOD: - ret = kvs_rbtree_mod(&global_rbtree, (char*)key, (char*)val); - if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; - else if (ret == 0) rsp_out->status = KVS_STATUS_OK; - else rsp_out->status = KVS_STATUS_NO_EXIST; - return 0; - - case KVS_CMD_REXIST: - ret = kvs_rbtree_exist(&global_rbtree, (char*)key); - rsp_out->status = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST; - return 0; -#endif - -#if ENABLE_HASH - case KVS_CMD_HSET: - ret = kvs_hash_set_bin(&global_hash, key, key_len, val, value_len); - if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; - else if (ret == 0) rsp_out->status = KVS_STATUS_OK; - else rsp_out->status = KVS_STATUS_EXIST; - return 0; - - case KVS_CMD_HGET: - result = kvs_hash_get_bin(&global_hash, key, key_len, &value_len); - if (!result) { rsp_out->status = KVS_STATUS_NO_EXIST; return 0; } - rsp_out->status = KVS_STATUS_OK; - rsp_out->data = result; - rsp_out->dlen = (uint32_t)value_len; - return 0; - - case KVS_CMD_HDEL: - ret = kvs_hash_del_bin(&global_hash, key, key_len); - if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; - else if (ret == 0) rsp_out->status = KVS_STATUS_OK; - else rsp_out->status = KVS_STATUS_NO_EXIST; - return 0; - - case KVS_CMD_HMOD: - ret = kvs_hash_mod_bin(&global_hash, key, key_len, val, value_len); - if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; - else if (ret == 0) rsp_out->status = KVS_STATUS_OK; - else rsp_out->status = KVS_STATUS_NO_EXIST; - return 0; - - case KVS_CMD_HEXIST: - ret = kvs_hash_exist_bin(&global_hash, key, key_len); - rsp_out->status = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST; - return 0; -#endif - case KVS_CMD_SAVE: - ret = kvs_save_to_file(); - if(ret == 0) rsp_out->status = KVS_STATUS_OK; - else rsp_out->status = KVS_STATUS_ERROR; - return 0; - default: - rsp_out->status = KVS_STATUS_BADREQ; - return -1; - } - - return -1; -} - -/** - * 构建单条响应 - * 返回:-1 失败,>=0 响应长度 - */ -int kvs_build_one_rsp(const kvs_rsp_t *results, uint8_t *response, size_t response_cap){ - if (!results || !response) return -1; - - const uint8_t *end = response + response_cap; - uint8_t *p = response; - - // 计算所需长度:1 + 1 + 4 + dlen - // 注意防止 size_t 溢出 - size_t need = 1u + 1u + 4u + (size_t)results->dlen; - if (need > response_cap) return -1; - - if (kvs_write_u8(&p, end, results->op) < 0) return -1; - if (kvs_write_u8(&p, end, results->status) < 0) return -1; - if (kvs_write_u32(&p, end, results->dlen) < 0) return -1; - - if (results->dlen > 0) { - if (!results->data) return -1; // 有长度却没指针,视为错误 - if (kvs_need(p, end, (size_t)results->dlen) < 0) return -1; - memcpy(p, results->data, results->dlen); - p += results->dlen; - } - - return (int)(p - response); -} - -int kvs_save_to_file(){ - #if ENABLE_ARRAY - int ret = kvs_array_save(&global_array, KVS_ARRAY_FILE); - #endif - - #if ENABLE_RBTREE - - #endif - - #if ENABLE_HASH - - #endif - - ksv_clear_log(global_cmd_log_fd); - - return ret; -} - -#include -int write_full(int fd, const void *buf, size_t len) -{ - const uint8_t *p = buf; - - while (len > 0) { - ssize_t n = write(fd, p, len); - if (n < 0) { - if (errno == EINTR) - continue; - return -1; - } - p += n; - len -= n; - } - return 0; -} - -// 1 read n suc, 0 eof, -1 error -int read_full(int fd, void *buf, size_t n) -{ - uint8_t *p = (uint8_t *)buf; - size_t got = 0; - - while (got < n) { - ssize_t r = read(fd, p + got, n - got); - if (r > 0) { - got += (size_t)r; - continue; - } - if (r == 0) { - return (got == 0) ? 0 : -1; - } - /* r < 0 */ - if (errno == EINTR) { - continue; - } - return -1; - } - - return 1; -} - -int kvs_save_cmd_to_logfile(const uint8_t *cmd, size_t len, int logfd){ - if (logfd < 0 || !cmd || len == 0) - return -1; - - if (len > UINT32_MAX) - return -2; - - uint32_t nlen = htonl((uint32_t)len); - - if (write_full(logfd, &nlen, sizeof(nlen)) < 0) - return -3; - - if (write_full(logfd, cmd, len) < 0) - return -4; - - if (fsync(logfd) < 0) - return -5; - - return 0; -} - -int kvs_replay_log(const char *logfile, int logfd){ - if (!logfile|| logfd<0) return -1; - - for (;;) { - uint32_t nlen = 0; - - int hr = read_full(logfd, &nlen, sizeof(nlen)); - if (hr == 0) break; /* EOF:正常结束 */ - if (hr < 0) { return -2; } /* 半截头 */ - - uint32_t len = ntohl(nlen); - if (len == 0) { return -3; } - - uint8_t *cmd = (uint8_t *)kvs_malloc(len); - if (!cmd) { return -5; } - - int pr = read_full(logfd, cmd, len); - if (pr <= 0) { /* 半截 payload */ - kvs_free(cmd); - return -6; - } - - kvs_req_t req; - memset(&req, 0, sizeof(req)); - - int clen = kvs_parse_one_cmd(cmd, (int)len, &req); - if (clen <= 0 || clen != (int)len) { - kvs_free_request(&req); - kvs_free(cmd); - return -7; - } - - kvs_rsp_t rsp; - memset(&rsp, 0, sizeof(rsp)); - - if (kvs_execute_one_cmd(&req, &rsp) < 0) { - kvs_free_request(&req); - kvs_free(cmd); - return -8; - } - - kvs_free_request(&req); - kvs_free(cmd); - } - - return 0; -} - -/** - * clear log file not close - */ -int ksv_clear_log(int logfd){ - if(logfd < 0) return -1; - ftruncate(logfd, 0); - lseek(logfd, 0, SEEK_SET); - return 0; -} \ No newline at end of file diff --git a/kvs_rw_tools.h b/kvs_rw_tools.h index b3ad90d..8e9c70a 100644 --- a/kvs_rw_tools.h +++ b/kvs_rw_tools.h @@ -16,6 +16,8 @@ int kvs_write_u32(uint8_t **pp, const uint8_t *end, uint32_t v); int kvs_write_file(FILE *fp, const void *buf, size_t n); int kvs_read_file(FILE *fp, void *buf, size_t n); +int write_full(int fd, const void *buf, size_t len); +int read_full(int fd, void *buf, size_t n); /** * Request @@ -39,7 +41,7 @@ enum { KVS_STATUS_BADREQ = 4 }; -enum { +typedef enum { KVS_CMD_START = 0, // array KVS_CMD_SET = KVS_CMD_START, @@ -62,7 +64,7 @@ enum { KVS_CMD_SAVE, KVS_CMD_COUNT, -}; +}kvs_cmd_t; typedef struct kvs_arg_s{ uint32_t len; @@ -70,13 +72,13 @@ typedef struct kvs_arg_s{ } kvs_arg_t; typedef struct kvs_req_s{ - uint8_t op; + kvs_cmd_t op; uint8_t argc; kvs_arg_t *args; }kvs_req_t; typedef struct kvs_rsp_s{ - uint8_t op; + kvs_cmd_t op; uint8_t status; uint32_t dlen; const uint8_t *data; diff --git a/kvstore.c b/kvstore.c index 021ee2b..0944f89 100644 --- a/kvstore.c +++ b/kvstore.c @@ -42,211 +42,350 @@ const char *response[] = { }; - -int kvs_split_token(char *msg, char *tokens[]) { - - if (msg == NULL || tokens == NULL) return -1; - - int idx = 0; - char *token = strtok(msg, " "); +// return: -1 fail, 0 half, >0 consumed +int kvs_parse_one_cmd(const uint8_t *request, int request_length, kvs_req_t *req_out){ + if (!request || request_length <= 0 || !req_out) return -1; - while (token != NULL) { - //printf("idx: %d, %s\n", idx, token); - - tokens[idx ++] = token; - token = strtok(NULL, " "); + req_out->op = KVS_CMD_COUNT; + req_out->argc = 0; + req_out->args = NULL; + + const uint8_t *p = request; + const uint8_t *end = request + (size_t)request_length; + + // OP + ARGC + if (kvs_need(p, end, 2)) { + return 0; // NEED_MORE + } + + uint8_t op = 0, argc = 0; + if (kvs_read_u8(&p, end, &op) < 0) return -1; + if (kvs_read_u8(&p, end, &argc) < 0) return -1; + + if (argc > KVS_MAX_ARGC) return -1; + + // 先扫描一遍确认整条命令数据都在 buffer 里 + const uint8_t *scan = p; + uint32_t lens[KVS_MAX_ARGC]; + if (argc > 0) { + for (uint8_t i = 0; i < argc; i++) { + if (kvs_need(scan, end, 4)) { + return 0; // NEED_MORE + } + uint32_t alen = 0; + if (kvs_read_u32(&scan, end, &alen) < 0) return -1; + + // 防御:单个参数长度限制 + if (alen > KVS_MAX_ARGLEN) return -1; + + // 防御:scan + alen 越界 / 半包 + if (kvs_need(scan, end, (size_t)alen)) { + return 0; // NEED_MORE + } + lens[i] = alen; + scan += alen; + } } - return idx; + size_t total_len = (size_t)(scan - request); + if (total_len > KVS_MAX_CMD_BYTES) return -1; + + req_out->op = op; + req_out->argc = argc; + + if (argc == 0) { + return (int)total_len; + } + + kvs_arg_t *args = (kvs_arg_t *)kvs_malloc((size_t)argc * sizeof(kvs_arg_t)); + if (!args) { + kvs_free_request(req_out); + return -1; + } + memset(args, 0, (size_t)argc * sizeof(kvs_arg_t)); + + for (uint8_t i = 0; i < argc; i++) { + uint32_t alen = 0; + if (kvs_read_u32(&p, end, &alen) < 0) { + kvs_free(args); + kvs_free_request(req_out); + return -1; + } + + // alen 与 lens[i] 应当一致(扫描时读过),不一致说明解析器/输入异常 + if (alen != lens[i]) { + kvs_free(args); + kvs_free_request(req_out); + return -1; + } + + args[i].len = alen; + args[i].data = p; // 直接指向输入 buffer(零拷贝) + p += alen; + } + + + req_out->args = args; + + return (int)(p - request); } +void kvs_free_request(kvs_req_t *req) { + if (!req) return; + if (req->args) { + kvs_free(req->args); + req->args = NULL; + } + req->op = KVS_CMD_COUNT; + req->argc = 0; +} -// SET Key Value -// tokens[0] : SET -// tokens[1] : Key -// tokens[2] : Value +/** + * 输入:req + * 输出:rsp + * 返回:-1 失败,参数错误,0 成功 + */ + int kvs_execute_one_cmd(const kvs_req_t *req, kvs_rsp_t *rsp_out) { + if(!req || !rsp_out) return -1; + rsp_out->op = req->op; + rsp_out->status = KVS_STATUS_ERROR; + rsp_out->data = NULL; + rsp_out->dlen = 0; -#if !BIN_SAFE -int kvs_filter_protocol(char **tokens, int count, char *response) { + int argc = req->argc; + kvs_cmd_t op = req->op; + kvs_arg_t *argv = req->args; - if (tokens[0] == NULL || count == 0 || response == NULL) return -1; + uint32_t key_len = 0; + const void *key = NULL; + uint32_t value_len = 0; + const void *val = NULL; - int cmd = KVS_CMD_START; - for (cmd = KVS_CMD_START;cmd < KVS_CMD_COUNT;cmd ++) { - if (strcmp(tokens[0], command[cmd]) == 0) { - break; - } + if(argc == 1){ + key_len = argv[0].len; + key = argv[0].data; + }else if(argc == 2){ + key_len = argv[0].len; + key = argv[0].data; + value_len = argv[1].len; + val = argv[1].data; } - int length = 0; - int ret = 0; - char *key = tokens[1]; - char *value = tokens[2]; + // 基本参数校验(按你原有命令语义) + switch (op) { + case KVS_CMD_SET: + case KVS_CMD_MOD: + case KVS_CMD_RSET: + case KVS_CMD_RMOD: + case KVS_CMD_HSET: + case KVS_CMD_HMOD: + if (argc != 2 || !key || !val) { rsp_out->status = KVS_STATUS_BADREQ; return -1; } + break; + case KVS_CMD_GET: + case KVS_CMD_DEL: + case KVS_CMD_EXIST: + case KVS_CMD_RGET: + case KVS_CMD_RDEL: + case KVS_CMD_REXIST: + case KVS_CMD_HGET: + case KVS_CMD_HDEL: + case KVS_CMD_HEXIST: + if (argc != 1 || !key) { rsp_out->status = KVS_STATUS_BADREQ; return -1; } + break; + case KVS_CMD_SAVE: + if(argc != 0) { rsp_out->status = KVS_STATUS_BADREQ; return -1; } + break; + default: + rsp_out->status = KVS_STATUS_BADREQ; + return -1; + } - switch(cmd) { + int ret = 0; + const char *result = NULL; + + switch (op) { #if ENABLE_ARRAY case KVS_CMD_SET: - ret = kvs_array_set(&global_array ,key, value); - if (ret < 0) { - length = sprintf(response, "ERROR\r\n"); - } else if (ret == 0) { - length = sprintf(response, "OK\r\n"); - } else { - length = sprintf(response, "EXIST\r\n"); - } - - break; - case KVS_CMD_GET: { - char *result = kvs_array_get(&global_array, key); - if (result == NULL) { - length = sprintf(response, "NO EXIST\r\n"); - } else { - length = sprintf(response, "%s\r\n", result); - } - break; - } + ret = kvs_array_set_bin(&global_array, key, key_len, val, value_len); + if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; + else if (ret == 0) rsp_out->status = KVS_STATUS_OK; + else rsp_out->status = KVS_STATUS_EXIST; + return 0; + + case KVS_CMD_GET: + result = kvs_array_get_bin(&global_array, key, key_len, &value_len); + if (!result) { rsp_out->status = KVS_STATUS_NO_EXIST; return 0; } + rsp_out->status = KVS_STATUS_OK; + rsp_out->data = (uint8_t*)result; + rsp_out->dlen = (uint32_t)value_len; + return 0; + case KVS_CMD_DEL: - ret = kvs_array_del(&global_array ,key); - if (ret < 0) { - length = sprintf(response, "ERROR\r\n"); - } else if (ret == 0) { - length = sprintf(response, "OK\r\n"); - } else { - length = sprintf(response, "NO EXIST\r\n"); - } - break; + ret = kvs_array_del_bin(&global_array, key, key_len); + if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; + else if (ret == 0) rsp_out->status = KVS_STATUS_OK; + else rsp_out->status = KVS_STATUS_NO_EXIST; + return 0; + case KVS_CMD_MOD: - ret = kvs_array_mod(&global_array ,key, value); - if (ret < 0) { - length = sprintf(response, "ERROR\r\n"); - } else if (ret == 0) { - length = sprintf(response, "OK\r\n"); - } else { - length = sprintf(response, "NO EXIST\r\n"); - } - break; + ret = kvs_array_mod_bin(&global_array, key, key_len, val, value_len); + if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; + else if (ret == 0) rsp_out->status = KVS_STATUS_OK; + else rsp_out->status = KVS_STATUS_NO_EXIST; + return 0; + case KVS_CMD_EXIST: - ret = kvs_array_exist(&global_array ,key); - if (ret == 0) { - length = sprintf(response, "EXIST\r\n"); - } else { - length = sprintf(response, "NO EXIST\r\n"); - } - break; + ret = kvs_array_exist_bin(&global_array, key, key_len); + rsp_out->status = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST; + return 0; #endif - // rbtree + #if ENABLE_RBTREE case KVS_CMD_RSET: - ret = kvs_rbtree_set(&global_rbtree ,key, value); - if (ret < 0) { - length = sprintf(response, "ERROR\r\n"); - } else if (ret == 0) { - length = sprintf(response, "OK\r\n"); - } else { - length = sprintf(response, "EXIST\r\n"); - } - - break; - case KVS_CMD_RGET: { - char *result = kvs_rbtree_get(&global_rbtree, key); - if (result == NULL) { - length = sprintf(response, "NO EXIST\r\n"); - } else { - length = sprintf(response, "%s\r\n", result); - } - break; - } + ret = kvs_rbtree_set(&global_rbtree, key, key_len, val, value_len); + if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; + else if (ret == 0) rsp_out->status = KVS_STATUS_OK; + else rsp_out->status = KVS_STATUS_EXIST; + return 0; + + case KVS_CMD_RGET: + result = kvs_rbtree_get(&global_rbtree, key, key_len, &value_len); + if (!result) { rsp_out->status = KVS_STATUS_NO_EXIST; return 0; } + rsp_out->status = KVS_STATUS_OK; + rsp_out->data = (uint8_t*)result; + rsp_out->dlen = (uint32_t)value_len; + return 0; + case KVS_CMD_RDEL: - ret = kvs_rbtree_del(&global_rbtree ,key); - if (ret < 0) { - length = sprintf(response, "ERROR\r\n"); - } else if (ret == 0) { - length = sprintf(response, "OK\r\n"); - } else { - length = sprintf(response, "NO EXIST\r\n"); - } - break; + ret = kvs_rbtree_del(&global_rbtree, key, key_len); + if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; + else if (ret == 0) rsp_out->status = KVS_STATUS_OK; + else rsp_out->status = KVS_STATUS_NO_EXIST; + return 0; + case KVS_CMD_RMOD: - ret = kvs_rbtree_mod(&global_rbtree ,key, value); - if (ret < 0) { - length = sprintf(response, "ERROR\r\n"); - } else if (ret == 0) { - length = sprintf(response, "OK\r\n"); - } else { - length = sprintf(response, "NO EXIST\r\n"); - } - break; + ret = kvs_rbtree_mod(&global_rbtree, key, key_len, val, value_len); + if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; + else if (ret == 0) rsp_out->status = KVS_STATUS_OK; + else rsp_out->status = KVS_STATUS_NO_EXIST; + return 0; + case KVS_CMD_REXIST: - ret = kvs_rbtree_exist(&global_rbtree ,key); - if (ret == 0) { - length = sprintf(response, "EXIST\r\n"); - } else { - length = sprintf(response, "NO EXIST\r\n"); - } - break; + ret = kvs_rbtree_exist(&global_rbtree, key, key_len); + rsp_out->status = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST; + return 0; #endif + #if ENABLE_HASH case KVS_CMD_HSET: - ret = kvs_hash_set(&global_hash ,key, value); - if (ret < 0) { - length = sprintf(response, "ERROR\r\n"); - } else if (ret == 0) { - length = sprintf(response, "OK\r\n"); - } else { - length = sprintf(response, "EXIST\r\n"); - } - - break; - case KVS_CMD_HGET: { - char *result = kvs_hash_get(&global_hash, key); - if (result == NULL) { - length = sprintf(response, "NO EXIST\r\n"); - } else { - length = sprintf(response, "%s\r\n", result); - } - break; - } + ret = kvs_hash_set_bin(&global_hash, key, key_len, val, value_len); + if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; + else if (ret == 0) rsp_out->status = KVS_STATUS_OK; + else rsp_out->status = KVS_STATUS_EXIST; + return 0; + + case KVS_CMD_HGET: + result = kvs_hash_get_bin(&global_hash, key, key_len, &value_len); + if (!result) { rsp_out->status = KVS_STATUS_NO_EXIST; return 0; } + rsp_out->status = KVS_STATUS_OK; + rsp_out->data = (uint8_t*)result; + rsp_out->dlen = (uint32_t)value_len; + return 0; + case KVS_CMD_HDEL: - ret = kvs_hash_del(&global_hash ,key); - if (ret < 0) { - length = sprintf(response, "ERROR\r\n"); - } else if (ret == 0) { - length = sprintf(response, "OK\r\n"); - } else { - length = sprintf(response, "NO EXIST\r\n"); - } - break; - case KVS_CMD_HMOD: - ret = kvs_hash_mod(&global_hash ,key, value); - if (ret < 0) { - length = sprintf(response, "ERROR\r\n"); - } else if (ret == 0) { - length = sprintf(response, "OK\r\n"); - } else { - length = sprintf(response, "NO EXIST\r\n"); - } - break; - case KVS_CMD_HEXIST: - ret = kvs_hash_exist(&global_hash ,key); - if (ret == 0) { - length = sprintf(response, "EXIST\r\n"); - } else { - length = sprintf(response, "NO EXIST\r\n"); - } - break; -#endif + ret = kvs_hash_del_bin(&global_hash, key, key_len); + if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; + else if (ret == 0) rsp_out->status = KVS_STATUS_OK; + else rsp_out->status = KVS_STATUS_NO_EXIST; + return 0; - default: - assert(0); + case KVS_CMD_HMOD: + ret = kvs_hash_mod_bin(&global_hash, key, key_len, val, value_len); + if (ret < 0) rsp_out->status = KVS_STATUS_ERROR; + else if (ret == 0) rsp_out->status = KVS_STATUS_OK; + else rsp_out->status = KVS_STATUS_NO_EXIST; + return 0; + + case KVS_CMD_HEXIST: + ret = kvs_hash_exist_bin(&global_hash, key, key_len); + rsp_out->status = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST; + return 0; +#endif + case KVS_CMD_SAVE: + ret = kvs_save_to_file(); + if(ret == 0) rsp_out->status = KVS_STATUS_OK; + else rsp_out->status = KVS_STATUS_ERROR; + return 0; + default: + rsp_out->status = KVS_STATUS_BADREQ; + return -1; } - return length; + return -1; } -#endif +/** + * 构建单条响应 + * 返回:-1 失败,>=0 响应长度 + */ +int kvs_build_one_rsp(const kvs_rsp_t *results, uint8_t *response, size_t response_cap){ + if (!results || !response) return -1; + + const uint8_t *end = response + response_cap; + uint8_t *p = response; + + // 计算所需长度:1 + 1 + 4 + dlen + // 注意防止 size_t 溢出 + size_t need = 1u + 1u + 4u + (size_t)results->dlen; + if (need > response_cap) return -1; + + if (kvs_write_u8(&p, end, (uint8_t)results->op) < 0) return -1; + if (kvs_write_u8(&p, end, results->status) < 0) return -1; + if (kvs_write_u32(&p, end, results->dlen) < 0) return -1; + + if (results->dlen > 0) { + if (!results->data) return -1; // 有长度却没指针,视为错误 + if (kvs_need(p, end, (size_t)results->dlen) < 0) return -1; + memcpy(p, results->data, results->dlen); + p += results->dlen; + } + + return (int)(p - response); +} + +int kvs_save_to_file(){ + int ret = 0; + int rc = 0; + #if ENABLE_ARRAY + rc = kvs_array_save(&global_array, KVS_ARRAY_FILE); + if(rc < 0){ + printf("kvs_engine_array save error\n"); + ret = -1; + } + #endif + + #if ENABLE_RBTREE + rc = kvs_rbtree_save(&global_rbtree, KVS_RBTREE_FILE); + if(rc < 0){ + printf("kvs_engine_rbtree save error\n"); + ret = -1; + } + #endif + + #if ENABLE_HASH + rc = kvs_hash_save(&global_hash, KVS_HASH_FILE); + if(rc < 0){ + printf("kvs_engine_hash save error\n"); + ret = -1; + } + #endif + + ksv_clear_log(global_cmd_log_fd); + + return ret; +} -#if NEW_KVSTORE /** * input : request request_length * output : response response_length @@ -296,7 +435,9 @@ int kvs_protocol(char *request, int request_length, char *response, int *respons }else{ // 执行成功,在这里保存到日志中。 if(rsp.status == KVS_STATUS_OK){ - if(req.op == KVS_CMD_SET || req.op == KVS_CMD_MOD || req.op == KVS_CMD_DEL){ + if(req.op != KVS_CMD_GET && req.op != KVS_CMD_EXIST + && req.op != KVS_CMD_RGET && req.op != KVS_CMD_REXIST + && req.op != KVS_CMD_HGET && req.op != KVS_CMD_HEXIST ){ kvs_save_cmd_to_logfile(p, len, global_cmd_log_fd); } } @@ -319,48 +460,6 @@ int kvs_protocol(char *request, int request_length, char *response, int *respons *response_length = out_len; return consumed; } -#else -/* - * msg: request message - * length: length of request message - * response: need to send - * @return : length of response - */ - -int kvs_protocol(char *msg, int length, char *response) { // - -// SET Key Value -// GET Key -// DEL Key - if (msg == NULL || length <= 0 || response == NULL) return -1; - - //printf("recv %d : %s\n", length, msg); - - char *tokens[KVS_MAX_TOKENS] = {0}; - - int count = kvs_split_token(msg, tokens); - if (count == -1) return -1; - - //memcpy(response, msg, length); - - return kvs_filter_protocol(tokens, count, response); -} -#endif - - -int init_cmd_log(const char *file, int *logfd){ - if(!file) return -1; - int fd = open(file, O_RDWR | O_CREAT | O_APPEND, 0644); - if(fd < 0) return -2; - - *logfd = fd; - return 0; -} - -int destroy_cmd_log(int logfd){ - close(logfd); - return 0; -} int init_kvengine(void) { @@ -374,11 +473,15 @@ int init_kvengine(void) { #if ENABLE_RBTREE memset(&global_rbtree, 0, sizeof(kvs_rbtree_t)); kvs_rbtree_create(&global_rbtree); + + kvs_rbtree_load(&global_rbtree, KVS_RBTREE_FILE); #endif #if ENABLE_HASH memset(&global_hash, 0, sizeof(kvs_hash_t)); kvs_hash_create(&global_hash); + + kvs_hash_load(&global_hash, KVS_HASH_FILE); #endif init_cmd_log(KVS_CMD_LOG_FILE, &global_cmd_log_fd); diff --git a/kvstore.h b/kvstore.h index 7b2f73e..e0f6f73 100644 --- a/kvstore.h +++ b/kvstore.h @@ -31,7 +31,10 @@ #define BIN_SAFE 1 #define KVS_CMD_LOG_FILE "kvs_cmd_log.db" -#define KVS_ARRAY_FILE "kvs_array.db" +#define KVS_ARRAY_FILE "kvs_snap_array.db" +#define KVS_RBTREE_FILE "kvs_snap_rbtree.db" +#define KVS_HASH_FILE "kvs_snap_hash.db" + // typedef int (*msg_handler)(char *msg, int length, char *response); @@ -41,7 +44,11 @@ extern int reactor_start(unsigned short port, msg_handler handler); extern int proactor_start(unsigned short port, msg_handler handler); extern int ntyco_start(unsigned short port, msg_handler handler); - +extern int init_cmd_log(const char *file, int *logfd); +extern int destroy_cmd_log(int logfd); +extern int kvs_save_cmd_to_logfile(const uint8_t *cmd, size_t len, int logfd); +extern int kvs_replay_log(const char *logfile, int logfd); +extern int ksv_clear_log(int logfd); #if ENABLE_ARRAY @@ -112,6 +119,38 @@ int kvs_array_exist(kvs_array_t *inst, char *key); #define RED 1 #define BLACK 2 +#if BIN_SAFE +typedef uint8_t KEY_TYPE; // key + +typedef struct _rbtree_node { + unsigned char color; + struct _rbtree_node *right; + struct _rbtree_node *left; + struct _rbtree_node *parent; + KEY_TYPE *key; + uint32_t key_len; + KEY_TYPE *value; + uint32_t value_len; +} rbtree_node; + +typedef struct _rbtree { + rbtree_node *root; + rbtree_node *nil; +} rbtree; + +typedef struct _rbtree kvs_rbtree_t; + +int kvs_rbtree_create(kvs_rbtree_t *inst); +void kvs_rbtree_destroy(kvs_rbtree_t *inst); +int kvs_rbtree_set(kvs_rbtree_t *inst, const void *key, uint32_t key_len, const void *value, uint32_t value_len); +void* kvs_rbtree_get(kvs_rbtree_t *inst, const void *key, uint32_t key_len, uint32_t *out_valuelen); +int kvs_rbtree_del(rbtree *inst, const void *key, uint32_t key_len); +int kvs_rbtree_mod(kvs_rbtree_t *inst, const void *key, uint32_t key_len, const void *value, uint32_t value_len); +int kvs_rbtree_exist(kvs_rbtree_t *inst, const void *key, uint32_t key_len); + +int kvs_rbtree_save(kvs_rbtree_t *inst, const char* filename); +int kvs_rbtree_load(kvs_rbtree_t *inst, const char* filename); +#else #define ENABLE_KEY_CHAR 1 #if ENABLE_KEY_CHAR @@ -144,7 +183,7 @@ char* kvs_rbtree_get(kvs_rbtree_t *inst, char *key); int kvs_rbtree_del(kvs_rbtree_t *inst, char *key); int kvs_rbtree_mod(kvs_rbtree_t *inst, char *key, char *value); int kvs_rbtree_exist(kvs_rbtree_t *inst, char *key); - +#endif #endif @@ -152,9 +191,6 @@ int kvs_rbtree_exist(kvs_rbtree_t *inst, char *key); #if ENABLE_HASH -#define MAX_KEY_LEN 128 -#define MAX_VALUE_LEN 512 -#define MAX_TABLE_SIZE 1024 #if BIN_SAFE #define MAX_TABLE_SIZE 1024 @@ -186,9 +222,14 @@ int kvs_hash_del_bin(kvs_hash_t *h, const void *key, uint32_t key_len); int kvs_hash_exist_bin(kvs_hash_t *h, const void *key, uint32_t key_len); int kvs_hash_count(kvs_hash_t *h); -int save(kvs_hash_t *h, const char* filename); +int kvs_hash_save(kvs_hash_t *inst, const char* filename); +int kvs_hash_load(kvs_hash_t *inst, const char* filename); #else +#define MAX_KEY_LEN 128 +#define MAX_VALUE_LEN 512 +#define MAX_TABLE_SIZE 1024 + #define ENABLE_KEY_POINTER 1 diff --git a/reactor.c b/reactor.c index 3d9b13f..edfed77 100644 --- a/reactor.c +++ b/reactor.c @@ -139,7 +139,7 @@ int accept_cb(int fd) { int recv_cb(int fd) { struct conn *c = &conn_list[fd]; int avail = BUFFER_LENGTH - c->rlength; - printf("avail: %d\n", avail); + // printf("avail: %d\n", avail); if (avail <= 0) { // 缓冲满了还没解析出来:协议异常或包过大 close(fd); diff --git a/test/test_client.c b/test/test_client.c index 906d9a7..fb64e68 100644 --- a/test/test_client.c +++ b/test/test_client.c @@ -65,7 +65,7 @@ int kvs_write_u32(uint8_t **pp, const uint8_t *end, uint32_t v) { -int getcmd(uint8_t op, const char *key, const char *value, uint8_t *buf){ +int getcmd(uint8_t op, const char *key, uint32_t key_len, const char *value, uint32_t value_len, uint8_t *buf){ if(!buf) return -1; uint8_t *end = buf + CMD_SIZE; uint8_t *p = buf; @@ -79,7 +79,7 @@ int getcmd(uint8_t op, const char *key, const char *value, uint8_t *buf){ // 写入 key if(key){ - int keylen = strlen(key); + int keylen = key_len; if (kvs_write_u32(&p, end, keylen) < 0) return -1; if (kvs_need(p, end, keylen) < 0) return -1; if (keylen > 0) { @@ -89,7 +89,7 @@ int getcmd(uint8_t op, const char *key, const char *value, uint8_t *buf){ } if(value){ - int vallen = strlen(value); + int vallen = value_len; if (kvs_write_u32(&p, end, vallen) < 0) return -1; if (kvs_need(p, end, vallen) < 0) return -1; if (vallen > 0) { @@ -102,6 +102,7 @@ int getcmd(uint8_t op, const char *key, const char *value, uint8_t *buf){ } int parse_response(const uint8_t *buf, int buflen, kvs_response_t *rsp) { + if(buflen == 0) return 0; const uint8_t *p = buf; const uint8_t *end = buf + buflen; @@ -139,7 +140,7 @@ int parse_response(const uint8_t *buf, int buflen, kvs_response_t *rsp) { void print_response(const char *cmd_name, const kvs_response_t *rsp) { printf("%s ", cmd_name); - if(rsp->op == KVS_CMD_GET){ + if(rsp->op == KVS_CMD_GET || rsp->op == KVS_CMD_HGET || rsp->op == KVS_CMD_RGET){ if (rsp->datalen > 0 && rsp->data != NULL) { printf("Data: "); // 尝试以字符串形式打印(如果是可打印字符) @@ -190,7 +191,7 @@ void print_response(const char *cmd_name, const kvs_response_t *rsp) { } int verify_response(const kvs_response_t *rsp, uint8_t expected_op, - uint8_t expected_status, const char *expected_data) { + uint8_t expected_status, const char *expected_data, uint32_t expected_len) { if (rsp->op != expected_op) { printf("❌ OP mismatch: expected %u, got %u\n", expected_op, rsp->op); return 0; @@ -202,7 +203,6 @@ int verify_response(const kvs_response_t *rsp, uint8_t expected_op, } if (expected_data != NULL) { - uint32_t expected_len = strlen(expected_data); if (rsp->datalen != expected_len) { printf("❌ Data length mismatch: expected %u, got %u\n", expected_len, rsp->datalen); return 0; diff --git a/test/test_client.h b/test/test_client.h index 9ab644f..bcc2e8a 100644 --- a/test/test_client.h +++ b/test/test_client.h @@ -72,12 +72,12 @@ int kvs_write_u8(uint8_t **pp, const uint8_t *end, uint8_t v); int kvs_write_u16(uint8_t **pp, const uint8_t *end, uint16_t v); int kvs_write_u32(uint8_t **pp, const uint8_t *end, uint32_t v); -int getcmd(uint8_t op, const char *key, const char *value, uint8_t *buf); +int getcmd(uint8_t op, const char *key, uint32_t key_len, const char *value, uint32_t value_len, uint8_t *buf); int parse_response(const uint8_t *buf, int buflen, kvs_response_t *rsp); void print_response(const char *cmd_name, const kvs_response_t *rsp); int verify_response(const kvs_response_t *rsp, uint8_t expected_op, - uint8_t expected_status, const char *expected_data); + uint8_t expected_status, const char *expected_data, uint32_t expected_len); @@ -101,10 +101,10 @@ static void kvs_batch_init(kvs_batch_t *b) * 用 getcmd() 生成单条命令,然后 append 到 batch buffer * 返回:0 成功,-1 失败(太多条 or buffer 不够) */ -static int kvs_batch_add(kvs_batch_t *b, uint8_t op, const char *key, const char *value){ +static int kvs_batch_add(kvs_batch_t *b, uint8_t op, const char *key, uint32_t key_len, const char *value, uint32_t value_len){ if (b->cnt >= KVS_BATCH_MAX) return -1; uint8_t tmp[CMD_SIZE]; - int n = getcmd(op, key, value, tmp); // 你提供的函数 + int n = getcmd(op, key, key_len, value, value_len, tmp); // 你提供的函数 if (n <= 0) return -1; if (b->len + n > (int)sizeof(b->buf)) return -1; @@ -122,7 +122,7 @@ static int kvs_batch_add(kvs_batch_t *b, uint8_t op, const char *key, const char */ static int kvs_batch_send(int fd, const kvs_batch_t *b) { - printf("send : %d\n", b->len); + // printf("send : %d\n", b->len); return (int)send(fd, b->buf, b->len, 0); } @@ -141,9 +141,7 @@ static int kvs_batch_recv_parse(int fd, int used = 0; while(parsed < b->cnt){ - printf("recv loop: parsed=%d\n", parsed); int nrecv = (int)recv(fd, recvbuf+used, recvbuf_cap, 0); - printf("recv nrecv=%d\n", nrecv); if (nrecv <= 0) return -1; int off = 0; @@ -156,7 +154,6 @@ static int kvs_batch_recv_parse(int fd, used+= consumed; parsed++; } - printf("after parse: parsed=%d, used=%d\n", parsed, used); } return parsed; } \ No newline at end of file diff --git a/test/testcase.c b/test/testcase.c index 3426a35..0ad1266 100644 --- a/test/testcase.c +++ b/test/testcase.c @@ -45,18 +45,19 @@ int recv_msg(int connfd, char *msg, int length) { } -void testcase(int connfd, uint8_t op, const char* key, const char* value, rsp_ret_status_e st, const char* rsp_value, const char* command_name){ +void testcase(int connfd, uint8_t op, const char* key, uint32_t key_len, const char* value, + uint32_t value_len, rsp_ret_status_e st, const char* rsp_value, uint32_t expect_len, const char* command_name){ uint8_t buf[CMD_SIZE]; uint8_t result[CMD_SIZE]; kvs_response_t rsp; int len, recv_len; - len = getcmd(op, key, value, buf); + len = getcmd(op, key, key_len, value, value_len, buf); send_msg(connfd, buf, len); recv_len = recv_msg(connfd, result, CMD_SIZE); if (parse_response(result, recv_len, &rsp) > 0) { PRESP(command_name, &rsp); - if(!verify_response(&rsp, op, st, rsp_value)) printf("%s\n", command_name); + if(!verify_response(&rsp, op, st, rsp_value, expect_len)) printf("%s\n", command_name); }else{ printf("parser error\n"); } @@ -67,23 +68,23 @@ void testcase(int connfd, uint8_t op, const char* key, const char* value, rsp_re void array_testcase_1w(int connfd) { - int count = 1000; + int count = 1; int i = 0; struct timeval tv_begin; gettimeofday(&tv_begin, NULL); for (i = 0;i < count;i ++) { - testcase(connfd, KVS_CMD_SET, "name", "lian", KVS_STATUS_OK, NULL, "SET NAME"); - testcase(connfd, KVS_CMD_GET, "name", NULL, KVS_STATUS_OK, "lian", "GET NAME"); - testcase(connfd, KVS_CMD_MOD, "name", "liu", KVS_STATUS_OK, NULL, "MOD NAME"); - testcase(connfd, KVS_CMD_GET, "name", NULL, KVS_STATUS_OK, "liu", "GET NAME"); - testcase(connfd, KVS_CMD_EXIST, "name", NULL, KVS_STATUS_EXIST, NULL, "EXIST NAME"); - testcase(connfd, KVS_CMD_DEL, "name", NULL, KVS_STATUS_OK, NULL, "DEL NAME"); - testcase(connfd, KVS_CMD_EXIST, "name", NULL, KVS_STATUS_NO_EXIST, NULL, "NOT EXIST NAME"); + testcase(connfd, KVS_CMD_SET, "name", 4, "l\r\0n", 4, KVS_STATUS_OK, NULL, 0, "SET NAME"); + testcase(connfd, KVS_CMD_GET, "name", 4, NULL, 0, KVS_STATUS_OK, "l\r\0n", 4, "GET NAME"); + testcase(connfd, KVS_CMD_MOD, "name", 4, "liu", 3, KVS_STATUS_OK, NULL, 0, "MOD NAME"); + testcase(connfd, KVS_CMD_GET, "name", 4, NULL, 0, KVS_STATUS_OK, "liu", 3, "GET NAME"); + testcase(connfd, KVS_CMD_EXIST, "name", 4, NULL, 0, KVS_STATUS_EXIST, NULL, 0, "EXIST NAME"); + testcase(connfd, KVS_CMD_DEL, "name", 4, NULL, 0, KVS_STATUS_OK, NULL, 0, "DEL NAME"); + testcase(connfd, KVS_CMD_EXIST, "name", 4, NULL, 0, KVS_STATUS_NO_EXIST, NULL, 0, "EXIST NAME"); - testcase(connfd, KVS_CMD_MOD, "stu", "liu", KVS_STATUS_NO_EXIST, NULL, "MOD NAME"); - testcase(connfd, KVS_CMD_DEL, "stu", NULL, KVS_STATUS_NO_EXIST, NULL, "DEL SUT"); + testcase(connfd, KVS_CMD_MOD, "stu", 3, "liu", 3, KVS_STATUS_NO_EXIST, NULL, 0, "MOD NAME"); + testcase(connfd, KVS_CMD_DEL, "stu", 3, NULL, 0, KVS_STATUS_NO_EXIST, NULL, 0, "DEL SUT"); } struct timeval tv_end; @@ -97,23 +98,23 @@ void array_testcase_1w(int connfd) { void rbtree_testcase_1w(int connfd) { - int count = 1000; + int count = 1; int i = 0; struct timeval tv_begin; gettimeofday(&tv_begin, NULL); for (i = 0;i < count;i ++) { - testcase(connfd, KVS_CMD_RSET, "name", "lian", KVS_STATUS_OK, NULL, "SET NAME"); - testcase(connfd, KVS_CMD_RGET, "name", NULL, KVS_STATUS_OK, "lian", "GET NAME"); - testcase(connfd, KVS_CMD_RMOD, "name", "liu", KVS_STATUS_OK, NULL, "MOD NAME"); - testcase(connfd, KVS_CMD_RGET, "name", NULL, KVS_STATUS_OK, "liu", "GET NAME"); - testcase(connfd, KVS_CMD_REXIST, "name", NULL, KVS_STATUS_EXIST, NULL, "EXIST NAME"); - testcase(connfd, KVS_CMD_RDEL, "name", NULL, KVS_STATUS_OK, NULL, "DEL NAME"); - testcase(connfd, KVS_CMD_REXIST, "name", NULL, KVS_STATUS_NO_EXIST, NULL, "NOT EXIST NAME"); + testcase(connfd, KVS_CMD_RSET, "name", 4, "l\r\0n", 4, KVS_STATUS_OK, NULL, 0, "RSET NAME"); + testcase(connfd, KVS_CMD_RGET, "name", 4, NULL, 0, KVS_STATUS_OK, "l\r\0n", 4, "RGET NAME"); + testcase(connfd, KVS_CMD_RMOD, "name", 4, "liu", 3, KVS_STATUS_OK, NULL, 0, "RMOD NAME"); + testcase(connfd, KVS_CMD_RGET, "name", 4, NULL, 0, KVS_STATUS_OK, "liu", 3, "RGET NAME"); + testcase(connfd, KVS_CMD_REXIST, "name", 4, NULL, 0, KVS_STATUS_EXIST, NULL, 0, "REXIST NAME"); + testcase(connfd, KVS_CMD_RDEL, "name", 4, NULL, 0, KVS_STATUS_OK, NULL, 0, "RDEL NAME"); + testcase(connfd, KVS_CMD_REXIST, "name", 4, NULL, 0, KVS_STATUS_NO_EXIST, NULL, 0, "REXIST NAME"); - testcase(connfd, KVS_CMD_RMOD, "stu", "liu", KVS_STATUS_NO_EXIST, NULL, "MOD NAME"); - testcase(connfd, KVS_CMD_RDEL, "stu", NULL, KVS_STATUS_NO_EXIST, NULL, "DEL SUT"); + testcase(connfd, KVS_CMD_RMOD, "stu", 3, "liu", 3, KVS_STATUS_NO_EXIST, NULL, 0, "RMOD NAME"); + testcase(connfd, KVS_CMD_RDEL, "stu", 3, NULL, 0, KVS_STATUS_NO_EXIST, NULL, 0, "RDEL SUT"); } struct timeval tv_end; @@ -127,23 +128,23 @@ void rbtree_testcase_1w(int connfd) { void hash_testcase_1w(int connfd) { - int count = 1000; + int count = 1; int i = 0; struct timeval tv_begin; gettimeofday(&tv_begin, NULL); for (i = 0;i < count;i ++) { - testcase(connfd, KVS_CMD_HSET, "name", "lian", KVS_STATUS_OK, NULL, "SET NAME"); - testcase(connfd, KVS_CMD_HGET, "name", NULL, KVS_STATUS_OK, "lian", "GET NAME"); - testcase(connfd, KVS_CMD_HMOD, "name", "liu", KVS_STATUS_OK, NULL, "MOD NAME"); - testcase(connfd, KVS_CMD_HGET, "name", NULL, KVS_STATUS_OK, "liu", "GET NAME"); - testcase(connfd, KVS_CMD_HEXIST, "name", NULL, KVS_STATUS_EXIST, NULL, "EXIST NAME"); - testcase(connfd, KVS_CMD_HDEL, "name", NULL, KVS_STATUS_OK, NULL, "DEL NAME"); - testcase(connfd, KVS_CMD_HEXIST, "name", NULL, KVS_STATUS_NO_EXIST, NULL, "NOT EXIST NAME"); + testcase(connfd, KVS_CMD_HSET, "name", 4, "l\r\0n", 4, KVS_STATUS_OK, NULL, 0, "HSET NAME"); + testcase(connfd, KVS_CMD_HGET, "name", 4, NULL, 0, KVS_STATUS_OK, "l\r\0n", 4, "HGET NAME"); + testcase(connfd, KVS_CMD_HMOD, "name", 4, "liu", 3, KVS_STATUS_OK, NULL, 0, "HMOD NAME"); + testcase(connfd, KVS_CMD_HGET, "name", 4, NULL, 0, KVS_STATUS_OK, "liu", 3, "HGET NAME"); + testcase(connfd, KVS_CMD_HEXIST, "name", 4, NULL, 0, KVS_STATUS_EXIST, NULL, 0, "HEXIST NAME"); + testcase(connfd, KVS_CMD_HDEL, "name", 4, NULL, 0, KVS_STATUS_OK, NULL, 0, "HDEL NAME"); + testcase(connfd, KVS_CMD_HEXIST, "name", 4, NULL, 0, KVS_STATUS_NO_EXIST, NULL, 0, "HEXIST NAME"); - testcase(connfd, KVS_CMD_HMOD, "stu", "liu", KVS_STATUS_NO_EXIST, NULL, "MOD NAME"); - testcase(connfd, KVS_CMD_HDEL, "stu", NULL, KVS_STATUS_NO_EXIST, NULL, "DEL SUT"); + testcase(connfd, KVS_CMD_HMOD, "stu", 3, "liu", 3, KVS_STATUS_NO_EXIST, NULL, 0, "HMOD NAME"); + testcase(connfd, KVS_CMD_HDEL, "stu", 3, NULL, 0, KVS_STATUS_NO_EXIST, NULL, 0, "HDEL SUT"); } struct timeval tv_end; @@ -155,18 +156,110 @@ void hash_testcase_1w(int connfd) { } -void do_batch_SET_example(int fd) -{ +// void do_batch_SET_example(int fd) +// { +// kvs_batch_t batch; +// kvs_batch_init(&batch); + +// char key[10]={0}, val[10]={0}; + +// // 组 batch(最多 64 条) +// for(int i = 0;i < 48; ++ i){ +// int len = sprintf(key, "k%d", i); +// len = sprintf(val, "v%d", i); +// kvs_batch_add(&batch, KVS_CMD_SET, key, val); +// } + +// // 一次性发送 +// kvs_batch_send(fd, &batch); + +// // 一次性 recv + parse +// uint8_t recvbuf[BATCH_SIZE]; +// kvs_response_t rsps[KVS_BATCH_MAX]; + +// int nrsp = kvs_batch_recv_parse(fd, &batch, rsps, recvbuf, sizeof(recvbuf)); + +// // 打印/处理 +// for (int i = 0; i < nrsp; i++) { +// int len = sprintf(key, "SET%d", i); +// PRESP(key, &rsps[i]); +// } +// } + +// void do_batch_GET_example(int fd) +// { +// kvs_batch_t batch; +// kvs_batch_init(&batch); + +// char key[10]={0}, val[10]={0}; + +// // 组 batch(最多 64 条) +// for(int i = 0;i < 48; ++ i){ +// int len = sprintf(key, "k%d", i); +// kvs_batch_add(&batch, KVS_CMD_GET, key, NULL); +// } + +// // 一次性发送 +// kvs_batch_send(fd, &batch); + +// // 一次性 recv + parse +// uint8_t recvbuf[BATCH_SIZE]; +// kvs_response_t rsps[KVS_BATCH_MAX]; + +// int nrsp = kvs_batch_recv_parse(fd, &batch, rsps, recvbuf, sizeof(recvbuf)); + +// // 打印/处理 +// for (int i = 0; i < nrsp; i++) { +// int len = sprintf(key, "GET%d", i); +// PRESP(key, &rsps[i]); +// } +// } + +// void do_batch_DEL_example(int fd) +// { +// kvs_batch_t batch; +// kvs_batch_init(&batch); + +// char key[10]={0}, val[10]={0}; + +// // 组 batch(最多 64 条) +// for(int i = 0;i < 48; ++ i){ +// int len = sprintf(key, "k%d", i); +// kvs_batch_add(&batch, KVS_CMD_DEL, key, NULL); +// } + +// // 一次性发送 +// kvs_batch_send(fd, &batch); + +// // 一次性 recv + parse +// uint8_t recvbuf[BATCH_SIZE]; +// kvs_response_t rsps[KVS_BATCH_MAX]; + +// int nrsp = kvs_batch_recv_parse(fd, &batch, rsps, recvbuf, sizeof(recvbuf)); + +// // 打印/处理 +// for (int i = 0; i < nrsp; i++) { +// int len = sprintf(key, "DEL%d", i); +// PRESP(key, &rsps[i]); +// } +// } + +void do_batch_test(int fd, int op, const char *key, const char *value){ kvs_batch_t batch; kvs_batch_init(&batch); - char key[10]={0}, val[10]={0}; + char bkey[15]={0}, bval[15]={0}; // 组 batch(最多 64 条) for(int i = 0;i < 48; ++ i){ - int len = sprintf(key, "k%d", i); - len = sprintf(val, "v%d", i); - kvs_batch_add(&batch, KVS_CMD_SET, key, val); + if(value == NULL){ + int klen = sprintf(bkey, "%s%d", key, i); + kvs_batch_add(&batch, op, bkey, klen, NULL, 0); + }else{ + int klen = sprintf(bkey, "%s%d", key, i); + int vlen = sprintf(bval, "%s%d", value, i); + kvs_batch_add(&batch, op, bkey, klen, bval, vlen); + } } // 一次性发送 @@ -180,71 +273,13 @@ void do_batch_SET_example(int fd) // 打印/处理 for (int i = 0; i < nrsp; i++) { - int len = sprintf(key, "SET%d", i); - PRESP(key, &rsps[i]); - } -} - -void do_batch_GET_example(int fd) -{ - kvs_batch_t batch; - kvs_batch_init(&batch); - - char key[10]={0}, val[10]={0}; - - // 组 batch(最多 64 条) - for(int i = 0;i < 48; ++ i){ - int len = sprintf(key, "k%d", i); - kvs_batch_add(&batch, KVS_CMD_GET, key, NULL); - } - - // 一次性发送 - kvs_batch_send(fd, &batch); - - // 一次性 recv + parse - uint8_t recvbuf[BATCH_SIZE]; - kvs_response_t rsps[KVS_BATCH_MAX]; - - int nrsp = kvs_batch_recv_parse(fd, &batch, rsps, recvbuf, sizeof(recvbuf)); - - // 打印/处理 - for (int i = 0; i < nrsp; i++) { - int len = sprintf(key, "GET%d", i); - PRESP(key, &rsps[i]); - } -} - -void do_batch_DEL_example(int fd) -{ - kvs_batch_t batch; - kvs_batch_init(&batch); - - char key[10]={0}, val[10]={0}; - - // 组 batch(最多 64 条) - for(int i = 0;i < 48; ++ i){ - int len = sprintf(key, "k%d", i); - kvs_batch_add(&batch, KVS_CMD_DEL, key, NULL); - } - - // 一次性发送 - kvs_batch_send(fd, &batch); - - // 一次性 recv + parse - uint8_t recvbuf[BATCH_SIZE]; - kvs_response_t rsps[KVS_BATCH_MAX]; - - int nrsp = kvs_batch_recv_parse(fd, &batch, rsps, recvbuf, sizeof(recvbuf)); - - // 打印/处理 - for (int i = 0; i < nrsp; i++) { - int len = sprintf(key, "DEL%d", i); - PRESP(key, &rsps[i]); + int len = sprintf(bkey, "PRT%d", i); + PRESP(bkey, &rsps[i]); } } void save(int connfd){ - testcase(connfd, KVS_CMD_SAVE, NULL, NULL, KVS_STATUS_OK, NULL, "SAVE"); + testcase(connfd, KVS_CMD_SAVE, NULL, 0, NULL, 0, KVS_STATUS_OK, NULL, 0, "SAVE"); } @@ -261,17 +296,29 @@ int main(int argc, char *argv[]) { int connfd = connect_tcpserver(ip, port); if(mode == 0){ - do_batch_SET_example(connfd); - }else if(mode == 1){ - do_batch_GET_example(connfd); - }else if(mode == 2){ - do_batch_DEL_example(connfd); - }else if(mode == 10){ array_testcase_1w(connfd); - }else if(mode == 11){ + }else if(mode == 1){ rbtree_testcase_1w(connfd); - }else if(mode == 12){ + }else if(mode == 2){ hash_testcase_1w(connfd); + }else if(mode == 10){ + do_batch_test(connfd, KVS_CMD_SET, "array_set", "array_val"); + }else if(mode == 11){ + do_batch_test(connfd, KVS_CMD_GET, "array_set", NULL); + }else if(mode == 12){ + do_batch_test(connfd, KVS_CMD_EXIST, "array_set", NULL); + }else if(mode == 20){ + do_batch_test(connfd, KVS_CMD_RSET, "rbtree_set", "rbtree_val"); + }else if(mode == 21){ + do_batch_test(connfd, KVS_CMD_RGET, "rbtree_set", NULL); + }else if(mode == 22){ + do_batch_test(connfd, KVS_CMD_REXIST, "rbtree_set", NULL); + }else if(mode == 30){ + do_batch_test(connfd, KVS_CMD_HSET, "hash_set", "hash_val"); + }else if(mode == 31){ + do_batch_test(connfd, KVS_CMD_HGET, "hash_set", NULL); + }else if(mode == 32){ + do_batch_test(connfd, KVS_CMD_HEXIST, "hash_set", NULL); }else if(mode == -1){ save(connfd); }