2
0
mirror of https://github.com/boostorg/redis.git synced 2026-01-19 04:42:09 +00:00

More improvements.

This commit is contained in:
Marcelo Zimbres
2021-12-18 23:00:16 +01:00
parent 790a3cebf9
commit 2d50b93913
14 changed files with 241 additions and 199 deletions

View File

@@ -52,10 +52,15 @@ subscriber_SOURCES = $(top_srcdir)/examples/subscriber.cpp
subscriber_CPPFLAGS = $(MY_CPPFLAGS)
subscriber_LDADD = $(MY_LDADD)
noinst_PROGRAMS += containers
containers_SOURCES = $(top_srcdir)/examples/containers.cpp
containers_CPPFLAGS = $(MY_CPPFLAGS)
containers_LDADD = $(MY_LDADD)
noinst_PROGRAMS += sets
sets_SOURCES = $(top_srcdir)/examples/sets.cpp
sets_CPPFLAGS = $(MY_CPPFLAGS)
sets_LDADD = $(MY_LDADD)
noinst_PROGRAMS += maps
maps_SOURCES = $(top_srcdir)/examples/maps.cpp
maps_CPPFLAGS = $(MY_CPPFLAGS)
maps_LDADD = $(MY_LDADD)
noinst_PROGRAMS += serialization
serialization_SOURCES = $(top_srcdir)/examples/serialization.cpp

View File

@@ -5,10 +5,10 @@
<tab type="mainpage" visible="yes" title=""/>
<tab type="pages" visible="yes" title="" intro=""/>
<tab type="modules" visible="yes" title="" intro=""/>
<!--tab type="namespaces" visible="yes" title="">
<tab type="namespaces" visible="yes" title="">
<tab type="namespacelist" visible="yes" title="" intro=""/>
<tab type="namespacemembers" visible="yes" title="" intro=""/>
</tab-->
</tab>
<tab type="interfaces" visible="yes" title="">
<tab type="interfacelist" visible="yes" title="" intro=""/>
<tab type="interfaceindex" visible="$ALPHABETICAL_INDEX" title=""/>

View File

@@ -12,8 +12,6 @@
#include <aedis/aedis.hpp>
#include <boost/asio/experimental/awaitable_operators.hpp>
#include "types.hpp"
using namespace aedis::net::experimental::awaitable_operators;
namespace aedis {
@@ -30,6 +28,7 @@ protected:
std::vector<node> push_resp_;
private:
using tcp_socket = net::use_awaitable_t<>::as_default_on_t<net::ip::tcp::socket>;
std::queue<serializer<QueueElem>> srs_;
tcp_socket socket_;
@@ -101,6 +100,7 @@ private:
// server when the connection is lost.
net::awaitable<void> connection_manager()
{
using tcp_resolver = aedis::net::use_awaitable_t<>::as_default_on_t<aedis::net::ip::tcp::resolver>;
for (;;) {
tcp_resolver resolver{socket_.get_executor()};
auto const res = co_await resolver.async_resolve("127.0.0.1", "6379");

View File

@@ -1,115 +0,0 @@
/* 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 <iostream>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <aedis/aedis.hpp>
#include "types.hpp"
#include "utils.ipp"
using aedis::command;
using aedis::resp3::serializer;
using aedis::resp3::async_read;
using aedis::resp3::node;
using aedis::resp3::adapt;
namespace net = aedis::net;
using net::async_write;
using net::buffer;
/** An example on how to serialize containers in a request and read
them back.
*/
std::string make_request()
{
std::set<std::string> set
{"one", "two", "three", "four"};
std::map<std::string, int> map
{ {"key1", 1}
, {"key2", 2}
, {"key3", 3}
};
serializer<command> sr;
sr.push(command::hello, 3);
sr.push(command::flushall);
// Set the containers in some of the redis built-in data structures.
sr.push_range(command::sadd, "key2", std::cbegin(set), std::cend(set));
sr.push_range(command::hset, "key3", std::cbegin(map), std::cend(map));
// Retrieves the containers back from redis.
sr.push(command::smembers, "key2");
sr.push(command::smembers, "key2");
sr.push(command::hgetall, "key3");
return sr.request();
}
net::awaitable<void> containers()
{
try {
auto socket = co_await connect();
// Sends the request to redis.
auto const req = make_request();
co_await async_write(socket, buffer(req));
// The expected responses
int sadd, hset;
std::set<std::string> smembers1;
std::unordered_set<std::string> smembers2;
std::map<std::string, int> hgetall;
// Reads the responses.
std::string buffer;
co_await async_read(socket, buffer); // hello
co_await async_read(socket, buffer); // flushall
co_await async_read(socket, buffer, adapt(sadd)); // sadd
co_await async_read(socket, buffer, adapt(hset)); // hset
co_await async_read(socket, buffer, adapt(smembers1)); // smembers
co_await async_read(socket, buffer, adapt(smembers2)); // smembers
co_await async_read(socket, buffer, adapt(hgetall)); // hgetall
// Prints the responses.
std::cout
<< "sadd: " << sadd << "\n"
<< "hset: " << hset << "\n"
;
std::cout << "smembers1: ";
for (auto const& e: smembers1) std::cout << e << " ";
std::cout << std::endl;
std::cout << "smembers2: ";
for (auto const& e: smembers2) std::cout << e << " ";
std::cout << std::endl;
std::cout << "hgetall: ";
for (auto const& e: hgetall) std::cout << e.first << " ==> " << e.second << "; ";
std::cout << std::endl;
} catch (std::exception const& e) {
std::cerr << e.what() << std::endl;
}
}
int main()
{
net::io_context ioc;
co_spawn(ioc, containers(), net::detached);
ioc.run();
}
/// \example containers.cpp

View File

@@ -5,84 +5,69 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include <string>
#include <iostream>
#include <charconv>
#include <aedis/aedis.hpp>
#include "types.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <deque>
#include "utils.ipp"
using aedis::command;
using aedis::resp3::type;
using aedis::resp3::serializer;
using aedis::resp3::async_read;
using aedis::resp3::node;
using aedis::resp3::adapt;
namespace net = aedis::net;
using net::async_write;
using net::buffer;
std::string make_request()
{
std::vector<int> vec {1, 2, 3, 4, 5, 6};
serializer<command> sr;
sr.push(command::hello, 3);
sr.push_range(command::rpush, "key2", std::cbegin(vec), std::cend(vec));
sr.push(command::lrange, "key2", 0, -1);
sr.push(command::lrange, "key2", 0, -1);
sr.push(command::lrange, "key2", 0, -1);
sr.push(command::lrange, "key2", 0, -1);
sr.push(command::lrange, "key2", 0, -1);
sr.push(command::lrange, "key2", 0, -1);
sr.push(command::quit);
return sr.request();
}
net::awaitable<void> ping()
{
try {
auto socket = co_await connect();
auto req = make_request();
co_await async_write(socket, buffer(req));
// Responses.
// The request.
std::vector<int> vec {1, 2, 3, 4, 5, 6};
serializer<command> sr;
sr.push(command::hello, 3);
sr.push(command::flushall);
sr.push_range(command::rpush, "key2", std::cbegin(vec), std::cend(vec));
sr.push(command::lrange, "key2", 0, -1);
sr.push(command::lrange, "key2", 0, -1);
sr.push(command::lrange, "key2", 0, -1);
sr.push(command::lrange, "key2", 0, -1);
sr.push(command::quit);
co_await async_write(socket, buffer(sr.request()));
// Responses and strings and ints in different containers.
std::vector<std::string> svec;
std::list<std::string> slist;
std::deque<std::string> sdeq;
std::list<int> list;
std::vector<int> vec;
std::deque<int> deq;
std::vector<int> ivec;
std::string rbuffer;
co_await async_read(socket, rbuffer); // hello
co_await async_read(socket, rbuffer); // flushall
co_await async_read(socket, rbuffer); // rpush
co_await async_read(socket, rbuffer, adapt(svec)); // lrange
co_await async_read(socket, rbuffer, adapt(slist)); // lrange
co_await async_read(socket, rbuffer, adapt(sdeq)); // lrange
co_await async_read(socket, rbuffer, adapt(list)); // lrange
co_await async_read(socket, rbuffer, adapt(vec)); // lrange
co_await async_read(socket, rbuffer, adapt(deq)); // lrange
co_await async_read(socket, rbuffer, adapt(svec));
co_await async_read(socket, rbuffer, adapt(slist));
co_await async_read(socket, rbuffer, adapt(sdeq));
co_await async_read(socket, rbuffer, adapt(ivec));
co_await async_read(socket, rbuffer); // quit.
for (auto e: svec) std::cout << e << " ";
std::cout << std::endl;
for (auto e: slist) std::cout << e << " ";
std::cout << std::endl;
for (auto e: list) std::cout << e << " ";
std::cout << std::endl;
for (auto e: vec) std::cout << e << " ";
std::cout << std::endl;
for (auto e: sdeq) std::cout << e << " ";
std::cout << std::endl;
for (auto e: deq) std::cout << e << " ";
for (auto e: ivec) std::cout << e << " ";
std::cout << std::endl;
co_await async_read(socket, rbuffer); // quit.
} catch (std::exception const& e) {
std::cerr << e.what() << std::endl;
}

90
examples/maps.cpp Normal file
View File

@@ -0,0 +1,90 @@
/* 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 <aedis/aedis.hpp>
#include <iostream>
#include <vector>
#include <map>
#include <unordered_map>
#include "utils.ipp"
using aedis::command;
using aedis::resp3::serializer;
using aedis::resp3::async_read;
using aedis::resp3::adapt;
namespace net = aedis::net;
using net::async_write;
using net::buffer;
/** An example on how to read maps into C++ containers.
*/
net::awaitable<void> containers()
{
try {
auto socket = co_await connect();
std::map<std::string, std::string> map
{ {"key1", "value1"}
, {"key2", "value2"}
, {"key3", "value3"}
};
serializer<command> sr;
sr.push(command::hello, 3);
sr.push(command::flushall);
sr.push_range(command::hset, "key", std::cbegin(map), std::cend(map));
sr.push(command::hgetall, "key");
sr.push(command::hgetall, "key");
sr.push(command::hgetall, "key");
sr.push(command::quit);
co_await async_write(socket, buffer(sr.request()));
// The expected responses
int hset;
std::vector<std::string> hgetall1;
std::map<std::string, std::string> hgetall2;
std::unordered_map<std::string, std::string> hgetall3;
// Reads the responses.
std::string buffer;
co_await async_read(socket, buffer); // hello
co_await async_read(socket, buffer); // flushall
co_await async_read(socket, buffer, adapt(hset));
co_await async_read(socket, buffer, adapt(hgetall1));
co_await async_read(socket, buffer, adapt(hgetall2));
co_await async_read(socket, buffer, adapt(hgetall3));
co_await async_read(socket, buffer);
// Prints the responses.
std::cout << "hset: " << hset << "\n";
std::cout << "hgetall (as vector): ";
for (auto const& e: hgetall1) std::cout << e << ", ";
std::cout << "\n";
std::cout << "hgetall (as map): ";
for (auto const& e: hgetall2) std::cout << e.first << " ==> " << e.second << "; ";
std::cout << "\n";
std::cout << "hgetall (as unordered_map): ";
for (auto const& e: hgetall3) std::cout << e.first << " ==> " << e.second << "; ";
std::cout << "\n";
} catch (std::exception const& e) {
std::cerr << e.what() << std::endl;
}
}
int main()
{
net::io_context ioc;
co_spawn(ioc, containers(), net::detached);
ioc.run();
}
/// \example sets.cpp

View File

@@ -5,13 +5,12 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include <aedis/aedis.hpp>
#include <string>
#include <iostream>
#include <charconv>
#include <aedis/aedis.hpp>
#include "types.hpp"
#include "utils.ipp"
using aedis::command;

87
examples/sets.cpp Normal file
View File

@@ -0,0 +1,87 @@
/* 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 <aedis/aedis.hpp>
#include <iostream>
#include <set>
#include <vector>
#include <unordered_map>
#include "utils.ipp"
using aedis::command;
using aedis::resp3::serializer;
using aedis::resp3::async_read;
using aedis::resp3::adapt;
namespace net = aedis::net;
using net::async_write;
using net::buffer;
/* An example on how to read sets in C++ containers.
*/
net::awaitable<void> containers()
{
try {
auto socket = co_await connect();
std::set<std::string> set
{"one", "two", "three", "four"};
serializer<command> sr;
sr.push(command::hello, 3);
sr.push(command::flushall);
sr.push_range(command::sadd, "key", std::cbegin(set), std::cend(set));
sr.push(command::smembers, "key");
sr.push(command::smembers, "key");
sr.push(command::smembers, "key");
sr.push(command::quit);
co_await async_write(socket, buffer(sr.request()));
// Objects to hold the responses.
int sadd;
std::vector<std::string> smembers1;
std::set<std::string> smembers2;
std::unordered_set<std::string> smembers3;
// Reads the responses.
std::string buffer;
co_await async_read(socket, buffer); // hello
co_await async_read(socket, buffer); // flushall
co_await async_read(socket, buffer, adapt(sadd));
co_await async_read(socket, buffer, adapt(smembers1));
co_await async_read(socket, buffer, adapt(smembers2));
co_await async_read(socket, buffer, adapt(smembers3));
co_await async_read(socket, buffer);
// Prints the responses.
std::cout << "sadd: " << sadd << "\n" ;
std::cout << "smembers (as vector): ";
for (auto const& e: smembers1) std::cout << e << " ";
std::cout << "\n";
std::cout << "smembers (as set): ";
for (auto const& e: smembers2) std::cout << e << " ";
std::cout << "\n";
std::cout << "smembers (as unordered_set): ";
for (auto const& e: smembers3) std::cout << e << " ";
std::cout << "\n";
} catch (std::exception const& e) {
std::cerr << e.what() << std::endl;
}
}
int main()
{
net::io_context ioc;
co_spawn(ioc, containers(), net::detached);
ioc.run();
}
/// \example sets.cpp

View File

@@ -1,14 +0,0 @@
/* 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/.
*/
#pragma once
#include <aedis/aedis.hpp>
using tcp_socket = aedis::net::use_awaitable_t<>::as_default_on_t<aedis::net::ip::tcp::socket>;
using tcp_resolver = aedis::net::use_awaitable_t<>::as_default_on_t<aedis::net::ip::tcp::resolver>;
using timer = aedis::net::use_awaitable_t<>::as_default_on_t<aedis::net::steady_timer>;

View File

@@ -5,11 +5,11 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include <iostream>
#include <aedis/net.hpp>
#include <aedis/aedis.hpp>
#include "types.hpp"
using tcp_socket = aedis::net::use_awaitable_t<>::as_default_on_t<aedis::net::ip::tcp::socket>;
using tcp_resolver = aedis::net::use_awaitable_t<>::as_default_on_t<aedis::net::ip::tcp::resolver>;
using timer = aedis::net::use_awaitable_t<>::as_default_on_t<aedis::net::steady_timer>;
aedis::net::awaitable<tcp_socket>
connect(

View File

@@ -10,7 +10,7 @@
#include <aedis/version.hpp>
#include <aedis/resp3/read.hpp>
#include <aedis/resp3/write.hpp>
#include <aedis/resp3/adapt.hpp>
#include <aedis/resp3/response_traits.hpp>
#include <aedis/resp3/serializer.hpp>
/** \mainpage Aedis

View File

@@ -13,7 +13,7 @@
#include <aedis/resp3/type.hpp>
#include <aedis/resp3/detail/parser.hpp>
#include <aedis/resp3/write.hpp>
#include <aedis/resp3/adapt.hpp>
#include <aedis/resp3/response_traits.hpp>
#include <boost/asio/yield.hpp>
@@ -98,13 +98,13 @@ read(
template <
class AsyncReadStream,
class Storage,
class ResponseAdapter = detail::adapter_ignore,
class ResponseAdapter = response_traits<void>::adapter_type,
class CompletionToken = net::default_completion_token_t<typename AsyncReadStream::executor_type>
>
auto async_read(
AsyncReadStream& stream,
Storage& buffer,
ResponseAdapter adapter = ResponseAdapter{},
ResponseAdapter adapter = adapt(),
CompletionToken&& token =
net::default_completion_token_t<typename AsyncReadStream::executor_type>{})
{

View File

@@ -9,9 +9,7 @@
#include <aedis/command.hpp>
#include <aedis/resp3/type.hpp>
#include <aedis/resp3/node.hpp>
#include <aedis/resp3/serializer.hpp>
#include <aedis/resp3/detail/adapters.hpp>
#include <aedis/resp3/detail/response_adapters.hpp>
#include <set>
#include <unordered_set>
@@ -23,10 +21,9 @@
namespace aedis {
namespace resp3 {
template <class>
struct response_traits;
// Adaptor for some non-aggregate data types.
/** \brief Adapts C++ data structures to resp3 parser.
*
*/
template <class T>
struct response_traits
{
@@ -91,6 +88,14 @@ struct response_traits<std::map<Key, T, Compare, Allocator>>
static auto adapt(response_type& s) noexcept { return adapter_type{s}; }
};
template <class Key, class Hash, class KeyEqual, class Allocator>
struct response_traits<std::unordered_map<Key, Hash, KeyEqual, Allocator>>
{
using response_type = std::unordered_map<Key, Hash, KeyEqual, Allocator>;
using adapter_type = detail::adapter_map<response_type>;
static auto adapt(response_type& s) noexcept { return adapter_type{s}; }
};
template <>
struct response_traits<void>
{