optimize and test pkv

This commit is contained in:
shuxin   zheng 2023-07-31 18:34:16 +08:00
parent dcd8b7478c
commit d1bf85c81c
11 changed files with 254 additions and 141 deletions

View File

@ -5,17 +5,21 @@
#include "stdafx.h"
#include "proto/redis_object.h"
#include "proto/redis_coder.h"
#include "redis_key.h"
#include "redis_string.h"
#include "redis_handler.h"
namespace pkv {
#define EQ !strcasecmp
redis_handler::redis_handler(shared_db& db, const redis_coder& parser,
redis_handler::redis_handler(shared_db& db, redis_coder& parser,
acl::socket_stream& conn)
: db_(db)
, parser_(parser)
, conn_(conn)
, builder_(parser.get_cache())
, coder_(parser.get_cache())
{
}
@ -68,13 +72,17 @@ bool redis_handler::handle_one(const redis_object &obj) {
//
//
if (EQ(cmd, "SET")) {
return set(obj);
redis_string redis(db_, obj, parser_);
return redis.set(builder_);
} else if (EQ(cmd, "GET")) {
return get(obj);
redis_string redis(db_, obj, parser_);
return redis.get(builder_);
} else if (EQ(cmd, "DEL")) {
return del(obj);
redis_key redis(db_, obj, parser_);
return redis.del(builder_);
} else if (EQ(cmd, "TYPE")) {
return type(obj);
redis_key redis(db_, obj, parser_);
return redis.type(builder_);
} else if (EQ(cmd, "HSET")) {
return hset(obj);
} else if (EQ(cmd, "HGET")) {
@ -96,118 +104,6 @@ bool redis_handler::handle_one(const redis_object &obj) {
return true;
}
bool redis_handler::set(const redis_object &obj) {
auto& objs = obj.get_objects();
if (objs.size() < 3) {
logger_error("invalid SET params' size=%zd", objs.size());
return false;
}
auto key = objs[1]->get_str();
if (key == nullptr || *key == 0) {
logger_error("key null");
return false;
}
auto value = objs[2]->get_str();
if (value == nullptr || *value == 0) {
logger_error("value null");
return false;
}
if (!var_cfg_disable_serialize) {
std::string buff;
coder_.create_object().set_string(value);
coder_.to_string(buff);
coder_.clear();
if (!var_cfg_disable_save) {
if (!db_->set(key, buff.c_str())) {
logger_error("db set error, key=%s", key);
return false;
}
}
}
builder_.create_object().set_status("OK");
return true;
}
bool redis_handler::get(const redis_object &obj) {
auto& objs = obj.get_objects();
if (objs.size() < 2) {
logger_error("invalid GET params' size=%zd", objs.size());
return false;
}
auto key = objs[1]->get_str();
if (key == nullptr || *key == 0) {
logger_error("key null");
return false;
}
std::string buff;
if (!db_->get(key, buff) || buff.empty()) {
logger_error("db get error, key=%s", key);
return false;
}
redis_coder builder;
size_t len = buff.size();
(void) builder.update(buff.c_str(), len);
if (len > 0) {
logger_error("invalid buff in db, key=%s", key);
return false;
}
auto& objs2 = builder.get_objects();
if (objs2.size() != 1) {
logger_error("invalid object in db, key=%s, size=%zd", key, objs2.size());
return false;
}
auto o = objs2[0];
if (o->get_type() != REDIS_OBJ_STRING) {
logger_error("invalid object type=%d, key=%s", (int) o->get_type(), key);
return false;
}
auto v = o->get_str();
if (v == nullptr || *v == 0) {
logger_error("value null, key=%s", key);
return false;
}
builder_.create_object().set_string(v);
return true;
}
bool redis_handler::del(const redis_object &obj) {
auto& objs = obj.get_objects();
if (objs.size() < 2) {
logger_error("invalid SET params' size=%zd", objs.size());
return false;
}
auto key = objs[1]->get_str();
if (key == nullptr || *key == 0) {
logger_error("key null");
return false;
}
if (!db_->del(key)) {
logger_error("db del error, key=%s", key);
return false;
}
builder_.create_object().set_number(1);
return true;
}
bool redis_handler::type(const redis_object &obj) {
builder_.create_object().set_status("string");
return true;
}
bool redis_handler::hset(const redis_object &obj) {
auto& objs = obj.get_objects();
if (objs.size() < 4) {
@ -233,7 +129,7 @@ bool redis_handler::hset(const redis_object &obj) {
return false;
}
redis_coder builder;
redis_coder builder(parser_.get_cache());
builder.create_object()
.create_child().set_string(name, true)
.create_child().set_string(value, true);
@ -281,7 +177,7 @@ bool redis_handler::hget(const redis_object &obj) {
//printf(">>hget: [%s]\r\n", buff.c_str());
redis_coder builder;
redis_coder builder(parser_.get_cache());
size_t len = buff.size();
(void) builder.update(buff.c_str(), len);
if (len > 0) {

View File

@ -13,7 +13,7 @@ class redis_object;
class redis_handler {
public:
explicit redis_handler(shared_db& db, const redis_coder& parser,
explicit redis_handler(shared_db& db, redis_coder& parser,
acl::socket_stream& conn);
~redis_handler() = default;
@ -21,17 +21,13 @@ public:
private:
shared_db& db_;
const redis_coder& parser_;
redis_coder& parser_;
acl::socket_stream& conn_;
redis_coder builder_;
redis_coder coder_;
acl::socket_stream& conn_;
bool handle_one(const redis_object& obj);
bool set(const redis_object& obj);
bool get(const redis_object& obj);
bool del(const redis_object& obj);
bool type(const redis_object& obj);
bool hset(const redis_object& obj);
bool hget(const redis_object& obj);
bool hdel(const redis_object& obj);

View File

@ -0,0 +1,43 @@
//
// Created by shuxin ¡¡¡¡zheng on 2023/7/31.
//
#include "stdafx.h"
#include "redis_key.h"
namespace pkv {
redis_key::redis_key(shared_db& db, const redis_object& obj, redis_coder& base)
: db_(db), obj_(obj), base_(base)
{
(void) base_;
}
bool redis_key::del(redis_coder& result) {
auto& objs = obj_.get_objects();
if (objs.size() < 2) {
logger_error("invalid SET params' size=%zd", objs.size());
return false;
}
auto key = objs[1]->get_str();
if (key == nullptr || *key == 0) {
logger_error("key null");
return false;
}
if (!db_->del(key)) {
logger_error("db del error, key=%s", key);
return false;
}
result.create_object().set_number(1);
return true;
}
bool redis_key::type(redis_coder& result) {
result.create_object().set_status("string");
return true;
}
} // namespace pkv

View File

@ -0,0 +1,28 @@
//
// Created by shuxin ¡¡¡¡zheng on 2023/7/31.
//
#pragma once
#include "dao/db.h"
#include "proto/redis_coder.h"
namespace pkv {
class redis_object;
class redis_coder;
class redis_key {
public:
redis_key(shared_db& db, const redis_object& obj, redis_coder& base);
~redis_key() = default;
bool del(redis_coder& result);
bool type(redis_coder& result);
private:
shared_db& db_;
const redis_object& obj_;
redis_coder& base_;
};
} // namespace pkv

View File

@ -0,0 +1,108 @@
//
// Created by shuxin ¡¡¡¡zheng on 2023/7/31.
//
#include "stdafx.h"
#include "proto/redis_coder.h"
#include "proto/redis_object.h"
#include "redis_string.h"
namespace pkv {
redis_string::redis_string(shared_db& db, const redis_object &obj,
redis_coder& base)
: db_(db), obj_(obj), base_(base) {}
bool redis_string::set(redis_coder& result) {
auto& objs = obj_.get_objects();
if (objs.size() < 3) {
logger_error("invalid SET params' size=%zd", objs.size());
return false;
}
auto key = objs[1]->get_str();
if (key == nullptr || *key == 0) {
logger_error("key null");
return false;
}
auto value = objs[2]->get_str();
if (value == nullptr || *value == 0) {
logger_error("value null");
return false;
}
if (!var_cfg_disable_serialize) {
std::string buff;
redis_coder coder(base_.get_cache());
coder.create_object().create_child().set_string("string", true) // type
.create_child().set_number(-1); // expire time
coder.create_object().set_string(value);
coder.to_string(buff);
coder.clear();
//printf("buf=[%s]\n", buff.c_str());
if (!var_cfg_disable_save) {
if (!db_->set(key, buff.c_str())) {
logger_error("db set error, key=%s", key);
return false;
}
}
}
result.create_object().set_status("OK");
return true;
}
bool redis_string::get(redis_coder& result) {
auto& objs = obj_.get_objects();
if (objs.size() < 2) {
logger_error("invalid GET params' size=%zd", objs.size());
return false;
}
auto key = objs[1]->get_str();
if (key == nullptr || *key == 0) {
logger_error("key null");
return false;
}
std::string buff;
if (!db_->get(key, buff) || buff.empty()) {
logger_error("db get error, key=%s", key);
return false;
}
//printf(">>>get key=%s, val=[%s]\n", key, buff.c_str());
redis_coder builder(base_.get_cache());
size_t len = buff.size();
(void) builder.update(buff.c_str(), len);
if (len > 0) {
logger_error("invalid buff in db, key=%s", key);
return false;
}
auto& objs2 = builder.get_objects();
if (objs2.size() != 2) {
logger_error("invalid object in db, key=%s, size=%zd", key, objs2.size());
return false;
}
auto o = objs2[1];
if (o->get_type() != REDIS_OBJ_STRING) {
logger_error("invalid object type=%d, key=%s", (int) o->get_type(), key);
return false;
}
auto v = o->get_str();
if (v == nullptr || *v == 0) {
logger_error("value null, key=%s", key);
return false;
}
result.create_object().set_string(v);
return true;
}
} // namespace pkv

View File

@ -0,0 +1,27 @@
//
// Created by shuxin ¡¡¡¡zheng on 2023/7/31.
//
#pragma once
#include "dao/db.h"
namespace pkv {
class redis_object;
class redis_coder;
class redis_string {
public:
redis_string(shared_db& db, const redis_object &obj, redis_coder& base);
~redis_string() = default;
bool set(redis_coder& result);
bool get(redis_coder& result);
private:
shared_db& db_;
const redis_object &obj_;
redis_coder& base_;
};
} // namespace pkv

View File

@ -52,7 +52,8 @@ void master_service::on_accept(acl::socket_stream& conn) {
}
void master_service::run(acl::socket_stream& conn, size_t size) {
pkv::redis_coder parser;
std::vector<redis_object*> cache;
pkv::redis_coder parser(cache);
pkv::redis_handler handler(db_, parser, conn);
char buf[size];
@ -80,6 +81,10 @@ void master_service::run(acl::socket_stream& conn, size_t size) {
parser.clear();
}
for (auto obj : cache) {
delete obj;
}
}
void master_service::proc_pre_jail() {

View File

@ -7,9 +7,16 @@
namespace pkv {
redis_coder::redis_coder(size_t cache_max) {
cache_max_ = cache_max;
curr_ = new redis_object(cache_, cache_max_);
redis_coder::redis_coder(std::vector<redis_object*>& cache, size_t cache_max)
: cache_(cache)
, cache_max_(cache_max)
{
if (cache_.empty()) {
curr_ = new redis_object(cache_, cache_max_);
} else {
curr_ = cache_.back();
cache_.pop_back();
}
}
redis_coder::~redis_coder() {
@ -17,10 +24,6 @@ redis_coder::~redis_coder() {
delete obj;
}
for (auto obj : cache_) {
delete obj;
}
delete curr_;
}
@ -105,7 +108,8 @@ bool test_redis_parse_once(const char* filepath) {
return false;
}
redis_coder parser;
std::vector<redis_object*> cache;
redis_coder parser(cache);
const char* data = buf.c_str();
size_t len = buf.size();
const char* left = parser.update(data, len);
@ -153,7 +157,8 @@ bool test_redis_parse_stream(const char* filepath) {
return false;
}
redis_coder parser;
std::vector<redis_object*> cache;
redis_coder parser(cache);
const char* data = buf.c_str();
size_t len = buf.size();
for (size_t i = 0; i < len; i++) {
@ -191,7 +196,8 @@ bool test_redis_parse_stream(const char* filepath) {
//////////////////////////////////////////////////////////////////////////////
bool test_redis_build() {
redis_coder builder;
std::vector<redis_object*> cache;
redis_coder builder(cache);
auto& obj = builder.create_object();

View File

@ -12,7 +12,7 @@ namespace pkv {
class redis_coder {
public:
explicit redis_coder(size_t cache_max = 10000);
explicit redis_coder(std::vector<redis_object*>& cache, size_t cache_max = 10000);
~redis_coder();
const char* update(const char* data, size_t& len);
@ -27,14 +27,18 @@ public:
void clear();
NODISCARD std::vector<redis_object*>& get_cache() const {
return cache_;
}
public:
NODISCARD redis_object& create_object();
bool to_string(std::string& out) const;
private:
std::vector<redis_object*>& cache_;
std::vector<redis_object*> objs_;
std::vector<redis_object*> cache_;
size_t cache_max_;
redis_object* curr_;
};

View File

@ -434,7 +434,7 @@ redis_object& redis_object::set_error(const std::string& data,
return return_parent ? *parent_ : *this;
}
redis_object& redis_object::set_number(int n, bool return_parent) {
redis_object& redis_object::set_number(long long n, bool return_parent) {
type_ = REDIS_OBJ_INTEGER;
buf_ = std::to_string(n);
return return_parent ? *parent_ : *this;

View File

@ -61,7 +61,7 @@ public:
public:
redis_object& set_status(const std::string& data, bool return_parent = false);
redis_object& set_error(const std::string& data, bool return_parent = false);
redis_object& set_number(int n, bool return_parent = false);
redis_object& set_number(long long n, bool return_parent = false);
redis_object& set_string(const std::string& data, bool return_parent = false);
redis_object& create_child();