简化协议,
/**
* Request
* Cmd: | OP(1) | argc(1) | repeat { arglen(4) | arg } |
*
* Response
* Rsp: | OP(1) | status(1) | datalen(4) | data |
*/
封装客户端进行批处理和单条命令测试。
This commit is contained in:
245
kvstore.c
245
kvstore.c
@@ -263,18 +263,22 @@ int kvs_filter_protocol(char **tokens, int count, char *response) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 输入:op argc argv
|
||||
* 输出 status
|
||||
* 输入:req
|
||||
* 输出:rsp
|
||||
*/
|
||||
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;
|
||||
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;
|
||||
|
||||
const char *key = (argc >= 1) ? argv[0] : NULL;
|
||||
const char *val = (argc >= 2) ? argv[1] : NULL;
|
||||
int argc = req->argc;
|
||||
int op = req->op;
|
||||
kvs_arg_t *argv = req->args;
|
||||
|
||||
const char *key = (argc >= 1) ? argv[0].data : NULL;
|
||||
const char *val = (argc >= 2) ? argv[1].data : NULL;
|
||||
|
||||
// 基本参数校验(按你原有命令语义)
|
||||
switch (op) {
|
||||
@@ -284,7 +288,7 @@ int kvs_filter_protocol(char **tokens, int count, char *response) {
|
||||
case KVS_CMD_RMOD:
|
||||
case KVS_CMD_HSET:
|
||||
case KVS_CMD_HMOD:
|
||||
if (argc != 2 || !key || !val) { *status_out = KVS_STATUS_BADREQ; return; }
|
||||
if (argc != 2 || !key || !val) { rsp_out->status = KVS_STATUS_BADREQ; return -1; }
|
||||
break;
|
||||
case KVS_CMD_GET:
|
||||
case KVS_CMD_DEL:
|
||||
@@ -295,11 +299,11 @@ int kvs_filter_protocol(char **tokens, int count, char *response) {
|
||||
case KVS_CMD_HGET:
|
||||
case KVS_CMD_HDEL:
|
||||
case KVS_CMD_HEXIST:
|
||||
if (argc != 1 || !key) { *status_out = KVS_STATUS_BADREQ; return; }
|
||||
if (argc != 1 || !key) { rsp_out->status = KVS_STATUS_BADREQ; return -1; }
|
||||
break;
|
||||
default:
|
||||
*status_out = KVS_STATUS_BADREQ;
|
||||
return;
|
||||
rsp_out->status = KVS_STATUS_BADREQ;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
@@ -309,147 +313,184 @@ int kvs_filter_protocol(char **tokens, int count, char *response) {
|
||||
#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;
|
||||
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(&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;
|
||||
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_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;
|
||||
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, (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;
|
||||
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, (char*)key);
|
||||
*status_out = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST;
|
||||
return;
|
||||
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) *status_out = KVS_STATUS_ERROR;
|
||||
else if (ret == 0) *status_out = KVS_STATUS_OK;
|
||||
else *status_out = KVS_STATUS_EXIST;
|
||||
return;
|
||||
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) { *status_out = KVS_STATUS_NO_EXIST; return; }
|
||||
*status_out = KVS_STATUS_OK;
|
||||
*data_out = result;
|
||||
*dlen_out = (uint32_t)strlen(result);
|
||||
return;
|
||||
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) *status_out = KVS_STATUS_ERROR;
|
||||
else if (ret == 0) *status_out = KVS_STATUS_OK;
|
||||
else *status_out = KVS_STATUS_NO_EXIST;
|
||||
return;
|
||||
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) *status_out = KVS_STATUS_ERROR;
|
||||
else if (ret == 0) *status_out = KVS_STATUS_OK;
|
||||
else *status_out = KVS_STATUS_NO_EXIST;
|
||||
return;
|
||||
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);
|
||||
*status_out = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST;
|
||||
return;
|
||||
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, (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;
|
||||
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(&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;
|
||||
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_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;
|
||||
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(&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;
|
||||
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(&global_hash, (char*)key);
|
||||
*status_out = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST;
|
||||
return;
|
||||
rsp_out->status = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST;
|
||||
return 0;
|
||||
#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);
|
||||
rsp_out->status = KVS_STATUS_BADREQ;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int resp_len = kvs_build_response(&req, results, (uint8_t *)response, KVS_MAX_RESPONSE);
|
||||
kvs_free(results);
|
||||
kvs_free_request(&req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (resp_len < 0) return 0; // error
|
||||
#if NEW_KVSTORE
|
||||
/**
|
||||
* input : request request_length
|
||||
* output : response response_length consumed_out
|
||||
* return : -1 error, =0 半包, 1 成功
|
||||
*/
|
||||
int kvs_protocol(char *request, int request_length, int *consumed_out, char *response, int *response_length){
|
||||
if (!request || request_length <= 0 || !consumed_out || !response || !response_length) return KVS_NEED_MORE;
|
||||
int consumed = 0;
|
||||
int out_len = 0;
|
||||
int budget = KVS_MAX_CMDS_PER_CALL;
|
||||
|
||||
response_len = resp_len;
|
||||
return response_len;
|
||||
while(consumed < request_length && (budget-- > 0)){
|
||||
kvs_req_t req;
|
||||
memset(&req, 0, sizeof(kvs_req_t));
|
||||
|
||||
const uint8_t *p = request+consumed;
|
||||
int remain = request_length - consumed;
|
||||
|
||||
int len = kvs_parse_one_cmd(p, remain, &req);
|
||||
if(len < 0){
|
||||
kvs_free_request(&req);
|
||||
*consumed_out = consumed;
|
||||
*response_length = out_len;
|
||||
return KVS_ERROR;
|
||||
}
|
||||
else if(len == 0){
|
||||
kvs_free_request(&req);
|
||||
break;
|
||||
}
|
||||
|
||||
kvs_rsp_t rsp;
|
||||
memset(&rsp, 0, sizeof(kvs_rsp_t));
|
||||
|
||||
if (kvs_execute_one_cmd(&req, &rsp) < 0){
|
||||
kvs_free_request(&req);
|
||||
*consumed_out = consumed;
|
||||
*response_length = out_len;
|
||||
return KVS_ERROR;
|
||||
}
|
||||
|
||||
if (out_len >= KVS_MAX_RESPONSE) {
|
||||
kvs_free_request(&req);
|
||||
*consumed_out = consumed;
|
||||
*response_length = out_len;
|
||||
return KVS_ERROR;
|
||||
}
|
||||
|
||||
int resp_len = kvs_build_one_rsp(&rsp, (uint8_t *)response+out_len, KVS_MAX_RESPONSE-out_len);
|
||||
kvs_free_request(&req);
|
||||
if (resp_len < 0) {
|
||||
*consumed_out = consumed;
|
||||
*response_length = out_len;
|
||||
return KVS_ERROR;
|
||||
}
|
||||
|
||||
// printf("resp_len:%d\n", resp_len);
|
||||
// printf("consumed:%d\n", len);
|
||||
out_len += resp_len;
|
||||
consumed += len;
|
||||
}
|
||||
|
||||
*consumed_out = consumed;
|
||||
*response_length = out_len;
|
||||
if (consumed == 0 && out_len == 0) return KVS_NEED_MORE;
|
||||
return KVS_OK;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user