提供array和hashtable的存储引擎层的二进制安全支持,把入口函数修改为接收参数长度,将strlen、strcmp、strcpy替换。
This commit is contained in:
3
Makefile
3
Makefile
@@ -1,7 +1,8 @@
|
|||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
FLAGS = -I ./NtyCo/core/ -L ./NtyCo/ -lntyco -lpthread -luring -ldl
|
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.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
|
||||||
TESTCASE_SRCS = testcase.c
|
TESTCASE_SRCS = testcase.c
|
||||||
TARGET = kvstore
|
TARGET = kvstore
|
||||||
SUBDIR = ./NtyCo/
|
SUBDIR = ./NtyCo/
|
||||||
|
|||||||
149
kvs_array.c
149
kvs_array.c
@@ -19,12 +19,13 @@ int kvs_array_create(kvs_array_t *inst) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(inst->table, 0, (size_t)KVS_ARRAY_SIZE * sizeof(kvs_array_item_t));
|
||||||
inst->total = 0;
|
inst->total = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kvs_array_destory(kvs_array_t *inst) {
|
void kvs_array_destroy(kvs_array_t *inst) {
|
||||||
|
|
||||||
if (!inst) return ;
|
if (!inst) return ;
|
||||||
|
|
||||||
@@ -35,6 +36,151 @@ void kvs_array_destory(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, size_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, size_t key_len,
|
||||||
|
const void *value, size_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, size_t key_len,
|
||||||
|
size_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, size_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, size_t key_len,
|
||||||
|
const void *value, size_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, size_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
/*
|
/*
|
||||||
* @return: <0, error; =0, success; >0, exist
|
* @return: <0, error; =0, success; >0, exist
|
||||||
*/
|
*/
|
||||||
@@ -187,3 +333,4 @@ int kvs_array_exist(kvs_array_t *inst, char *key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -84,7 +84,7 @@ int kvs_hash_create(kvs_hash_t *hash) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
void kvs_hash_destory(kvs_hash_t *hash) {
|
void kvs_hash_destroy(kvs_hash_t *hash) {
|
||||||
|
|
||||||
if (!hash) return;
|
if (!hash) return;
|
||||||
|
|
||||||
@@ -275,7 +275,7 @@ int main() {
|
|||||||
ret = kvs_hash_exist(&hash, "Teacher1");
|
ret = kvs_hash_exist(&hash, "Teacher1");
|
||||||
printf("Exist Teacher1 ret : %d\n", ret);
|
printf("Exist Teacher1 ret : %d\n", ret);
|
||||||
|
|
||||||
kvs_hash_destory(&hash);
|
kvs_hash_destroy(&hash);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
kvs_hash.o
Normal file
BIN
kvs_hash.o
Normal file
Binary file not shown.
300
kvs_hash_bin.c
Executable file
300
kvs_hash_bin.c
Executable file
@@ -0,0 +1,300 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "kvstore.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Key, Value -->
|
||||||
|
// Modify
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
kvs_hash_t global_hash;
|
||||||
|
|
||||||
|
|
||||||
|
//Connection
|
||||||
|
// 'C' + 'o' + 'n'
|
||||||
|
static int _hash(const void *key, size_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++) {
|
||||||
|
sum += p[i];
|
||||||
|
}
|
||||||
|
return sum % size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _key_equal(const hashnode_t *node, const void *key, size_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) {
|
||||||
|
hashnode_t *node = (hashnode_t*)kvs_malloc(sizeof(hashnode_t));
|
||||||
|
if (!node) return NULL;
|
||||||
|
memset(node, 0, sizeof(*node));
|
||||||
|
|
||||||
|
if (key_len > 0) {
|
||||||
|
node->key = (uint8_t*)kvs_malloc(key_len);
|
||||||
|
if (!node->key) { kvs_free(node); return NULL; }
|
||||||
|
memcpy(node->key, key, key_len);
|
||||||
|
node->key_len = key_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value_len > 0) {
|
||||||
|
node->value = (uint8_t*)kvs_malloc(value_len);
|
||||||
|
if (!node->value) {
|
||||||
|
kvs_free(node->key);
|
||||||
|
kvs_free(node);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy(node->value, value, value_len);
|
||||||
|
node->value_len = value_len;
|
||||||
|
} else {
|
||||||
|
node->value = NULL;
|
||||||
|
node->value_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->next = NULL;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
int kvs_hash_create(kvs_hash_t *hash) {
|
||||||
|
if (!hash) return -1;
|
||||||
|
|
||||||
|
hash->nodes = (hashnode_t**)kvs_malloc(sizeof(hashnode_t*) * MAX_TABLE_SIZE);
|
||||||
|
if (!hash->nodes) return -1;
|
||||||
|
|
||||||
|
memset(hash->nodes, 0, sizeof(hashnode_t*) * MAX_TABLE_SIZE);
|
||||||
|
hash->max_slots = MAX_TABLE_SIZE;
|
||||||
|
hash->count = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void kvs_hash_destroy(kvs_hash_t *hash) {
|
||||||
|
if (!hash || !hash->nodes) return;
|
||||||
|
|
||||||
|
for (int i = 0; i < hash->max_slots; i++) {
|
||||||
|
hashnode_t *node = hash->nodes[i];
|
||||||
|
while (node != NULL) {
|
||||||
|
hashnode_t *tmp = node;
|
||||||
|
node = node->next;
|
||||||
|
|
||||||
|
if (tmp->key) kvs_free(tmp->key);
|
||||||
|
if (tmp->value) kvs_free(tmp->value);
|
||||||
|
kvs_free(tmp);
|
||||||
|
}
|
||||||
|
hash->nodes[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
kvs_free(hash->nodes);
|
||||||
|
hash->nodes = NULL;
|
||||||
|
hash->max_slots = 0;
|
||||||
|
hash->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 5 + 2
|
||||||
|
|
||||||
|
// mp
|
||||||
|
/*
|
||||||
|
* @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) {
|
||||||
|
if (!hash || !hash->nodes || !key || key_len == 0 || !value) return -1;
|
||||||
|
|
||||||
|
int idx = _hash(key, key_len, MAX_TABLE_SIZE);
|
||||||
|
if (idx < 0) return -1;
|
||||||
|
|
||||||
|
hashnode_t *node = hash->nodes[idx];
|
||||||
|
while (node != NULL) {
|
||||||
|
if (_key_equal(node, key, key_len)) { // exist
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashnode_t *new_node = _create_node(key, key_len, value, value_len);
|
||||||
|
if (!new_node) return -2;
|
||||||
|
|
||||||
|
new_node->next = hash->nodes[idx];
|
||||||
|
hash->nodes[idx] = new_node;
|
||||||
|
hash->count ++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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) {
|
||||||
|
if (!hash || !hash->nodes || !key || key_len == 0 || !out_value_len) return NULL;
|
||||||
|
*out_value_len = 0;
|
||||||
|
|
||||||
|
int idx = _hash(key, key_len, MAX_TABLE_SIZE);
|
||||||
|
if (idx < 0) return NULL;
|
||||||
|
|
||||||
|
hashnode_t *node = hash->nodes[idx];
|
||||||
|
|
||||||
|
while (node != NULL) {
|
||||||
|
|
||||||
|
if (_key_equal(node, key, key_len)) {
|
||||||
|
*out_value_len = node->value_len;
|
||||||
|
return node->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @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) {
|
||||||
|
|
||||||
|
if (!hash || !hash->nodes || !key || key_len == 0 || !value) return -1;
|
||||||
|
|
||||||
|
int idx = _hash(key, key_len, MAX_TABLE_SIZE);
|
||||||
|
if (idx < 0) return -1;
|
||||||
|
|
||||||
|
hashnode_t *node = hash->nodes[idx];
|
||||||
|
|
||||||
|
while (node != NULL) {
|
||||||
|
|
||||||
|
if (_key_equal(node, key, key_len)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node == NULL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// node -->
|
||||||
|
if (node->value) kvs_free(node->value);
|
||||||
|
node->value = NULL;
|
||||||
|
node->value_len = 0;
|
||||||
|
|
||||||
|
if (value_len > 0) {
|
||||||
|
uint8_t *vcopy = (uint8_t*)kvs_malloc(value_len);
|
||||||
|
if (!vcopy) return -2;
|
||||||
|
memcpy(vcopy, value, value_len);
|
||||||
|
node->value = vcopy;
|
||||||
|
node->value_len = value_len;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int kvs_hash_count(kvs_hash_t *hash) {
|
||||||
|
return hash->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @return 0 success; <0 error/noexist
|
||||||
|
*/
|
||||||
|
int kvs_hash_del_bin(kvs_hash_t *hash, const void *key, size_t key_len) {
|
||||||
|
if (!hash || !key || key_len == 0) return -2;
|
||||||
|
|
||||||
|
int idx = _hash(key, key_len, MAX_TABLE_SIZE);
|
||||||
|
if (idx < 0) return -2;
|
||||||
|
|
||||||
|
hashnode_t *head = hash->nodes[idx];
|
||||||
|
if (head == NULL) return -1; // noexist
|
||||||
|
|
||||||
|
// head node
|
||||||
|
if (_key_equal(head, key, key_len)) {
|
||||||
|
hashnode_t *tmp = head->next;
|
||||||
|
hash->nodes[idx] = tmp;
|
||||||
|
|
||||||
|
if (head->key) kvs_free(head->key);
|
||||||
|
if (head->value) kvs_free(head->value);
|
||||||
|
kvs_free(head);
|
||||||
|
hash->count --;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashnode_t *cur = head;
|
||||||
|
while (cur->next != NULL) {
|
||||||
|
if (_key_equal(cur->next, key, key_len)) break; // search node
|
||||||
|
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur->next == NULL) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashnode_t *tmp = cur->next;
|
||||||
|
cur->next = tmp->next;
|
||||||
|
if (tmp->key) kvs_free(tmp->key);
|
||||||
|
if (tmp->value) kvs_free(tmp->value);
|
||||||
|
kvs_free(tmp);
|
||||||
|
|
||||||
|
hash->count --;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @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;
|
||||||
|
void *value = kvs_hash_get_bin(hash, key, key_len, &vlen);
|
||||||
|
return value ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
char *value1 = kvs_hash_get(&hash, "Teacher1");
|
||||||
|
printf("Teacher1 : %s\n", value1);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -451,7 +451,7 @@ int kvs_rbtree_create(kvs_rbtree_t *inst) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void kvs_rbtree_destory(kvs_rbtree_t *inst) {
|
void kvs_rbtree_destroy(kvs_rbtree_t *inst) {
|
||||||
|
|
||||||
if (inst == NULL) return ;
|
if (inst == NULL) return ;
|
||||||
|
|
||||||
|
|||||||
187
kvs_rw_tools.c
187
kvs_rw_tools.c
@@ -2,6 +2,18 @@
|
|||||||
#include "kvs_rw_tools.h"
|
#include "kvs_rw_tools.h"
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#if ENABLE_ARRAY
|
||||||
|
extern kvs_array_t global_array;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ENABLE_RBTREE
|
||||||
|
extern kvs_rbtree_t global_rbtree;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ENABLE_HASH
|
||||||
|
extern kvs_hash_t global_hash;
|
||||||
|
#endif
|
||||||
|
|
||||||
int kvs_need(const uint8_t *p, const uint8_t *end, size_t n) {
|
int kvs_need(const uint8_t *p, const uint8_t *end, size_t n) {
|
||||||
return (p + n <= end) ? 0 : -1;
|
return (p + n <= end) ? 0 : -1;
|
||||||
}
|
}
|
||||||
@@ -159,6 +171,181 @@ void kvs_free_request(kvs_req_t *req) {
|
|||||||
req->argc = 0;
|
req->argc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入:req
|
||||||
|
* 输出:rsp
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
|
||||||
|
size_t key_len = 0;
|
||||||
|
const void *key = NULL;
|
||||||
|
size_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;
|
||||||
|
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
|
||||||
|
default:
|
||||||
|
rsp_out->status = KVS_STATUS_BADREQ;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int kvs_build_one_rsp(const kvs_rsp_t *results, uint8_t *response, size_t response_cap){
|
int kvs_build_one_rsp(const kvs_rsp_t *results, uint8_t *response, size_t response_cap){
|
||||||
if (!results || !response) return -1;
|
if (!results || !response) return -1;
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ int kvs_write_u32(uint8_t **pp, const uint8_t *end, uint32_t v);
|
|||||||
#define KVS_MAX_CMDS_PER_CALL 64
|
#define KVS_MAX_CMDS_PER_CALL 64
|
||||||
// 1MB
|
// 1MB
|
||||||
#define KVS_MAX_RESPONSE (1024u * 1024u)
|
#define KVS_MAX_RESPONSE (1024u * 1024u)
|
||||||
#define KVS_MAX_ARGC 64
|
#define KVS_MAX_ARGC 4
|
||||||
#define KVS_MAX_ARGLEN (1024u * 1024u)
|
#define KVS_MAX_ARGLEN (1024u * 1024u)
|
||||||
#define KVS_MAX_CMD_BYTES (4u * 1024u * 1024u)
|
#define KVS_MAX_CMD_BYTES (4u * 1024u * 1024u)
|
||||||
|
|
||||||
@@ -37,6 +37,30 @@ enum {
|
|||||||
KVS_STATUS_BADREQ = 4
|
KVS_STATUS_BADREQ = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
KVS_CMD_START = 0,
|
||||||
|
// array
|
||||||
|
KVS_CMD_SET = KVS_CMD_START,
|
||||||
|
KVS_CMD_GET,
|
||||||
|
KVS_CMD_DEL,
|
||||||
|
KVS_CMD_MOD,
|
||||||
|
KVS_CMD_EXIST,
|
||||||
|
// rbtree
|
||||||
|
KVS_CMD_RSET,
|
||||||
|
KVS_CMD_RGET,
|
||||||
|
KVS_CMD_RDEL,
|
||||||
|
KVS_CMD_RMOD,
|
||||||
|
KVS_CMD_REXIST,
|
||||||
|
// hash
|
||||||
|
KVS_CMD_HSET,
|
||||||
|
KVS_CMD_HGET,
|
||||||
|
KVS_CMD_HDEL,
|
||||||
|
KVS_CMD_HMOD,
|
||||||
|
KVS_CMD_HEXIST,
|
||||||
|
|
||||||
|
KVS_CMD_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
KVS_OK = 1,
|
KVS_OK = 1,
|
||||||
KVS_NEED_MORE = 0,
|
KVS_NEED_MORE = 0,
|
||||||
|
|||||||
196
kvstore.c
196
kvstore.c
@@ -32,32 +32,6 @@ const char *command[] = {
|
|||||||
"HSET", "HGET", "HDEL", "HMOD", "HEXIST"
|
"HSET", "HGET", "HDEL", "HMOD", "HEXIST"
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
|
||||||
KVS_CMD_START = 0,
|
|
||||||
// array
|
|
||||||
KVS_CMD_SET = KVS_CMD_START,
|
|
||||||
KVS_CMD_GET,
|
|
||||||
KVS_CMD_DEL,
|
|
||||||
KVS_CMD_MOD,
|
|
||||||
KVS_CMD_EXIST,
|
|
||||||
// rbtree
|
|
||||||
KVS_CMD_RSET,
|
|
||||||
KVS_CMD_RGET,
|
|
||||||
KVS_CMD_RDEL,
|
|
||||||
KVS_CMD_RMOD,
|
|
||||||
KVS_CMD_REXIST,
|
|
||||||
// hash
|
|
||||||
KVS_CMD_HSET,
|
|
||||||
KVS_CMD_HGET,
|
|
||||||
KVS_CMD_HDEL,
|
|
||||||
KVS_CMD_HMOD,
|
|
||||||
KVS_CMD_HEXIST,
|
|
||||||
|
|
||||||
KVS_CMD_COUNT,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char *response[] = {
|
const char *response[] = {
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -86,6 +60,10 @@ int kvs_split_token(char *msg, char *tokens[]) {
|
|||||||
// tokens[1] : Key
|
// tokens[1] : Key
|
||||||
// tokens[2] : Value
|
// tokens[2] : Value
|
||||||
|
|
||||||
|
#if BIN_SAFE
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
int kvs_filter_protocol(char **tokens, int count, char *response) {
|
int kvs_filter_protocol(char **tokens, int count, char *response) {
|
||||||
|
|
||||||
if (tokens[0] == NULL || count == 0 || response == NULL) return -1;
|
if (tokens[0] == NULL || count == 0 || response == NULL) return -1;
|
||||||
@@ -262,168 +240,8 @@ int kvs_filter_protocol(char **tokens, int count, char *response) {
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 输入:req
|
|
||||||
* 输出:rsp
|
|
||||||
*/
|
|
||||||
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;
|
|
||||||
|
|
||||||
const char *key = (argc >= 1) ? argv[0].data : NULL;
|
|
||||||
const char *val = (argc >= 2) ? argv[1].data : 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) { 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;
|
|
||||||
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(&global_array, (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_GET:
|
|
||||||
result = kvs_array_get(&global_array, (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_DEL:
|
|
||||||
ret = kvs_array_del(&global_array, (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_MOD:
|
|
||||||
ret = kvs_array_mod(&global_array, (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_EXIST:
|
|
||||||
ret = kvs_array_exist(&global_array, (char*)key);
|
|
||||||
rsp_out->status = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST;
|
|
||||||
return 0;
|
|
||||||
#endif
|
#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(&global_hash, (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_HGET:
|
|
||||||
result = kvs_hash_get(&global_hash, (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_HDEL:
|
|
||||||
ret = kvs_hash_del(&global_hash, (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_HMOD:
|
|
||||||
ret = kvs_hash_mod(&global_hash, (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_HEXIST:
|
|
||||||
ret = kvs_hash_exist(&global_hash, (char*)key);
|
|
||||||
rsp_out->status = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST;
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
rsp_out->status = KVS_STATUS_BADREQ;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if NEW_KVSTORE
|
#if NEW_KVSTORE
|
||||||
/**
|
/**
|
||||||
@@ -542,13 +360,13 @@ int init_kvengine(void) {
|
|||||||
|
|
||||||
void dest_kvengine(void) {
|
void dest_kvengine(void) {
|
||||||
#if ENABLE_ARRAY
|
#if ENABLE_ARRAY
|
||||||
kvs_array_destory(&global_array);
|
kvs_array_destroy(&global_array);
|
||||||
#endif
|
#endif
|
||||||
#if ENABLE_RBTREE
|
#if ENABLE_RBTREE
|
||||||
kvs_rbtree_destory(&global_rbtree);
|
kvs_rbtree_destroy(&global_rbtree);
|
||||||
#endif
|
#endif
|
||||||
#if ENABLE_HASH
|
#if ENABLE_HASH
|
||||||
kvs_hash_destory(&global_hash);
|
kvs_hash_destroy(&global_hash);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
80
kvstore.h
80
kvstore.h
@@ -19,11 +19,6 @@
|
|||||||
|
|
||||||
#define NETWORK_SELECT NETWORK_REACTOR
|
#define NETWORK_SELECT NETWORK_REACTOR
|
||||||
|
|
||||||
// 8MB
|
|
||||||
#define MAX_PAYLOAD_LEN 8388608
|
|
||||||
#define MAX_OPCOUNT 1024
|
|
||||||
// 4MB
|
|
||||||
#define MAX_ARG_LEN 4194304
|
|
||||||
|
|
||||||
#define KVS_MAX_TOKENS 128
|
#define KVS_MAX_TOKENS 128
|
||||||
|
|
||||||
@@ -33,6 +28,8 @@
|
|||||||
|
|
||||||
#define NEW_KVSTORE 1
|
#define NEW_KVSTORE 1
|
||||||
|
|
||||||
|
#define BIN_SAFE 1
|
||||||
|
|
||||||
|
|
||||||
// typedef int (*msg_handler)(char *msg, int length, char *response);
|
// 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);
|
typedef int (*msg_handler)(char *request, int request_length, int *consumed_out, char *response, int *response_length);
|
||||||
@@ -45,6 +42,37 @@ extern int ntyco_start(unsigned short port, msg_handler handler);
|
|||||||
|
|
||||||
#if ENABLE_ARRAY
|
#if ENABLE_ARRAY
|
||||||
|
|
||||||
|
#if BIN_SAFE
|
||||||
|
#define KVS_ARRAY_SIZE 1024
|
||||||
|
|
||||||
|
typedef struct kvs_array_item_s {
|
||||||
|
uint8_t *key;
|
||||||
|
size_t key_len;
|
||||||
|
|
||||||
|
uint8_t *value;
|
||||||
|
size_t value_len;
|
||||||
|
} kvs_array_item_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct kvs_array_s {
|
||||||
|
kvs_array_item_t *table;
|
||||||
|
int total; // 元素上界
|
||||||
|
} kvs_array_t;
|
||||||
|
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
#else
|
||||||
typedef struct kvs_array_item_s {
|
typedef struct kvs_array_item_s {
|
||||||
char *key;
|
char *key;
|
||||||
char *value;
|
char *value;
|
||||||
@@ -59,14 +87,14 @@ typedef struct kvs_array_s {
|
|||||||
} kvs_array_t;
|
} kvs_array_t;
|
||||||
|
|
||||||
int kvs_array_create(kvs_array_t *inst);
|
int kvs_array_create(kvs_array_t *inst);
|
||||||
void kvs_array_destory(kvs_array_t *inst);
|
void kvs_array_destroy(kvs_array_t *inst);
|
||||||
|
|
||||||
int kvs_array_set(kvs_array_t *inst, char *key, char *value);
|
int kvs_array_set(kvs_array_t *inst, char *key, char *value);
|
||||||
char* kvs_array_get(kvs_array_t *inst, char *key);
|
char* kvs_array_get(kvs_array_t *inst, char *key);
|
||||||
int kvs_array_del(kvs_array_t *inst, char *key);
|
int kvs_array_del(kvs_array_t *inst, char *key);
|
||||||
int kvs_array_mod(kvs_array_t *inst, char *key, char *value);
|
int kvs_array_mod(kvs_array_t *inst, char *key, char *value);
|
||||||
int kvs_array_exist(kvs_array_t *inst, char *key);
|
int kvs_array_exist(kvs_array_t *inst, char *key);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -102,7 +130,7 @@ typedef struct _rbtree {
|
|||||||
typedef struct _rbtree kvs_rbtree_t;
|
typedef struct _rbtree kvs_rbtree_t;
|
||||||
|
|
||||||
int kvs_rbtree_create(kvs_rbtree_t *inst);
|
int kvs_rbtree_create(kvs_rbtree_t *inst);
|
||||||
void kvs_rbtree_destory(kvs_rbtree_t *inst);
|
void kvs_rbtree_destroy(kvs_rbtree_t *inst);
|
||||||
int kvs_rbtree_set(kvs_rbtree_t *inst, char *key, char *value);
|
int kvs_rbtree_set(kvs_rbtree_t *inst, char *key, char *value);
|
||||||
char* kvs_rbtree_get(kvs_rbtree_t *inst, char *key);
|
char* kvs_rbtree_get(kvs_rbtree_t *inst, char *key);
|
||||||
int kvs_rbtree_del(kvs_rbtree_t *inst, char *key);
|
int kvs_rbtree_del(kvs_rbtree_t *inst, char *key);
|
||||||
@@ -120,6 +148,38 @@ int kvs_rbtree_exist(kvs_rbtree_t *inst, char *key);
|
|||||||
#define MAX_VALUE_LEN 512
|
#define MAX_VALUE_LEN 512
|
||||||
#define MAX_TABLE_SIZE 1024
|
#define MAX_TABLE_SIZE 1024
|
||||||
|
|
||||||
|
#if BIN_SAFE
|
||||||
|
#define MAX_TABLE_SIZE 1024
|
||||||
|
typedef struct hashnode_s {
|
||||||
|
uint8_t *key;
|
||||||
|
size_t key_len;
|
||||||
|
|
||||||
|
uint8_t *value;
|
||||||
|
size_t value_len;
|
||||||
|
|
||||||
|
struct hashnode_s *next;
|
||||||
|
} hashnode_t;
|
||||||
|
|
||||||
|
typedef struct hashtable_s {
|
||||||
|
hashnode_t **nodes;
|
||||||
|
int max_slots;
|
||||||
|
int count;
|
||||||
|
} hashtable_t;
|
||||||
|
|
||||||
|
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_count(kvs_hash_t *h);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
#define ENABLE_KEY_POINTER 1
|
#define ENABLE_KEY_POINTER 1
|
||||||
|
|
||||||
|
|
||||||
@@ -149,14 +209,14 @@ typedef struct hashtable_s kvs_hash_t;
|
|||||||
|
|
||||||
|
|
||||||
int kvs_hash_create(kvs_hash_t *hash);
|
int kvs_hash_create(kvs_hash_t *hash);
|
||||||
void kvs_hash_destory(kvs_hash_t *hash);
|
void kvs_hash_destroy(kvs_hash_t *hash);
|
||||||
int kvs_hash_set(hashtable_t *hash, char *key, char *value);
|
int kvs_hash_set(hashtable_t *hash, char *key, char *value);
|
||||||
char * kvs_hash_get(kvs_hash_t *hash, char *key);
|
char * kvs_hash_get(kvs_hash_t *hash, char *key);
|
||||||
int kvs_hash_mod(kvs_hash_t *hash, char *key, char *value);
|
int kvs_hash_mod(kvs_hash_t *hash, char *key, char *value);
|
||||||
int kvs_hash_del(kvs_hash_t *hash, char *key);
|
int kvs_hash_del(kvs_hash_t *hash, char *key);
|
||||||
int kvs_hash_exist(kvs_hash_t *hash, char *key);
|
int kvs_hash_exist(kvs_hash_t *hash, char *key);
|
||||||
|
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
#define BATCH_SIZE (65536)
|
#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 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 print_response
|
||||||
|
#define PRESP
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
@@ -67,21 +67,21 @@ void testcase(int connfd, uint8_t op, const char* key, const char* value, rsp_re
|
|||||||
|
|
||||||
void array_testcase_1w(int connfd) {
|
void array_testcase_1w(int connfd) {
|
||||||
|
|
||||||
int count = 1;
|
int count = 10000;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
struct timeval tv_begin;
|
struct timeval tv_begin;
|
||||||
gettimeofday(&tv_begin, NULL);
|
gettimeofday(&tv_begin, NULL);
|
||||||
|
|
||||||
for (i = 0;i < count;i ++) {
|
for (i = 0;i < count;i ++) {
|
||||||
testcase(connfd, KVS_CMD_SET, "nage", "lian", KVS_STATUS_OK, NULL, "SET NAME");
|
testcase(connfd, KVS_CMD_HSET, "nage", "lian", KVS_STATUS_OK, NULL, "SET NAME");
|
||||||
testcase(connfd, KVS_CMD_GET, "nage", NULL, KVS_STATUS_OK, "lian", "GET NAME");
|
testcase(connfd, KVS_CMD_HGET, "nage", NULL, KVS_STATUS_OK, "lian", "GET NAME");
|
||||||
testcase(connfd, KVS_CMD_MOD, "nage", "liu", KVS_STATUS_OK, NULL, "MOD NAME");
|
testcase(connfd, KVS_CMD_HMOD, "nage", "liu", KVS_STATUS_OK, NULL, "MOD NAME");
|
||||||
testcase(connfd, KVS_CMD_GET, "nage", NULL, KVS_STATUS_OK, "liu", "GET NAME");
|
testcase(connfd, KVS_CMD_HGET, "nage", NULL, KVS_STATUS_OK, "liu", "GET NAME");
|
||||||
|
|
||||||
testcase(connfd, KVS_CMD_EXIST, "nage", NULL, KVS_STATUS_EXIST, NULL, "EXIST NAME");
|
testcase(connfd, KVS_CMD_HEXIST, "nage", NULL, KVS_STATUS_EXIST, NULL, "EXIST NAME");
|
||||||
testcase(connfd, KVS_CMD_DEL, "nage", NULL, KVS_STATUS_OK, NULL, "DEL NAME");
|
testcase(connfd, KVS_CMD_HDEL, "nage", NULL, KVS_STATUS_OK, NULL, "DEL NAME");
|
||||||
testcase(connfd, KVS_CMD_EXIST, "nage", NULL, KVS_STATUS_NO_EXIST, NULL, "NOT EXIST NAME");
|
testcase(connfd, KVS_CMD_HEXIST, "nage", NULL, KVS_STATUS_NO_EXIST, NULL, "NOT EXIST NAME");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct timeval tv_end;
|
struct timeval tv_end;
|
||||||
@@ -98,11 +98,14 @@ void do_batch_example(int fd)
|
|||||||
kvs_batch_t batch;
|
kvs_batch_t batch;
|
||||||
kvs_batch_init(&batch);
|
kvs_batch_init(&batch);
|
||||||
|
|
||||||
|
char key[10]={0}, val[10]={0};
|
||||||
|
|
||||||
// 组 batch(最多 64 条)
|
// 组 batch(最多 64 条)
|
||||||
kvs_batch_add(&batch, KVS_CMD_SET, "k1", "v1");
|
for(int i = 0;i < 24; ++ i){
|
||||||
kvs_batch_add(&batch, KVS_CMD_SET, "k2", "v2");
|
int len = sprintf(key, "k%d", i);
|
||||||
kvs_batch_add(&batch, KVS_CMD_GET, "k1", NULL);
|
len = sprintf(val, "v%d", i);
|
||||||
kvs_batch_add(&batch, KVS_CMD_GET, "k2", NULL);
|
kvs_batch_add(&batch, KVS_CMD_HSET, key, val);
|
||||||
|
}
|
||||||
|
|
||||||
// 一次性发送
|
// 一次性发送
|
||||||
kvs_batch_send(fd, &batch);
|
kvs_batch_send(fd, &batch);
|
||||||
@@ -118,10 +121,13 @@ void do_batch_example(int fd)
|
|||||||
PRESP("BATCH", &rsps[i]);
|
PRESP("BATCH", &rsps[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%d\n", nrsp);
|
|
||||||
|
|
||||||
testcase(fd, KVS_CMD_GET, "k1", NULL, KVS_STATUS_OK, "v1", "GET k1");
|
for(int i = 0;i < 24; ++ i){
|
||||||
testcase(fd, KVS_CMD_GET, "k2", NULL, KVS_STATUS_OK, "v2", "GET k2");
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -136,8 +142,8 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
int connfd = connect_tcpserver(ip, port);
|
int connfd = connect_tcpserver(ip, port);
|
||||||
|
|
||||||
// array_testcase_1w(connfd);
|
array_testcase_1w(connfd);
|
||||||
do_batch_example(connfd);
|
// do_batch_example(connfd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user