协议定义与实现, 协议支持 批处理、特殊字符如\r\n\0。与单条命令测试。

/**
 * Header: 	| magic(4) | payloadLen(4) |
 *
 * Request
 * Payload: | opcount(4) | repeat Cmd |
 * Cmd: 	| OP(1) | argc(4) | repeat Arg |
 * Arg:		| arglen(4) | arg |
 *
 * Response
 * Payload: | opcount(4) | repeat Rsp |
 * Rsp:		| OP(1) | status(1) | datalen(4) | data |
 */

 kvstore层,先解析,再执行,最后构建返回体。
 一个是半包问题,没有处理。
 另一个是感觉协议结构有点麻烦,
This commit is contained in:
2026-01-05 23:20:37 +08:00
parent 7524c57442
commit 0dc86f5aa5
10 changed files with 890 additions and 9 deletions

197
kvstore.c
View File

@@ -3,7 +3,7 @@
#include "kvstore.h"
#include "kvs_rw_tools.h"
#if ENABLE_ARRAY
extern kvs_array_t global_array;
@@ -262,7 +262,196 @@ int kvs_filter_protocol(char **tokens, int count, char *response) {
return length;
}
/**
* 输入op argc argv
* 输出 status
*/
void kvs_exec_one_op(uint8_t op, uint32_t argc, char **argv,
uint8_t *status_out,
const char **data_out, uint32_t *dlen_out) {
*status_out = KVS_STATUS_ERROR;
*data_out = NULL;
*dlen_out = 0;
const char *key = (argc >= 1) ? argv[0] : NULL;
const char *val = (argc >= 2) ? argv[1] : NULL;
// 基本参数校验(按你原有命令语义)
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) { *status_out = KVS_STATUS_BADREQ; return; }
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) { *status_out = KVS_STATUS_BADREQ; return; }
break;
default:
*status_out = KVS_STATUS_BADREQ;
return;
}
int ret = 0;
const char *result = NULL;
switch (op) {
#if ENABLE_ARRAY
case KVS_CMD_SET:
ret = kvs_array_set(&global_array, (char*)key, (char*)val);
if (ret < 0) *status_out = KVS_STATUS_ERROR;
else if (ret == 0) *status_out = KVS_STATUS_OK;
else *status_out = KVS_STATUS_EXIST;
return;
case KVS_CMD_GET:
result = kvs_array_get(&global_array, (char*)key);
if (!result) { *status_out = KVS_STATUS_NO_EXIST; return; }
*status_out = KVS_STATUS_OK;
*data_out = result;
*dlen_out = (uint32_t)strlen(result);
return;
case KVS_CMD_DEL:
ret = kvs_array_del(&global_array, (char*)key);
if (ret < 0) *status_out = KVS_STATUS_ERROR;
else if (ret == 0) *status_out = KVS_STATUS_OK;
else *status_out = KVS_STATUS_NO_EXIST;
return;
case KVS_CMD_MOD:
ret = kvs_array_mod(&global_array, (char*)key, (char*)val);
if (ret < 0) *status_out = KVS_STATUS_ERROR;
else if (ret == 0) *status_out = KVS_STATUS_OK;
else *status_out = KVS_STATUS_NO_EXIST;
return;
case KVS_CMD_EXIST:
ret = kvs_array_exist(&global_array, (char*)key);
*status_out = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST;
return;
#endif
#if ENABLE_RBTREE
case KVS_CMD_RSET:
ret = kvs_rbtree_set(&global_rbtree, (char*)key, (char*)val);
if (ret < 0) *status_out = KVS_STATUS_ERROR;
else if (ret == 0) *status_out = KVS_STATUS_OK;
else *status_out = KVS_STATUS_EXIST;
return;
case KVS_CMD_RGET:
result = kvs_rbtree_get(&global_rbtree, (char*)key);
if (!result) { *status_out = KVS_STATUS_NO_EXIST; return; }
*status_out = KVS_STATUS_OK;
*data_out = result;
*dlen_out = (uint32_t)strlen(result);
return;
case KVS_CMD_RDEL:
ret = kvs_rbtree_del(&global_rbtree, (char*)key);
if (ret < 0) *status_out = KVS_STATUS_ERROR;
else if (ret == 0) *status_out = KVS_STATUS_OK;
else *status_out = KVS_STATUS_NO_EXIST;
return;
case KVS_CMD_RMOD:
ret = kvs_rbtree_mod(&global_rbtree, (char*)key, (char*)val);
if (ret < 0) *status_out = KVS_STATUS_ERROR;
else if (ret == 0) *status_out = KVS_STATUS_OK;
else *status_out = KVS_STATUS_NO_EXIST;
return;
case KVS_CMD_REXIST:
ret = kvs_rbtree_exist(&global_rbtree, (char*)key);
*status_out = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST;
return;
#endif
#if ENABLE_HASH
case KVS_CMD_HSET:
ret = kvs_hash_set(&global_hash, (char*)key, (char*)val);
if (ret < 0) *status_out = KVS_STATUS_ERROR;
else if (ret == 0) *status_out = KVS_STATUS_OK;
else *status_out = KVS_STATUS_EXIST;
return;
case KVS_CMD_HGET:
result = kvs_hash_get(&global_hash, (char*)key);
if (!result) { *status_out = KVS_STATUS_NO_EXIST; return; }
*status_out = KVS_STATUS_OK;
*data_out = result;
*dlen_out = (uint32_t)strlen(result);
return;
case KVS_CMD_HDEL:
ret = kvs_hash_del(&global_hash, (char*)key);
if (ret < 0) *status_out = KVS_STATUS_ERROR;
else if (ret == 0) *status_out = KVS_STATUS_OK;
else *status_out = KVS_STATUS_NO_EXIST;
return;
case KVS_CMD_HMOD:
ret = kvs_hash_mod(&global_hash, (char*)key, (char*)val);
if (ret < 0) *status_out = KVS_STATUS_ERROR;
else if (ret == 0) *status_out = KVS_STATUS_OK;
else *status_out = KVS_STATUS_NO_EXIST;
return;
case KVS_CMD_HEXIST:
ret = kvs_hash_exist(&global_hash, (char*)key);
*status_out = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST;
return;
#endif
default:
*status_out = KVS_STATUS_BADREQ;
return;
}
}
#if NEW_KVSTORE
// int kvs_protocol(char *msg, int length, char *response, int *response_len){
int kvs_protocol(char *msg, int length, char *response){
if (!msg || length <= 0 || !response) return 0;
int response_len = 0;
kvs_request_t req;
int consumed = kvs_parse_request((const uint8_t *)msg, length, &req);
if (consumed < 0) return 0; // 解析失败
else if(consumed == 0) return 0; // 半包
kvs_response_t *results = (kvs_response_t *)kvs_malloc(sizeof(kvs_response_t) * req.opcount);
if (!results) { kvs_free_request(&req); return -1; }
memset(results, 0, sizeof(kvs_response_t) * req.opcount);
if (kvs_execute_request(&req, results) < 0) {
kvs_free(results);
kvs_free_request(&req);
return -1;
}
int resp_len = kvs_build_response(&req, results, (uint8_t *)response, KVS_MAX_RESPONSE);
kvs_free(results);
kvs_free_request(&req);
if (resp_len < 0) return 0; // error
response_len = resp_len;
return response_len;
}
#else
/*
* msg: request message
* length: length of request message
@@ -288,7 +477,7 @@ int kvs_protocol(char *msg, int length, char *response) { //
return kvs_filter_protocol(tokens, count, response);
}
#endif
int init_kvengine(void) {
@@ -337,9 +526,9 @@ int main(int argc, char *argv[]) {
#if (NETWORK_SELECT == NETWORK_REACTOR)
reactor_start(port, kvs_protocol); //
#elif (NETWORK_SELECT == NETWORK_PROACTOR)
ntyco_start(port, kvs_protocol);
#elif (NETWORK_SELECT == NETWORK_NTYCO)
proactor_start(port, kvs_protocol);
#elif (NETWORK_SELECT == NETWORK_NTYCO)
ntyco_start(port, kvs_protocol);
#endif
dest_kvengine();