From 3cc97b9454141ee2a25a105c2caf3c3b9d07af24 Mon Sep 17 00:00:00 2001 From: 1iaan Date: Wed, 7 Jan 2026 18:43:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=85=A8=E9=87=8F=E6=8C=81?= =?UTF-8?q?=E4=B9=85=E5=8C=96=EF=BC=9Asave=E6=93=8D=E4=BD=9C=E8=90=BD?= =?UTF-8?q?=E7=9B=98=EF=BC=8C=E5=90=AF=E5=8A=A8=E6=97=B6=E8=AF=BB=E5=8F=96?= =?UTF-8?q?=E5=88=B0=E5=86=85=E5=AD=98=20=E5=A2=9E=E9=87=8F=E6=8C=81?= =?UTF-8?q?=E4=B9=85=E5=8C=96=EF=BC=9A=E6=89=A7=E8=A1=8C=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E6=97=B6=E5=B0=86cmd=E8=BF=BD=E5=8A=A0?= =?UTF-8?q?=E5=88=B0log=E4=B8=AD=EF=BC=8C=E5=90=AF=E5=8A=A8=E6=97=B6?= =?UTF-8?q?=E9=80=90=E6=9D=A1=E5=8F=96=E5=87=BA=E9=A1=BA=E5=BA=8F=E6=89=A7?= =?UTF-8?q?=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kvs_array.c | 95 +++++++++++++++++++++++--- kvs_hash_bin.c | 22 +++--- kvs_rw_tools.c | 167 ++++++++++++++++++++++++++++++++++++++++++++- kvs_rw_tools.h | 7 ++ kvstore.c | 38 +++++++++-- kvstore.h | 41 ++++++----- test/test_client.c | 19 +++--- test/test_client.h | 7 +- test/testcase.c | 51 ++++++++------ 9 files changed, 373 insertions(+), 74 deletions(-) diff --git a/kvs_array.c b/kvs_array.c index 0c483ee..cab6998 100644 --- a/kvs_array.c +++ b/kvs_array.c @@ -1,6 +1,8 @@ #include "kvstore.h" +#include "kvs_rw_tools.h" +#include // singleton @@ -40,7 +42,7 @@ void kvs_array_destroy(kvs_array_t *inst) { /** * return: ==-2 not exist, == -1 error, >= 0 exist idx */ -int kvs_array_find_index(kvs_array_t *inst, const void *key, size_t key_len) { +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]; @@ -56,8 +58,8 @@ int kvs_array_find_index(kvs_array_t *inst, const void *key, size_t key_len) { * return: <0 error; 0 success; 1 exist */ int kvs_array_set_bin(kvs_array_t *inst, - const void *key, size_t key_len, - const void *value, size_t value_len) { + 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; @@ -109,9 +111,7 @@ int kvs_array_set_bin(kvs_array_t *inst, return 0; } -void *kvs_array_get_bin(kvs_array_t *inst, - const void *key, size_t key_len, - size_t *out_value_len) { +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; @@ -123,7 +123,7 @@ void *kvs_array_get_bin(kvs_array_t *inst, return it->value; // 注意:由 store 持有 } -int kvs_array_del_bin(kvs_array_t *inst, const void *key, size_t key_len) { +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); @@ -148,8 +148,8 @@ int kvs_array_del_bin(kvs_array_t *inst, const void *key, size_t key_len) { } int kvs_array_mod_bin(kvs_array_t *inst, - const void *key, size_t key_len, - const void *value, size_t value_len) { + 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); @@ -174,12 +174,87 @@ int kvs_array_mod_bin(kvs_array_t *inst, return 0; } -int kvs_array_exist_bin(kvs_array_t *inst, const void *key, size_t key_len) { +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 diff --git a/kvs_hash_bin.c b/kvs_hash_bin.c index 979ad03..fe006c8 100755 --- a/kvs_hash_bin.c +++ b/kvs_hash_bin.c @@ -20,26 +20,26 @@ kvs_hash_t global_hash; //Connection // 'C' + 'o' + 'n' -static int _hash(const void *key, size_t key_len, int size) { +static int _hash(const void *key, uint32_t key_len, int size) { if (!key || size <= 0) return -1; const uint8_t *p = (const uint8_t *)key; uint32_t sum = 0; - for (size_t i = 0; i < key_len; i++) { + for (uint32_t i = 0; i < key_len; i++) { sum += p[i]; } return sum % size; } -static int _key_equal(const hashnode_t *node, const void *key, size_t key_len) { +static int _key_equal(const hashnode_t *node, const void *key, uint32_t key_len) { if (!node || !key) return 0; if (!node->key) return 0; if (node->key_len != key_len) return 0; return memcmp(node->key, key, key_len) == 0; } -static hashnode_t *_create_node(const void *key, size_t key_len, - const void *value, size_t value_len) { +static hashnode_t *_create_node(const void *key, uint32_t key_len, + const void *value, uint32_t value_len) { hashnode_t *node = (hashnode_t*)kvs_malloc(sizeof(hashnode_t)); if (!node) return NULL; memset(node, 0, sizeof(*node)); @@ -113,7 +113,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, size_t key_len, const void *value, size_t value_len) { +int kvs_hash_set_bin(kvs_hash_t *hash, const void *key, uint32_t key_len, const void *value, uint32_t value_len) { if (!hash || !hash->nodes || !key || key_len == 0 || !value) return -1; int idx = _hash(key, key_len, MAX_TABLE_SIZE); @@ -140,7 +140,7 @@ int kvs_hash_set_bin(kvs_hash_t *hash, const void *key, size_t key_len, const vo /* * get 返回:value 指针(由 hash 持有),并通过 out_value_len 返回长度 */ -void *kvs_hash_get_bin(kvs_hash_t *hash, const void *key, size_t key_len, size_t *out_value_len) { +void *kvs_hash_get_bin(kvs_hash_t *hash, const void *key, uint32_t key_len, uint32_t *out_value_len) { if (!hash || !hash->nodes || !key || key_len == 0 || !out_value_len) return NULL; *out_value_len = 0; @@ -166,7 +166,7 @@ void *kvs_hash_get_bin(kvs_hash_t *hash, const void *key, size_t key_len, size_ /* * @return <0 error; =0 success; >0 no exist */ -int kvs_hash_mod_bin(kvs_hash_t *hash, const void *key, size_t key_len, const void *value, size_t value_len) { +int kvs_hash_mod_bin(kvs_hash_t *hash, const void *key, uint32_t key_len, const void *value, uint32_t value_len) { if (!hash || !hash->nodes || !key || key_len == 0 || !value) return -1; @@ -210,7 +210,7 @@ int kvs_hash_count(kvs_hash_t *hash) { /* * @return 0 success; <0 error/noexist */ -int kvs_hash_del_bin(kvs_hash_t *hash, const void *key, size_t key_len) { +int kvs_hash_del_bin(kvs_hash_t *hash, const void *key, uint32_t key_len) { if (!hash || !key || key_len == 0) return -2; int idx = _hash(key, key_len, MAX_TABLE_SIZE); @@ -258,8 +258,8 @@ int kvs_hash_del_bin(kvs_hash_t *hash, const void *key, size_t key_len) { /* * @return 0 exist, 1 no exist */ -int kvs_hash_exist_bin(kvs_hash_t *hash, const void *key, size_t key_len) { - size_t vlen = 0; +int kvs_hash_exist_bin(kvs_hash_t *hash, const void *key, uint32_t key_len) { + uint32_t vlen = 0; void *value = kvs_hash_get_bin(hash, key, key_len, &vlen); return value ? 0 : 1; } diff --git a/kvs_rw_tools.c b/kvs_rw_tools.c index 21f7a11..9b44ddb 100644 --- a/kvs_rw_tools.c +++ b/kvs_rw_tools.c @@ -1,6 +1,7 @@ #include "kvstore.h" #include "kvs_rw_tools.h" #include +#include #if ENABLE_ARRAY extern kvs_array_t global_array; @@ -14,11 +15,13 @@ extern kvs_rbtree_t global_rbtree; extern kvs_hash_t global_hash; #endif +// 0 suc, -1 err int kvs_need(const uint8_t *p, const uint8_t *end, size_t n) { return (p + n <= end) ? 0 : -1; } // 注意u8类型不需要ntoh或者hton +// 0 suc, -1 err int kvs_read_u8(const uint8_t **pp, const uint8_t *end, uint8_t *out) { const uint8_t *p = *pp; if (kvs_need(p, end, 1) < 0) return -1; @@ -73,6 +76,31 @@ int kvs_write_u32(uint8_t **pp, const uint8_t *end, uint32_t v) { return 0; } +// -1 err, 0 suc +int kvs_write_file(FILE *fp, const void *buf, size_t n) { + const uint8_t *p = (const uint8_t *)buf; + while (n > 0) { + size_t w = fwrite(p, 1, n, fp); + if (w == 0) return -1; + p += w; + n -= w; + } + return 0; +} + +// -1 err, 0 suc +int kvs_read_file(FILE *fp, void *buf, size_t n){ + uint8_t *p = (uint8_t *)buf; + while (n > 0) { + size_t r = fread(p, 1, n, fp); + if (r == 0) return -1; // EOF or error + p += r; + n -= r; + } + 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; @@ -186,9 +214,9 @@ void kvs_free_request(kvs_req_t *req) { int op = req->op; kvs_arg_t *argv = req->args; - size_t key_len = 0; + uint32_t key_len = 0; const void *key = NULL; - size_t value_len = 0; + uint32_t value_len = 0; const void *val = NULL; if(argc == 1){ @@ -222,6 +250,9 @@ void kvs_free_request(kvs_req_t *req) { 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; @@ -338,6 +369,11 @@ void kvs_free_request(kvs_req_t *req) { 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; @@ -371,3 +407,130 @@ int kvs_build_one_rsp(const kvs_rsp_t *results, uint8_t *response, size_t respon 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 + + 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; +} \ No newline at end of file diff --git a/kvs_rw_tools.h b/kvs_rw_tools.h index 81cd003..b2ae6ee 100644 --- a/kvs_rw_tools.h +++ b/kvs_rw_tools.h @@ -3,6 +3,7 @@ #include #include +// int kvs_need(const uint8_t *p, const uint8_t *end, size_t n); int kvs_read_u8(const uint8_t **pp, const uint8_t *end, uint8_t *out); int kvs_read_u16(const uint8_t **pp, const uint8_t *end, uint16_t *out); @@ -12,6 +13,8 @@ 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 kvs_write_file(FILE *fp, const void *buf, size_t n); +int kvs_read_file(FILE *fp, void *buf, size_t n); /** @@ -58,6 +61,7 @@ enum { KVS_CMD_HMOD, KVS_CMD_HEXIST, + KVS_CMD_SAVE, KVS_CMD_COUNT, }; @@ -89,6 +93,9 @@ int kvs_parse_one_cmd(const uint8_t *request, int request_length, kvs_req_t *req void kvs_free_request(kvs_req_t *req); int kvs_execute_one_cmd(const kvs_req_t *req, kvs_rsp_t *rsp_out); int kvs_build_one_rsp(const kvs_rsp_t *results, uint8_t *response, size_t response_cap); +int kvs_save_to_file(); +int kvs_save_cmd_to_logfile(const uint8_t *cmd, size_t len, int logfd); +int kvs_replay_log(const char *logfile, int logfd); #endif diff --git a/kvstore.c b/kvstore.c index 8ecd5c1..21cf39f 100644 --- a/kvstore.c +++ b/kvstore.c @@ -4,6 +4,10 @@ #include "kvstore.h" #include "kvs_rw_tools.h" +#include +#include +#include +#include #if ENABLE_ARRAY extern kvs_array_t global_array; @@ -17,6 +21,8 @@ extern kvs_rbtree_t global_rbtree; extern kvs_hash_t global_hash; #endif +int global_cmd_log_fd = -1; + void *kvs_malloc(size_t size) { return malloc(size); } @@ -60,10 +66,7 @@ int kvs_split_token(char *msg, char *tokens[]) { // tokens[1] : Key // tokens[2] : Value -#if BIN_SAFE - - -#else +#if !BIN_SAFE int kvs_filter_protocol(char **tokens, int count, char *response) { if (tokens[0] == NULL || count == 0 || response == NULL) return -1; @@ -282,6 +285,12 @@ int kvs_protocol(char *request, int request_length, int *consumed_out, char *res *consumed_out = consumed; *response_length = out_len; return KVS_ERROR; + }else{ +// 执行成功,在这里保存到日志中。 + if(req.op == KVS_CMD_SET || req.op == KVS_CMD_MOD || req.op == KVS_CMD_DEL){ + printf("%d:%d\n", req.op, req.argc); + kvs_save_cmd_to_logfile(p, len, global_cmd_log_fd); + } } if (out_len >= KVS_MAX_RESPONSE) { @@ -338,11 +347,28 @@ int kvs_protocol(char *msg, int length, char *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) { #if ENABLE_ARRAY memset(&global_array, 0, sizeof(kvs_array_t)); kvs_array_create(&global_array); + + kvs_array_load(&global_array, KVS_ARRAY_FILE); #endif #if ENABLE_RBTREE @@ -355,6 +381,9 @@ int init_kvengine(void) { kvs_hash_create(&global_hash); #endif + init_cmd_log(KVS_CMD_LOG_FILE, &global_cmd_log_fd); + kvs_replay_log(KVS_CMD_LOG_FILE, global_cmd_log_fd); + return 0; } @@ -369,6 +398,7 @@ void dest_kvengine(void) { kvs_hash_destroy(&global_hash); #endif + destroy_cmd_log(global_cmd_log_fd); } diff --git a/kvstore.h b/kvstore.h index eef0110..7f23244 100644 --- a/kvstore.h +++ b/kvstore.h @@ -30,6 +30,9 @@ #define BIN_SAFE 1 +#define KVS_CMD_LOG_FILE "kvs_cmd_log.db" +#define KVS_ARRAY_FILE "kvs_array.db" + // typedef int (*msg_handler)(char *msg, int length, char *response); typedef int (*msg_handler)(char *request, int request_length, int *consumed_out, char *response, int *response_length); @@ -47,10 +50,10 @@ extern int ntyco_start(unsigned short port, msg_handler handler); typedef struct kvs_array_item_s { uint8_t *key; - size_t key_len; + uint32_t key_len; uint8_t *value; - size_t value_len; + uint32_t value_len; } kvs_array_item_t; @@ -62,16 +65,21 @@ typedef struct kvs_array_s { int kvs_array_create(kvs_array_t *inst); void kvs_array_destroy(kvs_array_t *inst); int kvs_array_set_bin(kvs_array_t *inst, - const void *key, size_t key_len, - const void *value, size_t value_len); + const void *key, uint32_t key_len, + const void *value, uint32_t value_len); void *kvs_array_get_bin(kvs_array_t *inst, - const void *key, size_t key_len, - size_t *out_value_len); -int kvs_array_del_bin(kvs_array_t *inst, const void *key, size_t key_len); + const void *key, uint32_t key_len, + uint32_t *out_value_len); +int kvs_array_del_bin(kvs_array_t *inst, const void *key, uint32_t key_len); int kvs_array_mod_bin(kvs_array_t *inst, - const void *key, size_t key_len, - const void *value, size_t value_len); -int kvs_array_exist_bin(kvs_array_t *inst, const void *key, size_t key_len); + const void *key, uint32_t key_len, + const void *value, uint32_t value_len); +int kvs_array_exist_bin(kvs_array_t *inst, const void *key, uint32_t key_len); + + +int kvs_array_save(kvs_array_t *inst, const char* filename); +int kvs_array_load(kvs_array_t *inst, const char* filename); + #else typedef struct kvs_array_item_s { char *key; @@ -170,14 +178,15 @@ typedef struct hashtable_s kvs_hash_t; int kvs_hash_create(kvs_hash_t *hash); void kvs_hash_destroy(kvs_hash_t *hash); -int kvs_hash_set_bin(kvs_hash_t *h, const void *key, size_t key_len, const void *value, size_t value_len); -void *kvs_hash_get_bin(kvs_hash_t *h, const void *key, size_t key_len, size_t *out_value_len); -int kvs_hash_get_copy_bin(kvs_hash_t *h, const void *key, size_t key_len, void **out_buf, size_t *out_len); -int kvs_hash_mod_bin(kvs_hash_t *h, const void *key, size_t key_len, const void *value, size_t value_len); -int kvs_hash_del_bin(kvs_hash_t *h, const void *key, size_t key_len); -int kvs_hash_exist_bin(kvs_hash_t *h, const void *key, size_t key_len); +int kvs_hash_set_bin(kvs_hash_t *h, const void *key, uint32_t key_len, const void *value, uint32_t value_len); +void *kvs_hash_get_bin(kvs_hash_t *h, const void *key, uint32_t key_len, uint32_t *out_value_len); +int kvs_hash_get_copy_bin(kvs_hash_t *h, const void *key, uint32_t key_len, void **out_buf, uint32_t *out_len); +int kvs_hash_mod_bin(kvs_hash_t *h, const void *key, uint32_t key_len, const void *value, uint32_t value_len); +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); #else #define ENABLE_KEY_POINTER 1 diff --git a/test/test_client.c b/test/test_client.c index aba1442..f56f0b5 100644 --- a/test/test_client.c +++ b/test/test_client.c @@ -66,10 +66,11 @@ 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){ - if(!key || !buf) return -1; + if(!buf) return -1; uint8_t *end = buf + CMD_SIZE; uint8_t *p = buf; - uint8_t argc = ((value == NULL)?1 : 2); + uint8_t argc = (key == NULL)?0:1; + argc += (value == NULL)?0:1; if (kvs_write_u8(&p, end, op) < 0) return -1; @@ -77,12 +78,14 @@ int getcmd(uint8_t op, const char *key, const char *value, uint8_t *buf){ // 写入 key - int keylen = strlen(key); - if (kvs_write_u32(&p, end, keylen) < 0) return -1; - if (kvs_need(p, end, keylen) < 0) return -1; - if (keylen > 0) { - memcpy(p, key, keylen); - p += keylen; + if(key){ + int keylen = strlen(key); + if (kvs_write_u32(&p, end, keylen) < 0) return -1; + if (kvs_need(p, end, keylen) < 0) return -1; + if (keylen > 0) { + memcpy(p, key, keylen); + p += keylen; + } } if(value){ diff --git a/test/test_client.h b/test/test_client.h index 74e9ca5..6709ad6 100644 --- a/test/test_client.h +++ b/test/test_client.h @@ -18,8 +18,8 @@ #define BATCH_SIZE (65536) #define TIME_SUB_MS(tv1, tv2) ((tv1.tv_sec - tv2.tv_sec) * 1000 + (tv1.tv_usec - tv2.tv_usec) / 1000) -// #define PRESP print_response -#define PRESP +#define PRESP print_response +// #define PRESP typedef enum { @@ -50,7 +50,8 @@ enum { KVS_CMD_HDEL, KVS_CMD_HMOD, KVS_CMD_HEXIST, - + KVS_CMD_SAVE, + KVS_CMD_COUNT, }; diff --git a/test/testcase.c b/test/testcase.c index bf341a2..617ac54 100644 --- a/test/testcase.c +++ b/test/testcase.c @@ -67,21 +67,23 @@ void testcase(int connfd, uint8_t op, const char* key, const char* value, rsp_re void array_testcase_1w(int connfd) { - int count = 10000; + int count = 1000; int i = 0; struct timeval tv_begin; gettimeofday(&tv_begin, NULL); for (i = 0;i < count;i ++) { - testcase(connfd, KVS_CMD_HSET, "nage", "lian", KVS_STATUS_OK, NULL, "SET NAME"); - testcase(connfd, KVS_CMD_HGET, "nage", NULL, KVS_STATUS_OK, "lian", "GET NAME"); - testcase(connfd, KVS_CMD_HMOD, "nage", "liu", KVS_STATUS_OK, NULL, "MOD NAME"); - testcase(connfd, KVS_CMD_HGET, "nage", NULL, KVS_STATUS_OK, "liu", "GET NAME"); - - testcase(connfd, KVS_CMD_HEXIST, "nage", NULL, KVS_STATUS_EXIST, NULL, "EXIST NAME"); - testcase(connfd, KVS_CMD_HDEL, "nage", NULL, KVS_STATUS_OK, NULL, "DEL NAME"); - testcase(connfd, KVS_CMD_HEXIST, "nage", NULL, KVS_STATUS_NO_EXIST, NULL, "NOT EXIST NAME"); + 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_MOD, "stu", "liu", KVS_STATUS_NO_EXIST, NULL, "MOD NAME"); + testcase(connfd, KVS_CMD_DEL, "stu", NULL, KVS_STATUS_NO_EXIST, NULL, "DEL SUT"); } struct timeval tv_end; @@ -89,7 +91,7 @@ void array_testcase_1w(int connfd) { int time_used = TIME_SUB_MS(tv_end, tv_begin); // ms - printf("array testcase --> time_used: %d, qps: %d\n", time_used, 70000 * 1000 / time_used); + printf("array testcase --> time_used: %d, qps: %d\n", time_used, 9000 * 1000 / time_used); } @@ -104,7 +106,7 @@ void do_batch_example(int fd) for(int i = 0;i < 24; ++ i){ int len = sprintf(key, "k%d", i); len = sprintf(val, "v%d", i); - kvs_batch_add(&batch, KVS_CMD_HSET, key, val); + kvs_batch_add(&batch, KVS_CMD_SET, key, val); } // 一次性发送 @@ -122,28 +124,37 @@ void do_batch_example(int fd) } - for(int i = 0;i < 24; ++ i){ - int len = sprintf(key, "k%d", i); - len = sprintf(val, "v%d", i); - testcase(fd, KVS_CMD_HGET, key, NULL, KVS_STATUS_OK, val, "GET K"); - } + // for(int i = 0;i < 24; ++ i){ + // int len = sprintf(key, "k%d", i); + // len = sprintf(val, "v%d", i); + // testcase(fd, KVS_CMD_GET, key, NULL, KVS_STATUS_OK, val, "GET K"); + // } } +void save(int connfd){ + testcase(connfd, KVS_CMD_SAVE, NULL, NULL, KVS_STATUS_OK, NULL, "SAVE"); +} + int main(int argc, char *argv[]) { - if (argc != 3) { + if (argc != 4) { printf("arg error\n"); return -1; } char *ip = argv[1]; int port = atoi(argv[2]); + int mode = atoi(argv[3]); int connfd = connect_tcpserver(ip, port); - array_testcase_1w(connfd); - // do_batch_example(connfd); - + if(mode == 0){ + do_batch_example(connfd); + }else if(mode == 1){ + array_testcase_1w(connfd); + }else if(mode == 2){ + save(connfd); + } return 0; } \ No newline at end of file