mirror of
https://github.com/boostorg/redis.git
synced 2026-02-03 09:22:18 +00:00
More changes in the architecture.
This commit is contained in:
@@ -83,7 +83,7 @@ net::awaitable<void> read_hashes_coro()
|
||||
|
||||
std::string buffer;
|
||||
|
||||
resp::response_array<std::string> keys;
|
||||
resp::response_array keys;
|
||||
co_await resp::async_read(socket, buffer, keys);
|
||||
//print(keys.result);
|
||||
|
||||
@@ -96,7 +96,7 @@ net::awaitable<void> read_hashes_coro()
|
||||
co_await async_write(socket, net::buffer(pv.payload));
|
||||
|
||||
for (auto const& key : keys.result) {
|
||||
resp::response_array<std::string> value;
|
||||
resp::response_array value;
|
||||
co_await resp::async_read(socket, buffer, value);
|
||||
//print(value.result);
|
||||
}
|
||||
@@ -118,7 +118,7 @@ void read_hashes(net::io_context& ioc)
|
||||
|
||||
std::string buffer;
|
||||
|
||||
resp::response_array<std::string> keys;
|
||||
resp::response_array keys;
|
||||
resp::read(socket, buffer, keys);
|
||||
|
||||
// Generates the request to retrieve all hashes.
|
||||
@@ -130,7 +130,7 @@ void read_hashes(net::io_context& ioc)
|
||||
write(socket, pv);
|
||||
|
||||
for (auto const& key : keys.result) {
|
||||
resp::response_array<std::string> value;
|
||||
resp::response_array value;
|
||||
resp::read(socket, buffer, value);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,44 +18,20 @@ using tcp = net::ip::tcp;
|
||||
void fill1(resp::request<resp::event>& req)
|
||||
{
|
||||
req.ping();
|
||||
//req.multi();
|
||||
req.rpush("list", {1, 2, 3});
|
||||
req.multi();
|
||||
req.lrange("list");
|
||||
//req.exec();
|
||||
req.exec();
|
||||
req.ping();
|
||||
}
|
||||
|
||||
net::awaitable<void> example()
|
||||
{
|
||||
try {
|
||||
auto ex = co_await net::this_coro::executor;
|
||||
tcp::resolver resv(ex);
|
||||
auto const r = resv.resolve("127.0.0.1", "6379");
|
||||
tcp::socket socket {ex};
|
||||
co_await async_connect(socket, r, net::use_awaitable);
|
||||
|
||||
auto reqs = resp::make_request_queue<resp::event>();
|
||||
resp::response_buffers resps;
|
||||
resp::receiver_print recv{resps};
|
||||
net::steady_timer st{ex};
|
||||
|
||||
co_spawn(ex, resp::async_reader(socket, reqs, resps, recv), net::detached);
|
||||
resp::async_writer(socket, reqs, st, net::detached);
|
||||
queue_writer(reqs, fill1, st);
|
||||
|
||||
net::steady_timer timer(ex, std::chrono::years{1});
|
||||
co_await timer.async_wait(net::use_awaitable);
|
||||
|
||||
} catch (std::exception const& e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
net::io_context ioc {1};
|
||||
co_spawn(ioc, example(), net::detached);
|
||||
auto conn = std::make_shared<resp::connection<resp::event>>(ioc);
|
||||
resp::receiver_base<resp::event> recv;
|
||||
conn->start(recv);
|
||||
conn->send(fill1);
|
||||
ioc.run();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ net::awaitable<void> example()
|
||||
switch (req.events.front().second) {
|
||||
case myevents::interesting1:
|
||||
{
|
||||
resp::response_list<int> res;
|
||||
resp::response_basic_array<int> res;
|
||||
co_await resp::async_read(socket, buffer, res);
|
||||
resp::print(res.result, "Interesting1");
|
||||
} break;
|
||||
|
||||
@@ -17,103 +17,23 @@ using tcp = net::ip::tcp;
|
||||
|
||||
enum class myevent {zero, one, two, ignore};
|
||||
|
||||
#define EXPAND_MYEVENT_CASE(x) case myevent::x: return #x
|
||||
|
||||
inline
|
||||
auto to_string(myevent t)
|
||||
void fill1(resp::request<resp::event>& req)
|
||||
{
|
||||
switch (t) {
|
||||
EXPAND_MYEVENT_CASE(zero);
|
||||
EXPAND_MYEVENT_CASE(one);
|
||||
EXPAND_MYEVENT_CASE(two);
|
||||
EXPAND_MYEVENT_CASE(ignore);
|
||||
default: assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, myevent e)
|
||||
{
|
||||
os << to_string(e);
|
||||
return os;
|
||||
}
|
||||
|
||||
auto filler(resp::request<myevent>& req)
|
||||
{
|
||||
//req.subscribe("channel");
|
||||
//req.subscribe("__keyspace@0__:user:*");
|
||||
//req.ping(myevent::one);
|
||||
//req.set("aaaa", {std::to_string(1)});
|
||||
//req.get("aaaa");
|
||||
//req.del("aaaa");
|
||||
//req.rpush("user:Marcelo", {1, 2, 3}, myevent::two);
|
||||
//req.lrange("user:Marcelo");
|
||||
//req.publish("channel", "Some message");
|
||||
//req.multi();
|
||||
//req.lrange("user:Marcelo", 0, -1, myevent::zero);
|
||||
//req.exec();
|
||||
req.set("aaaa", {std::to_string(2)});
|
||||
req.get("aaaa");
|
||||
//req.multi();
|
||||
//req.lrange("user:Marcelo");
|
||||
req.ping();
|
||||
//req.lrange("user:Marcelo", 0, -1, myevent::zero);
|
||||
//req.ping();
|
||||
//req.lrange("user:Marcelo");
|
||||
req.ping();
|
||||
//req.lrange("user:Marcelo");
|
||||
//req.lrange("user:Marcelo");
|
||||
//req.exec();
|
||||
//req.set("eee", {std::to_string(8)});
|
||||
//req.get("eee");
|
||||
//req.del("eee");
|
||||
}
|
||||
|
||||
void fill1(resp::request<myevent>& req)
|
||||
{
|
||||
req.multi();
|
||||
req.rpush("list", {1, 2, 3});
|
||||
req.multi();
|
||||
req.lrange("list");
|
||||
req.exec();
|
||||
req.ping();
|
||||
}
|
||||
|
||||
net::awaitable<void> subscriber()
|
||||
{
|
||||
try {
|
||||
auto ex = co_await net::this_coro::executor;
|
||||
tcp::resolver resv(ex);
|
||||
auto const r = resv.resolve("127.0.0.1", "6379");
|
||||
tcp::socket socket {ex};
|
||||
co_await async_connect(socket, r, net::use_awaitable);
|
||||
|
||||
auto reqs = resp::make_request_queue<myevent>();
|
||||
resp::response_buffers_ignore resps;
|
||||
resp::receiver_print recv;
|
||||
net::steady_timer st{ex};
|
||||
|
||||
co_spawn(
|
||||
ex,
|
||||
resp::async_reader(socket, reqs, resps, recv),
|
||||
net::detached);
|
||||
|
||||
resp::async_writer(socket, reqs, st, net::detached);
|
||||
|
||||
for (;;) {
|
||||
queue_writer(reqs, fill1, st);
|
||||
net::steady_timer timer(ex, std::chrono::milliseconds{1000});
|
||||
co_await timer.async_wait(net::use_awaitable);
|
||||
}
|
||||
|
||||
} catch (std::exception const& e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
net::io_context ioc {1};
|
||||
co_spawn(ioc, subscriber(), net::detached);
|
||||
auto conn = std::make_shared<resp::connection<resp::event>>(ioc);
|
||||
resp::receiver_base<resp::event> recv;
|
||||
conn->start(recv);
|
||||
conn->send(fill1);
|
||||
ioc.run();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,22 +28,6 @@
|
||||
|
||||
namespace aedis { namespace resp {
|
||||
|
||||
inline
|
||||
void print_command_raw(std::string const& data, int n)
|
||||
{
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (data[i] == '\n') {
|
||||
std::cout << "\\n";
|
||||
continue;
|
||||
}
|
||||
if (data[i] == '\r') {
|
||||
std::cout << "\\r";
|
||||
continue;
|
||||
}
|
||||
std::cout << data[i];
|
||||
}
|
||||
}
|
||||
|
||||
// The parser supports up to 5 levels of nested structures. The first
|
||||
// element in the sizes stack is a sentinel and must be different from
|
||||
// 1.
|
||||
@@ -253,28 +237,20 @@ auto async_read_type(
|
||||
stream);
|
||||
}
|
||||
|
||||
struct receiver_ignore {
|
||||
template <class Event>
|
||||
void receive(response_id<Event> const&) {}
|
||||
template <class Event>
|
||||
void receive_transaction(std::queue<response_id<Event>>) {}
|
||||
};
|
||||
|
||||
template <
|
||||
class AsyncReadWriteStream,
|
||||
class Event,
|
||||
class ResponseBuffer,
|
||||
class Receiver = receiver_ignore>
|
||||
class Receiver>
|
||||
net::awaitable<void>
|
||||
async_reader(
|
||||
AsyncReadWriteStream& socket,
|
||||
std::queue<request<Event>>& reqs,
|
||||
ResponseBuffer& resps,
|
||||
Receiver recv = receiver_ignore{})
|
||||
Receiver& recv,
|
||||
std::queue<request<typename Receiver::event_type>>& reqs)
|
||||
{
|
||||
using response_id_type = response_id<Event>;
|
||||
using event_type = typename Receiver::event_type;
|
||||
using response_id_type = response_id<event_type>;
|
||||
|
||||
std::string buffer;
|
||||
resp::response_buffers resps;
|
||||
|
||||
// Used to queue the events of a transaction.
|
||||
std::queue<response_id_type> trans;
|
||||
@@ -327,7 +303,7 @@ async_reader(
|
||||
net::use_awaitable);
|
||||
|
||||
trans.pop(); // Removes multi.
|
||||
recv.receive_transaction(std::move(trans));
|
||||
resps.forward_transaction(std::move(trans), recv);
|
||||
trans = {};
|
||||
|
||||
req.events.pop(); // exec
|
||||
@@ -351,7 +327,7 @@ async_reader(
|
||||
*tmp,
|
||||
net::use_awaitable);
|
||||
|
||||
recv.receive(id);
|
||||
resps.forward(id, recv);
|
||||
|
||||
if (t != type::push)
|
||||
req.events.pop();
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
#include "type.hpp"
|
||||
@@ -16,78 +17,97 @@
|
||||
|
||||
namespace aedis { namespace resp {
|
||||
|
||||
class receiver_print {
|
||||
template <class Event>
|
||||
class receiver_base {
|
||||
public:
|
||||
using event_type = Event;
|
||||
|
||||
virtual void on_array(command cmd, Event ev, response_array::data_type& v) noexcept
|
||||
{ print(v); }
|
||||
virtual void on_push(command cmd, Event ev, response_array::data_type& v) noexcept
|
||||
{ print(v); }
|
||||
virtual void on_map(command cmd, Event ev, response_array::data_type& v) noexcept
|
||||
{ print(v); }
|
||||
virtual void on_set(command cmd, Event ev, response_array::data_type& v) noexcept
|
||||
{ print(v); }
|
||||
virtual void on_attribute(command cmd, Event ev, response_array::data_type& v) noexcept
|
||||
{ print(v); }
|
||||
virtual void on_simple_string(command cmd, Event ev, response_simple_string::data_type& v) noexcept
|
||||
{ std::cout << v << std::endl; }
|
||||
virtual void on_simple_error(command cmd, Event ev, response_simple_error::data_type& v) noexcept
|
||||
{ std::cout << v << std::endl; }
|
||||
virtual void on_number(command cmd, Event ev, response_number::data_type& v) noexcept
|
||||
{ std::cout << v << std::endl; }
|
||||
virtual void on_double(command cmd, Event ev, response_double::data_type& v) noexcept
|
||||
{ std::cout << v << std::endl; }
|
||||
virtual void on_big_number(command cmd, Event ev, response_big_number::data_type& v) noexcept
|
||||
{ std::cout << v << std::endl; }
|
||||
virtual void on_boolean(command cmd, Event ev, response_bool::data_type& v) noexcept
|
||||
{ std::cout << v << std::endl; }
|
||||
virtual void on_blob_string(command cmd, Event ev, response_blob_string::data_type& v) noexcept
|
||||
{ std::cout << v << std::endl; }
|
||||
virtual void on_blob_error(command cmd, Event ev, response_blob_error::data_type& v) noexcept
|
||||
{ std::cout << v << std::endl; }
|
||||
virtual void on_verbatim_string(command cmd, Event ev, response_verbatim_string::data_type& v) noexcept
|
||||
{ std::cout << v << std::endl; }
|
||||
virtual void on_streamed_string_part(command cmd, Event ev, response_streamed_string_part::data_type& v) noexcept
|
||||
{ std::cout << v << std::endl; }
|
||||
};
|
||||
|
||||
template <class Event>
|
||||
class connection :
|
||||
public std::enable_shared_from_this<connection<Event>> {
|
||||
private:
|
||||
response_buffers& buffer_;
|
||||
net::steady_timer st_;
|
||||
tcp::resolver resv_;
|
||||
tcp::socket socket_;
|
||||
std::queue<request<Event>> reqs_;
|
||||
|
||||
template <class Receiver>
|
||||
net::awaitable<void>
|
||||
reconnect_loop(Receiver& recv)
|
||||
{
|
||||
try {
|
||||
auto ex = co_await net::this_coro::executor;
|
||||
auto const r = resv_.resolve("127.0.0.1", "6379");
|
||||
co_await async_connect(socket_, r, net::use_awaitable);
|
||||
resp::async_writer(socket_, reqs_, st_, net::detached);
|
||||
co_await co_spawn(
|
||||
ex,
|
||||
resp::async_reader(socket_, recv, reqs_),
|
||||
net::use_awaitable);
|
||||
} catch (std::exception const& e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
socket_.close();
|
||||
st_.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
receiver_print(response_buffers& buffer)
|
||||
: buffer_{buffer}
|
||||
{}
|
||||
using event_type = Event;
|
||||
|
||||
// The ids in the queue parameter have an unspecified message type.
|
||||
template <class Event>
|
||||
void receive_transaction(std::queue<response_id<Event>> ids)
|
||||
connection(net::io_context& ioc)
|
||||
: st_{ioc}
|
||||
, resv_{ioc}
|
||||
, socket_{ioc}
|
||||
, reqs_ (resp::make_request_queue<Event>())
|
||||
{ }
|
||||
|
||||
template <class Receiver>
|
||||
void start(Receiver& recv)
|
||||
{
|
||||
while (!std::empty(ids)) {
|
||||
std::cout << ids.front() << std::endl;
|
||||
ids.pop();
|
||||
}
|
||||
net::co_spawn(
|
||||
socket_.get_executor(),
|
||||
[self = this->shared_from_this(), recv] () mutable { return self->reconnect_loop(recv); },
|
||||
net::detached);
|
||||
}
|
||||
|
||||
template <class Event>
|
||||
void receive(response_id<Event> const& id)
|
||||
{
|
||||
buffer_.tree().clear();
|
||||
template <class Filler>
|
||||
void send(Filler filler)
|
||||
{ queue_writer(reqs_, filler, st_); }
|
||||
|
||||
std::cout << id;
|
||||
switch (id.t) {
|
||||
case type::push:
|
||||
buffer_.push().clear();
|
||||
break;
|
||||
case type::set:
|
||||
buffer_.set().clear();
|
||||
break;
|
||||
case type::map:
|
||||
buffer_.map().clear();
|
||||
break;
|
||||
case type::attribute:
|
||||
buffer_.attribute().clear();
|
||||
break;
|
||||
case type::array:
|
||||
buffer_.array().clear();
|
||||
break;
|
||||
case type::simple_error:
|
||||
buffer_.simple_error().clear();
|
||||
break;
|
||||
case type::simple_string:
|
||||
buffer_.simple_string().clear();
|
||||
break;
|
||||
case type::number:
|
||||
break;
|
||||
case type::double_type:
|
||||
break;
|
||||
case type::big_number:
|
||||
buffer_.big_number().clear();
|
||||
break;
|
||||
case type::boolean:
|
||||
break;
|
||||
case type::blob_error:
|
||||
buffer_.blob_error().clear();
|
||||
break;
|
||||
case type::blob_string:
|
||||
buffer_.blob_string().clear();
|
||||
break;
|
||||
case type::verbatim_string:
|
||||
buffer_.verbatim_string().clear();
|
||||
break;
|
||||
case type::streamed_string_part:
|
||||
buffer_.streamed_string_part().clear();
|
||||
break;
|
||||
default:{}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
auto& requests() {return reqs_;}
|
||||
auto const& requests() const {return reqs_;}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -146,8 +146,9 @@ private:
|
||||
|
||||
void add(std::string_view s, type t)
|
||||
{
|
||||
assert(!std::empty(result));
|
||||
if (std::ssize(result.back().value) == result.back().expected_size) {
|
||||
if (std::empty(result)) {
|
||||
result.emplace_back(depth_, t, 1, std::vector<std::string>{std::string{s}});
|
||||
} else if (std::ssize(result.back().value) == result.back().expected_size) {
|
||||
result.emplace_back(depth_, t, 1, std::vector<std::string>{std::string{s}});
|
||||
} else {
|
||||
result.back().value.push_back(std::string{s});
|
||||
@@ -186,7 +187,8 @@ private:
|
||||
{ from_string_view(s, result); }
|
||||
|
||||
public:
|
||||
T result;
|
||||
using data_type = T;
|
||||
data_type result;
|
||||
};
|
||||
|
||||
using response_number = response_basic_number<long long int>;
|
||||
@@ -200,7 +202,8 @@ private:
|
||||
void on_blob_string_impl(std::string_view s) override
|
||||
{ from_string_view(s, result); }
|
||||
public:
|
||||
std::basic_string<CharT, Traits, Allocator> result;
|
||||
using data_type = std::basic_string<CharT, Traits, Allocator>;
|
||||
data_type result;
|
||||
};
|
||||
|
||||
using response_blob_string = response_basic_blob_string<char>;
|
||||
@@ -214,7 +217,8 @@ private:
|
||||
void on_blob_error_impl(std::string_view s) override
|
||||
{ from_string_view(s, result); }
|
||||
public:
|
||||
std::basic_string<CharT, Traits, Allocator> result;
|
||||
using data_type = std::basic_string<CharT, Traits, Allocator>;
|
||||
data_type result;
|
||||
};
|
||||
|
||||
using response_blob_error = response_basic_blob_error<char>;
|
||||
@@ -229,7 +233,8 @@ private:
|
||||
void on_simple_string_impl(std::string_view s) override
|
||||
{ from_string_view(s, result); }
|
||||
public:
|
||||
std::basic_string<CharT, Traits, Allocator> result;
|
||||
using data_type = std::basic_string<CharT, Traits, Allocator>;
|
||||
data_type result;
|
||||
};
|
||||
|
||||
using response_simple_string = response_basic_simple_string<char>;
|
||||
@@ -245,7 +250,8 @@ private:
|
||||
{ from_string_view(s, result); }
|
||||
|
||||
public:
|
||||
std::basic_string<CharT, Traits, Allocator> result;
|
||||
using data_type = std::basic_string<CharT, Traits, Allocator>;
|
||||
data_type result;
|
||||
};
|
||||
|
||||
using response_simple_error = response_basic_simple_error<char>;
|
||||
@@ -262,7 +268,8 @@ private:
|
||||
{ from_string_view(s, result); }
|
||||
|
||||
public:
|
||||
std::basic_string<CharT, Traits, Allocator> result;
|
||||
using data_type = std::basic_string<CharT, Traits, Allocator>;
|
||||
data_type result;
|
||||
};
|
||||
|
||||
using response_big_number = response_basic_big_number<char>;
|
||||
@@ -279,29 +286,12 @@ private:
|
||||
{ from_string_view(s, result); }
|
||||
|
||||
public:
|
||||
std::basic_string<CharT, Traits, Allocator> result;
|
||||
using data_type = std::basic_string<CharT, Traits, Allocator>;
|
||||
data_type result;
|
||||
};
|
||||
|
||||
using response_double = response_basic_double<char>;
|
||||
|
||||
template <
|
||||
class T,
|
||||
class Allocator = std::allocator<T>>
|
||||
class response_list : public response_base {
|
||||
private:
|
||||
void on_blob_string_impl(std::string_view s) override
|
||||
{
|
||||
T r;
|
||||
from_string_view(s, r);
|
||||
result.push_back(std::move(r));
|
||||
}
|
||||
|
||||
void select_array_impl(int n) override { }
|
||||
|
||||
public:
|
||||
std::list<T, Allocator> result;
|
||||
};
|
||||
|
||||
template<
|
||||
class CharT = char,
|
||||
class Traits = std::char_traits<CharT>,
|
||||
@@ -312,7 +302,8 @@ private:
|
||||
void on_verbatim_string_impl(std::string_view s) override
|
||||
{ from_string_view(s, result); }
|
||||
public:
|
||||
std::basic_string<CharT, Traits, Allocator> result;
|
||||
using data_type = std::basic_string<CharT, Traits, Allocator>;
|
||||
data_type result;
|
||||
};
|
||||
|
||||
using response_verbatim_string = response_basic_verbatim_string<char>;
|
||||
@@ -322,15 +313,16 @@ template<
|
||||
class Traits = std::char_traits<CharT>,
|
||||
class Allocator = std::allocator<CharT>
|
||||
>
|
||||
class response_basic_streamed_string : public response_base {
|
||||
class response_basic_streamed_string_part : public response_base {
|
||||
private:
|
||||
void on_streamed_string_part_impl(std::string_view s) override
|
||||
{ result += s; }
|
||||
public:
|
||||
std::basic_string<CharT, Traits, Allocator> result;
|
||||
using data_type = std::basic_string<CharT, Traits, Allocator>;
|
||||
data_type result;
|
||||
};
|
||||
|
||||
using response_streamed_string = response_basic_streamed_string<char>;
|
||||
using response_streamed_string_part = response_basic_streamed_string_part<char>;
|
||||
|
||||
template <
|
||||
class Key,
|
||||
@@ -367,7 +359,8 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
bool result;
|
||||
using data_type = bool;
|
||||
data_type result;
|
||||
};
|
||||
|
||||
template<
|
||||
@@ -395,7 +388,7 @@ template <
|
||||
class T,
|
||||
class Allocator = std::allocator<T>
|
||||
>
|
||||
class response_array : public response_base {
|
||||
class response_basic_array : public response_base {
|
||||
private:
|
||||
void add(std::string_view s = {})
|
||||
{
|
||||
@@ -419,14 +412,17 @@ private:
|
||||
void on_streamed_string_part_impl(std::string_view s = {}) override { add(s); }
|
||||
|
||||
public:
|
||||
std::vector<T, Allocator> result;
|
||||
using data_type = std::vector<T, Allocator>;
|
||||
data_type result;
|
||||
};
|
||||
|
||||
template <class T, class Allocator = std::allocator<T>>
|
||||
using response_flat_map = response_array<T, Allocator>;
|
||||
using response_array = response_basic_array<std::string>;
|
||||
|
||||
template <class T, class Allocator = std::allocator<T>>
|
||||
using response_flat_set = response_array<T, Allocator>;
|
||||
using response_flat_map = response_basic_array<T, Allocator>;
|
||||
|
||||
template <class T, class Allocator = std::allocator<T>>
|
||||
using response_flat_set = response_basic_array<T, Allocator>;
|
||||
|
||||
template <class T, std::size_t N>
|
||||
class response_static_array : public response_base {
|
||||
@@ -482,84 +478,27 @@ struct response_id {
|
||||
Event event;
|
||||
};
|
||||
|
||||
class response_buffers_ignore {
|
||||
private:
|
||||
response_ignore buf_;
|
||||
|
||||
public:
|
||||
template <class Event>
|
||||
response_base* get(response_id<Event> id) { return &buf_; }
|
||||
};
|
||||
|
||||
class response_buffers {
|
||||
private:
|
||||
// TODO: Use a variant to store all responses.
|
||||
response_tree tree_;
|
||||
|
||||
response_array<std::string> array_;
|
||||
response_array<std::string> push_;
|
||||
response_array<std::string> set_;
|
||||
response_array<std::string> map_;
|
||||
response_array<std::string> attribute_;
|
||||
response_array array_;
|
||||
response_array push_;
|
||||
response_array set_;
|
||||
response_array map_;
|
||||
response_array attribute_;
|
||||
response_simple_string simple_string_;
|
||||
response_simple_error simple_error_;
|
||||
response_number number_;
|
||||
response_double double_;
|
||||
response_bool boolean_;
|
||||
response_bool bool_;
|
||||
response_big_number big_number_;
|
||||
response_blob_string blob_string_;
|
||||
response_blob_error blob_error_;
|
||||
response_verbatim_string verbatim_string_;
|
||||
response_streamed_string streamed_string_part_;
|
||||
response_ignore ignore_;
|
||||
response_streamed_string_part streamed_string_part_;
|
||||
|
||||
public:
|
||||
auto& tree() {return tree_.result;};
|
||||
|
||||
auto& array() {return array_.result;};
|
||||
auto const& array() const noexcept {return array_.result;};
|
||||
|
||||
auto& push() {return push_.result;};
|
||||
auto const& push() const noexcept {return push_.result;};
|
||||
|
||||
auto& set() {return set_.result;};
|
||||
auto const& set() const noexcept {return set_.result;};
|
||||
|
||||
auto& map() {return map_.result;};
|
||||
auto const& map() const noexcept {return map_.result;};
|
||||
|
||||
auto& attribute() {return attribute_.result;};
|
||||
auto const& attribute() const noexcept {return attribute_.result;};
|
||||
|
||||
auto& simple_string() {return simple_string_.result;};
|
||||
auto const& simple_string() const noexcept {return simple_string_.result;};
|
||||
|
||||
auto& simple_error() {return simple_error_.result;};
|
||||
auto const& simple_error() const noexcept {return simple_error_.result;};
|
||||
|
||||
auto& number() {return number_.result;};
|
||||
auto const& number() const noexcept {return number_.result;};
|
||||
|
||||
auto& boolean() {return boolean_.result;};
|
||||
auto const& boolean() const noexcept {return boolean_.result;};
|
||||
|
||||
auto& double_type() {return double_.result;};
|
||||
auto const& double_type() const noexcept {return double_.result;};
|
||||
|
||||
auto& big_number() {return big_number_.result;};
|
||||
auto const& big_number() const noexcept {return big_number_.result;};
|
||||
|
||||
auto& blob_error() {return blob_error_.result;};
|
||||
auto const& blob_error() const noexcept {return blob_error_.result;};
|
||||
|
||||
auto& blob_string() {return blob_string_.result;};
|
||||
auto const& blob_string() const noexcept {return blob_string_.result;};
|
||||
|
||||
auto& verbatim_string() {return verbatim_string_.result;};
|
||||
auto const& verbatim_string() const noexcept {return verbatim_string_.result;};
|
||||
|
||||
auto& streamed_string_part() {return streamed_string_part_.result;};
|
||||
auto const& streamed_string_part() const noexcept {return streamed_string_part_.result;};
|
||||
|
||||
// When the id is from a transaction the type of the message is not
|
||||
// specified.
|
||||
template <class Event>
|
||||
@@ -579,12 +518,103 @@ public:
|
||||
case type::number: return &number_;
|
||||
case type::double_type: return &double_;
|
||||
case type::big_number: return &big_number_;
|
||||
case type::boolean: return &boolean_;
|
||||
case type::boolean: return &bool_;
|
||||
case type::blob_error: return &blob_error_;
|
||||
case type::blob_string: return &blob_string_;
|
||||
case type::verbatim_string: return &verbatim_string_;
|
||||
case type::streamed_string_part: return &streamed_string_part_;
|
||||
default: return &ignore_;
|
||||
default: {
|
||||
throw std::runtime_error("response_buffers");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <
|
||||
class Event,
|
||||
class Receiver>
|
||||
void
|
||||
forward_transaction(
|
||||
std::queue<response_id<Event>> ids,
|
||||
Receiver& recv)
|
||||
{
|
||||
while (!std::empty(ids)) {
|
||||
std::cout << ids.front() << std::endl;
|
||||
ids.pop();
|
||||
}
|
||||
|
||||
tree_.result.clear();
|
||||
}
|
||||
|
||||
template <
|
||||
class Event,
|
||||
class Receiver>
|
||||
void
|
||||
forward(
|
||||
response_id<Event> const& id,
|
||||
Receiver& recv)
|
||||
{
|
||||
// TODO: Handle null.
|
||||
switch (id.t) {
|
||||
case type::push:
|
||||
recv.on_push(id.cmd, id.event, push_.result);
|
||||
push_.result.clear();
|
||||
break;
|
||||
case type::set:
|
||||
recv.on_set(id.cmd, id.event, set_.result);
|
||||
set_.result.clear();
|
||||
break;
|
||||
case type::map:
|
||||
recv.on_map(id.cmd, id.event, map_.result);
|
||||
map_.result.clear();
|
||||
break;
|
||||
case type::attribute:
|
||||
recv.on_attribute(id.cmd, id.event, attribute_.result);
|
||||
attribute_.result.clear();
|
||||
break;
|
||||
case type::array:
|
||||
recv.on_array(id.cmd, id.event, array_.result);
|
||||
array_.result.clear();
|
||||
break;
|
||||
case type::simple_error:
|
||||
recv.on_simple_error(id.cmd, id.event, simple_error_.result);
|
||||
simple_error_.result.clear();
|
||||
break;
|
||||
case type::simple_string:
|
||||
recv.on_simple_string(id.cmd, id.event, simple_string_.result);
|
||||
simple_string_.result.clear();
|
||||
break;
|
||||
case type::number:
|
||||
recv.on_number(id.cmd, id.event, number_.result);
|
||||
break;
|
||||
case type::double_type:
|
||||
recv.on_double(id.cmd, id.event, double_.result);
|
||||
break;
|
||||
case type::big_number:
|
||||
recv.on_big_number(id.cmd, id.event, big_number_.result);
|
||||
big_number_.result.clear();
|
||||
break;
|
||||
case type::boolean:
|
||||
recv.on_boolean(id.cmd, id.event, bool_.result);
|
||||
bool_.result = false;
|
||||
break;
|
||||
case type::blob_error:
|
||||
recv.on_blob_error(id.cmd, id.event, blob_error_.result);
|
||||
blob_error_.result.clear();
|
||||
break;
|
||||
case type::blob_string:
|
||||
recv.on_blob_string(id.cmd, id.event, blob_string_.result);
|
||||
blob_string_.result.clear();
|
||||
break;
|
||||
case type::verbatim_string:
|
||||
recv.on_verbatim_string(id.cmd, id.event, verbatim_string_.result);
|
||||
verbatim_string_.result.clear();
|
||||
break;
|
||||
case type::streamed_string_part:
|
||||
recv.on_streamed_string_part(id.cmd, id.event, streamed_string_part_.result);
|
||||
streamed_string_part_.result.clear();
|
||||
break;
|
||||
default:{}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -599,7 +629,7 @@ operator<<(std::ostream& os, aedis::resp::response_id<Event> const& id)
|
||||
os
|
||||
<< std::left << std::setw(15) << aedis::resp::to_string(id.cmd)
|
||||
<< std::left << std::setw(20) << aedis::resp::to_string(id.t)
|
||||
<< std::left << std::setw(20) << (int)id.event
|
||||
<< std::left << std::setw(4) << (int)id.event
|
||||
;
|
||||
return os;
|
||||
}
|
||||
|
||||
@@ -14,19 +14,36 @@ namespace aedis { namespace resp {
|
||||
template <class Iter>
|
||||
void print(Iter begin, Iter end, char const* p)
|
||||
{
|
||||
std::cout << p << ": ";
|
||||
if (p)
|
||||
std::cout << p << ": ";
|
||||
for (; begin != end; ++begin)
|
||||
std::cout << *begin << " ";
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template <class Range>
|
||||
void print(Range const& v, char const* p = "")
|
||||
void print(Range const& v, char const* p = nullptr)
|
||||
{
|
||||
using std::cbegin;
|
||||
using std::cend;
|
||||
print(cbegin(v), cend(v), p);
|
||||
}
|
||||
|
||||
inline
|
||||
void print_command_raw(std::string const& data, int n)
|
||||
{
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (data[i] == '\n') {
|
||||
std::cout << "\\n";
|
||||
continue;
|
||||
}
|
||||
if (data[i] == '\r') {
|
||||
std::cout << "\\r";
|
||||
continue;
|
||||
}
|
||||
std::cout << data[i];
|
||||
}
|
||||
}
|
||||
|
||||
} // resp
|
||||
} // aedis
|
||||
|
||||
@@ -32,7 +32,7 @@ void check_equal(T const& a, T const& b, std::string const& msg = "")
|
||||
|
||||
net::awaitable<void> test_list()
|
||||
{
|
||||
std::list<int> list {1 ,2, 3, 4, 5, 6};
|
||||
std::vector<int> list {1 ,2, 3, 4, 5, 6};
|
||||
|
||||
resp::request p;
|
||||
p.hello("3");
|
||||
@@ -70,15 +70,15 @@ net::awaitable<void> test_list()
|
||||
}
|
||||
|
||||
{ // lrange
|
||||
resp::response_list<int> res;
|
||||
resp::response_basic_array<int> res;
|
||||
co_await resp::async_read(socket, buffer, res);
|
||||
check_equal(res.result, list, "lrange-1");
|
||||
}
|
||||
|
||||
{ // lrange
|
||||
resp::response_list<int> res;
|
||||
resp::response_basic_array<int> res;
|
||||
co_await resp::async_read(socket, buffer, res);
|
||||
check_equal(res.result, std::list<int>{3, 4, 5}, "lrange-2");
|
||||
check_equal(res.result, std::vector<int>{3, 4, 5}, "lrange-2");
|
||||
}
|
||||
|
||||
{ // ltrim
|
||||
@@ -257,7 +257,7 @@ net::awaitable<void> array()
|
||||
{ // Dynamic
|
||||
std::string cmd {"*3\r\n$3\r\none\r\n$3\r\ntwo\r\n$5\r\nthree\r\n"};
|
||||
test_tcp_socket ts {cmd};
|
||||
resp::response_array<std::string> res;
|
||||
resp::response_array res;
|
||||
co_await resp::async_read(ts, buffer, res);
|
||||
check_equal(res.result, {"one", "two", "three"}, "array (dynamic)");
|
||||
}
|
||||
@@ -281,7 +281,7 @@ net::awaitable<void> array()
|
||||
{
|
||||
std::string cmd {"*0\r\n"};
|
||||
test_tcp_socket ts {cmd};
|
||||
resp::response_array<std::string> res;
|
||||
resp::response_array res;
|
||||
co_await resp::async_read(ts, buffer, res);
|
||||
check_equal(res.result, {}, "array (empty)");
|
||||
}
|
||||
@@ -470,7 +470,7 @@ net::awaitable<void> streamed_string()
|
||||
{
|
||||
std::string cmd {"$?\r\n;4\r\nHell\r\n;5\r\no wor\r\n;1\r\nd\r\n;0\r\n"};
|
||||
test_tcp_socket ts {cmd};
|
||||
resp::response_streamed_string res;
|
||||
resp::response_streamed_string_part res;
|
||||
co_await resp::async_read(ts, buffer, res);
|
||||
check_equal(res.result, {"Hello word"}, "streamed string");
|
||||
}
|
||||
@@ -478,7 +478,7 @@ net::awaitable<void> streamed_string()
|
||||
{
|
||||
std::string cmd {"$?\r\n;0\r\n"};
|
||||
test_tcp_socket ts {cmd};
|
||||
resp::response_array<std::string> res;
|
||||
resp::response_array res;
|
||||
co_await resp::async_read(ts, buffer, res);
|
||||
check_equal(res.result, {}, "streamed string (empty)");
|
||||
}
|
||||
@@ -490,7 +490,7 @@ net::awaitable<void> offline()
|
||||
//{
|
||||
// std::string cmd {"|1\r\n+key-popularity\r\n%2\r\n$1\r\na\r\n,0.1923\r\n$1\r\nb\r\n,0.0012\r\n"};
|
||||
// test_tcp_socket ts {cmd};
|
||||
// resp::response_array<std::string> res;
|
||||
// resp::response_array res;
|
||||
// co_await resp::async_read(ts, buffer, res);
|
||||
// check_equal(res.result, {"key-popularity", "a", "0.1923", "b", "0.0012"}, "attribute");
|
||||
//}
|
||||
@@ -498,7 +498,7 @@ net::awaitable<void> offline()
|
||||
//{
|
||||
// std::string cmd {">4\r\n+pubsub\r\n+message\r\n+foo\r\n+bar\r\n"};
|
||||
// test_tcp_socket ts {cmd};
|
||||
// resp::response_array<std::string> res;
|
||||
// resp::response_array res;
|
||||
// co_await resp::async_read(ts, buffer, res);
|
||||
// check_equal(res.result, {"pubsub", "message", "foo", "bar"}, "push type");
|
||||
//}
|
||||
@@ -506,7 +506,7 @@ net::awaitable<void> offline()
|
||||
//{
|
||||
// std::string cmd {">0\r\n"};
|
||||
// test_tcp_socket ts {cmd};
|
||||
// resp::response_array<std::string> res;
|
||||
// resp::response_array res;
|
||||
// co_await resp::async_read(ts, buffer, res);
|
||||
// check_equal(res.result, {}, "push type (empty)");
|
||||
//}
|
||||
|
||||
Reference in New Issue
Block a user