From a3ff6808477174c587afbebd337ef6aeb975e354 Mon Sep 17 00:00:00 2001 From: Marcelo Zimbres Date: Mon, 15 Nov 2021 23:22:55 +0100 Subject: [PATCH] Missing files. --- examples/containers.cpp | 63 ++++++++++++++++++++ examples/custom_response1.cpp | 101 +++++++++++++++++++++++++++++++ examples/custom_response2.cpp | 108 ++++++++++++++++++++++++++++++++++ 3 files changed, 272 insertions(+) create mode 100644 examples/containers.cpp create mode 100644 examples/custom_response1.cpp create mode 100644 examples/custom_response2.cpp diff --git a/examples/containers.cpp b/examples/containers.cpp new file mode 100644 index 00000000..ddf14fde --- /dev/null +++ b/examples/containers.cpp @@ -0,0 +1,63 @@ +/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include + +#include "types.hpp" +#include "utils.ipp" + +using namespace aedis; + +net::awaitable stl_containers() +{ + std::vector vec + {1, 2, 3, 4, 5, 6}; + + std::set set + {"one", "two", "three"}; + + std::map map + { {"key1", "value1"} + , {"key2", "value2"} + , {"key3", "value3"} + }; + + resp3::request req; + req.push(command::hello, 3); + req.push(command::flushall); + req.push_range(command::rpush, "vector", std::cbegin(vec), std::cend(vec)); + req.push_range(command::sadd, "set", std::cbegin(set), std::cend(set)); + req.push_range(command::hset, "map", std::cbegin(map), std::cend(map)); + + auto socket = co_await make_connection("127.0.0.1", "6379"); + co_await async_write(socket, req); + + std::string buffer; + while (!std::empty(req.commands)) { + resp3::response resp; + co_await async_read(socket, buffer, resp); + + std::cout + << req.commands.front() << ":\n" + << resp << std::endl; + + req.commands.pop(); + } +} + +int main() +{ + net::io_context ioc; + co_spawn(ioc, stl_containers(), net::detached); + ioc.run(); +} diff --git a/examples/custom_response1.cpp b/examples/custom_response1.cpp new file mode 100644 index 00000000..86611f60 --- /dev/null +++ b/examples/custom_response1.cpp @@ -0,0 +1,101 @@ +/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +#include + +#include "types.hpp" +#include "utils.ipp" + +using aedis::command; +using aedis::resp3::type; +using aedis::resp3::request; +using aedis::resp3::response; +using aedis::resp3::async_read; +using aedis::resp3::response_base; + +namespace net = aedis::net; + +/** Illustrates how to write a custom response. Useful to users + * seeking to improve performance and reduce latency. + */ + + +/** A response that parses the result of a response directly in an int + * variable. The same reasoning can be applied for keys containing + * e.g. json strings. + * + */ +struct response_int : response_base { + int result; + + void + add(type t, + std::size_t aggregate_size, + std::size_t depth, + char const* data, + std::size_t data_size) override + { + auto r = std::from_chars(data, data + data_size, result); + if (r.ec == std::errc::invalid_argument) + throw std::runtime_error("from_chars: Unable to convert"); + } +}; + +/// To ignore the reponse of a command use the response base class. +using response_ignore = response_base; + +/** This coroutine avoids reading the response to a get command in a + * temporary buffer by using a custom response. This is always + * possible when the application knows the data type being stored in + * a specific key. + */ +net::awaitable example() +{ + try { + request req; + req.push(command::hello, 3); + + req.push(command::set, "key", 42); + req.push(command::get, "key"); + req.push(command::quit); + + auto socket = co_await make_connection("127.0.0.1", "6379"); + co_await async_write(socket, req); + + std::string buffer; + response_ignore ignore; + + // hello + co_await async_read(socket, buffer, ignore); + + // set + co_await async_read(socket, buffer, ignore); + + // get + response_int int_resp; + co_await async_read(socket, buffer, int_resp); + + std::cout << int_resp.result << std::endl; + + // quit. + co_await async_read(socket, buffer, ignore); + + } catch (std::exception const& e) { + std::cerr << e.what() << std::endl; + } +} + +int main() +{ + net::io_context ioc; + co_spawn(ioc, example(), net::detached); + ioc.run(); +} diff --git a/examples/custom_response2.cpp b/examples/custom_response2.cpp new file mode 100644 index 00000000..b56f40f0 --- /dev/null +++ b/examples/custom_response2.cpp @@ -0,0 +1,108 @@ +/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +#include + +#include "types.hpp" +#include "utils.ipp" + +using aedis::command; +using aedis::resp3::type; +using aedis::resp3::request; +using aedis::resp3::response; +using aedis::resp3::async_read; +using aedis::resp3::response_base; + +namespace net = aedis::net; + +/** Similar to custon_response1 but handles aggregagate data types. + * + * Instead of reading a response into a std::vector and + * then converting to a std::vector we parse the ints form the + * read buffer directly into an int. + */ + +/** A response type that parses the response directly in a + * std::vector + */ +class response_vector : public response_base { +private: + int i_ = 0; + +public: + std::vector result; + + void + add(type t, + std::size_t aggregate_size, + std::size_t depth, + char const* data, + std::size_t data_size) override + { + if (is_aggregate(t)) { + auto const m = element_multiplicity(t); + result.resize(m * aggregate_size); + } else { + auto r = std::from_chars(data, data + data_size, result.at(i_)); + if (r.ec == std::errc::invalid_argument) + throw std::runtime_error("from_chars: Unable to convert"); + ++i_; + } + } +}; + +using response_ignore = response_base; + +net::awaitable ping() +{ + try { + request req; + req.push(command::hello, 3); + + std::vector vec {1, 2, 3, 4, 5, 6}; + req.push_range(command::rpush, "key2", std::cbegin(vec), std::cend(vec)); + + req.push(command::lrange, "key2", 0, -1); + req.push(command::quit); + + auto socket = co_await make_connection("127.0.0.1", "6379"); + co_await async_write(socket, req); + + std::string buffer; + response_ignore ignore; + + // hello + co_await async_read(socket, buffer, ignore); + + // rpush + co_await async_read(socket, buffer, ignore); + + // lrange + response_vector vec_resp; + co_await async_read(socket, buffer, vec_resp); + + for (auto e: vec_resp.result) + std::cout << e << std::endl; + + // quit. + co_await async_read(socket, buffer, ignore); + + } catch (std::exception const& e) { + std::cerr << e.what() << std::endl; + } +} + +int main() +{ + net::io_context ioc; + co_spawn(ioc, ping(), net::detached); + ioc.run(); +}