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

Simplifications in the node class.

This commit is contained in:
Marcelo Zimbres
2022-01-05 02:21:22 +01:00
parent 98ebd62d7c
commit f6a4bd4364
13 changed files with 167 additions and 188 deletions

View File

@@ -2,9 +2,9 @@
<!-- Generated by doxygen 1.9.1 -->
<!-- Navigation index tabs for HTML output -->
<navindex>
<tab type="mainpage" visible="yes" title=""/>
<tab type="mainpage" visible="yes" title="Contents"/>
<tab type="pages" visible="no" title="" intro=""/>
<tab type="modules" visible="yes" title="Reference" intro=""/>
<tab type="modules" visible="no" title="Reference" intro=""/>
<tab type="namespaces" visible="no" title="">
<tab type="namespacelist" visible="yes" title="" intro=""/>
<tab type="namespacemembers" visible="yes" title="" intro=""/>

View File

@@ -17,28 +17,29 @@ using namespace aedis::net::experimental::awaitable_operators;
namespace aedis {
namespace resp3 {
/* Example: A general purpose redis client.
/** \brief Example: A general purpose redis client.
* \ingroup classes
This class is meant to be an example. Users are meant to derive
from this class and override
This class is meant to be an example. Users are meant to derive
from this class and override
1. on_event.
2. on_push.
1. on_event.
2. on_push.
The ReponseId type is required to provide the get_command() member
function.
The ReponseId type is required to provide the get_command() member
function.
*/
template <class ResponseId>
class client_base
: public std::enable_shared_from_this<client_base<ResponseId>> {
protected:
// The response used for push types.
/// The response used for push types.
std::vector<node> push_resp_;
private:
// Hello response.
std::vector<node> hello_;
private:
using tcp_socket = net::use_awaitable_t<>::as_default_on_t<net::ip::tcp::socket>;
std::queue<serializer<ResponseId>> srs_;
tcp_socket socket_;
@@ -150,18 +151,18 @@ private:
}
public:
// Constructor.
/// Constructor.
client_base(net::any_io_executor ex)
: socket_{ex}
, timer_{ex}
{ }
// Destructor.
/// Destructor.
virtual ~client_base() { }
/* Starts the client.
/** \brief Starts the client.
*
* Stablishes a connection with the redis server and keeps waiting for messages to send.
* Stablishes a connection with the redis server and keeps waiting for messages to send.
*/
void start()
{
@@ -170,7 +171,7 @@ public:
net::detached);
}
/* \brief Adds commands the requests queue and sends if possible.
/** \brief Adds commands the requests queue and sends if possible.
*
* The filler callable get a request by reference, for example
*
@@ -197,13 +198,13 @@ public:
timer_.cancel_one();
}
/* \brief Called when the response to a specific command is received.
/** \brief Called when the response to a specific command is received.
*
* Override this function to receive events in your derived class.
*/
virtual void on_event(ResponseId) {};
/* \brief Called when server push is received.
/** \brief Called when server push is received.
*
* Override this function to receive push events in the derived class.
*/

View File

@@ -14,12 +14,20 @@
//\tableofcontents
/** \mainpage Manual
/** \mainpage
Some text.
- \subpage usage
- \subpage tutorial
Reference
- \subpage enums
- \subpage classes
- \subpage operators
- \subpage read_write_ops
- \subpage functions
*/
/** \page usage Usage
@@ -50,14 +58,27 @@
* \brief Includes all headers that are necessary in order to use aedis.
*/
/** \defgroup enums Enums.
* \brief All enums defined by this library.
/** \defgroup enums Enums
* \brief Enums defined by this library.
*/
/** \defgroup functions Free functions.
/** \defgroup classes Classes
* \brief Classes defined by this library.
*/
/** \defgroup functions Free functions (other)
* \brief All functions defined by this library.
*/
/** \defgroup classes Classes and structs.
* \brief All classes (and structs) defined by this library.
/** \defgroup read_write_ops Free functions (read/write operations)
* \brief alkjd ajs
*/
/** \defgroup operators Operators
* \brief alkjd ajs
*/

View File

@@ -11,8 +11,8 @@
namespace aedis {
/** \brief Enum of all redis commands.
* \ingroup enums Library enums
/** \brief Redis commands.
* \ingroup enums
*/
enum class command {
/// https://redis.io/commands/acl
@@ -426,19 +426,16 @@ enum class command {
unknown
};
/** \ingroup functions Library functions
* @{
*/
/** Converts a command to a string
/** \brief Converts a command to a string
* \ingroup functions
*
* \param c The command to convert.
*/
char const* to_string(command c);
/// Write the text for a command name to an output stream.
/** \brief Write the text for a command name to an output stream.
* \ingroup operators
*/
std::ostream& operator<<(std::ostream& os, command c);
/*! @} */
} // aedis

View File

@@ -12,11 +12,11 @@
namespace aedis {
namespace resp3 {
/** \brief Creates a void adapter
/** \brief Creates a void response adapter.
\ingroup functions
The adapter returned by this function ignores any data and is
useful to avoid wasting time with responses on which the user is
The adapter returned by this function ignores responses and is
useful to avoid wasting time with responses which the user is
insterested in.
Example usage:

View File

@@ -6,23 +6,21 @@ namespace aedis {
namespace resp3 {
namespace adapter {
/** \brief Error that may occurr while processing a response.
/** \brief Errors that may occurr while processing a response.
* \ingroup enums
*
* The errors that may occurr while processing a response.
*/
enum class error
{
/// Expects a simple RESP3 type but e.g. got an aggregate.
/// Expects a simple RESP3 type but got an e.g. aggregate.
expects_simple_type = 1,
/// Unexpect depth in the response tree.
/// Nested response not supported.
nested_unsupported,
/// RESP3 simple error.
/// Got RESP3 simple error.
simple_error,
/// RESP3 blob_error.
/// Got RESP3 blob_error.
blob_error
};

View File

@@ -7,7 +7,7 @@
namespace aedis {
namespace resp3 {
/** \brief Errors that may occurr when parsing RESP3 messages.
/** \brief RESP3 parsing errors.
* \ingroup enums
*/
enum class error
@@ -21,7 +21,7 @@ enum class error
/// Received less bytes than expected.
unexpected_read_size,
/// The maximum depth of embedded types has beed exceeded.
/// The maximum depth of a nested response was exceeded.
exceeeds_max_nested_depth
};
@@ -53,7 +53,9 @@ std::error_category const& category()
} // detail
/// Converts an error in an std::error_code object.
/** \brief Converts an error in an std::error_code object.
* \ingroup functions
*/
inline
std::error_code make_error_code(error e)
{

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com)
/* Copyright (c) 2019 - 2022 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
@@ -12,43 +12,19 @@
namespace aedis {
namespace resp3 {
void node::dump(std::string& out, dump_format format, int indent) const
std::string to_string(node const& in)
{
switch (format) {
case node::dump_format::raw:
{
out += std::to_string(depth);
out += '\t';
out += to_string(data_type);
out += '\t';
out += std::to_string(aggregate_size);
out += '\t';
if (!is_aggregate(data_type))
out += data;
} break;
case node::dump_format::clean:
{
std::string prefix(indent * depth, ' ');
out += prefix;
if (is_aggregate(data_type)) {
out += "(";
out += to_string(data_type);
out += ")";
if (aggregate_size == 0) {
std::string prefix2(indent * (depth + 1), ' ');
out += "\n";
out += prefix2;
out += "(empty)";
}
} else {
if (std::empty(data))
out += "(empty)";
else
out += data;
}
} break;
default: { }
}
std::string out;
out += std::to_string(in.depth);
out += '\t';
out += to_string(in.data_type);
out += '\t';
out += std::to_string(in.aggregate_size);
out += '\t';
if (!is_aggregate(in.data_type))
out += in.data;
return out;
}
bool operator==(node const& a, node const& b)
@@ -61,17 +37,30 @@ bool operator==(node const& a, node const& b)
std::ostream& operator<<(std::ostream& os, node const& o)
{
std::string res;
o.dump(res, node::dump_format::clean, 3);
os << res;
os << to_string(o);
return os;
}
std::ostream& operator<<(std::ostream& os, std::vector<node> const& r)
{
os << dump(std::cbegin(r), std::cend(r));
os << to_string(r);
return os;
}
std::string to_string(std::vector<node> const& vec)
{
if (std::empty(vec))
return {};
auto begin = std::cbegin(vec);
std::string res;
for (; begin != std::prev(std::cend(vec)); ++begin) {
res += to_string(*begin);
res += '\n';
}
res += to_string(*begin);
return res;
}
} // resp3
} // aedis

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com)
/* Copyright (c) 2019 - 2022 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
@@ -10,6 +10,7 @@
#include <aedis/resp3/type.hpp>
#include <string>
#include <vector>
namespace aedis {
namespace resp3 {
@@ -18,9 +19,7 @@ namespace resp3 {
* \ingroup classes
*/
struct node {
enum class dump_format {raw, clean};
/// The RESP3 type of the data in this node.
/// The RESP3 type of the data in this node.
type data_type;
/// The number of children this node is parent of.
@@ -31,56 +30,34 @@ struct node {
/// The actual data. For aggregate data types this is always empty.
std::string data;
/// Converts the node to a string and appends to out.
void dump(std::string& out, dump_format format = dump_format::raw, int indent = 3) const;
};
/** \ingroup functions
* @{
/** \brief Converts the node to a string.
* \ingroup functions
*/
std::string to_string(node const& obj);
/// Compares a node for equality.
/** \brief Compares a node for equality.
* \ingroup operators
*/
bool operator==(node const& a, node const& b);
/// Writes the node to the stream.
std::ostream& operator<<(std::ostream& os, node const& o);
template <class ForwardIterator>
std::string dump(
ForwardIterator begin,
ForwardIterator end,
node::dump_format format = node::dump_format::clean,
int indent = 3)
{
if (begin == end)
return {};
std::string res;
for (; begin != std::prev(end); ++begin) {
begin->dump(res, format, indent);
res += '\n';
}
begin->dump(res, format, indent);
return res;
}
/// Equality comparison for a node.
bool operator==(node const& a, node const& b);
/** Writes the text representation of node to the output stream.
*
/** \brief Writes the node to the stream.
* \ingroup operators
*
* NOTE: Binary data is not converted to text.
*/
std::ostream& operator<<(std::ostream& os, node const& o);
/** Writes the text representation of the response to the output
* stream the response to the output stream.
/** \brief Writes the response to the output stream
* \ingroup functions
*/
std::string to_string(std::vector<node> const& vec);
/** \brief Writes the response to the output stream
* \ingroup operators
*/
std::ostream& operator<<(std::ostream& os, std::vector<node> const& r);
/*! @} */
} // resp3
} // aedis

View File

@@ -20,11 +20,8 @@
namespace aedis {
namespace resp3 {
/** \ingroup functions
* @{
*/
/** \brief Read the response to a command sychronously.
* \ingroup read_write_ops
*
* This function has to be called once for each command in the
* request until the whole request has been read.
@@ -91,6 +88,7 @@ read(
}
/** \brief Reads the reponse to a command.
* \ingroup read_write_ops
*
* This function has to be called once for each command in the
* request until the whole request has been read.
@@ -121,6 +119,7 @@ read(
}
/** @brief Reads the response to a Redis command asynchronously.
* \ingroup read_write_ops
*
* This function has to be called once for each command in the
* request until the whole request has been read.
@@ -161,6 +160,7 @@ auto async_read(
}
/** \brief Reads the RESP3 type of the next incomming.
* \ingroup read_write_ops
*
* This function won't consume any data from the buffer. The
* completion handler must have the following signature.
@@ -191,8 +191,6 @@ auto async_read_type(
>(detail::type_op<AsyncReadStream, Buffer> {stream, &buffer}, token, stream);
}
/*! @} */
} // resp3
} // aedis

View File

@@ -21,20 +21,18 @@
namespace aedis {
namespace resp3 {
/** @brief Serializers user data into a redis request.
/** @brief Serializes user data into a redis request.
* \ingroup classes
*
* This class offers functions to serialize user data into a redis
* request. A request is composed of one or more redis commands and
* is referred to in the redis documentation as a pipeline, see
* A request is composed of one or more redis commands and is
* referred to in the redis documentation as a pipeline, see
* https://redis.io/topics/pipelining.
*
* The class maintains an internal queue of already added commands to
* assist users processing the response to each individual command
* contained in the request.
*
* The element type of this queue is passed as a template parameter
* in the request class. For example
* This class also maintains an internal queue of already added
* commands to assist users processing the response to each
* individual command contained in the request. The element type of
* this queue is passed as a template parameter in the request class.
* For example
*
* @code
* request<command> req;
@@ -67,7 +65,7 @@ public:
std::queue<ResponseId> commands;
public:
/** Clears the serializer.
/** \brief Clears the serializer.
*
* Note: Already acquired memory won't be released. The is useful
* to reusing memory insteam of allocating again each time.
@@ -82,17 +80,16 @@ public:
*/
auto const& request() const noexcept {return request_;}
/** @brief Appends a new command to end of the request.
/** @brief Appends a new command to the end of the request.
*
* Non-string types will be converted to string by using
* to_string which must be made available by the user.
* to_string, which must be made available by the user.
*/
template <class... Ts>
void push(ResponseId qelem, Ts const&... args)
{
// Note: Should we detect any std::pair in the type in the pack
// to calculate the herader size correctly or let users handle
// this?
// TODO: Should we detect any std::pair in the type in the pack
// to calculate the herader size correctly?
auto constexpr pack_size = sizeof...(Ts);
detail::add_header(request_, 1 + pack_size);
@@ -105,7 +102,7 @@ public:
commands.emplace(qelem);
}
/** @brief Appends a new command to end of the request.
/** @brief Appends a new command to the end of the request.
This overload is useful for commands that have a key. For example
@@ -144,7 +141,7 @@ public:
commands.emplace(qelem);
}
/** @brief Appends a new command to end of the request.
/** @brief Appends a new command to the end of the request.
This overload is useful for commands that don't have a key. For
example

View File

@@ -14,71 +14,70 @@
namespace aedis {
namespace resp3 {
/** \brief Enum that describes the redis data types and some helper functions.
/** \brief RESP3 types
\ingroup enums
This file contains the enum used to identify the redis data type
and some helper functions.
The RESP3 specification can be found at https://github.com/antirez/RESP3/blob/74adea588783e463c7e84793b325b088fe6edd1c/spec.md
The RESP3 full specification can be found at https://github.com/antirez/RESP3/blob/74adea588783e463c7e84793b325b088fe6edd1c/spec.md
*/
enum class type
{ /// Array data type (aggregate).
{ /// Aggregate
array,
/// Push data type (aggregate).
/// Aaggregate
push,
/// Set data type (aggregate).
/// Aggregate
set,
/// Map data type (aggregate).
/// Aggregate
map,
/// Attribute data type (aggregate).
/// Aggregate
attribute,
/// Simple-string data type.
/// Simple
simple_string,
/// Simple-error data type.
/// Simple
simple_error,
/// Number data type.
/// Simple
number,
/// Double data type.
/// Simple
doublean,
/// Boolean data type.
/// Simple
boolean,
/// Big-number data type.
/// Simple
big_number,
/// Null data type.
/// Simple
null,
/// Blob-error data type.
/// Simple
blob_error,
/// Verbatim-string data type.
/// Simple
verbatim_string,
/// Blob-string data type.
/// Simple
blob_string,
/// Streamed-string-part data type.
/// Simple
streamed_string_part,
/// Represents an invalid data type.
invalid,
/// Invalid
invalid
};
/** \ingroup functions
* @{
/** \brief Returns the string representation of the type.
* \ingroup functions
*/
/// Returns the string representation of the type.
char const* to_string(type t);
/// Writes the type to the output stream.
/** \brief Writes the type to the output stream.
* \ingroup operators
*/
std::ostream& operator<<(std::ostream& os, type t);
/// Returns true if the data type is an aggregate.
/** \brief Returns true if the data type is an aggregate.
* \ingroup functions
*/
bool is_aggregate(type t);
/** @brief Returns the element multilicity.
* \ingroup functions
*
* For type map and attribute this value is 2, all other types have 1.
*/
* For type map and attribute this value is 2, all other types have
* 1.
*/
std::size_t element_multiplicity(type t);
/*! @} */
} // resp3
} // aedis

View File

@@ -14,7 +14,7 @@
namespace aedis {
namespace resp3 {
/** \ingroup functions
/** \ingroup read_write_ops
* @{
*/