You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by is...@apache.org on 2022/10/04 08:12:30 UTC
[ignite-3] branch main updated: IGNITE-17426 C++ 3.0: Implement table API (#1154)
This is an automated email from the ASF dual-hosted git repository.
isapego pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new 96139067d6 IGNITE-17426 C++ 3.0: Implement table API (#1154)
96139067d6 is described below
commit 96139067d6215ba6508b10c4fbdaa9b473752a4b
Author: Igor Sapego <is...@apache.org>
AuthorDate: Tue Oct 4 11:12:25 2022 +0300
IGNITE-17426 C++ 3.0: Implement table API (#1154)
---
modules/platforms/cpp/client-test/CMakeLists.txt | 1 +
.../platforms/cpp/client-test/src/gtest_logger.h | 20 +-
.../cpp/client-test/src/ignite_client_test.cpp | 123 +----------
.../src/ignite_runner_suite.h} | 27 +--
modules/platforms/cpp/client-test/src/main.cpp | 12 +-
.../{ignite_client_test.cpp => tables_test.cpp} | 83 ++++---
.../cpp/client/include/ignite/table/tables.h | 15 +-
.../platforms/cpp/client/src/client_operation.h | 3 +
.../platforms/cpp/client/src/cluster_connection.h | 17 +-
modules/platforms/cpp/client/src/ignite_client.cpp | 2 +-
.../platforms/cpp/client/src/node_connection.cpp | 2 +-
modules/platforms/cpp/client/src/node_connection.h | 2 +-
.../platforms/cpp/client/src/response_handler.h | 6 +-
.../platforms/cpp/client/src/table/table_impl.h | 6 +-
modules/platforms/cpp/client/src/table/tables.cpp | 4 +
.../platforms/cpp/client/src/table/tables_impl.cpp | 28 ++-
.../platforms/cpp/client/src/table/tables_impl.h | 12 +-
modules/platforms/cpp/common/factory.h | 22 ++
modules/platforms/cpp/common/guid.h | 239 ---------------------
modules/platforms/cpp/common/ignite_result.h | 192 +++++++----------
modules/platforms/cpp/common/uuid.h | 28 +--
.../include/ignite/network/length_prefix_codec.h | 17 +-
.../include/ignite/protocol/extension_types.h | 2 +-
.../cpp/protocol/include/ignite/protocol/reader.h | 46 +++-
.../cpp/protocol/include/ignite/protocol/utils.h | 48 ++++-
modules/platforms/cpp/protocol/src/reader.cpp | 39 +---
modules/platforms/cpp/protocol/src/utils.cpp | 39 +++-
27 files changed, 401 insertions(+), 634 deletions(-)
diff --git a/modules/platforms/cpp/client-test/CMakeLists.txt b/modules/platforms/cpp/client-test/CMakeLists.txt
index 84cc3d57a8..6a1b98f44d 100644
--- a/modules/platforms/cpp/client-test/CMakeLists.txt
+++ b/modules/platforms/cpp/client-test/CMakeLists.txt
@@ -28,6 +28,7 @@ enable_testing()
set(SOURCES
src/ignite_client_test.cpp
src/main.cpp
+ src/tables_test.cpp
)
add_executable(${TARGET} ${SOURCES})
diff --git a/modules/platforms/cpp/client-test/src/gtest_logger.h b/modules/platforms/cpp/client-test/src/gtest_logger.h
index 5c501c5fdf..ebf9d1fba1 100644
--- a/modules/platforms/cpp/client-test/src/gtest_logger.h
+++ b/modules/platforms/cpp/client-test/src/gtest_logger.h
@@ -17,18 +17,20 @@
#pragma once
+#include "ignite/ignite_logger.h"
+
+#include <gtest/gtest.h>
+
#include <memory>
#include <sstream>
#include <string>
-#include <gtest/gtest.h>
-
namespace ignite {
/**
* Test logger.
*/
-class GtestLogger : public IgniteLogger {
+class gtest_logger : public IgniteLogger {
public:
/**
* Construct.
@@ -36,25 +38,25 @@ public:
* @param includeTs Include timestamps.
* @param debug Enable debug.
*/
- GtestLogger(bool includeTs, bool debug)
+ gtest_logger(bool includeTs, bool debug)
: m_includeTs(includeTs)
, m_debug(debug) { }
void logError(std::string_view message) override {
- std::cout << "[ ] [ ERROR ] " + std::string(message) + '\n' << std::flush;
+ std::cout << "[ ] [ ERROR ] " + get_timestamp() + std::string(message) + '\n' << std::flush;
}
void logWarning(std::string_view message) override {
- std::cout << "[ ] [ WARNING ] " + std::string(message) + '\n' << std::flush;
+ std::cout << "[ ] [ WARNING ] " + get_timestamp() + std::string(message) + '\n' << std::flush;
}
void logInfo(std::string_view message) override {
- std::cout << "[ ] [ INFO ] " + std::string(message) + '\n' << std::flush;
+ std::cout << "[ ] [ INFO ] " + get_timestamp() + std::string(message) + '\n' << std::flush;
}
void logDebug(std::string_view message) override {
if (m_debug)
- std::cout << "[ ] [ DEBUG ] " + std::string(message) + '\n' << std::flush;
+ std::cout << "[ ] [ DEBUG ] " + get_timestamp() + std::string(message) + '\n' << std::flush;
}
private:
@@ -63,7 +65,7 @@ private:
*
* @return Timestamp string.
*/
- [[nodiscard]] std::string getTimestamp() const {
+ [[nodiscard]] std::string get_timestamp() const {
if (!m_includeTs)
return {};
diff --git a/modules/platforms/cpp/client-test/src/ignite_client_test.cpp b/modules/platforms/cpp/client-test/src/ignite_client_test.cpp
index 7abb00898c..ef6f05cde7 100644
--- a/modules/platforms/cpp/client-test/src/ignite_client_test.cpp
+++ b/modules/platforms/cpp/client-test/src/ignite_client_test.cpp
@@ -15,40 +15,25 @@
* limitations under the License.
*/
-#include <chrono>
-#include <string_view>
-#include <thread>
-
-#include <gtest/gtest.h>
+#include "ignite_runner_suite.h"
#include "ignite/ignite_client.h"
#include "ignite/ignite_client_configuration.h"
-#include "gtest_logger.h"
+#include <gtest/gtest.h>
-using namespace ignite;
+#include <chrono>
-static const std::initializer_list<std::string_view> NODE_ADDRS = {"127.0.0.1:10942", "127.0.0.1:10943"};
+using namespace ignite;
/**
* Test suite.
*/
-class ClientTest : public ::testing::Test {
-protected:
- ClientTest() = default;
- ~ClientTest() override = default;
+class client_test : public ignite_runner_suite {};
- /**
- * Get logger.
- *
- * @return Logger for tests.
- */
- static std::shared_ptr<GtestLogger> getLogger() { return std::make_shared<GtestLogger>(true, true); }
-};
-
-TEST_F(ClientTest, GetConfiguration) {
+TEST_F(client_test, get_configuration) {
IgniteClientConfiguration cfg{NODE_ADDRS};
- cfg.setLogger(getLogger());
+ cfg.setLogger(get_logger());
cfg.setConnectionLimit(42);
auto client = IgniteClient::start(cfg, std::chrono::seconds(5));
@@ -58,97 +43,3 @@ TEST_F(ClientTest, GetConfiguration) {
EXPECT_EQ(cfg.getEndpoints(), cfg2.getEndpoints());
EXPECT_EQ(cfg.getConnectionLimit(), cfg2.getConnectionLimit());
}
-
-TEST_F(ClientTest, TablesGetTablePromises) {
- IgniteClientConfiguration cfg{NODE_ADDRS};
- cfg.setLogger(getLogger());
-
- auto clientPromise = std::make_shared<std::promise<IgniteClient>>();
- IgniteClient::startAsync(cfg, std::chrono::seconds(5), ignite_result<IgniteClient>::promise_setter(clientPromise));
-
- auto client = clientPromise->get_future().get();
-
- auto tables = client.getTables();
-
- auto tablePromise = std::make_shared<std::promise<std::optional<Table>>>();
- tables.getTableAsync("PUB.some_unknown", ignite_result<std::optional<Table>>::promise_setter(tablePromise));
-
- auto tableUnknown = tablePromise->get_future().get();
- EXPECT_FALSE(tableUnknown.has_value());
-
- tablePromise = std::make_shared<std::promise<std::optional<Table>>>();
- tables.getTableAsync("PUB.tbl1", ignite_result<std::optional<Table>>::promise_setter(tablePromise));
-
- auto table = tablePromise->get_future().get();
- ASSERT_TRUE(table.has_value());
- EXPECT_EQ(table->getName(), "PUB.tbl1");
-}
-
-template <typename T>
-bool checkAndSetOperationError(std::promise<void> &operation, const ignite_result<T> &res) {
- if (res.has_error()) {
- operation.set_exception(std::make_exception_ptr(res.error()));
- return false;
- }
- if (!res.has_value()) {
- operation.set_exception(std::make_exception_ptr(ignite_error("There is no value in client result")));
- return false;
- }
- return true;
-}
-
-TEST_F(ClientTest, TablesGetTableCallbacks) {
- auto operation0 = std::make_shared<std::promise<void>>();
- auto operation1 = std::make_shared<std::promise<void>>();
- auto operation2 = std::make_shared<std::promise<void>>();
-
- IgniteClientConfiguration cfg{NODE_ADDRS};
- cfg.setLogger(getLogger());
-
- IgniteClient client;
-
- IgniteClient::startAsync(cfg, std::chrono::seconds(5), [&](ignite_result<IgniteClient> clientRes) {
- if (!checkAndSetOperationError(*operation0, clientRes))
- return;
-
- client = std::move(clientRes).value();
- auto tables = client.getTables();
-
- operation0->set_value();
- tables.getTableAsync("PUB.some_unknown", [&](auto tableRes) {
- if (!checkAndSetOperationError(*operation1, tableRes))
- return;
-
- auto tableUnknown = std::move(tableRes).value();
- if (tableUnknown.has_value()) {
- operation1->set_exception(std::make_exception_ptr(ignite_error("Table should be null")));
- return;
- }
-
- operation1->set_value();
- });
-
- tables.getTableAsync("PUB.tbl1", [&](auto tableRes) {
- if (!checkAndSetOperationError(*operation2, tableRes))
- return;
-
- auto table = std::move(tableRes).value();
- if (!table.has_value()) {
- operation2->set_exception(std::make_exception_ptr(ignite_error("Table should not be null")));
- return;
- }
- if (table->getName() != "PUB.tbl1") {
- operation2->set_exception(
- std::make_exception_ptr(ignite_error("Table has unexpected name: " + table->getName())));
- return;
- }
-
- operation2->set_value();
- });
- });
-
- // Waiting for all operations to complete
- operation0->get_future().get();
- operation1->get_future().get();
- operation2->get_future().get();
-}
diff --git a/modules/platforms/cpp/common/factory.h b/modules/platforms/cpp/client-test/src/ignite_runner_suite.h
similarity index 64%
copy from modules/platforms/cpp/common/factory.h
copy to modules/platforms/cpp/client-test/src/ignite_runner_suite.h
index dd58c592d6..4904dc43b4 100644
--- a/modules/platforms/cpp/common/factory.h
+++ b/modules/platforms/cpp/client-test/src/ignite_runner_suite.h
@@ -17,29 +17,30 @@
#pragma once
+#include "gtest_logger.h"
+
+#include <gtest/gtest.h>
+
#include <memory>
namespace ignite {
/**
- * Factory class.
- *
- * @tparam T Instances of this type factory builds.
+ * Test suite.
*/
-template <typename T>
-class factory {
-public:
- /**
- * Destructor.
- */
- virtual ~factory() = default;
+class ignite_runner_suite : public ::testing::Test {
+protected:
+ static constexpr std::initializer_list<std::string_view> NODE_ADDRS = {"127.0.0.1:10942", "127.0.0.1:10943"};
+
+ ignite_runner_suite() = default;
+ ~ignite_runner_suite() override = default;
/**
- * Build instance.
+ * Get logger.
*
- * @return New instance of type @c T.
+ * @return Logger for tests.
*/
- virtual std::unique_ptr<T> build() = 0;
+ static std::shared_ptr<gtest_logger> get_logger() { return std::make_shared<gtest_logger>(false, true); }
};
} // namespace ignite
diff --git a/modules/platforms/cpp/client-test/src/main.cpp b/modules/platforms/cpp/client-test/src/main.cpp
index a61126d273..cbe91c3325 100644
--- a/modules/platforms/cpp/client-test/src/main.cpp
+++ b/modules/platforms/cpp/client-test/src/main.cpp
@@ -15,18 +15,18 @@
* limitations under the License.
*/
-#include <chrono>
-#include <thread>
+#include "ignite_runner.h"
+#include "common/ignite_error.h"
#include <gtest/gtest.h>
-#include "common/ignite_error.h"
-#include "ignite_runner.h"
+#include <chrono>
+#include <thread>
/**
* Run prior to any other tests.
*/
-void BeforeAll() {
+void before_all() {
ignite::IgniteRunner runner;
// Ignite dry run to make sure everything is built, all artifacts downloaded
@@ -40,7 +40,7 @@ void BeforeAll() {
int main(int argc, char **argv) {
int res = 0;
- BeforeAll();
+ before_all();
ignite::IgniteRunner runner;
try {
runner.start(false);
diff --git a/modules/platforms/cpp/client-test/src/ignite_client_test.cpp b/modules/platforms/cpp/client-test/src/tables_test.cpp
similarity index 71%
copy from modules/platforms/cpp/client-test/src/ignite_client_test.cpp
copy to modules/platforms/cpp/client-test/src/tables_test.cpp
index 7abb00898c..fc82788517 100644
--- a/modules/platforms/cpp/client-test/src/ignite_client_test.cpp
+++ b/modules/platforms/cpp/client-test/src/tables_test.cpp
@@ -15,69 +15,43 @@
* limitations under the License.
*/
-#include <chrono>
-#include <string_view>
-#include <thread>
-
-#include <gtest/gtest.h>
+#include "ignite_runner_suite.h"
#include "ignite/ignite_client.h"
#include "ignite/ignite_client_configuration.h"
-#include "gtest_logger.h"
+#include <gtest/gtest.h>
-using namespace ignite;
+#include <algorithm>
+#include <chrono>
+#include <thread>
-static const std::initializer_list<std::string_view> NODE_ADDRS = {"127.0.0.1:10942", "127.0.0.1:10943"};
+using namespace ignite;
/**
* Test suite.
*/
-class ClientTest : public ::testing::Test {
-protected:
- ClientTest() = default;
- ~ClientTest() override = default;
-
- /**
- * Get logger.
- *
- * @return Logger for tests.
- */
- static std::shared_ptr<GtestLogger> getLogger() { return std::make_shared<GtestLogger>(true, true); }
-};
-
-TEST_F(ClientTest, GetConfiguration) {
- IgniteClientConfiguration cfg{NODE_ADDRS};
- cfg.setLogger(getLogger());
- cfg.setConnectionLimit(42);
-
- auto client = IgniteClient::start(cfg, std::chrono::seconds(5));
-
- const auto &cfg2 = client.getConfiguration();
+class tables_test : public ignite_runner_suite {};
- EXPECT_EQ(cfg.getEndpoints(), cfg2.getEndpoints());
- EXPECT_EQ(cfg.getConnectionLimit(), cfg2.getConnectionLimit());
-}
-
-TEST_F(ClientTest, TablesGetTablePromises) {
+TEST_F(tables_test, tables_get_table_async_promises) {
IgniteClientConfiguration cfg{NODE_ADDRS};
- cfg.setLogger(getLogger());
+ cfg.setLogger(get_logger());
auto clientPromise = std::make_shared<std::promise<IgniteClient>>();
- IgniteClient::startAsync(cfg, std::chrono::seconds(5), ignite_result<IgniteClient>::promise_setter(clientPromise));
+ IgniteClient::startAsync(cfg, std::chrono::seconds(5), result_promise_setter(clientPromise));
auto client = clientPromise->get_future().get();
auto tables = client.getTables();
auto tablePromise = std::make_shared<std::promise<std::optional<Table>>>();
- tables.getTableAsync("PUB.some_unknown", ignite_result<std::optional<Table>>::promise_setter(tablePromise));
+ tables.getTableAsync("PUB.some_unknown", result_promise_setter(tablePromise));
auto tableUnknown = tablePromise->get_future().get();
EXPECT_FALSE(tableUnknown.has_value());
tablePromise = std::make_shared<std::promise<std::optional<Table>>>();
- tables.getTableAsync("PUB.tbl1", ignite_result<std::optional<Table>>::promise_setter(tablePromise));
+ tables.getTableAsync("PUB.tbl1", result_promise_setter(tablePromise));
auto table = tablePromise->get_future().get();
ASSERT_TRUE(table.has_value());
@@ -85,7 +59,7 @@ TEST_F(ClientTest, TablesGetTablePromises) {
}
template <typename T>
-bool checkAndSetOperationError(std::promise<void> &operation, const ignite_result<T> &res) {
+bool check_and_set_operation_error(std::promise<void> &operation, const ignite_result<T> &res) {
if (res.has_error()) {
operation.set_exception(std::make_exception_ptr(res.error()));
return false;
@@ -97,18 +71,18 @@ bool checkAndSetOperationError(std::promise<void> &operation, const ignite_resul
return true;
}
-TEST_F(ClientTest, TablesGetTableCallbacks) {
+TEST_F(tables_test, tables_get_table_async_callbacks) {
auto operation0 = std::make_shared<std::promise<void>>();
auto operation1 = std::make_shared<std::promise<void>>();
auto operation2 = std::make_shared<std::promise<void>>();
IgniteClientConfiguration cfg{NODE_ADDRS};
- cfg.setLogger(getLogger());
+ cfg.setLogger(get_logger());
IgniteClient client;
IgniteClient::startAsync(cfg, std::chrono::seconds(5), [&](ignite_result<IgniteClient> clientRes) {
- if (!checkAndSetOperationError(*operation0, clientRes))
+ if (!check_and_set_operation_error(*operation0, clientRes))
return;
client = std::move(clientRes).value();
@@ -116,7 +90,7 @@ TEST_F(ClientTest, TablesGetTableCallbacks) {
operation0->set_value();
tables.getTableAsync("PUB.some_unknown", [&](auto tableRes) {
- if (!checkAndSetOperationError(*operation1, tableRes))
+ if (!check_and_set_operation_error(*operation1, tableRes))
return;
auto tableUnknown = std::move(tableRes).value();
@@ -129,7 +103,7 @@ TEST_F(ClientTest, TablesGetTableCallbacks) {
});
tables.getTableAsync("PUB.tbl1", [&](auto tableRes) {
- if (!checkAndSetOperationError(*operation2, tableRes))
+ if (!check_and_set_operation_error(*operation2, tableRes))
return;
auto table = std::move(tableRes).value();
@@ -152,3 +126,24 @@ TEST_F(ClientTest, TablesGetTableCallbacks) {
operation1->get_future().get();
operation2->get_future().get();
}
+
+TEST_F(tables_test, tables_get_tables_async_promises) {
+ IgniteClientConfiguration cfg{NODE_ADDRS};
+ cfg.setLogger(get_logger());
+
+ auto client = IgniteClient::start(cfg, std::chrono::seconds(5));
+
+ auto tablesApi = client.getTables();
+
+ auto tablesPromise = std::make_shared<std::promise<std::vector<Table>>>();
+ tablesApi.getTablesAsync(result_promise_setter(tablesPromise));
+
+ auto tables = tablesPromise->get_future().get();
+ ASSERT_GT(tables.size(), 0);
+
+ auto it = std::find_if(tables.begin(), tables.end(), [] (auto& table) {
+ return table.getName() == "PUB.TBL1";
+ });
+
+ ASSERT_NE(it, tables.end());
+}
diff --git a/modules/platforms/cpp/client/include/ignite/table/tables.h b/modules/platforms/cpp/client/include/ignite/table/tables.h
index 358a4245de..fad3cadd90 100644
--- a/modules/platforms/cpp/client/include/ignite/table/tables.h
+++ b/modules/platforms/cpp/client/include/ignite/table/tables.h
@@ -57,12 +57,21 @@ public:
* "public.tbl0" - the table "PUBLIC.TBL0" will be looked up,
* "PUBLIC.\"Tbl0\"" - "PUBLIC.Tbl0",
* "\"MySchema\".\"Tbl0\"" - "MySchema.Tbl0", etc.
- * @param callback Callback to be called once operation is complete.
- * @return Table with corresponding name or @c std::nullopt if the table does not exist.
- * @throw ignite_error In case of error.
+ * @param callback Callback to be called once operation is complete. On success, the callback is invoked with
+ * an instance of the table with corresponding name or @c std::nullopt if the table does not exist.
+ * @throw ignite_error In case of error while trying to send a request.
*/
IGNITE_API void getTableAsync(const std::string &name, ignite_callback<std::optional<Table>> callback);
+ /**
+ * Gets all tables.
+ *
+ * @param callback Callback to be called once operation is complete. On success, the callback is invoked with
+ * a vector of all tables.
+ * @throw ignite_error In case of error while trying to send a request.
+ */
+ IGNITE_API void getTablesAsync(ignite_callback<std::vector<Table>> callback);
+
private:
/**
* Constructor
diff --git a/modules/platforms/cpp/client/src/client_operation.h b/modules/platforms/cpp/client/src/client_operation.h
index d186c79b35..298dbf4f69 100644
--- a/modules/platforms/cpp/client/src/client_operation.h
+++ b/modules/platforms/cpp/client/src/client_operation.h
@@ -23,6 +23,9 @@ namespace ignite::detail {
* Client operation code.
*/
enum class ClientOperation {
+ /** Get all tables. */
+ TABLES_GET = 3,
+
/** Get table. */
TABLE_GET = 4,
diff --git a/modules/platforms/cpp/client/src/cluster_connection.h b/modules/platforms/cpp/client/src/cluster_connection.h
index 467942b52a..4a232bb09d 100644
--- a/modules/platforms/cpp/client/src/cluster_connection.h
+++ b/modules/platforms/cpp/client/src/cluster_connection.h
@@ -86,8 +86,6 @@ public:
/**
* Stop connection.
- *
- * @return Future representing finishing of the connection process.
*/
void stop();
@@ -97,8 +95,7 @@ public:
* @tparam T Result type.
* @param op Operation code.
* @param wr Writer function.
- * @param rd Reader function.
- * @return Future result.
+ * @param handler Response handler.
*/
template <typename T>
void performRequest(ClientOperation op, const std::function<void(protocol::Writer &)> &wr,
@@ -114,6 +111,18 @@ public:
}
}
+ /**
+ * Perform request.
+ *
+ * @tparam T Result type.
+ * @param op Operation code.
+ * @param handler Response handler.
+ */
+ template <typename T>
+ void performRequest(ClientOperation op, std::shared_ptr<ResponseHandlerImpl<T>> handler) {
+ performRequest(op, [](protocol::Writer&) {}, std::move(handler));
+ }
+
private:
/**
* Get random node connection.
diff --git a/modules/platforms/cpp/client/src/ignite_client.cpp b/modules/platforms/cpp/client/src/ignite_client.cpp
index d7b09770e7..7b5a0febd7 100644
--- a/modules/platforms/cpp/client/src/ignite_client.cpp
+++ b/modules/platforms/cpp/client/src/ignite_client.cpp
@@ -27,7 +27,7 @@ void IgniteClient::startAsync(IgniteClientConfiguration configuration, std::chro
ignite_callback<IgniteClient> callback) {
// TODO: IGNITE-17762 Async start should not require starting thread internally. Replace with async timer.
(void)std::async([cfg = std::move(configuration), timeout, callback = std::move(callback)]() mutable {
- auto res = ignite_result<IgniteClient>::of_operation(
+ auto res = result_of_operation<IgniteClient>(
[cfg = std::move(cfg), timeout]() { return start(cfg, timeout); });
callback(std::move(res));
});
diff --git a/modules/platforms/cpp/client/src/node_connection.cpp b/modules/platforms/cpp/client/src/node_connection.cpp
index b39bc75e67..5903eabcdb 100644
--- a/modules/platforms/cpp/client/src/node_connection.cpp
+++ b/modules/platforms/cpp/client/src/node_connection.cpp
@@ -30,7 +30,7 @@ NodeConnection::NodeConnection(
NodeConnection::~NodeConnection() {
for (auto &handler : m_requestHandlers) {
- auto handlingRes = ignite_result<void>::of_operation([&]() {
+ auto handlingRes = result_of_operation<void>([&]() {
auto res = handler.second->setError(ignite_error("Connection closed before response was received"));
if (res.has_error())
m_logger->logError(
diff --git a/modules/platforms/cpp/client/src/node_connection.h b/modules/platforms/cpp/client/src/node_connection.h
index d506ca5031..81451b2e29 100644
--- a/modules/platforms/cpp/client/src/node_connection.h
+++ b/modules/platforms/cpp/client/src/node_connection.h
@@ -88,7 +88,7 @@ public:
* @tparam T Result type.
* @param op Operation code.
* @param wr Writer function.
- * @param rd Reader function.
+ * @param handler Response handler.
* @return @c true on success and @c false otherwise.
*/
template <typename T>
diff --git a/modules/platforms/cpp/client/src/response_handler.h b/modules/platforms/cpp/client/src/response_handler.h
index 168c41e59a..127f7998f6 100644
--- a/modules/platforms/cpp/client/src/response_handler.h
+++ b/modules/platforms/cpp/client/src/response_handler.h
@@ -90,8 +90,8 @@ public:
if (!callback)
return {};
- auto res = ignite_result<T>::of_operation([&]() { return m_readFunc(reader); });
- return ignite_result<void>::of_operation([&]() { callback(std::move(res)); });
+ auto res = result_of_operation<T>([&]() { return m_readFunc(reader); });
+ return result_of_operation<void>([&]() { callback(std::move(res)); });
}
/**
@@ -104,7 +104,7 @@ public:
if (!callback)
return {};
- return ignite_result<void>::of_operation([&]() { callback({std::move(err)}); });
+ return result_of_operation<void>([&]() { callback({std::move(err)}); });
}
private:
diff --git a/modules/platforms/cpp/client/src/table/table_impl.h b/modules/platforms/cpp/client/src/table/table_impl.h
index 05225bdce2..9f130e25f9 100644
--- a/modules/platforms/cpp/client/src/table/table_impl.h
+++ b/modules/platforms/cpp/client/src/table/table_impl.h
@@ -21,7 +21,7 @@
#include <memory>
#include <utility>
-#include "common/guid.h"
+#include "common/uuid.h"
namespace ignite::detail {
@@ -46,7 +46,7 @@ public:
* @param name Name.
* @param id ID.
*/
- TableImpl(std::string name, Guid id)
+ TableImpl(std::string name, uuid id)
: m_name(std::move(name))
, m_id(id) { }
@@ -62,7 +62,7 @@ private:
std::string m_name;
/** Table ID. */
- Guid m_id;
+ uuid m_id;
};
} // namespace ignite::detail
diff --git a/modules/platforms/cpp/client/src/table/tables.cpp b/modules/platforms/cpp/client/src/table/tables.cpp
index 40475f706e..4f5d6512dd 100644
--- a/modules/platforms/cpp/client/src/table/tables.cpp
+++ b/modules/platforms/cpp/client/src/table/tables.cpp
@@ -28,6 +28,10 @@ void Tables::getTableAsync(const std::string &name, ignite_callback<std::optiona
getImpl().getTableAsync(name, std::move(callback));
}
+void Tables::getTablesAsync(ignite_callback<std::vector<Table>> callback) {
+ getImpl().getTablesAsync(std::move(callback));
+}
+
Tables::Tables(std::shared_ptr<void> impl)
: m_impl(std::move(impl)) {
}
diff --git a/modules/platforms/cpp/client/src/table/tables_impl.cpp b/modules/platforms/cpp/client/src/table/tables_impl.cpp
index af74fc3a14..a08eb024dd 100644
--- a/modules/platforms/cpp/client/src/table/tables_impl.cpp
+++ b/modules/platforms/cpp/client/src/table/tables_impl.cpp
@@ -15,8 +15,6 @@
* limitations under the License.
*/
-#include "common/utils.h"
-
#include "ignite/protocol/reader.h"
#include "ignite/protocol/writer.h"
#include "table/tables_impl.h"
@@ -28,8 +26,8 @@ void TablesImpl::getTableAsync(const std::string &name, ignite_callback<std::opt
if (reader.tryReadNil())
return std::nullopt;
- auto guid = reader.readGuid();
- auto tableImpl = std::make_shared<TableImpl>(name, guid);
+ auto id = reader.readUuid();
+ auto tableImpl = std::make_shared<TableImpl>(name, id);
return std::make_optional(Table(tableImpl));
};
@@ -41,4 +39,26 @@ void TablesImpl::getTableAsync(const std::string &name, ignite_callback<std::opt
ClientOperation::TABLE_GET, [&name](protocol::Writer &writer) { writer.write(name); }, std::move(handler));
}
+void TablesImpl::getTablesAsync(ignite_callback<std::vector<Table>> callback) {
+ auto readerFunc = [](protocol::Reader &reader) -> std::vector<Table> {
+ if (reader.tryReadNil())
+ return {};
+
+ std::vector<Table> tables;
+ tables.reserve(reader.readMapSize());
+
+ reader.readMap<uuid, std::string>([&tables] (auto&& id, auto&& name) {
+ auto tableImpl = std::make_shared<TableImpl>(std::forward<std::string>(name), std::forward<uuid>(id));
+ tables.push_back(Table{tableImpl});
+ });
+
+ return std::move(tables);
+ };
+
+ auto handler =
+ std::make_shared<ResponseHandlerImpl<std::vector<Table>>>(std::move(readerFunc), std::move(callback));
+
+ m_connection->performRequest(ClientOperation::TABLES_GET, std::move(handler));
+}
+
} // namespace ignite::detail
diff --git a/modules/platforms/cpp/client/src/table/tables_impl.h b/modules/platforms/cpp/client/src/table/tables_impl.h
index 2b1f94da3b..b40eec4054 100644
--- a/modules/platforms/cpp/client/src/table/tables_impl.h
+++ b/modules/platforms/cpp/client/src/table/tables_impl.h
@@ -46,11 +46,19 @@ public:
*
* @param name Table name.
* @param callback Callback.
- * @return TableImpl with corresponding name.
- * @throw ignite_error In case of error.
+ * @throw ignite_error In case of error while trying to send a request.
*/
void getTableAsync(const std::string &name, ignite_callback<std::optional<Table>> callback);
+ /**
+ * Gets all tables.
+ *
+ * @param callback Callback to be called once operation is complete. On success, the callback is invoked with
+ * a vector of all tables.
+ * @throw ignite_error In case of error while trying to send a request.
+ */
+ void getTablesAsync(ignite_callback<std::vector<Table>> callback);
+
private:
/** Cluster connection. */
std::shared_ptr<ClusterConnection> m_connection;
diff --git a/modules/platforms/cpp/common/factory.h b/modules/platforms/cpp/common/factory.h
index dd58c592d6..1da364532f 100644
--- a/modules/platforms/cpp/common/factory.h
+++ b/modules/platforms/cpp/common/factory.h
@@ -42,4 +42,26 @@ public:
virtual std::unique_ptr<T> build() = 0;
};
+/**
+ * Basic factory class.
+ *
+ * @tparam TB Base type.
+ * @tparam TC Concrete type.
+ */
+template <typename TB, typename TC>
+class basic_factory : public factory<TB> {
+public:
+ /**
+ * Destructor.
+ */
+ virtual ~basic_factory() = default;
+
+ /**
+ * Build instance.
+ *
+ * @return New instance of type @c T.
+ */
+ [[nodiscard]] std::unique_ptr<TB> build() override { return std::make_unique<TC>(); }
+};
+
} // namespace ignite
diff --git a/modules/platforms/cpp/common/guid.h b/modules/platforms/cpp/common/guid.h
deleted file mode 100644
index 37ed6b49bb..0000000000
--- a/modules/platforms/cpp/common/guid.h
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file
- * Declares ignite::Guid class.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <iomanip>
-
-namespace ignite {
-
-/**
- * Global universally unique identifier (GUID).
- */
-class Guid {
-public:
- // Default
- Guid() = default;
-
- /**
- * Constructor.
- *
- * @param most Most significant bits.
- * @param least Least significant bits.
- */
- Guid(int64_t most, int64_t least)
- : m_most(most)
- , m_least(least) { }
-
- /**
- * Returns the most significant 64 bits of this instance.
- *
- * @return The most significant 64 bits of this instance.
- */
- [[nodiscard]] std::int64_t getMostSignificantBits() const { return m_most; }
-
- /**
- * Returns the least significant 64 bits of this instance.
- *
- * @return The least significant 64 bits of this instance.
- */
- [[nodiscard]] std::int64_t getLeastSignificantBits() const { return m_least; }
-
- /**
- * The version number associated with this instance. The version
- * number describes how this Guid was generated.
- *
- * The version number has the following meaning:
- * 1 Time-based UUID;
- * 2 DCE security UUID;
- * 3 Name-based UUID;
- * 4 Randomly generated UUID.
- *
- * @return The version number of this instance.
- */
- [[nodiscard]] std::int32_t getVersion() const { return static_cast<int32_t>((m_most >> 12) & 0x0F); }
-
- /**
- * The variant number associated with this instance. The variant
- * number describes the layout of the Guid.
- *
- * The variant number has the following meaning:
- * 0 Reserved for NCS backward compatibility;
- * 2 IETF RFC 4122 (Leach-Salz), used by this class;
- * 6 Reserved, Microsoft Corporation backward compatibility;
- * 7 Reserved for future definition.
- *
- * @return The variant number of this instance.
- */
- [[nodiscard]] std::int32_t getVariant() const {
- auto least = static_cast<uint64_t>(m_least);
- return static_cast<std::int32_t>((least >> (64 - (least >> 62))) & (least >> 63));
- }
-
- /**
- * Compare to another value.
- *
- * @param other Instance to compare to.
- * @return Zero if equals, negative number if less and positive if more.
- */
- [[nodiscard]] std::int64_t compare(const Guid &other) const {
- if (m_most < other.m_most)
- return -1;
-
- if (m_most > other.m_most)
- return 1;
-
- if (m_least < other.m_least)
- return -1;
-
- if (m_least > other.m_least)
- return 1;
-
- return 0;
- }
-
-private:
- /** Most significant bits. */
- std::int64_t m_most{0};
-
- /** Least significant bits. */
- std::int64_t m_least{0};
-};
-
-/**
- * Comparison operator.
- *
- * @param val1 First value.
- * @param val2 Second value.
- * @return True if equal.
- */
-inline bool operator==(const Guid &val1, const Guid &val2) {
- return val1.compare(val2) == 0;
-}
-
-/**
- * Comparison operator.
- *
- * @param val1 First value.
- * @param val2 Second value.
- * @return True if not equal.
- */
-inline bool operator!=(const Guid &val1, const Guid &val2) {
- return val1.compare(val2) != 0;
-}
-
-/**
- * Comparison operator.
- *
- * @param val1 First value.
- * @param val2 Second value.
- * @return True if less.
- */
-inline bool operator<(const Guid &val1, const Guid &val2) {
- return val1.compare(val2) < 0;
-}
-
-/**
- * Comparison operator.
- *
- * @param val1 First value.
- * @param val2 Second value.
- * @return True if less or equal.
- */
-inline bool operator<=(const Guid &val1, const Guid &val2) {
- return val1.compare(val2) <= 0;
-}
-
-/**
- * Comparison operator.
- *
- * @param val1 First value.
- * @param val2 Second value.
- * @return True if greater.
- */
-inline bool operator>(const Guid &val1, const Guid &val2) {
- return val1.compare(val2) > 0;
-}
-
-/**
- * Comparison operator.
- *
- * @param val1 First value.
- * @param val2 Second value.
- * @return True if greater or equal.
- */
-inline bool operator>=(const Guid &val1, const Guid &val2) {
- return val1.compare(val2) >= 0;
-}
-
-/**
- * Output operator.
- *
- * @param os Output stream.
- * @param guid Guid to output.
- * @return Reference to the first param.
- */
-template <typename C>
-::std::basic_ostream<C> &operator<<(std::basic_ostream<C> &os, const Guid &guid) {
- auto part1 = uint32_t(guid.getMostSignificantBits() >> 32);
- auto part2 = uint16_t(guid.getMostSignificantBits() >> 16);
- auto part3 = uint16_t(guid.getMostSignificantBits());
- auto part4 = uint16_t(guid.getLeastSignificantBits() >> 48);
- uint64_t part5 = guid.getLeastSignificantBits() & 0x0000FFFFFFFFFFFFU;
-
- // clang-format off
- os << std::hex
- << std::setfill<C>('0') << std::setw(8) << part1 << '-'
- << std::setfill<C>('0') << std::setw(4) << part2 << '-'
- << std::setfill<C>('0') << std::setw(4) << part3 << '-'
- << std::setfill<C>('0') << std::setw(4) << part4 << '-'
- << std::setfill<C>('0') << std::setw(12) << part5 << std::dec;
- // clang-format on
-
- return os;
-}
-
-/**
- * Input operator.
- *
- * @param is Input stream.
- * @param guid Guid to input.
- * @return Reference to the first param.
- */
-template <typename C>
-::std::basic_istream<C> &operator>>(std::basic_istream<C> &is, Guid &guid) {
- uint64_t parts[5];
-
- C delim;
- for (int i = 0; i < 4; ++i) {
- is >> std::hex >> parts[i] >> delim;
- if (delim != static_cast<C>('-'))
- return is;
- }
-
- is >> std::hex >> parts[4];
- guid = Guid(int64_t((parts[0] << 32) | (parts[1] << 16) | parts[2]), int64_t((parts[3] << 48) | parts[4]));
- return is;
-}
-
-} // namespace ignite
diff --git a/modules/platforms/cpp/common/ignite_result.h b/modules/platforms/cpp/common/ignite_result.h
index 2bbaf3af43..67b3957759 100644
--- a/modules/platforms/cpp/common/ignite_result.h
+++ b/modules/platforms/cpp/common/ignite_result.h
@@ -17,14 +17,15 @@
#pragma once
+#include "common/ignite_error.h"
+
#include <cstdint>
#include <functional>
#include <future>
#include <optional>
+#include <variant>
#include <string>
-#include "common/ignite_error.h"
-
namespace ignite {
/**
@@ -42,8 +43,7 @@ public:
* @param value Value.
*/
ignite_result(T &&value) // NOLINT(google-explicit-constructor)
- : m_value(std::move(value))
- , m_error(std::nullopt) { }
+ : m_value(std::move(value)) { }
/**
* Constructor.
@@ -51,22 +51,21 @@ public:
* @param message Message.
*/
ignite_result(ignite_error &&error) // NOLINT(google-explicit-constructor)
- : m_value(std::nullopt)
- , m_error(std::move(error)) { }
+ : m_value(std::move(error)) { }
/**
* Has value.
*
* @return @c true if the result has value.
*/
- [[nodiscard]] bool has_value() const noexcept { return m_value.has_value(); }
+ [[nodiscard]] bool has_value() const noexcept { return !has_error(); }
/**
* Has error.
*
* @return @c true if the result has error.
*/
- [[nodiscard]] bool has_error() const noexcept { return m_error.has_value(); }
+ [[nodiscard]] bool has_error() const noexcept { return std::holds_alternative<ignite_error>(m_value); }
/**
* Get value.
@@ -77,7 +76,7 @@ public:
if (!has_value())
throw ignite_error("No value is present in result");
- return std::move(m_value.value());
+ return std::get<T>(std::move(m_value));
}
/**
@@ -89,7 +88,7 @@ public:
if (!has_value())
throw ignite_error("No value is present in result");
- return m_value.value();
+ return std::get<T>(m_value);
}
/**
@@ -101,7 +100,7 @@ public:
if (!has_value())
throw ignite_error("No value is present in result");
- return m_value.value();
+ return std::get<T>(m_value);
}
/**
@@ -113,7 +112,7 @@ public:
if (!has_error())
throw ignite_error("No error is present in result");
- return std::move(m_error.value());
+ return std::move(std::get<ignite_error>(m_value));
}
/**
@@ -125,7 +124,7 @@ public:
if (!has_error())
throw ignite_error("No error is present in result");
- return m_error.value();
+ return std::get<ignite_error>(m_value);
}
/**
@@ -137,68 +136,20 @@ public:
if (!has_error())
throw ignite_error("No error is present in result");
- return m_error.value();
+ return std::get<ignite_error>(m_value);
}
/**
- * Bool operator. Can be used to check result for an error.
+ * Bool operator.
+ * Can be used to check result for an error.
*
* @return @c true if result does not contain error.
*/
explicit operator bool() const noexcept { return !has_error(); }
- /**
- * Wrap operation result in ignite_result.
- * @param operation Operation to wrap.
- * @return ignite_result
- */
- static ignite_result of_operation(const std::function<T()> &operation) noexcept {
- // TODO: IGNITE-17760 Move to common once it's re-factored
- try {
- return {operation()};
- } catch (const ignite_error &err) {
- return {ignite_error(err)};
- } catch (const std::exception &err) {
- std::string msg("Standard library exception is thrown: ");
- msg += err.what();
- return {ignite_error(status_code::GENERIC, msg, std::current_exception())};
- } catch (...) {
- return {ignite_error(status_code::UNKNOWN, "Unknown error is encountered when processing network event",
- std::current_exception())};
- }
- }
-
- /**
- * Return promise setter.
- *
- * @param pr Promise.
- * @return Promise setter.
- */
- static std::function<void(ignite_result<T>)> promise_setter(std::shared_ptr<std::promise<T>> pr) {
- // TODO: IGNITE-17760 Move to common once it's re-factored
- return [pr = std::move(pr)](
- ignite_result<T> &&res) mutable { ignite_result<T>::set_promise(*pr, std::move(res)); };
- }
-
private:
- /**
- * Set promise from result.
- *
- * @param pr Promise to set.
- */
- static void set_promise(std::promise<T> &pr, ignite_result res) {
- if (res.has_error()) {
- pr.set_exception(std::make_exception_ptr(std::move(res.m_error.value())));
- } else {
- pr.set_value(std::move(res.m_value.value()));
- }
- }
-
/** Value. */
- std::optional<T> m_value;
-
- /** Error. */
- std::optional<ignite_error> m_error;
+ std::variant<ignite_error, T> m_value;
};
/**
@@ -218,9 +169,8 @@ public:
*
* @param message Message.
*/
- ignite_result(ignite_error &&error)
- : // NOLINT(google-explicit-constructor)
- m_error(std::move(error)) { }
+ ignite_result(ignite_error &&error) // NOLINT(google-explicit-constructor)
+ : m_error(std::move(error)) { }
/**
* Has error.
@@ -254,65 +204,81 @@ public:
}
/**
- * Bool operator. Can be used to check result for an error.
+ * Bool operator.
+ * Can be used to check result for an error.
*
* @return @c true if result does not contain error.
*/
explicit operator bool() const noexcept { return !has_error(); }
- /**
- * Wrap operation result in ignite_result.
- * @param operation Operation to wrap.
- * @return ignite_result
- */
- static ignite_result of_operation(const std::function<void()> &operation) noexcept {
- // TODO: IGNITE-17760 Move to common once it's re-factored
- try {
+
+private:
+ /** Error. */
+ std::optional<ignite_error> m_error;
+};
+
+template <typename T>
+using ignite_callback = std::function<void(ignite_result<T> &&)>;
+
+/**
+ * Wrap operation result in ignite_result.
+ *
+ * @param operation Operation to wrap.
+ * @return ignite_result
+ */
+template <typename T>
+ignite_result<T> result_of_operation(const std::function<T()> &operation) noexcept {
+ // TODO: IGNITE-17760 Move to common once it's re-factored
+ try {
+ if constexpr (std::is_same<decltype(operation()), void>::value) {
operation();
return {};
- } catch (const ignite_error &err) {
- return {ignite_error(err)};
- } catch (const std::exception &err) {
- std::string msg("Standard library exception is thrown: ");
- msg += err.what();
- return {ignite_error(status_code::GENERIC, msg, std::current_exception())};
- } catch (...) {
- return {ignite_error(status_code::UNKNOWN, "Unknown error is encountered when processing network event",
- std::current_exception())};
+ } else {
+ return {operation()};
}
+ } catch (const ignite_error &err) {
+ return {ignite_error(err)};
+ } catch (const std::exception &err) {
+ std::string msg("Standard library exception is thrown: ");
+ msg += err.what();
+ return {ignite_error(status_code::GENERIC, msg, std::current_exception())};
+ } catch (...) {
+ return {ignite_error(status_code::UNKNOWN, "Unknown error is encountered when processing network event",
+ std::current_exception())};
}
+}
- /**
- * Return promise setter.
- *
- * @param pr Promise.
- * @return Promise setter.
- */
- static std::function<void(ignite_result<void>)> promise_setter(std::shared_ptr<std::promise<void>> pr) {
- // TODO: IGNITE-17760 Move to common once it's re-factored
- return [pr = std::move(pr)](
- ignite_result<void> &&res) mutable { ignite_result<void>::set_promise(*pr, std::move(res)); };
- }
-
-private:
- /**
- * Set promise from result.
- *
- * @param pr Promise to set.
- */
- static void set_promise(std::promise<void> &pr, ignite_result res) {
- if (res.has_error()) {
- pr.set_exception(std::make_exception_ptr(std::move(res.m_error.value())));
- } else {
+/**
+ * Set promise from result.
+ *
+ * @param pr Promise to set.
+ * @param res Result to use.
+ */
+template <typename T>
+void result_set_promise(std::promise<T> &pr, ignite_result<T> &&res) {
+ // TODO: IGNITE-17760 Move to common once it's re-factored
+ if (!res) {
+ pr.set_exception(std::make_exception_ptr(std::move(res).error()));
+ } else {
+ if constexpr (std::is_same<T, void>::value) {
pr.set_value();
+ } else {
+ pr.set_value(std::move(res).value());
}
}
+}
- /** Error. */
- std::optional<ignite_error> m_error;
-};
-
+/**
+ * Get promise setter for a promise to be used with ignite result.
+ *
+ * @param pr Promise.
+ * @return Promise setter.
+ */
template <typename T>
-using ignite_callback = std::function<void(ignite_result<T> &&)>;
+std::function<void(ignite_result<T>)> result_promise_setter(std::shared_ptr<std::promise<T>> pr) {
+ // TODO: IGNITE-17760 Move to common once it's re-factored
+ return [pr = std::move(pr)](
+ ignite_result<T> &&res) mutable { result_set_promise<T>(*pr, std::move(res)); };
+}
} // namespace ignite
diff --git a/modules/platforms/cpp/common/uuid.h b/modules/platforms/cpp/common/uuid.h
index f78d4fddbf..848b313e06 100644
--- a/modules/platforms/cpp/common/uuid.h
+++ b/modules/platforms/cpp/common/uuid.h
@@ -51,14 +51,14 @@ public:
*
* @return The most significant 64 bits of this instance.
*/
- constexpr std::int64_t getMostSignificantBits() const noexcept { return most; }
+ [[nodiscard]] constexpr std::int64_t getMostSignificantBits() const noexcept { return most; }
/**
* Returns the least significant 64 bits of this instance.
*
* @return The least significant 64 bits of this instance.
*/
- constexpr std::int64_t getLeastSignificantBits() const noexcept { return least; }
+ [[nodiscard]] constexpr std::int64_t getLeastSignificantBits() const noexcept { return least; }
/**
* The version number associated with this instance. The version
@@ -72,7 +72,7 @@ public:
*
* @return The version number of this instance.
*/
- constexpr std::int32_t version() const noexcept { return static_cast<std::int32_t>((most >> 12) & 0x0f); }
+ [[nodiscard]] constexpr std::int32_t version() const noexcept { return static_cast<std::int32_t>((most >> 12) & 0x0f); }
/**
* The variant number associated with this instance. The variant
@@ -86,8 +86,8 @@ public:
*
* @return The variant number of this instance.
*/
- constexpr std::int32_t variant() const noexcept {
- std::uint64_t least0 = static_cast<uint64_t>(least);
+ [[nodiscard]] constexpr std::int32_t variant() const noexcept {
+ auto least0 = static_cast<uint64_t>(least);
return static_cast<std::int32_t>((least0 >> (64 - (least0 >> 62))) & (least >> 63));
}
@@ -97,7 +97,7 @@ public:
* @param other Instance to compare to.
* @return Zero if equals, negative number if less, and positive if greater.
*/
- constexpr int compare(const uuid &other) const noexcept {
+ [[nodiscard]] constexpr int compare(const uuid &other) const noexcept {
if (most != other.most) {
return most < other.most ? -1 : 1;
}
@@ -190,11 +190,14 @@ constexpr bool operator>=(const uuid &lhs, const uuid &rhs) noexcept {
*/
template <typename C, typename T>
::std::basic_ostream<C, T> &operator<<(std::basic_ostream<C, T> &os, const uuid &uuid) {
- uint32_t part1 = static_cast<uint32_t>(uuid.getMostSignificantBits() >> 32);
- uint16_t part2 = static_cast<uint16_t>(uuid.getMostSignificantBits() >> 16);
- uint16_t part3 = static_cast<uint16_t>(uuid.getMostSignificantBits());
- uint16_t part4 = static_cast<uint16_t>(uuid.getLeastSignificantBits() >> 48);
- uint64_t part5 = uuid.getLeastSignificantBits() & 0x0000FFFFFFFFFFFFU;
+ auto msb = uuid.getMostSignificantBits();
+ auto lsb = uuid.getLeastSignificantBits();
+
+ auto part1 = static_cast<std::uint32_t>(msb >> 32);
+ auto part2 = static_cast<std::uint16_t>(msb >> 16);
+ auto part3 = static_cast<std::uint16_t>(msb);
+ auto part4 = static_cast<std::uint16_t>(lsb >> 48);
+ uint64_t part5 = lsb & 0x0000FFFFFFFFFFFFU;
std::ios_base::fmtflags savedFlags = os.flags();
@@ -240,7 +243,8 @@ template <typename C, typename T>
is.flags(savedFlags);
- result = uuid((parts[0] << 32) | (parts[1] << 16) | parts[2], (parts[3] << 48) | parts[4]);
+ result = uuid(std::int64_t((parts[0] << 32) | (parts[1] << 16) | parts[2]),
+ std::int64_t((parts[3] << 48) | parts[4]));
return is;
}
diff --git a/modules/platforms/cpp/network/include/ignite/network/length_prefix_codec.h b/modules/platforms/cpp/network/include/ignite/network/length_prefix_codec.h
index 07e240604c..2a9b662185 100644
--- a/modules/platforms/cpp/network/include/ignite/network/length_prefix_codec.h
+++ b/modules/platforms/cpp/network/include/ignite/network/length_prefix_codec.h
@@ -86,20 +86,7 @@ private:
bool m_magicReceived;
};
-/**
- * Factory for LengthPrefixCodec.
- */
-class LengthPrefixCodecFactory : public factory<Codec> {
-public:
- // Default
- LengthPrefixCodecFactory() = default;
-
- /**
- * Build instance.
- *
- * @return New instance of type @c T.
- */
- std::unique_ptr<Codec> build() override { return std::make_unique<LengthPrefixCodec>(); }
-};
+/** Factory for LengthPrefixCodec. */
+typedef basic_factory<Codec, LengthPrefixCodec> LengthPrefixCodecFactory;
} // namespace ignite::network
diff --git a/modules/platforms/cpp/protocol/include/ignite/protocol/extension_types.h b/modules/platforms/cpp/protocol/include/ignite/protocol/extension_types.h
index 48102193f6..d6b564b5fb 100644
--- a/modules/platforms/cpp/protocol/include/ignite/protocol/extension_types.h
+++ b/modules/platforms/cpp/protocol/include/ignite/protocol/extension_types.h
@@ -29,7 +29,7 @@ enum class ExtensionTypes : std::int8_t {
DECIMAL = 2,
- GUID = 3,
+ UUID = 3,
DATE = 4,
diff --git a/modules/platforms/cpp/protocol/include/ignite/protocol/reader.h b/modules/platforms/cpp/protocol/include/ignite/protocol/reader.h
index 0686d78b48..135a51bedf 100644
--- a/modules/platforms/cpp/protocol/include/ignite/protocol/reader.h
+++ b/modules/platforms/cpp/protocol/include/ignite/protocol/reader.h
@@ -22,9 +22,11 @@
#include <msgpack.h>
-#include "common/guid.h"
+#include "common/uuid.h"
#include "common/types.h"
+#include "ignite/protocol/utils.h"
+
namespace ignite::protocol {
/**
@@ -87,11 +89,42 @@ public:
[[nodiscard]] std::optional<std::string> readStringNullable();
/**
- * Read GUID.
+ * Read UUID.
+ *
+ * @return UUID value.
+ */
+ [[nodiscard]] uuid readUuid();
+
+ /**
+ * Read Map size.
+ *
+ * @return Map size.
+ */
+ [[nodiscard]] uint32_t readMapSize() const {
+ checkDataInStream();
+
+ if (m_currentVal.data.type != MSGPACK_OBJECT_MAP)
+ throw ignite_error("The value in stream is not a Map");
+
+ return m_currentVal.data.via.map.size;
+ }
+
+ /**
+ * Read Map.
*
- * @return GUID value.
+ * @tparam K Key type.
+ * @tparam V Value type.
+ * @param handler Pair handler.
*/
- [[nodiscard]] Guid readGuid();
+ template<typename K, typename V>
+ void readMap(const std::function<void(K&&, V&&)>& handler) {
+ auto size = readMapSize();
+ for (std::uint32_t i = 0; i < size; ++i) {
+ auto key = unpack_object<K>(m_currentVal.data.via.map.ptr[i].key);
+ auto val = unpack_object<V>(m_currentVal.data.via.map.ptr[i].val);
+ handler(std::move(key), std::move(val));
+ }
+ }
/**
* If the next value is Nil, read it and move reader to the next position.
@@ -114,7 +147,10 @@ private:
/**
* Check whether there is a data in stream and throw ignite_error if there is none.
*/
- void checkDataInStream();
+ void checkDataInStream() const {
+ if (m_moveRes < 0)
+ throw ignite_error("No more data in stream");
+ }
/** Buffer. */
bytes_view m_buffer;
diff --git a/modules/platforms/cpp/protocol/include/ignite/protocol/utils.h b/modules/platforms/cpp/protocol/include/ignite/protocol/utils.h
index 9cc0d9934e..4d97d9df06 100644
--- a/modules/platforms/cpp/protocol/include/ignite/protocol/utils.h
+++ b/modules/platforms/cpp/protocol/include/ignite/protocol/utils.h
@@ -24,11 +24,18 @@
#include <optional>
#include "common/ignite_error.h"
+#include "common/bytes.h"
#include "common/types.h"
+#include "common/uuid.h"
-#include "ignite/protocol/reader.h"
+#include "ignite/protocol/extension_types.h"
+
+struct msgpack_object;
namespace ignite::protocol {
+
+class Reader;
+
/** Magic bytes. */
static constexpr std::array<std::byte, 4> MAGIC_BYTES = {
std::byte('I'), std::byte('G'), std::byte('N'), std::byte('I')};
@@ -187,12 +194,45 @@ inline void writeInt16(int16_t value, std::byte *buffer, size_t offset = 0) {
return writeUint16(std::uint16_t(value), buffer, offset);
}
+template<typename T>
+T unpack_object(const msgpack_object&);
+
+/**
+ * Unpack number.
+ *
+ * @param object MsgPack object.
+ * @return Number.
+ * @throw ignite_error if the object is not a number.
+ */
+template<>
+int64_t unpack_object(const msgpack_object& object);
+
+/**
+ * Unpack string.
+ *
+ * @param object MsgPack object.
+ * @return String.
+ * @throw ignite_error if the object is not a string.
+ */
+template<>
+std::string unpack_object(const msgpack_object& object);
+
+/**
+ * Unpack UUID.
+ *
+ * @param object MsgPack object.
+ * @return UUID.
+ * @throw ignite_error if the object is not a UUID.
+ */
+template<>
+uuid unpack_object(const msgpack_object& object);
+
/**
- * Make random GUID.
+ * Make random UUID.
*
- * @return Random GUID instance.
+ * @return Random UUID instance.
*/
-ignite::Guid makeRandomGuid();
+ignite::uuid makeRandomUuid();
/**
* Read error.
diff --git a/modules/platforms/cpp/protocol/src/reader.cpp b/modules/platforms/cpp/protocol/src/reader.cpp
index ef552f4200..42431fadfa 100644
--- a/modules/platforms/cpp/protocol/src/reader.cpp
+++ b/modules/platforms/cpp/protocol/src/reader.cpp
@@ -16,8 +16,8 @@
*/
#include "common/ignite_error.h"
+#include "common/bytes.h"
-#include "ignite/protocol/extension_types.h"
#include "ignite/protocol/reader.h"
#include "ignite/protocol/utils.h"
@@ -42,12 +42,7 @@ Reader::Reader(bytes_view buffer)
std::int64_t Reader::readInt64() {
checkDataInStream();
- msgpack_object object = m_currentVal.data;
- if (object.type != MSGPACK_OBJECT_NEGATIVE_INTEGER && object.type != MSGPACK_OBJECT_POSITIVE_INTEGER)
- throw ignite_error("The value in stream is not an integer number");
-
- auto res = object.via.i64;
-
+ auto res = unpack_object<int64_t>(m_currentVal.data);
next();
return res;
@@ -56,12 +51,7 @@ std::int64_t Reader::readInt64() {
std::string Reader::readString() {
checkDataInStream();
- msgpack_object object = m_currentVal.data;
- if (object.type != MSGPACK_OBJECT_STR)
- throw ignite_error("The value in stream is not a string");
-
- std::string res{object.via.str.ptr, object.via.str.size};
-
+ std::string res = unpack_object<std::string>(m_currentVal.data);
next();
return res;
@@ -74,24 +64,12 @@ std::optional<std::string> Reader::readStringNullable() {
return readString();
}
-Guid Reader::readGuid() {
+uuid Reader::readUuid() {
checkDataInStream();
- if (m_currentVal.data.type != MSGPACK_OBJECT_EXT
- && m_currentVal.data.via.ext.type != std::int8_t(ExtensionTypes::GUID))
- throw ignite_error("The value in stream is not a GUID");
-
- if (m_currentVal.data.via.ext.size != 16)
- throw ignite_error("Unexpected value size");
-
- auto data = reinterpret_cast<const std::byte *>(m_currentVal.data.via.ext.ptr);
-
- int64_t most = protocol::readInt64(data);
- int64_t least = protocol::readInt64(data, 8);
-
- Guid res(most, least);
-
+ uuid res = unpack_object<uuid>(m_currentVal.data);
next();
+
return res;
}
@@ -109,9 +87,4 @@ void Reader::next() {
m_moveRes = msgpack_unpacker_next(&m_unpacker, &m_currentVal);
}
-void Reader::checkDataInStream() {
- if (m_moveRes < 0)
- throw ignite_error("No more data in stream");
-}
-
} // namespace ignite::protocol
diff --git a/modules/platforms/cpp/protocol/src/utils.cpp b/modules/platforms/cpp/protocol/src/utils.cpp
index 85e02df6e2..7d9eccadfe 100644
--- a/modules/platforms/cpp/protocol/src/utils.cpp
+++ b/modules/platforms/cpp/protocol/src/utils.cpp
@@ -19,11 +19,46 @@
#include <random>
#include <sstream>
+#include <msgpack.h>
+
+#include "ignite/protocol/reader.h"
#include "ignite/protocol/utils.h"
namespace ignite::protocol {
-Guid makeRandomGuid() {
+template<>
+int64_t unpack_object(const msgpack_object &object) {
+ if (object.type != MSGPACK_OBJECT_NEGATIVE_INTEGER && object.type != MSGPACK_OBJECT_POSITIVE_INTEGER)
+ throw ignite_error("The value in stream is not an integer number");
+
+ return object.via.i64;
+}
+
+template<>
+uuid unpack_object(const msgpack_object &object) {
+ if (object.type != MSGPACK_OBJECT_EXT && object.via.ext.type != std::int8_t(ExtensionTypes::UUID))
+ throw ignite_error("The value in stream is not a UUID");
+
+ if (object.via.ext.size != 16)
+ throw ignite_error("Unexpected UUID size: " + std::to_string(object.via.ext.size));
+
+ auto data = reinterpret_cast<const std::byte *>(object.via.ext.ptr);
+
+ auto msb = bytes::load<Endian::LITTLE, int64_t>(data);
+ auto lsb = bytes::load<Endian::LITTLE, int64_t>(data + 8);
+
+ return {msb, lsb};
+}
+
+template<>
+std::string unpack_object(const msgpack_object &object) {
+ if (object.type != MSGPACK_OBJECT_STR)
+ throw ignite_error("The value in stream is not a string");
+
+ return {object.via.str.ptr, object.via.str.size};
+}
+
+uuid makeRandomUuid() {
static std::mutex randomMutex;
static std::random_device rd;
static std::mt19937 gen(rd());
@@ -39,7 +74,7 @@ std::optional<ignite_error> readError(Reader &reader) {
if (reader.tryReadNil())
return std::nullopt;
- Guid traceId = reader.tryReadNil() ? makeRandomGuid() : reader.readGuid();
+ uuid traceId = reader.tryReadNil() ? makeRandomUuid() : reader.readUuid();
int32_t code = reader.tryReadNil() ? 65537 : reader.readInt32();
std::string className = reader.readString();
std::string message = reader.readString();