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/09/09 20:00:41 UTC

[ignite-3] branch ignite-17424 created (now 4dfb667079)

This is an automated email from the ASF dual-hosted git repository.

isapego pushed a change to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


      at 4dfb667079 IGNITE-17424 Tests run

This branch includes the following new commits:

     new 9bbe9dfb69 IGNITE-17424 Project stub
     new b26ca7c06f IGNITE-17424 Fix compilation for MSVC
     new 51fb15c7f0 IGNITE-17424 Basic test stub
     new 2e76d35c09 IGNITE-17424 Basic test utils
     new e07dda1935 IGNITE-17424 Start Ignite node
     new 61c64082a8 IGNITE-17424 Start and stop Ignite node
     new 5b0fc43ef3 IGNITE-17424 Cleanup
     new 713b1988cd IGNITE-17424 Dry-run prior to all tests
     new 4ca5c36ef0 IGNITE-17424 Re-factoring
     new 13ec1bbe94 IGNITE-17424 Re-factoring
     new f97d215260 IGNITE-17424 Add IgniteClientConfiguration
     new 63f137235b IGNITE-17424 IgniteClient implementation stub
     new ba4e87ea7c IGNITE-17424 Re-factoring
     new 04b98b5d7a IGNITE-17424 Add logging support
     new dd73b730b1 IGNITE-17424 Compiles on Windows
     new 5ab37fa54c IGNITE-17424 Links on Windows
     new 4dfb667079 IGNITE-17424 Tests run

The 17 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[ignite-3] 08/17: IGNITE-17424 Dry-run prior to all tests

Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 713b1988cd38f62739f3d7a7722048f9ae0889bc
Author: Igor Sapego <is...@apache.org>
AuthorDate: Tue Aug 30 13:14:15 2022 +0400

    IGNITE-17424 Dry-run prior to all tests
---
 modules/platforms/cpp/client-test/CMakeLists.txt   |  3 +-
 .../ignite_node.h => client-test/src/main.cpp}     | 57 +++++++++-------------
 .../cpp/test-common/include/ignite_node.h          |  9 ++++
 .../platforms/cpp/test-common/include/process.h    | 12 ++++-
 .../platforms/cpp/test-common/src/ignite_node.cpp  | 12 +++--
 modules/platforms/cpp/test-common/src/process.cpp  | 27 +++++++---
 6 files changed, 73 insertions(+), 47 deletions(-)

diff --git a/modules/platforms/cpp/client-test/CMakeLists.txt b/modules/platforms/cpp/client-test/CMakeLists.txt
index 40c4d0df40..34202f707e 100644
--- a/modules/platforms/cpp/client-test/CMakeLists.txt
+++ b/modules/platforms/cpp/client-test/CMakeLists.txt
@@ -27,11 +27,12 @@ include_directories(${GTEST_INCLUDE_DIR})
 
 set(SOURCES
 	src/ignite_client_test.cpp
+	src/main.cpp
 )
 
 add_executable(${TARGET} ${SOURCES})
 
-target_link_libraries(${TARGET} ignite-test-common ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY})
+target_link_libraries(${TARGET} ignite-test-common ${GTEST_LIBRARY})
 
 set(TEST_TARGET IgniteClientTest)
 add_test(NAME ${TEST_TARGET} COMMAND ${TARGET})
diff --git a/modules/platforms/cpp/test-common/include/ignite_node.h b/modules/platforms/cpp/client-test/src/main.cpp
similarity index 55%
copy from modules/platforms/cpp/test-common/include/ignite_node.h
copy to modules/platforms/cpp/client-test/src/main.cpp
index c72ac06777..1f8eeae3d6 100644
--- a/modules/platforms/cpp/test-common/include/ignite_node.h
+++ b/modules/platforms/cpp/client-test/src/main.cpp
@@ -15,39 +15,30 @@
  * limitations under the License.
  */
 
-#pragma once
+#include <chrono>
 
-#include "process.h"
+#include <gtest/gtest.h>
 
-namespace ignite
+#include "ignite_node.h"
+
+void BeforeAll()
 {
-    class IgniteNode
-    {
-    public:
-        /**
-         * Constructor.
-         */
-        IgniteNode() = default;
-
-        /**
-         * Destructor.
-         */
-        ~IgniteNode() = default;
-
-        /**
-         * Start node.
-         *
-         * @param dryRun Perform a dry run. Mostly used to ensure that code is compiled and all artifacts are downloaded.
-         */
-        void start(bool dryRun = false);
-
-        /**
-         * Stop node.
-         */
-        void stop();
-
-    private:
-        /** Underlying process. */
-        std::unique_ptr<Process> process;
-    };
-} // namespace ignite
+    ignite::IgniteNode node;
+
+    // Ignite dry run to make sure everything is built, all artifacts downloaded
+    // and Ignite node is ready to run.
+    node.start(true);
+
+    // Five minutes should be enough but feel free to increase.
+    node.join(std::chrono::minutes(5));
+    node.stop();
+}
+
+
+int main(int argc, char** argv)
+{
+    BeforeAll();
+
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/modules/platforms/cpp/test-common/include/ignite_node.h b/modules/platforms/cpp/test-common/include/ignite_node.h
index c72ac06777..10bc130b2c 100644
--- a/modules/platforms/cpp/test-common/include/ignite_node.h
+++ b/modules/platforms/cpp/test-common/include/ignite_node.h
@@ -17,6 +17,8 @@
 
 #pragma once
 
+#include <chrono>
+
 #include "process.h"
 
 namespace ignite
@@ -46,6 +48,13 @@ namespace ignite
          */
         void stop();
 
+        /**
+         * Join node process.
+         *
+         * @param timeout Timeout.
+         */
+        void join(std::chrono::milliseconds timeout);
+
     private:
         /** Underlying process. */
         std::unique_ptr<Process> process;
diff --git a/modules/platforms/cpp/test-common/include/process.h b/modules/platforms/cpp/test-common/include/process.h
index b2d6d50121..ab45700ccb 100644
--- a/modules/platforms/cpp/test-common/include/process.h
+++ b/modules/platforms/cpp/test-common/include/process.h
@@ -17,6 +17,7 @@
 
 #pragma once
 
+#include <chrono>
 #include <string>
 
 namespace ignite
@@ -44,9 +45,16 @@ namespace ignite
         virtual bool start() = 0;
 
         /**
-         * Stop process.
+         * Kill the process.
          */
-        virtual void stop() = 0;
+        virtual void kill() = 0;
+
+        /**
+         * Join process.
+         *
+         * @param timeout Timeout.
+         */
+        virtual void join(std::chrono::milliseconds timeout) = 0;
 
     protected:
         /**
diff --git a/modules/platforms/cpp/test-common/src/ignite_node.cpp b/modules/platforms/cpp/test-common/src/ignite_node.cpp
index c4c7e8a9d1..560b9f54fd 100644
--- a/modules/platforms/cpp/test-common/src/ignite_node.cpp
+++ b/modules/platforms/cpp/test-common/src/ignite_node.cpp
@@ -52,15 +52,21 @@ namespace ignite
         process = Process::make(command, workDir.string());
         if (!process->start())
         {
-            throw std::runtime_error("Failed to invoke Ignite command: '" + command + "'");
-
             process.reset();
+
+            throw std::runtime_error("Failed to invoke Ignite command: '" + command + "'");
         }
     }
 
     void IgniteNode::stop()
     {
         if (process)
-            process->stop();
+            process->kill();
+    }
+
+    void IgniteNode::join(std::chrono::milliseconds timeout)
+    {
+        if (process)
+            process->join(timeout);
     }
 } // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/test-common/src/process.cpp b/modules/platforms/cpp/test-common/src/process.cpp
index 4620b53aec..4911031bbc 100644
--- a/modules/platforms/cpp/test-common/src/process.cpp
+++ b/modules/platforms/cpp/test-common/src/process.cpp
@@ -18,7 +18,7 @@
 #ifdef WIN32
 #   include <windows.h>
 #   include <tlhelp32.h>
-#endif // WIN32
+#endif
 
 #include <filesystem>
 #include <utility>
@@ -34,7 +34,7 @@ namespace
      * @param processId ID of the parent process.
      * @return Process tree.
      */
-    std::vector<DWORD> getProcessTree(DWORD processId)
+    std::vector<DWORD> getProcessTree(DWORD processId) // NOLINT(misc-no-recursion)
     {
         std::vector<DWORD> children;
         PROCESSENTRY32 pe;
@@ -120,9 +120,9 @@ namespace
         }
 
         /**
-         * Stop process.
+         * Kill the process.
          */
-        void stop() override
+        void kill() override
         {
             std::vector<DWORD> processTree = getProcessTree(info.dwProcessId);
             for (auto procId : processTree)
@@ -137,12 +137,22 @@ namespace
 
             TerminateProcess(info.hProcess, 1);
 
-            WaitForSingleObject( info.hProcess, INFINITE );
-
             CloseHandle( info.hProcess );
             CloseHandle( info.hThread );
         }
 
+        /**
+         * Join process.
+         *
+         * @param timeout Timeout.
+         */
+        void join(std::chrono::milliseconds timeout) override
+        {
+            auto msecs = timeout.count() < 0 ? INFINITE : static_cast<DWORD>(timeout.count());
+
+            WaitForSingleObject(info.hProcess, msecs);
+        }
+
     private:
         /** Running flag. */
         bool running;
@@ -157,8 +167,9 @@ namespace
         PROCESS_INFORMATION info;
     };
 
-#else
-#endif
+#else // #ifdef WIN32
+
+#endif // #ifdef WIN32
 }
 
 namespace ignite


[ignite-3] 03/17: IGNITE-17424 Basic test stub

Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 51fb15c7f03e3e1e8d3bd1656e9a7d703b1c4a41
Author: Igor Sapego <is...@apache.org>
AuthorDate: Sun Aug 28 18:30:12 2022 +0400

    IGNITE-17424 Basic test stub
---
 modules/platforms/cpp/CMakeLists.txt               |  9 +++--
 modules/platforms/cpp/client-test/CMakeLists.txt   |  2 +-
 .../cpp/client-test/src/ignite_client_test.cpp     | 41 ++++++++++++++++++++++
 modules/platforms/cpp/client/CMakeLists.txt        |  2 +-
 modules/platforms/cpp/conanfile.txt                |  5 ++-
 .../platforms/cpp/schema/BinaryTupleBuilder.cpp    |  2 +-
 6 files changed, 53 insertions(+), 8 deletions(-)

diff --git a/modules/platforms/cpp/CMakeLists.txt b/modules/platforms/cpp/CMakeLists.txt
index fd36bf09ab..436c8e847e 100644
--- a/modules/platforms/cpp/CMakeLists.txt
+++ b/modules/platforms/cpp/CMakeLists.txt
@@ -23,6 +23,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
 set(CMAKE_PROJECT_VERSION ${PROJECT_VERSION})
 
+include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
+conan_basic_setup()
+
 #include(GNUInstallDirs)
 set(INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}/ignite)
 
@@ -64,6 +67,8 @@ if (${ENABLE_CLIENT})
 endif()
 
 if (${ENABLE_TESTS})
-    add_subdirectory(test-common)
-    add_subdirectory(client-test)
+	if (${ENABLE_CLIENT})
+		add_subdirectory(test-common)
+    	add_subdirectory(client-test)
+	endif()
 endif()
diff --git a/modules/platforms/cpp/client-test/CMakeLists.txt b/modules/platforms/cpp/client-test/CMakeLists.txt
index 33601b2175..40c4d0df40 100644
--- a/modules/platforms/cpp/client-test/CMakeLists.txt
+++ b/modules/platforms/cpp/client-test/CMakeLists.txt
@@ -31,7 +31,7 @@ set(SOURCES
 
 add_executable(${TARGET} ${SOURCES})
 
-target_link_libraries(${TARGET} ignite-test-common ignite-client ${GTEST_LIBRARY_DEBUG} ${GTEST_MAIN_LIBRARY_DEBUG})
+target_link_libraries(${TARGET} ignite-test-common ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY})
 
 set(TEST_TARGET IgniteClientTest)
 add_test(NAME ${TEST_TARGET} COMMAND ${TARGET})
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 e69de29bb2..416ca4af6b 100644
--- a/modules/platforms/cpp/client-test/src/ignite_client_test.cpp
+++ b/modules/platforms/cpp/client-test/src/ignite_client_test.cpp
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+class ClientTest : public ::testing::Test {
+protected:
+    ClientTest() = default;
+    ~ClientTest() = default;
+
+    void SetUp() override
+    {
+        // Code here will be called immediately after the constructor (right
+        // before each test).
+    }
+
+    void TearDown() override
+    {
+        // Code here will be called immediately after each test (right
+        // before the destructor).
+    }
+};
+
+TEST_F(ClientTest, TestTest)
+{
+    EXPECT_EQ(1, 1);
+}
\ No newline at end of file
diff --git a/modules/platforms/cpp/client/CMakeLists.txt b/modules/platforms/cpp/client/CMakeLists.txt
index 06cce53656..b060a9b051 100644
--- a/modules/platforms/cpp/client/CMakeLists.txt
+++ b/modules/platforms/cpp/client/CMakeLists.txt
@@ -30,7 +30,7 @@ add_library(${TARGET} SHARED ${SOURCES})
 set_target_properties(${TARGET} PROPERTIES VERSION ${CMAKE_PROJECT_VERSION})
 
 if (WIN32)
-    set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME "ignite.client")
+    set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME "ignite-client")
 endif()
 
 target_link_libraries(${TARGET} ignite-common)
diff --git a/modules/platforms/cpp/conanfile.txt b/modules/platforms/cpp/conanfile.txt
index facca55edf..48b519d8a1 100644
--- a/modules/platforms/cpp/conanfile.txt
+++ b/modules/platforms/cpp/conanfile.txt
@@ -1,7 +1,6 @@
 [requires]
-msgpack/3.3.0
+msgpack-cxx/4.1.1
 gtest/1.12.1
 
 [generators]
-CMakeDeps
-CMakeToolchain
\ No newline at end of file
+cmake
\ No newline at end of file
diff --git a/modules/platforms/cpp/schema/BinaryTupleBuilder.cpp b/modules/platforms/cpp/schema/BinaryTupleBuilder.cpp
index 07cf16dde3..e93d6c2f53 100644
--- a/modules/platforms/cpp/schema/BinaryTupleBuilder.cpp
+++ b/modules/platforms/cpp/schema/BinaryTupleBuilder.cpp
@@ -141,7 +141,7 @@ void BinaryTupleBuilder::putDouble(BytesView bytes) {
     if (size != sizeof(float)) {
         putBytes(BytesView{bytes.data(), size});
     } else {
-        float floatValue = value;
+        float floatValue = static_cast<float>(value);
         putBytes(BytesView{reinterpret_cast<std::byte*>(&floatValue), sizeof(float)});
     }
 }


[ignite-3] 01/17: IGNITE-17424 Project stub

Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 9bbe9dfb69cb578ea47c66af7e2a977767119576
Author: Igor Sapego <is...@apache.org>
AuthorDate: Sun Aug 28 14:26:57 2022 +0400

    IGNITE-17424 Project stub
---
 .gitignore                                         |  2 +
 modules/platforms/cpp/CMakeLists.txt               | 44 ++++++++++++++++++----
 .../platforms/cpp/{ => client-test}/CMakeLists.txt | 31 +++++++--------
 .../cpp/client-test/src/ignite_client_test.cpp     |  0
 modules/platforms/cpp/{ => client}/CMakeLists.txt  | 39 ++++++++++---------
 .../cpp/client/include/ignite/ignite_client.h      |  0
 modules/platforms/cpp/client/src/ignite_client.cpp |  0
 modules/platforms/cpp/conanfile.txt                |  7 ++++
 .../platforms/cpp/{ => test-common}/CMakeLists.txt | 30 ++++++---------
 .../platforms/cpp/test-common/include/test_utils.h |  0
 .../platforms/cpp/test-common/src/test_utils.cpp   |  0
 11 files changed, 91 insertions(+), 62 deletions(-)

diff --git a/.gitignore b/.gitignore
index 2db27b173d..316612563b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,3 +17,5 @@ build/
 *.iml
 *.ipr
 out/
+
+modules/platforms/cpp/cmake-build-*
\ No newline at end of file
diff --git a/modules/platforms/cpp/CMakeLists.txt b/modules/platforms/cpp/CMakeLists.txt
index 6aa16d0f6e..c4c3b0e195 100644
--- a/modules/platforms/cpp/CMakeLists.txt
+++ b/modules/platforms/cpp/CMakeLists.txt
@@ -18,24 +18,52 @@
 cmake_minimum_required(VERSION 3.10)
 project(Ignite.C++ VERSION 3 LANGUAGES CXX)
 
-set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD 14)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
-include(GNUInstallDirs)
+set(CMAKE_PROJECT_VERSION ${PROJECT_VERSION})
+
+#include(GNUInstallDirs)
 set(INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}/ignite)
 
 option(ENABLE_ADDRESS_SANITIZER "If address sanitizer is enabled" OFF)
 option(ENABLE_UB_SANITIZER "If undefined behavior sanitizer is enabled" OFF)
+option(ENABLE_CLIENT "Build Ignite.C++ Client module" ON)
+option(ENABLE_TESTS "Build Ignite.C++ tests" OFF)
+option(WARNINGS_AS_ERRORS "Treat warning as errors" OFF)
+
+if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
+	if (ENABLE_ADDRESS_SANITIZER)
+		add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=address>)
+		add_link_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=address>)
+	endif()
+
+	if (ENABLE_UB_SANITIZER)
+		add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=undefined>)
+		add_link_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=undefined>)
+	endif()
+endif()
 
-if (ENABLE_ADDRESS_SANITIZER)
-    add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=address>)
-    add_link_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=address>)
+if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstandalone-debug")
 endif()
 
-if (ENABLE_UB_SANITIZER)
-    add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=undefined>)
-    add_link_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=undefined>)
+if (${WARNINGS_AS_ERRORS})
+    if (MSVC)
+        add_compile_options(/WX)
+    else()
+        add_compile_options(-Wall -Wextra -Werror -Wno-variadic-macros)
+    endif()
 endif()
 
 add_subdirectory(common)
 add_subdirectory(schema)
+
+if (${ENABLE_CLIENT})
+    add_subdirectory(client)
+endif()
+
+if (${ENABLE_TESTS})
+    add_subdirectory(test-common)
+    add_subdirectory(client-test)
+endif()
diff --git a/modules/platforms/cpp/CMakeLists.txt b/modules/platforms/cpp/client-test/CMakeLists.txt
similarity index 50%
copy from modules/platforms/cpp/CMakeLists.txt
copy to modules/platforms/cpp/client-test/CMakeLists.txt
index 6aa16d0f6e..31c54604a6 100644
--- a/modules/platforms/cpp/CMakeLists.txt
+++ b/modules/platforms/cpp/client-test/CMakeLists.txt
@@ -15,27 +15,22 @@
 # limitations under the License.
 #
 
-cmake_minimum_required(VERSION 3.10)
-project(Ignite.C++ VERSION 3 LANGUAGES CXX)
+project(ignite-client-test)
 
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(TARGET ${PROJECT_NAME})
 
-include(GNUInstallDirs)
-set(INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}/ignite)
+include_directories(include src)
 
-option(ENABLE_ADDRESS_SANITIZER "If address sanitizer is enabled" OFF)
-option(ENABLE_UB_SANITIZER "If undefined behavior sanitizer is enabled" OFF)
+enable_testing()
+find_package(gtest REQUIRED)
+include_directories(${GTEST_INCLUDE_DIR})
 
-if (ENABLE_ADDRESS_SANITIZER)
-    add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=address>)
-    add_link_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=address>)
-endif()
+set(SOURCES
+	src/ignite_client_test.cpp
+)
 
-if (ENABLE_UB_SANITIZER)
-    add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=undefined>)
-    add_link_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=undefined>)
-endif()
+add_executable(${TARGET} ${SOURCES})
 
-add_subdirectory(common)
-add_subdirectory(schema)
+target_link_libraries(${TARGET} ignite-test-common ignite-client ${GTEST_LIBRARY_DEBUG} ${GTEST_MAIN_LIBRARY_DEBUG})
+
+add_test(NAME ${TEST_TARGET} COMMAND ${TARGET})
diff --git a/modules/platforms/cpp/client-test/src/ignite_client_test.cpp b/modules/platforms/cpp/client-test/src/ignite_client_test.cpp
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/modules/platforms/cpp/CMakeLists.txt b/modules/platforms/cpp/client/CMakeLists.txt
similarity index 50%
copy from modules/platforms/cpp/CMakeLists.txt
copy to modules/platforms/cpp/client/CMakeLists.txt
index 6aa16d0f6e..06cce53656 100644
--- a/modules/platforms/cpp/CMakeLists.txt
+++ b/modules/platforms/cpp/client/CMakeLists.txt
@@ -15,27 +15,32 @@
 # limitations under the License.
 #
 
-cmake_minimum_required(VERSION 3.10)
-project(Ignite.C++ VERSION 3 LANGUAGES CXX)
+project(ignite-client)
 
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(TARGET ${PROJECT_NAME})
 
-include(GNUInstallDirs)
-set(INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}/ignite)
+include_directories(include src)
 
-option(ENABLE_ADDRESS_SANITIZER "If address sanitizer is enabled" OFF)
-option(ENABLE_UB_SANITIZER "If undefined behavior sanitizer is enabled" OFF)
+set(SOURCES
+	src/ignite_client.cpp
+)
 
-if (ENABLE_ADDRESS_SANITIZER)
-    add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=address>)
-    add_link_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=address>)
-endif()
+add_library(${TARGET} SHARED ${SOURCES})
+
+set_target_properties(${TARGET} PROPERTIES VERSION ${CMAKE_PROJECT_VERSION})
 
-if (ENABLE_UB_SANITIZER)
-    add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=undefined>)
-    add_link_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=undefined>)
+if (WIN32)
+    set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME "ignite.client")
 endif()
 
-add_subdirectory(common)
-add_subdirectory(schema)
+target_link_libraries(${TARGET} ignite-common)
+
+target_include_directories(${TARGET} INTERFACE include)
+
+install(TARGETS ${TARGET} 
+    RUNTIME DESTINATION bin
+    ARCHIVE DESTINATION lib
+    LIBRARY DESTINATION lib
+)
+
+install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_PREFIX}/include FILES_MATCHING PATTERN "*.h*")
\ No newline at end of file
diff --git a/modules/platforms/cpp/client/include/ignite/ignite_client.h b/modules/platforms/cpp/client/include/ignite/ignite_client.h
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/modules/platforms/cpp/client/src/ignite_client.cpp b/modules/platforms/cpp/client/src/ignite_client.cpp
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/modules/platforms/cpp/conanfile.txt b/modules/platforms/cpp/conanfile.txt
new file mode 100644
index 0000000000..facca55edf
--- /dev/null
+++ b/modules/platforms/cpp/conanfile.txt
@@ -0,0 +1,7 @@
+[requires]
+msgpack/3.3.0
+gtest/1.12.1
+
+[generators]
+CMakeDeps
+CMakeToolchain
\ No newline at end of file
diff --git a/modules/platforms/cpp/CMakeLists.txt b/modules/platforms/cpp/test-common/CMakeLists.txt
similarity index 50%
copy from modules/platforms/cpp/CMakeLists.txt
copy to modules/platforms/cpp/test-common/CMakeLists.txt
index 6aa16d0f6e..eb186ba9ca 100644
--- a/modules/platforms/cpp/CMakeLists.txt
+++ b/modules/platforms/cpp/test-common/CMakeLists.txt
@@ -15,27 +15,19 @@
 # limitations under the License.
 #
 
-cmake_minimum_required(VERSION 3.10)
-project(Ignite.C++ VERSION 3 LANGUAGES CXX)
+project(ignite-test-common)
 
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(TARGET ${PROJECT_NAME})
 
-include(GNUInstallDirs)
-set(INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}/ignite)
+#include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${JNI_INCLUDE_DIRS})
+include_directories(include)
 
-option(ENABLE_ADDRESS_SANITIZER "If address sanitizer is enabled" OFF)
-option(ENABLE_UB_SANITIZER "If undefined behavior sanitizer is enabled" OFF)
+set(SOURCES
+	src/test_utils.cpp
+)
 
-if (ENABLE_ADDRESS_SANITIZER)
-    add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=address>)
-    add_link_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=address>)
-endif()
+add_library(${TARGET} OBJECT ${SOURCES})
 
-if (ENABLE_UB_SANITIZER)
-    add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=undefined>)
-    add_link_options($<$<COMPILE_LANGUAGE:CXX>:-fsanitize=undefined>)
-endif()
-
-add_subdirectory(common)
-add_subdirectory(schema)
+set_target_properties(${TARGET} PROPERTIES VERSION ${CMAKE_PROJECT_VERSION})
+set_target_properties(${TARGET} PROPERTIES POSITION_INDEPENDENT_CODE 1)
+target_include_directories(${TARGET} INTERFACE include)
diff --git a/modules/platforms/cpp/test-common/include/test_utils.h b/modules/platforms/cpp/test-common/include/test_utils.h
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/modules/platforms/cpp/test-common/src/test_utils.cpp b/modules/platforms/cpp/test-common/src/test_utils.cpp
new file mode 100644
index 0000000000..e69de29bb2


[ignite-3] 04/17: IGNITE-17424 Basic test utils

Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 2e76d35c09343e7a192909a8ea76adb076902673
Author: Igor Sapego <is...@apache.org>
AuthorDate: Mon Aug 29 11:21:39 2022 +0400

    IGNITE-17424 Basic test utils
---
 modules/platforms/cpp/CMakeLists.txt               | 10 ++-
 modules/platforms/cpp/test-common/CMakeLists.txt   |  3 +-
 .../cpp/test-common/include/ignite_node.h          | 50 +++++++++++++
 .../platforms/cpp/test-common/include/test_utils.h | 36 ++++++++++
 .../platforms/cpp/test-common/src/ignite_node.cpp  | 37 ++++++++++
 .../platforms/cpp/test-common/src/test_utils.cpp   | 83 ++++++++++++++++++++++
 6 files changed, 217 insertions(+), 2 deletions(-)

diff --git a/modules/platforms/cpp/CMakeLists.txt b/modules/platforms/cpp/CMakeLists.txt
index 436c8e847e..54fc4ed113 100644
--- a/modules/platforms/cpp/CMakeLists.txt
+++ b/modules/platforms/cpp/CMakeLists.txt
@@ -26,7 +26,15 @@ set(CMAKE_PROJECT_VERSION ${PROJECT_VERSION})
 include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
 conan_basic_setup()
 
-#include(GNUInstallDirs)
+if (UNIX)
+	include(GNUInstallDirs)
+endif()
+
+if (MSVC)
+	add_compile_options(/source-charset:utf-8 /execution-charset:utf-8)
+	add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS)
+endif()
+
 set(INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}/ignite)
 
 option(ENABLE_ADDRESS_SANITIZER "If address sanitizer is enabled" OFF)
diff --git a/modules/platforms/cpp/test-common/CMakeLists.txt b/modules/platforms/cpp/test-common/CMakeLists.txt
index eb186ba9ca..396ee4ed72 100644
--- a/modules/platforms/cpp/test-common/CMakeLists.txt
+++ b/modules/platforms/cpp/test-common/CMakeLists.txt
@@ -23,7 +23,8 @@ set(TARGET ${PROJECT_NAME})
 include_directories(include)
 
 set(SOURCES
-	src/test_utils.cpp
+        src/ignite_node.cpp
+        src/test_utils.cpp
 )
 
 add_library(${TARGET} OBJECT ${SOURCES})
diff --git a/modules/platforms/cpp/test-common/include/ignite_node.h b/modules/platforms/cpp/test-common/include/ignite_node.h
new file mode 100644
index 0000000000..ad0a889336
--- /dev/null
+++ b/modules/platforms/cpp/test-common/include/ignite_node.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdio>
+
+namespace ignite
+{
+    class IgniteNode
+    {
+    public:
+        /**
+         * Constructor.
+         */
+        IgniteNode() = default;
+
+        /**
+         * Destructor.
+         */
+        ~IgniteNode() = default;
+
+        /**
+         * Start node.
+         */
+        void start();
+
+        /**
+         * Stop node.
+         */
+        void stop();
+
+    private:
+        FILE* file;
+    };
+} // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/test-common/include/test_utils.h b/modules/platforms/cpp/test-common/include/test_utils.h
index e69de29bb2..8905bdbc65 100644
--- a/modules/platforms/cpp/test-common/include/test_utils.h
+++ b/modules/platforms/cpp/test-common/include/test_utils.h
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <string>
+
+namespace ignite
+{
+    /**
+     * Resolve IGNITE_HOME directory. Resolution is performed in several steps:
+     * 1) Check for path provided as argument.
+     * 2) Check for environment variable.
+     * 3) Check for current working directory.
+     * Result of these checks are evaluated based on existence of certain predefined folders inside possible Ignite
+     * home. If they are found, IGNITE_HOME is considered resolved.
+     *
+     * @param path Optional path to check.
+     * @return Resolved Ignite home.
+     */
+    std::string resolveIgniteHome(const std::string& path = "");
+} // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/test-common/src/ignite_node.cpp b/modules/platforms/cpp/test-common/src/ignite_node.cpp
new file mode 100644
index 0000000000..2c2863c122
--- /dev/null
+++ b/modules/platforms/cpp/test-common/src/ignite_node.cpp
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#include <iostream>
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <array>
+
+#include "ignite_node.h"
+
+namespace ignite
+{
+    void IgniteNode::start()
+    {
+
+    }
+
+    void IgniteNode::stop()
+    {
+
+    }
+} // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/test-common/src/test_utils.cpp b/modules/platforms/cpp/test-common/src/test_utils.cpp
index e69de29bb2..3ca15df6d5 100644
--- a/modules/platforms/cpp/test-common/src/test_utils.cpp
+++ b/modules/platforms/cpp/test-common/src/test_utils.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#include <filesystem>
+#include <functional>
+
+#include "test_utils.h"
+
+namespace ignite
+{
+
+    /**
+     * Checks if the path looks like binary release home directory.
+     * Internally checks for presence of core library.
+     * @return @c true if the path looks like binary release home directory.
+     */
+    bool looksLikeBinaryReleaseHome(const std::filesystem::path& path)
+    {
+        std::filesystem::path coreLibPath = path / "libs";
+        if (!is_directory(coreLibPath))
+            return false;
+
+        auto iter = std::filesystem::directory_iterator{coreLibPath};
+        return std::any_of(iter, std::filesystem::end(iter), [](auto entry) {
+            const std::filesystem::path& entryPath = entry.path();
+            if (entryPath.extension() != "jar")
+                return false;
+
+            std::string stem = entryPath.stem().string();
+            return stem.find("ignite-core") == 0;
+        });
+    }
+
+    /**
+     * Checks if the path looks like source release home directory.
+     * Internally checks for presence of core source directory.
+     * @return @c true if the path looks like binary release home directory.
+     */
+    bool looksLikeSourceReleaseHome(const std::filesystem::path& path)
+    {
+        std::filesystem::path coreSourcePath =
+                path / "modules" / "core" / "src" / "main" / "java" / "org" / "apache" / "ignite";
+
+        return std::filesystem::is_directory(coreSourcePath);
+    }
+
+    std::string resolveIgniteHome(const std::string& path)
+    {
+        std::error_code error;
+
+        std::filesystem::path home = std::filesystem::canonical(path, error);
+        if (!error && std::filesystem::is_directory(path))
+            return home.string();
+
+        home = std::filesystem::canonical(std::getenv("IGNITE_HOME"), error);
+        if (!error && std::filesystem::is_directory(home))
+            return home.string();
+
+        home = std::filesystem::current_path();
+        while (!home.empty() && home.has_relative_path())
+        {
+            if (looksLikeBinaryReleaseHome(home) || looksLikeSourceReleaseHome(home))
+                return home.string();
+
+            home = home.parent_path();
+        }
+        return home.string();
+    }
+} // namespace ignite
\ No newline at end of file


[ignite-3] 17/17: IGNITE-17424 Tests run

Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 4dfb667079331cb2a0b1d00cbb875251708f88b1
Author: Igor Sapego <is...@apache.org>
AuthorDate: Thu Sep 8 00:39:32 2022 +0400

    IGNITE-17424 Tests run
---
 modules/platforms/cpp/client-test/CMakeLists.txt   |  2 +-
 .../cpp/client-test/src/ignite_client_test.cpp     | 41 ++++++++++++++++++++--
 modules/platforms/cpp/client/CMakeLists.txt        |  4 +++
 .../cpp/client/include/ignite/ignite_client.h      | 12 +++----
 modules/platforms/cpp/client/src/ignite_client.cpp |  8 ++---
 .../src/ignite_client.cpp => common/Export.h}      | 35 ++++++------------
 6 files changed, 62 insertions(+), 40 deletions(-)

diff --git a/modules/platforms/cpp/client-test/CMakeLists.txt b/modules/platforms/cpp/client-test/CMakeLists.txt
index aae4c83c7e..d78aa2faa1 100644
--- a/modules/platforms/cpp/client-test/CMakeLists.txt
+++ b/modules/platforms/cpp/client-test/CMakeLists.txt
@@ -32,7 +32,7 @@ set(SOURCES
 
 add_executable(${TARGET} ${SOURCES})
 
-target_link_libraries(${TARGET} ignite-test-common ${GTEST_LIBRARY})
+target_link_libraries(${TARGET} ignite-test-common ignite-client ${GTEST_LIBRARY})
 
 set(TEST_TARGET IgniteClientTest)
 add_test(NAME ${TEST_TARGET} COMMAND ${TARGET})
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 7fc40ed724..9982a62698 100644
--- a/modules/platforms/cpp/client-test/src/ignite_client_test.cpp
+++ b/modules/platforms/cpp/client-test/src/ignite_client_test.cpp
@@ -20,12 +20,17 @@
 
 #include <gtest/gtest.h>
 
+#include "ignite/ignite_client_configuration.h"
+#include "ignite/ignite_client.h"
+
 #include "ignite_node.h"
 
+using namespace ignite;
+
 class ClientTest : public ::testing::Test {
 protected:
     ClientTest() = default;
-    ~ClientTest() = default;
+    ~ClientTest() override = default;
 
     void SetUp() override
     {
@@ -40,13 +45,45 @@ protected:
     }
 };
 
+class TestLogger : public IgniteLogger
+{
+public:
+    void logError(std::string_view message) override
+    {
+        std::cout << "ERROR:   " << message << std::endl;
+    }
+
+    void logWarning(std::string_view message) override
+    {
+        std::cout << "WARNING: " << message << std::endl;
+    }
+
+    void logInfo(std::string_view message) override
+    {
+        std::cout << "INFO:    " << message << std::endl;
+    }
+
+    void logDebug(std::string_view message) override
+    {
+        std::cout << "DEBUG:   " << message << std::endl;
+    }
+};
+
 TEST_F(ClientTest, TestTest)
 {
-    ignite::IgniteNode node;
+    IgniteNode node;
 
     node.start();
 
+    // TODO: Implement node startup await
     std::this_thread::sleep_for(std::chrono::seconds(20));
 
+    IgniteClientConfiguration cfg{"127.0.0.1:10942"};
+    cfg.setLogger(std::make_shared<TestLogger>());
+
+    std::cout << "Connecting..." << std::endl;
+
+    auto client = IgniteClient::startAsync(cfg).get();
+
     node.stop();
 }
\ No newline at end of file
diff --git a/modules/platforms/cpp/client/CMakeLists.txt b/modules/platforms/cpp/client/CMakeLists.txt
index f4d5af46b9..fe28b791ae 100644
--- a/modules/platforms/cpp/client/CMakeLists.txt
+++ b/modules/platforms/cpp/client/CMakeLists.txt
@@ -36,6 +36,10 @@ if (WIN32)
     set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME "ignite-client")
 endif()
 
+if (WIN32)
+    add_definitions(-DIGNITE_EXPORTS)
+endif()
+
 target_link_libraries(${TARGET} ignite-common ignite-network ignite-protocol)
 
 target_include_directories(${TARGET} INTERFACE include)
diff --git a/modules/platforms/cpp/client/include/ignite/ignite_client.h b/modules/platforms/cpp/client/include/ignite/ignite_client.h
index 4a8b45d30e..fab15c17dd 100644
--- a/modules/platforms/cpp/client/include/ignite/ignite_client.h
+++ b/modules/platforms/cpp/client/include/ignite/ignite_client.h
@@ -20,16 +20,12 @@
 #include <future>
 #include <memory>
 
+#include "common/export.h"
 #include <ignite/ignite_client_configuration.h>
 
 namespace ignite
 {
 
-namespace impl
-{
-class IgniteClientImpl;
-}
-
 /**
  * Ignite client.
  */
@@ -65,7 +61,7 @@ public:
      * @param configuration Client configuration.
      * @return Future with either Ignite client or exception.
      */
-    static std::future<IgniteClient> startAsync(IgniteClientConfiguration configuration);
+    IGNITE_API static std::future<IgniteClient> startAsync(IgniteClientConfiguration configuration);
 
 private:
     /**
@@ -73,10 +69,10 @@ private:
      *
      * @param impl Implementation
      */
-    explicit IgniteClient(std::unique_ptr<impl::IgniteClientImpl> impl);
+    explicit IgniteClient(std::shared_ptr<void> impl);
 
     /** Implementation. */
-    std::unique_ptr<impl::IgniteClientImpl> m_impl;
+    std::shared_ptr<void> m_impl;
 };
 
 } // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/client/src/ignite_client.cpp b/modules/platforms/cpp/client/src/ignite_client.cpp
index ddb8975344..234b8776d6 100644
--- a/modules/platforms/cpp/client/src/ignite_client.cpp
+++ b/modules/platforms/cpp/client/src/ignite_client.cpp
@@ -22,12 +22,10 @@
 namespace ignite
 {
 
-
 std::future<IgniteClient> IgniteClient::startAsync(IgniteClientConfiguration configuration)
 {
-    return std::async(std::launch::async, [cfg = std::move(configuration)]() {
-
-        auto impl = std::make_unique<impl::IgniteClientImpl>(cfg);
+    return std::async(std::launch::async, [cfg = std::move(configuration)] () mutable {
+        auto impl = std::make_shared<impl::IgniteClientImpl>(std::move(cfg));
 
         impl->start();
 
@@ -35,7 +33,7 @@ std::future<IgniteClient> IgniteClient::startAsync(IgniteClientConfiguration con
     });
 }
 
-IgniteClient::IgniteClient(std::unique_ptr<impl::IgniteClientImpl> impl) :
+IgniteClient::IgniteClient(std::shared_ptr<void> impl) :
     m_impl(std::move(impl)) { }
 
 } // namespace ignite
diff --git a/modules/platforms/cpp/client/src/ignite_client.cpp b/modules/platforms/cpp/common/Export.h
similarity index 59%
copy from modules/platforms/cpp/client/src/ignite_client.cpp
copy to modules/platforms/cpp/common/Export.h
index ddb8975344..f619affdbf 100644
--- a/modules/platforms/cpp/client/src/ignite_client.cpp
+++ b/modules/platforms/cpp/common/Export.h
@@ -15,27 +15,14 @@
  * limitations under the License.
  */
 
-#include "ignite/ignite_client.h"
-
-#include "ignite_client_impl.h"
-
-namespace ignite
-{
-
-
-std::future<IgniteClient> IgniteClient::startAsync(IgniteClientConfiguration configuration)
-{
-    return std::async(std::launch::async, [cfg = std::move(configuration)]() {
-
-        auto impl = std::make_unique<impl::IgniteClientImpl>(cfg);
-
-        impl->start();
-
-        return IgniteClient(std::move(impl));
-    });
-}
-
-IgniteClient::IgniteClient(std::unique_ptr<impl::IgniteClientImpl> impl) :
-    m_impl(std::move(impl)) { }
-
-} // namespace ignite
+#pragma once
+
+#ifdef _WIN32
+#    ifdef IGNITE_EXPORTS
+#        define IGNITE_API __declspec(dllexport)
+#    else
+#        define IGNITE_API __declspec(dllimport)
+#    endif
+#elif
+#    define IGNITE_API
+#endif


[ignite-3] 11/17: IGNITE-17424 Add IgniteClientConfiguration

Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit f97d215260154c6f6880ab0a591d2011135adce0
Author: Igor Sapego <is...@apache.org>
AuthorDate: Tue Aug 30 18:33:24 2022 +0400

    IGNITE-17424 Add IgniteClientConfiguration
---
 .../cpp/client/include/ignite/ignite_client.h      | 41 +++++++++-
 .../include/ignite/ignite_client_configuration.h   | 91 ++++++++++++++++++++++
 modules/platforms/cpp/client/src/ignite_client.cpp |  5 ++
 3 files changed, 135 insertions(+), 2 deletions(-)

diff --git a/modules/platforms/cpp/client/include/ignite/ignite_client.h b/modules/platforms/cpp/client/include/ignite/ignite_client.h
index 03dbfe0ce3..3c47c31641 100644
--- a/modules/platforms/cpp/client/include/ignite/ignite_client.h
+++ b/modules/platforms/cpp/client/include/ignite/ignite_client.h
@@ -17,22 +17,59 @@
 
 #pragma once
 
+#include <future>
+#include <memory>
+
+#include <ignite/ignite_client_configuration.h>
+
 namespace ignite
 {
 
+namespace impl
+{
+class IgniteClientImpl;
+}
+
 /**
  * Ignite client.
  */
 class IgniteClient
 {
 public:
+    // Deleted
     IgniteClient() = delete;
-    IgniteClient(IgniteClient&) = delete;
-    IgniteClient& operator=(IgniteClient&) = delete;
 
+    // Default
+    ~IgniteClient() = default;
+    IgniteClient(IgniteClient&&) = default;
+    IgniteClient(const IgniteClient&) = default;
+    IgniteClient& operator=(IgniteClient&&) = default;
+    IgniteClient& operator=(const IgniteClient&) = default;
 
+    /**
+     * Start client asynchronously.
+     *
+     * Client tries to establish connection to every endpoint. First endpoint is
+     * selected randomly. After that round-robin is used to determine the next
+     * address to establish connection to.
+     *
+     * System means are used to resolve endpoint IP addresses. If more than one
+     * IP address is returned, client attempts to connect to them in random order.
+     *
+     * Only one connection establishment can be in process at the same time.
+     *
+     * Client considered connected to a cluster when there is at least one
+     * connection to any node of the cluster. Upon this event, future will be set
+     * with a usable IgniteClient instance.
+     *
+     * @param configuration Client configuration.
+     * @return Future with either Ignite client or exception.
+     */
+    static std::future<IgniteClient> startAsync(IgniteClientConfiguration configuration);
 
 private:
+    /** Implementation. */
+    std::shared_ptr<impl::IgniteClientImpl> m_impl;
 };
 
 } // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/client/include/ignite/ignite_client_configuration.h b/modules/platforms/cpp/client/include/ignite/ignite_client_configuration.h
new file mode 100644
index 0000000000..3212a0e9cf
--- /dev/null
+++ b/modules/platforms/cpp/client/include/ignite/ignite_client_configuration.h
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <initializer_list>
+#include <string>
+#include <vector>
+
+namespace ignite
+{
+
+/**
+ * Ignite client configuration.
+ */
+class IgniteClientConfiguration
+{
+public:
+    /**
+     * TCP port used by client by default if not specified explicitly.
+     */
+    static constexpr uint16_t DEFAULT_PORT = 10800;
+
+    // Default
+    IgniteClientConfiguration() = default;
+    ~IgniteClientConfiguration() = default;
+    IgniteClientConfiguration(IgniteClientConfiguration&&) = default;
+    IgniteClientConfiguration(const IgniteClientConfiguration&) = default;
+    IgniteClientConfiguration& operator=(IgniteClientConfiguration&&) = default;
+    IgniteClientConfiguration& operator=(const IgniteClientConfiguration&) = default;
+
+    /**
+     * Constructor.
+     *
+     * @param endpoint Endpoints list.
+     */
+    IgniteClientConfiguration(std::initializer_list<std::string> endpoints) :
+        m_endpoints(endpoints) { }
+
+    /**
+     * Get endpoints.
+     *
+     * @see setEndpoints() for more detailed description.
+     *
+     * @return Endpoints.
+     */
+    [[nodiscard]]
+    const std::vector<std::string>& getEndpoints() const
+    {
+        return m_endpoints;
+    }
+
+    /**
+     * Set endpoints.
+     *
+     * Examples of supported formats:
+     * - 192.168.1.25 - Default port is used, see DEFAULT_PORT;
+     * - 192.168.1.25:780 - Custom port;
+     * - 192.168.1.25:780..787  - Custom port range - ports are checked from
+     *      lesser to greater until an open port is found;
+     * - my-host.com - Default port is used, see DEFAULT_PORT;
+     * - my-host.com:780 - Custom port;
+     * - my-host.com:780..787 - Custom port range.
+     *
+     * @param endpoints Endpoints.
+     */
+    void setEndpoints(std::initializer_list<std::string> endpoints)
+    {
+        IgniteClientConfiguration::m_endpoints = endpoints;
+    }
+
+private:
+    /** Endpoints. */
+    std::vector<std::string> m_endpoints;
+};
+
+} // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/client/src/ignite_client.cpp b/modules/platforms/cpp/client/src/ignite_client.cpp
index bcc60eb2c1..e94dd89d1e 100644
--- a/modules/platforms/cpp/client/src/ignite_client.cpp
+++ b/modules/platforms/cpp/client/src/ignite_client.cpp
@@ -20,4 +20,9 @@
 namespace ignite
 {
 
+std::future<IgniteClient> IgniteClient::startAsync(IgniteClientConfiguration configuration)
+{
+    return {};
+}
+
 } // namespace ignite


[ignite-3] 09/17: IGNITE-17424 Re-factoring

Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 4ca5c36ef09aff87b2b676e8ea14a267b473b3cd
Author: Igor Sapego <is...@apache.org>
AuthorDate: Tue Aug 30 17:14:32 2022 +0400

    IGNITE-17424 Re-factoring
---
 modules/platforms/cpp/client-test/src/main.cpp     |   3 +
 .../cpp/client/include/ignite/ignite_client.h      |  38 +++++
 modules/platforms/cpp/client/src/ignite_client.cpp |  23 +++
 modules/platforms/cpp/common/Platform.h            |  12 +-
 modules/platforms/cpp/test-common/CMakeLists.txt   |   3 +-
 .../cpp/test-common/include/ignite_node.h          |  80 +++++-----
 .../platforms/cpp/test-common/include/process.h    |  76 ++++-----
 .../platforms/cpp/test-common/include/test_utils.h |  34 ++--
 .../platforms/cpp/test-common/src/ignite_node.cpp  |  77 ++++-----
 modules/platforms/cpp/test-common/src/process.cpp  | 160 ++-----------------
 .../platforms/cpp/test-common/src/test_utils.cpp   | 112 ++++++-------
 .../cpp/test-common/src/win/win_process.h          | 173 +++++++++++++++++++++
 12 files changed, 461 insertions(+), 330 deletions(-)

diff --git a/modules/platforms/cpp/client-test/src/main.cpp b/modules/platforms/cpp/client-test/src/main.cpp
index 1f8eeae3d6..50dcdff9da 100644
--- a/modules/platforms/cpp/client-test/src/main.cpp
+++ b/modules/platforms/cpp/client-test/src/main.cpp
@@ -21,6 +21,9 @@
 
 #include "ignite_node.h"
 
+/**
+ * Run prior to any other tests.
+ */
 void BeforeAll()
 {
     ignite::IgniteNode node;
diff --git a/modules/platforms/cpp/client/include/ignite/ignite_client.h b/modules/platforms/cpp/client/include/ignite/ignite_client.h
index e69de29bb2..03dbfe0ce3 100644
--- a/modules/platforms/cpp/client/include/ignite/ignite_client.h
+++ b/modules/platforms/cpp/client/include/ignite/ignite_client.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+namespace ignite
+{
+
+/**
+ * Ignite client.
+ */
+class IgniteClient
+{
+public:
+    IgniteClient() = delete;
+    IgniteClient(IgniteClient&) = delete;
+    IgniteClient& operator=(IgniteClient&) = delete;
+
+
+
+private:
+};
+
+} // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/client/src/ignite_client.cpp b/modules/platforms/cpp/client/src/ignite_client.cpp
index e69de29bb2..bcc60eb2c1 100644
--- a/modules/platforms/cpp/client/src/ignite_client.cpp
+++ b/modules/platforms/cpp/client/src/ignite_client.cpp
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+#include "ignite/ignite_client.h"
+
+namespace ignite
+{
+
+} // namespace ignite
diff --git a/modules/platforms/cpp/common/Platform.h b/modules/platforms/cpp/common/Platform.h
index 2901abf986..4955529660 100644
--- a/modules/platforms/cpp/common/Platform.h
+++ b/modules/platforms/cpp/common/Platform.h
@@ -17,6 +17,15 @@
 
 #pragma once
 
+/**
+ * Macro SWITCH_WIN_OTHER that uses first option on Windows and second on any other OS.
+ */
+#ifdef WIN32
+#   define SWITCH_WIN_OTHER(x, y) (x)
+#else
+#   define SWITCH_WIN_OTHER(x, y) (y)
+#endif
+
 #define LITTLE_ENDIAN 1
 #define BIG_ENDIAN 2
 
@@ -29,4 +38,5 @@
 #else
 //TODO: Fix this
 #   define BYTE_ORDER LITTLE_ENDIAN
-#endif
\ No newline at end of file
+#endif
+
diff --git a/modules/platforms/cpp/test-common/CMakeLists.txt b/modules/platforms/cpp/test-common/CMakeLists.txt
index a157d5ed98..92485f7f89 100644
--- a/modules/platforms/cpp/test-common/CMakeLists.txt
+++ b/modules/platforms/cpp/test-common/CMakeLists.txt
@@ -19,7 +19,6 @@ project(ignite-test-common)
 
 set(TARGET ${PROJECT_NAME})
 
-#include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${JNI_INCLUDE_DIRS})
 include_directories(include)
 
 set(SOURCES
@@ -32,4 +31,6 @@ add_library(${TARGET} OBJECT ${SOURCES})
 
 set_target_properties(${TARGET} PROPERTIES VERSION ${CMAKE_PROJECT_VERSION})
 set_target_properties(${TARGET} PROPERTIES POSITION_INDEPENDENT_CODE 1)
+
+target_link_libraries(${TARGET} ignite-common)
 target_include_directories(${TARGET} INTERFACE include)
diff --git a/modules/platforms/cpp/test-common/include/ignite_node.h b/modules/platforms/cpp/test-common/include/ignite_node.h
index 10bc130b2c..4850e07624 100644
--- a/modules/platforms/cpp/test-common/include/ignite_node.h
+++ b/modules/platforms/cpp/test-common/include/ignite_node.h
@@ -23,40 +23,48 @@
 
 namespace ignite
 {
-    class IgniteNode
-    {
-    public:
-        /**
-         * Constructor.
-         */
-        IgniteNode() = default;
-
-        /**
-         * Destructor.
-         */
-        ~IgniteNode() = default;
-
-        /**
-         * Start node.
-         *
-         * @param dryRun Perform a dry run. Mostly used to ensure that code is compiled and all artifacts are downloaded.
-         */
-        void start(bool dryRun = false);
-
-        /**
-         * Stop node.
-         */
-        void stop();
-
-        /**
-         * Join node process.
-         *
-         * @param timeout Timeout.
-         */
-        void join(std::chrono::milliseconds timeout);
-
-    private:
-        /** Underlying process. */
-        std::unique_ptr<Process> process;
-    };
+
+/**
+ * Represents Ignite server node process.
+ *
+ * Ignite node is started from command line. It is recommended to re-use
+ * a single Ignite node as much as possible to make tests as quick as possible.
+ */
+class IgniteNode
+{
+public:
+    /**
+     * Constructor.
+     */
+    IgniteNode() = default;
+
+    /**
+     * Destructor.
+     */
+    ~IgniteNode() = default;
+
+    /**
+     * Start node.
+     *
+     * @param dryRun Perform a dry run. Mostly used to ensure that code is compiled and all artifacts are downloaded.
+     */
+    void start(bool dryRun = false);
+
+    /**
+     * Stop node.
+     */
+    void stop();
+
+    /**
+     * Join node process.
+     *
+     * @param timeout Timeout.
+     */
+    void join(std::chrono::milliseconds timeout);
+
+private:
+    /** Underlying process. */
+    std::unique_ptr<Process> process;
+};
+
 } // namespace ignite
diff --git a/modules/platforms/cpp/test-common/include/process.h b/modules/platforms/cpp/test-common/include/process.h
index ab45700ccb..4f4707c4fe 100644
--- a/modules/platforms/cpp/test-common/include/process.h
+++ b/modules/platforms/cpp/test-common/include/process.h
@@ -19,48 +19,54 @@
 
 #include <chrono>
 #include <string>
+#include <memory>
 
 namespace ignite
 {
-    class Process
-    {
-    public:
-        /**
-         * Destructor.
-         */
-        virtual ~Process() = default;
 
-        /**
-         * Make new process instance.
-         *
-         * @param command Command.
-         * @param workDir Working directory.
-         * @return Process.
-         */
-        static std::unique_ptr<Process> make(std::string command, std::string workDir);
+/**
+ * Represents system process launched using commandline instruction.
+ */
+class Process
+{
+public:
+    /**
+     * Destructor.
+     */
+    virtual ~Process() = default;
+
+    /**
+     * Make new process instance.
+     *
+     * @param command Command.
+     * @param workDir Working directory.
+     * @return Process.
+     */
+    static std::unique_ptr<Process> make(std::string command, std::string workDir);
+
+    /**
+     * Start process.
+     */
+    virtual bool start() = 0;
 
-        /**
-         * Start process.
-         */
-        virtual bool start() = 0;
+    /**
+     * Kill the process.
+     */
+    virtual void kill() = 0;
 
-        /**
-         * Kill the process.
-         */
-        virtual void kill() = 0;
+    /**
+     * Join process.
+     *
+     * @param timeout Timeout.
+     */
+    virtual void join(std::chrono::milliseconds timeout) = 0;
 
-        /**
-         * Join process.
-         *
-         * @param timeout Timeout.
-         */
-        virtual void join(std::chrono::milliseconds timeout) = 0;
+protected:
+    /**
+     * Constructor.
+     */
+    Process() = default;
+};
 
-    protected:
-        /**
-         * Constructor.
-         */
-        Process() = default;
-    };
 } // namespace ignite
 
diff --git a/modules/platforms/cpp/test-common/include/test_utils.h b/modules/platforms/cpp/test-common/include/test_utils.h
index 01626fd703..3857a321e4 100644
--- a/modules/platforms/cpp/test-common/include/test_utils.h
+++ b/modules/platforms/cpp/test-common/include/test_utils.h
@@ -23,21 +23,23 @@
 
 namespace ignite
 {
-    /**
-     * Resolve IGNITE_HOME directory. Resolution is performed in several steps:
-     * 1) Check for path provided as argument.
-     * 2) Check for environment variable.
-     * 3) Check for current working directory.
-     * Result of these checks are evaluated based on existence of certain predefined folders inside possible Ignite
-     * home. If they are found, IGNITE_HOME is considered resolved.
-     *
-     * @param path Optional path to check.
-     * @return Resolved Ignite home.
-     */
-    std::string resolveIgniteHome(const std::string& path = "");
 
-    /**
-     * Get path to maven executable.
-     */
-    std::string getMavenPath();
+/**
+ * Resolve IGNITE_HOME directory. Resolution is performed in several steps:
+ * 1) Check for path provided as argument.
+ * 2) Check for environment variable.
+ * 3) Check for current working directory.
+ * Result of these checks are evaluated based on existence of certain predefined folders inside possible Ignite
+ * home. If they are found, IGNITE_HOME is considered resolved.
+ *
+ * @param path Optional path to check.
+ * @return Resolved Ignite home.
+ */
+std::string resolveIgniteHome(const std::string& path = "");
+
+/**
+ * Get path to maven executable.
+ */
+std::string getMavenPath();
+
 } // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/test-common/src/ignite_node.cpp b/modules/platforms/cpp/test-common/src/ignite_node.cpp
index 560b9f54fd..3c6f7ab6a3 100644
--- a/modules/platforms/cpp/test-common/src/ignite_node.cpp
+++ b/modules/platforms/cpp/test-common/src/ignite_node.cpp
@@ -19,54 +19,61 @@
 #include <stdexcept>
 #include <iostream>
 
+#include "common/Platform.h"
+
 #include "ignite_node.h"
 #include "test_utils.h"
 
-namespace ignite
+namespace
 {
-    void IgniteNode::start(bool dryRun)
-    {
-        std::string home = resolveIgniteHome();
-        if (home.empty())
-            throw std::runtime_error(
-                    "Can not resolve Ignite home directory. Try setting IGNITE_HOME explicitly");
 
-        std::string command =
-#ifdef WIN32
-        "cmd.exe /c ";
-#else
-        "/bin/bash -c ";
-#endif
+/**
+ * System shell command string.
+ */
+constexpr std::string_view SYSTEM_SHELL = SWITCH_WIN_OTHER("cmd.exe /c ", "/bin/bash -c ");
 
-        command += getMavenPath() + " exec:java@platform-test-node-runner";
+} // anonymous namespace
 
-        if (dryRun)
-            command += " -Dexec.args=dry-run";
+namespace ignite
+{
 
-        auto workDir = std::filesystem::path(home) / "modules" / "runner";
+void IgniteNode::start(bool dryRun)
+{
+    std::string home = resolveIgniteHome();
+    if (home.empty())
+        throw std::runtime_error(
+                "Can not resolve Ignite home directory. Try setting IGNITE_HOME explicitly");
 
-        std::cout << "IGNITE_HOME=" << home << std::endl;
-        std::cout << "working dir=" << workDir << std::endl;
-        std::cout << "command=" << command << std::endl;
+    std::string command = std::string(SYSTEM_SHELL) + getMavenPath() + " exec:java@platform-test-node-runner";
 
-        process = Process::make(command, workDir.string());
-        if (!process->start())
-        {
-            process.reset();
+    if (dryRun)
+        command += " -Dexec.args=dry-run";
 
-            throw std::runtime_error("Failed to invoke Ignite command: '" + command + "'");
-        }
-    }
+    auto workDir = std::filesystem::path(home) / "modules" / "runner";
 
-    void IgniteNode::stop()
-    {
-        if (process)
-            process->kill();
-    }
+    std::cout << "IGNITE_HOME=" << home << std::endl;
+    std::cout << "working dir=" << workDir << std::endl;
+    std::cout << "command=" << command << std::endl;
 
-    void IgniteNode::join(std::chrono::milliseconds timeout)
+    process = Process::make(command, workDir.string());
+    if (!process->start())
     {
-        if (process)
-            process->join(timeout);
+        process.reset();
+
+        throw std::runtime_error("Failed to invoke Ignite command: '" + command + "'");
     }
+}
+
+void IgniteNode::stop()
+{
+    if (process)
+        process->kill();
+}
+
+void IgniteNode::join(std::chrono::milliseconds timeout)
+{
+    if (process)
+        process->join(timeout);
+}
+
 } // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/test-common/src/process.cpp b/modules/platforms/cpp/test-common/src/process.cpp
index 4911031bbc..f2ce10854a 100644
--- a/modules/platforms/cpp/test-common/src/process.cpp
+++ b/modules/platforms/cpp/test-common/src/process.cpp
@@ -16,8 +16,9 @@
  */
 
 #ifdef WIN32
-#   include <windows.h>
-#   include <tlhelp32.h>
+#   include "win/win_process.h"
+#else
+#   include "linux/linux_process.h"
 #endif
 
 #include <filesystem>
@@ -26,159 +27,16 @@
 
 #include "process.h"
 
-namespace
-{
-#ifdef WIN32
-    /**
-     * Get process tree.
-     * @param processId ID of the parent process.
-     * @return Process tree.
-     */
-    std::vector<DWORD> getProcessTree(DWORD processId) // NOLINT(misc-no-recursion)
-    {
-        std::vector<DWORD> children;
-        PROCESSENTRY32 pe;
-
-        memset(&pe, 0, sizeof(PROCESSENTRY32));
-        pe.dwSize = sizeof(PROCESSENTRY32);
-
-        HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
-
-        if (Process32First(hSnap, &pe))
-        {
-            BOOL bContinue = TRUE;
-
-            while (bContinue)
-            {
-                if (pe.th32ParentProcessID == processId)
-                    children.push_back(pe.th32ProcessID);
-
-                bContinue = Process32Next(hSnap, &pe);
-            }
-        }
-
-        std::vector<DWORD> tree(children);
-        for (auto procId : children)
-        {
-            std::vector<DWORD> childTree = getProcessTree(procId);
-            tree.insert(tree.end(), childTree.begin(), childTree.end());
-        }
-
-        return tree;
-    }
-
-    /**
-     * Implementation of Process for Windows.
-     */
-    class WinProcess : public ignite::Process
-    {
-    public:
-        /**
-         * Constructor.
-         *
-         * @param command Command.
-         * @param workDir Working directory.
-         */
-        WinProcess(std::string command, std::string workDir) :
-            running(false),
-            command(std::move(command)),
-            workDir(std::move(workDir)),
-            info{}
-        { }
-
-        /**
-         * Destructor.
-         */
-        ~WinProcess() override = default;
-
-
-        /**
-         * Start process.
-         */
-        bool start() override
-        {
-            if (running)
-                return false;
-
-            STARTUPINFO si;
-
-            std::memset(&si, 0, sizeof(si));
-            si.cb = sizeof(si);
-            std::memset(&info, 0, sizeof(info));
-
-            std::vector<char> cmd(command.begin(), command.end());
-            cmd.push_back(0);
-
-            BOOL success = CreateProcess(
-                    NULL, cmd.data(), NULL, NULL,
-                    FALSE, 0, NULL, workDir.c_str(),
-                    &si, &info);
-
-            running = success == TRUE;
-
-            return running;
-        }
-
-        /**
-         * Kill the process.
-         */
-        void kill() override
-        {
-            std::vector<DWORD> processTree = getProcessTree(info.dwProcessId);
-            for (auto procId : processTree)
-            {
-                HANDLE hChildProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, procId);
-                if (hChildProc)
-                {
-                    TerminateProcess(hChildProc, 1);
-                    CloseHandle(hChildProc);
-                }
-            }
-
-            TerminateProcess(info.hProcess, 1);
-
-            CloseHandle( info.hProcess );
-            CloseHandle( info.hThread );
-        }
-
-        /**
-         * Join process.
-         *
-         * @param timeout Timeout.
-         */
-        void join(std::chrono::milliseconds timeout) override
-        {
-            auto msecs = timeout.count() < 0 ? INFINITE : static_cast<DWORD>(timeout.count());
-
-            WaitForSingleObject(info.hProcess, msecs);
-        }
-
-    private:
-        /** Running flag. */
-        bool running;
-
-        /** Command. */
-        const std::string command;
-
-        /** Working directory. */
-        const std::string workDir;
-
-        /** Process information. */
-        PROCESS_INFORMATION info;
-    };
-
-#else // #ifdef WIN32
-
-#endif // #ifdef WIN32
-}
 
 namespace ignite
 {
-    std::unique_ptr<Process> Process::make(std::string command, std::string workDir)
-    {
+
+std::unique_ptr<Process> Process::make(std::string command, std::string workDir)
+{
 #ifdef WIN32
-        return std::unique_ptr<Process>(new WinProcess(std::move(command), std::move(workDir)));
+    return std::unique_ptr<Process>(new win::WinProcess(std::move(command), std::move(workDir)));
 #else
 #endif
-    }
+}
+
 } // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/test-common/src/test_utils.cpp b/modules/platforms/cpp/test-common/src/test_utils.cpp
index f6b0a46386..97e811e984 100644
--- a/modules/platforms/cpp/test-common/src/test_utils.cpp
+++ b/modules/platforms/cpp/test-common/src/test_utils.cpp
@@ -24,71 +24,73 @@
 
 namespace ignite
 {
-    /**
-     * Checks if the path looks like binary release home directory.
-     * Internally checks for presence of core library.
-     * @return @c true if the path looks like binary release home directory.
-     */
-    bool looksLikeBinaryReleaseHome(const std::filesystem::path& path)
-    {
-        std::filesystem::path coreLibPath = path / "libs";
-        if (!is_directory(coreLibPath))
-            return false;
-
-        auto iter = std::filesystem::directory_iterator{coreLibPath};
-        return std::any_of(iter, std::filesystem::end(iter), [](auto entry) {
-            const std::filesystem::path& entryPath = entry.path();
-            if (entryPath.extension() != "jar")
-                return false;
 
-            std::string stem = entryPath.stem().string();
-            return stem.find("ignite-core") == 0;
-        });
-    }
-
-    /**
-     * Checks if the path looks like source release home directory.
-     * Internally checks for presence of core source directory.
-     * @return @c true if the path looks like binary release home directory.
-     */
-    bool looksLikeSourceReleaseHome(const std::filesystem::path& path)
-    {
-        std::filesystem::path coreSourcePath =
-                path / "modules" / "core" / "src" / "main" / "java" / "org" / "apache" / "ignite";
+/**
+ * Checks if the path looks like binary release home directory.
+ * Internally checks for presence of core library.
+ * @return @c true if the path looks like binary release home directory.
+ */
+bool looksLikeBinaryReleaseHome(const std::filesystem::path& path)
+{
+    std::filesystem::path coreLibPath = path / "libs";
+    if (!is_directory(coreLibPath))
+        return false;
 
-        return std::filesystem::is_directory(coreSourcePath);
-    }
+    auto iter = std::filesystem::directory_iterator{coreLibPath};
+    return std::any_of(iter, std::filesystem::end(iter), [](auto entry) {
+        const std::filesystem::path& entryPath = entry.path();
+        if (entryPath.extension() != "jar")
+            return false;
 
-    std::string resolveIgniteHome(const std::string& path)
-    {
-        std::error_code error;
+        std::string stem = entryPath.stem().string();
+        return stem.find("ignite-core") == 0;
+    });
+}
 
-        std::filesystem::path home = std::filesystem::canonical(path, error);
-        if (!error && std::filesystem::is_directory(path))
-            return home.string();
+/**
+ * Checks if the path looks like source release home directory.
+ * Internally checks for presence of core source directory.
+ * @return @c true if the path looks like binary release home directory.
+ */
+bool looksLikeSourceReleaseHome(const std::filesystem::path& path)
+{
+    std::filesystem::path coreSourcePath =
+            path / "modules" / "core" / "src" / "main" / "java" / "org" / "apache" / "ignite";
 
-        const char *env = std::getenv("IGNITE_HOME");
-        if (env)
-        {
-            home = std::filesystem::canonical(env, error);
-            if (!error && std::filesystem::is_directory(home))
-                return home.string();
-        }
+    return std::filesystem::is_directory(coreSourcePath);
+}
 
-        home = std::filesystem::current_path();
-        while (!home.empty() && home.has_relative_path())
-        {
-            if (looksLikeBinaryReleaseHome(home) || looksLikeSourceReleaseHome(home))
-                return home.string();
+std::string resolveIgniteHome(const std::string& path)
+{
+    std::error_code error;
 
-            home = home.parent_path();
-        }
+    std::filesystem::path home = std::filesystem::canonical(path, error);
+    if (!error && std::filesystem::is_directory(path))
         return home.string();
+
+    const char *env = std::getenv("IGNITE_HOME");
+    if (env)
+    {
+        home = std::filesystem::canonical(env, error);
+        if (!error && std::filesystem::is_directory(home))
+            return home.string();
     }
 
-    std::string getMavenPath()
+    home = std::filesystem::current_path();
+    while (!home.empty() && home.has_relative_path())
     {
-        // Currently, we only support systems with "mvn" command in PATH
-        return "mvn";
+        if (looksLikeBinaryReleaseHome(home) || looksLikeSourceReleaseHome(home))
+            return home.string();
+
+        home = home.parent_path();
     }
+    return home.string();
+}
+
+std::string getMavenPath()
+{
+    // Currently, we only support systems with "mvn" command in PATH
+    return "mvn";
+}
+
 } // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/test-common/src/win/win_process.h b/modules/platforms/cpp/test-common/src/win/win_process.h
new file mode 100644
index 0000000000..b0c29c5941
--- /dev/null
+++ b/modules/platforms/cpp/test-common/src/win/win_process.h
@@ -0,0 +1,173 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+// It's OK that this code is entirely in header as it only supposed to be included from a single file.
+
+#include <windows.h>
+#include <tlhelp32.h>
+
+#include <vector>
+#include <chrono>
+#include <string>
+
+#include "process.h"
+
+namespace ignite::win
+{
+
+/**
+ * Get process tree.
+ * @param processId ID of the parent process.
+ * @return Process tree.
+ */
+std::vector<DWORD> getProcessTree(DWORD processId) // NOLINT(misc-no-recursion)
+{
+    std::vector<DWORD> children;
+    PROCESSENTRY32 pe;
+
+    memset(&pe, 0, sizeof(PROCESSENTRY32));
+    pe.dwSize = sizeof(PROCESSENTRY32);
+
+    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+
+    if (Process32First(hSnap, &pe))
+    {
+        BOOL bContinue = TRUE;
+
+        while (bContinue)
+        {
+            if (pe.th32ParentProcessID == processId)
+                children.push_back(pe.th32ProcessID);
+
+            bContinue = Process32Next(hSnap, &pe);
+        }
+    }
+
+    std::vector<DWORD> tree(children);
+    for (auto procId : children)
+    {
+        std::vector<DWORD> childTree = getProcessTree(procId);
+        tree.insert(tree.end(), childTree.begin(), childTree.end());
+    }
+
+    return tree;
+}
+
+/**
+ * Implementation of Process for Windows.
+ */
+class WinProcess : public ignite::Process
+{
+public:
+    /**
+     * Constructor.
+     *
+     * @param command Command.
+     * @param workDir Working directory.
+     */
+    WinProcess(std::string command, std::string workDir) :
+            running(false),
+            command(std::move(command)),
+            workDir(std::move(workDir)),
+            info{}
+    { }
+
+    /**
+     * Destructor.
+     */
+    ~WinProcess() override = default;
+
+
+    /**
+     * Start process.
+     */
+    bool start() override
+    {
+        if (running)
+            return false;
+
+        STARTUPINFO si;
+
+        std::memset(&si, 0, sizeof(si));
+        si.cb = sizeof(si);
+        std::memset(&info, 0, sizeof(info));
+
+        std::vector<char> cmd(command.begin(), command.end());
+        cmd.push_back(0);
+
+        BOOL success = CreateProcess(
+                NULL, cmd.data(), NULL, NULL,
+                FALSE, 0, NULL, workDir.c_str(),
+                &si, &info);
+
+        running = success == TRUE;
+
+        return running;
+    }
+
+    /**
+     * Kill the process.
+     */
+    void kill() override
+    {
+        std::vector<DWORD> processTree = getProcessTree(info.dwProcessId);
+        for (auto procId : processTree)
+        {
+            HANDLE hChildProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, procId);
+            if (hChildProc)
+            {
+                TerminateProcess(hChildProc, 1);
+                CloseHandle(hChildProc);
+            }
+        }
+
+        TerminateProcess(info.hProcess, 1);
+
+        CloseHandle( info.hProcess );
+        CloseHandle( info.hThread );
+    }
+
+    /**
+     * Join process.
+     *
+     * @param timeout Timeout.
+     */
+    void join(std::chrono::milliseconds timeout) override
+    {
+        auto msecs = timeout.count() < 0 ? INFINITE : static_cast<DWORD>(timeout.count());
+
+        WaitForSingleObject(info.hProcess, msecs);
+    }
+
+private:
+    /** Running flag. */
+    bool running;
+
+    /** Command. */
+    const std::string command;
+
+    /** Working directory. */
+    const std::string workDir;
+
+    /** Process information. */
+    PROCESS_INFORMATION info;
+};
+
+} // namespace ignite::win
+


[ignite-3] 06/17: IGNITE-17424 Start and stop Ignite node

Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 61c64082a870d209db6b3648961b143eb61befff
Author: Igor Sapego <is...@apache.org>
AuthorDate: Mon Aug 29 23:02:00 2022 +0400

    IGNITE-17424 Start and stop Ignite node
---
 .../cpp/client-test/src/ignite_client_test.cpp     |  16 +-
 modules/platforms/cpp/test-common/CMakeLists.txt   |   1 +
 .../cpp/test-common/include/ignite_node.h          |  52 ++++---
 .../include/{ignite_node.h => process.h}           |  46 +++---
 .../platforms/cpp/test-common/include/test_utils.h |  19 ---
 .../platforms/cpp/test-common/src/ignite_node.cpp  |  51 ++++--
 modules/platforms/cpp/test-common/src/process.cpp  | 173 +++++++++++++++++++++
 .../platforms/cpp/test-common/src/test_utils.cpp   |  18 ---
 8 files changed, 263 insertions(+), 113 deletions(-)

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 2413b1839b..7fc40ed724 100644
--- a/modules/platforms/cpp/client-test/src/ignite_client_test.cpp
+++ b/modules/platforms/cpp/client-test/src/ignite_client_test.cpp
@@ -42,25 +42,11 @@ protected:
 
 TEST_F(ClientTest, TestTest)
 {
-    std::cout << "Hello" << std::endl;
-
     ignite::IgniteNode node;
 
     node.start();
 
-    for (int i = 0; i < 20; ++i)
-    {
-        std::cout << node.getOutput();
-
-        std::this_thread::sleep_for(std::chrono::seconds(1));
-    }
+    std::this_thread::sleep_for(std::chrono::seconds(20));
 
     node.stop();
-
-    for (int i = 0; i < 2; ++i)
-    {
-        std::cout << node.getOutput();
-
-        std::this_thread::sleep_for(std::chrono::seconds(1));
-    }
 }
\ No newline at end of file
diff --git a/modules/platforms/cpp/test-common/CMakeLists.txt b/modules/platforms/cpp/test-common/CMakeLists.txt
index 396ee4ed72..a157d5ed98 100644
--- a/modules/platforms/cpp/test-common/CMakeLists.txt
+++ b/modules/platforms/cpp/test-common/CMakeLists.txt
@@ -24,6 +24,7 @@ include_directories(include)
 
 set(SOURCES
         src/ignite_node.cpp
+        src/process.cpp
         src/test_utils.cpp
 )
 
diff --git a/modules/platforms/cpp/test-common/include/ignite_node.h b/modules/platforms/cpp/test-common/include/ignite_node.h
index 224aa3e124..490a7985e0 100644
--- a/modules/platforms/cpp/test-common/include/ignite_node.h
+++ b/modules/platforms/cpp/test-common/include/ignite_node.h
@@ -15,46 +15,54 @@
  * limitations under the License.
  */
 
-#ifndef TEST_COMMON_IGNITE_NODE
-#define TEST_COMMON_IGNITE_NODE
+#pragma once
 
-//#include <cstdio>
+#include "process.h"
 
 namespace ignite
 {
     class IgniteNode
     {
     public:
-//        /**
-//         * Constructor.
-//         */
-//        IgniteNode() = default;
+        /**
+         * Constructor.
+         */
+        IgniteNode() = default;
 
-//        /**
-//         * Destructor.
-//         */
-//        ~IgniteNode() = default;
+        /**
+         * Destructor.
+         */
+        ~IgniteNode() = default;
 
         /**
          * Start node.
+         *
+         * @param dryRun Perform a dry run. Mostly used to ensure that code is compiled and all artifacts are downloaded.
          */
-        void start();
+        void start(bool dryRun = false);
 
         /**
          * Stop node.
          */
         void stop();
 
-        /**
-         * Get current node output.
-         *
-         * @param max Max bytes to get.
-         * @return Output.
-         */
-        std::string getOutput(int max = 1024);
+//        /**
+//         * Check whether node is still running.
+//         *
+//         * @return @c true if the node is running.
+//         */
+//        bool isRunning();
+//
+//        /**
+//         * Get current node output.
+//         *
+//         * @param max Max bytes to get.
+//         * @return Output.
+//         */
+//        std::string getOutput(int max = 1024);
+
     private:
-        FILE* stream;
+        /** Underlying process. */
+        std::unique_ptr<Process> process;
     };
 } // namespace ignite
-
-#endif // TEST_COMMON_IGNITE_NODE
diff --git a/modules/platforms/cpp/test-common/include/ignite_node.h b/modules/platforms/cpp/test-common/include/process.h
similarity index 62%
copy from modules/platforms/cpp/test-common/include/ignite_node.h
copy to modules/platforms/cpp/test-common/include/process.h
index 224aa3e124..b2d6d50121 100644
--- a/modules/platforms/cpp/test-common/include/ignite_node.h
+++ b/modules/platforms/cpp/test-common/include/process.h
@@ -15,46 +15,44 @@
  * limitations under the License.
  */
 
-#ifndef TEST_COMMON_IGNITE_NODE
-#define TEST_COMMON_IGNITE_NODE
+#pragma once
 
-//#include <cstdio>
+#include <string>
 
 namespace ignite
 {
-    class IgniteNode
+    class Process
     {
     public:
-//        /**
-//         * Constructor.
-//         */
-//        IgniteNode() = default;
+        /**
+         * Destructor.
+         */
+        virtual ~Process() = default;
 
-//        /**
-//         * Destructor.
-//         */
-//        ~IgniteNode() = default;
+        /**
+         * Make new process instance.
+         *
+         * @param command Command.
+         * @param workDir Working directory.
+         * @return Process.
+         */
+        static std::unique_ptr<Process> make(std::string command, std::string workDir);
 
         /**
-         * Start node.
+         * Start process.
          */
-        void start();
+        virtual bool start() = 0;
 
         /**
-         * Stop node.
+         * Stop process.
          */
-        void stop();
+        virtual void stop() = 0;
 
+    protected:
         /**
-         * Get current node output.
-         *
-         * @param max Max bytes to get.
-         * @return Output.
+         * Constructor.
          */
-        std::string getOutput(int max = 1024);
-    private:
-        FILE* stream;
+        Process() = default;
     };
 } // namespace ignite
 
-#endif // TEST_COMMON_IGNITE_NODE
diff --git a/modules/platforms/cpp/test-common/include/test_utils.h b/modules/platforms/cpp/test-common/include/test_utils.h
index ca0d00a51f..01626fd703 100644
--- a/modules/platforms/cpp/test-common/include/test_utils.h
+++ b/modules/platforms/cpp/test-common/include/test_utils.h
@@ -40,23 +40,4 @@ namespace ignite
      * Get path to maven executable.
      */
     std::string getMavenPath();
-
-    /**
-     * Open process.
-     *
-     * @param command System shell command line instruction.
-     * @param type Mode of the returned process output stream. Can be one of the following:
-     *  "r" - The calling process can read the spawned command's standard output using the returned stream.
-     *  "w" - The calling process can write to the spawned command's standard input using the returned stream.
-     * @return File stream for the process.
-     */
-    FILE* processOpen(const char *command, const char *type);
-
-    /**
-     * Waits for the associated process to terminate and returns the exit status of the command.
-     *
-     * @param stream Return value from the previous call to processOpen().
-     * @return Returns the exit status of the terminating command processor, or -1 if an error occurs.
-     */
-    int processClose(FILE* stream);
 } // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/test-common/src/ignite_node.cpp b/modules/platforms/cpp/test-common/src/ignite_node.cpp
index 1fb4bfb6eb..47807989a8 100644
--- a/modules/platforms/cpp/test-common/src/ignite_node.cpp
+++ b/modules/platforms/cpp/test-common/src/ignite_node.cpp
@@ -15,17 +15,18 @@
  * limitations under the License.
  */
 
-#include <iostream>
+#include <filesystem>
 #include <stdexcept>
 #include <vector>
 #include <utility>
+#include <iostream>
 
 #include "ignite_node.h"
 #include "test_utils.h"
 
 namespace ignite
 {
-    void IgniteNode::start()
+    void IgniteNode::start(bool dryRun)
     {
         std::string home = resolveIgniteHome();
         if (home.empty())
@@ -39,24 +40,44 @@ namespace ignite
         "/bin/bash -c ";
 #endif
 
-        command += getMavenPath() + " " + "exec:java@platform-test-node-runner";
+        command += getMavenPath() + " exec:java@platform-test-node-runner";
+
+        if (dryRun)
+            command += " -Dexec.args=dry-run";
+
+        auto workDir = std::filesystem::path(home) / "modules" / "runner";
+
+        std::cout << "IGNITE_HOME=" << home << std::endl;
+        std::cout << "working dir=" << workDir << std::endl;
+        std::cout << "command=" << command << std::endl;
 
-        stream = processOpen(command.c_str(), "r");
+        process = Process::make(command, workDir.string());
+        if (!process->start())
+        {
+            throw std::runtime_error("Failed to invoke Ignite command: '" + command + "'");
+
+            process.reset();
+        }
     }
 
     void IgniteNode::stop()
     {
-        if (stream)
-            processClose(stream);
+        if (process)
+            process->stop();
     }
 
-    std::string IgniteNode::getOutput(int max)
-    {
-        std::string buffer(max, 0);
-
-        size_t actual = std::fread(buffer.data(), 1, max, stream);
-        buffer.resize(actual);
-
-        return buffer;
-    }
+//    bool IgniteNode::isRunning()
+//    {
+//        return std::feof(stream) == 0 && std::ferror(stream) == 0;
+//    }
+//
+//    std::string IgniteNode::getOutput(int max)
+//    {
+//        std::string buffer(max, 0);
+//
+//        size_t actual = std::fread(buffer.data(), 1, max, stream);
+//        buffer.resize(actual);
+//
+//        return buffer;
+//    }
 } // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/test-common/src/process.cpp b/modules/platforms/cpp/test-common/src/process.cpp
new file mode 100644
index 0000000000..4620b53aec
--- /dev/null
+++ b/modules/platforms/cpp/test-common/src/process.cpp
@@ -0,0 +1,173 @@
+/*
+ * 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.
+ */
+
+#ifdef WIN32
+#   include <windows.h>
+#   include <tlhelp32.h>
+#endif // WIN32
+
+#include <filesystem>
+#include <utility>
+#include <vector>
+
+#include "process.h"
+
+namespace
+{
+#ifdef WIN32
+    /**
+     * Get process tree.
+     * @param processId ID of the parent process.
+     * @return Process tree.
+     */
+    std::vector<DWORD> getProcessTree(DWORD processId)
+    {
+        std::vector<DWORD> children;
+        PROCESSENTRY32 pe;
+
+        memset(&pe, 0, sizeof(PROCESSENTRY32));
+        pe.dwSize = sizeof(PROCESSENTRY32);
+
+        HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+
+        if (Process32First(hSnap, &pe))
+        {
+            BOOL bContinue = TRUE;
+
+            while (bContinue)
+            {
+                if (pe.th32ParentProcessID == processId)
+                    children.push_back(pe.th32ProcessID);
+
+                bContinue = Process32Next(hSnap, &pe);
+            }
+        }
+
+        std::vector<DWORD> tree(children);
+        for (auto procId : children)
+        {
+            std::vector<DWORD> childTree = getProcessTree(procId);
+            tree.insert(tree.end(), childTree.begin(), childTree.end());
+        }
+
+        return tree;
+    }
+
+    /**
+     * Implementation of Process for Windows.
+     */
+    class WinProcess : public ignite::Process
+    {
+    public:
+        /**
+         * Constructor.
+         *
+         * @param command Command.
+         * @param workDir Working directory.
+         */
+        WinProcess(std::string command, std::string workDir) :
+            running(false),
+            command(std::move(command)),
+            workDir(std::move(workDir)),
+            info{}
+        { }
+
+        /**
+         * Destructor.
+         */
+        ~WinProcess() override = default;
+
+
+        /**
+         * Start process.
+         */
+        bool start() override
+        {
+            if (running)
+                return false;
+
+            STARTUPINFO si;
+
+            std::memset(&si, 0, sizeof(si));
+            si.cb = sizeof(si);
+            std::memset(&info, 0, sizeof(info));
+
+            std::vector<char> cmd(command.begin(), command.end());
+            cmd.push_back(0);
+
+            BOOL success = CreateProcess(
+                    NULL, cmd.data(), NULL, NULL,
+                    FALSE, 0, NULL, workDir.c_str(),
+                    &si, &info);
+
+            running = success == TRUE;
+
+            return running;
+        }
+
+        /**
+         * Stop process.
+         */
+        void stop() override
+        {
+            std::vector<DWORD> processTree = getProcessTree(info.dwProcessId);
+            for (auto procId : processTree)
+            {
+                HANDLE hChildProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, procId);
+                if (hChildProc)
+                {
+                    TerminateProcess(hChildProc, 1);
+                    CloseHandle(hChildProc);
+                }
+            }
+
+            TerminateProcess(info.hProcess, 1);
+
+            WaitForSingleObject( info.hProcess, INFINITE );
+
+            CloseHandle( info.hProcess );
+            CloseHandle( info.hThread );
+        }
+
+    private:
+        /** Running flag. */
+        bool running;
+
+        /** Command. */
+        const std::string command;
+
+        /** Working directory. */
+        const std::string workDir;
+
+        /** Process information. */
+        PROCESS_INFORMATION info;
+    };
+
+#else
+#endif
+}
+
+namespace ignite
+{
+    std::unique_ptr<Process> Process::make(std::string command, std::string workDir)
+    {
+#ifdef WIN32
+        return std::unique_ptr<Process>(new WinProcess(std::move(command), std::move(workDir)));
+#else
+#endif
+    }
+} // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/test-common/src/test_utils.cpp b/modules/platforms/cpp/test-common/src/test_utils.cpp
index 65fe5b8975..f6b0a46386 100644
--- a/modules/platforms/cpp/test-common/src/test_utils.cpp
+++ b/modules/platforms/cpp/test-common/src/test_utils.cpp
@@ -91,22 +91,4 @@ namespace ignite
         // Currently, we only support systems with "mvn" command in PATH
         return "mvn";
     }
-
-    FILE *processOpen(const char *command, const char *type)
-    {
-#ifdef WIN32
-        return _popen(command, type);
-#else
-        return popen(command, type);
-#endif
-    }
-
-    int processClose(FILE *stream)
-    {
-#ifdef WIN32
-        return _pclose(stream);
-#else
-        return pclose(stream);
-#endif
-    }
 } // namespace ignite
\ No newline at end of file


[ignite-3] 15/17: IGNITE-17424 Compiles on Windows

Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit dd73b730b18f8c2cbec1805b8d672c3d73d3aa59
Author: Igor Sapego <is...@apache.org>
AuthorDate: Wed Sep 7 20:42:57 2022 +0400

    IGNITE-17424 Compiles on Windows
---
 modules/platforms/cpp/CMakeLists.txt               |   2 +
 modules/platforms/cpp/client/CMakeLists.txt        |   7 +-
 .../cpp/client/src/cluster_connection.cpp          | 292 +++++++++++++++++
 .../platforms/cpp/client/src/cluster_connection.h  | 176 +++++++++++
 .../src/ignite_client_impl.cpp}                    |  34 +-
 .../platforms/cpp/client/src/ignite_client_impl.h  |  13 +-
 .../Platform.h => client/src/node_connection.cpp}  |  38 +--
 modules/platforms/cpp/client/src/node_connection.h |  77 +++++
 .../{ignite_client_impl.h => protocol_context.h}   |  47 +--
 .../platforms/cpp/client/src/protocol_version.h    | 202 ++++++++++++
 modules/platforms/cpp/common/CMakeLists.txt        |   3 +-
 modules/platforms/cpp/common/Platform.h            |   4 +-
 .../platforms/cpp/common/{Platform.h => factory.h} |  41 ++-
 modules/platforms/cpp/common/guid.h                | 267 ++++++++++++++++
 modules/platforms/cpp/common/ignite_error.h        | 104 ++++++
 modules/platforms/cpp/conanfile.txt                |   3 +-
 modules/platforms/cpp/network/CMakeLists.txt       |  70 +++++
 .../include/ignite/network/async_client_pool.h     |  65 ++++
 .../network/include/ignite/network/async_handler.h |  80 +++++
 .../include/ignite/network/codec.h}                |  53 ++--
 .../include/ignite/network/codec_data_filter.h     |  99 ++++++
 .../network/include/ignite/network/data_buffer.h   | 150 +++++++++
 .../network/include/ignite/network/data_filter.h   |  90 ++++++
 .../include/ignite/network/data_filter_adapter.h   | 131 ++++++++
 .../include/ignite/network/data_sink.h}            |  49 +--
 .../cpp/network/include/ignite/network/end_point.h | 165 ++++++++++
 .../include/ignite/network/length_prefix_codec.h   | 103 ++++++
 .../include/ignite/network/network.h}              |  36 +--
 .../cpp/network/include/ignite/network/tcp_range.h | 174 +++++++++++
 .../os/linux/src/network/connecting_context.cpp    | 110 +++++++
 .../os/linux/src/network/connecting_context.h      |  96 ++++++
 .../os/linux/src/network/linux_async_client.cpp    | 198 ++++++++++++
 .../os/linux/src/network/linux_async_client.h      | 249 +++++++++++++++
 .../linux/src/network/linux_async_client_pool.cpp  | 212 +++++++++++++
 .../os/linux/src/network/linux_async_client_pool.h | 205 ++++++++++++
 .../src/network/linux_async_worker_thread.cpp      | 348 +++++++++++++++++++++
 .../linux/src/network/linux_async_worker_thread.h  | 163 ++++++++++
 .../cpp/network/os/linux/src/network/sockets.cpp   | 176 +++++++++++
 .../cpp/network/os/linux/src/network/sockets.h     | 102 ++++++
 .../cpp/network/os/win/src/network/sockets.cpp     | 164 ++++++++++
 .../cpp/network/os/win/src/network/sockets.h       |  65 ++++
 .../os/win/src/network/utils.cpp}                  |  45 ++-
 .../os/win/src/network/win_async_client.cpp        | 176 +++++++++++
 .../network/os/win/src/network/win_async_client.h  | 270 ++++++++++++++++
 .../os/win/src/network/win_async_client_pool.cpp   | 234 ++++++++++++++
 .../os/win/src/network/win_async_client_pool.h     | 204 ++++++++++++
 .../src/network/win_async_connecting_thread.cpp    | 250 +++++++++++++++
 .../win/src/network/win_async_connecting_thread.h  | 125 ++++++++
 .../os/win/src/network/win_async_worker_thread.cpp | 138 ++++++++
 .../os/win/src/network/win_async_worker_thread.h}  |  63 ++--
 .../src/network/async_client_pool_adapter.cpp      |  70 +++++
 .../src/network/async_client_pool_adapter.h        |  98 ++++++
 .../cpp/network/src/network/codec_data_filter.cpp  | 100 ++++++
 .../cpp/network/src/network/data_buffer.cpp        | 115 +++++++
 .../network/src/network/error_handling_filter.cpp  |  87 ++++++
 .../network/src/network/error_handling_filter.h    |  85 +++++
 .../network/src/network/length_prefix_codec.cpp    |  74 +++++
 .../Platform.h => network/src/network/network.cpp} |  46 +--
 .../cpp/network/src/network/tcp_range.cpp          | 150 +++++++++
 modules/platforms/cpp/network/src/network/utils.h  | 150 +++++++++
 .../cpp/{test-common => protocol}/CMakeLists.txt   |   8 +-
 .../cpp/protocol/include/ignite/protocol/buffer.h  | 125 ++++++++
 .../include/ignite/protocol/extension_types.h}     |  39 ++-
 .../cpp/protocol/include/ignite/protocol/reader.h  | 124 ++++++++
 .../cpp/protocol/include/ignite/protocol/utils.h   | 199 ++++++++++++
 .../cpp/protocol/include/ignite/protocol/writer.h  | 110 +++++++
 modules/platforms/cpp/protocol/src/buffer.cpp      |  76 +++++
 modules/platforms/cpp/protocol/src/reader.cpp      | 124 ++++++++
 modules/platforms/cpp/protocol/src/writer.cpp      |  72 +++++
 modules/platforms/cpp/test-common/CMakeLists.txt   |   6 +-
 70 files changed, 7741 insertions(+), 285 deletions(-)

diff --git a/modules/platforms/cpp/CMakeLists.txt b/modules/platforms/cpp/CMakeLists.txt
index ca11746ca4..22bc34aae3 100644
--- a/modules/platforms/cpp/CMakeLists.txt
+++ b/modules/platforms/cpp/CMakeLists.txt
@@ -73,6 +73,8 @@ add_subdirectory(common)
 add_subdirectory(schema)
 
 if (${ENABLE_CLIENT})
+	add_subdirectory(protocol)
+	add_subdirectory(network)
     add_subdirectory(client)
 endif()
 
diff --git a/modules/platforms/cpp/client/CMakeLists.txt b/modules/platforms/cpp/client/CMakeLists.txt
index b060a9b051..f4d5af46b9 100644
--- a/modules/platforms/cpp/client/CMakeLists.txt
+++ b/modules/platforms/cpp/client/CMakeLists.txt
@@ -22,7 +22,10 @@ set(TARGET ${PROJECT_NAME})
 include_directories(include src)
 
 set(SOURCES
+    src/cluster_connection.cpp
 	src/ignite_client.cpp
+    src/ignite_client_impl.cpp
+    src/node_connection.cpp
 )
 
 add_library(${TARGET} SHARED ${SOURCES})
@@ -33,7 +36,7 @@ if (WIN32)
     set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME "ignite-client")
 endif()
 
-target_link_libraries(${TARGET} ignite-common)
+target_link_libraries(${TARGET} ignite-common ignite-network ignite-protocol)
 
 target_include_directories(${TARGET} INTERFACE include)
 
@@ -43,4 +46,4 @@ install(TARGETS ${TARGET}
     LIBRARY DESTINATION lib
 )
 
-install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_PREFIX}/include FILES_MATCHING PATTERN "*.h*")
\ No newline at end of file
+install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_PREFIX}/include FILES_MATCHING PATTERN "*.h*")
diff --git a/modules/platforms/cpp/client/src/cluster_connection.cpp b/modules/platforms/cpp/client/src/cluster_connection.cpp
new file mode 100644
index 0000000000..fa9f10f8a0
--- /dev/null
+++ b/modules/platforms/cpp/client/src/cluster_connection.cpp
@@ -0,0 +1,292 @@
+/*
+ * 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.
+ */
+
+#include <random>
+
+#include "ignite/network/codec.h"
+#include "ignite/network/codec_data_filter.h"
+#include "ignite/network/length_prefix_codec.h"
+#include "ignite/network/network.h"
+
+#include "ignite/protocol/writer.h"
+#include "ignite/protocol/reader.h"
+
+#include "cluster_connection.h"
+
+namespace
+{
+
+/**
+ * Make random GUID.
+ *
+ * @return Random GUID instance.
+ */
+ignite::Guid makeRandomGuid()
+{
+    static std::random_device rd;
+    static std::mt19937 gen(rd());
+
+    std::uniform_int_distribution<int64_t> distrib;
+    return {distrib(gen), distrib(gen)};
+}
+
+} // namespace
+
+namespace ignite::impl
+{
+
+ClusterConnection::ClusterConnection(const IgniteClientConfiguration &configuration) :
+    m_configuration(configuration),
+    m_pool(),
+    m_logger(m_configuration.getLogger()) { }
+
+void ClusterConnection::start()
+{
+    using namespace network;
+
+    if (m_pool)
+        return;
+
+    std::vector<TcpRange> addrs;
+    addrs.reserve(m_configuration.getEndpoints().size());
+    for (const auto& strAddr : m_configuration.getEndpoints())
+    {
+        std::optional<TcpRange> ep = TcpRange::parse(strAddr, DEFAULT_TCP_PORT);
+        if (!ep)
+            throw IgniteError("Can not parse address range: " + strAddr);
+
+        addrs.push_back(std::move(ep.value()));
+    }
+
+    DataFilters filters;
+
+    std::shared_ptr<Factory<Codec>> codecFactory = std::make_shared<LengthPrefixCodecFactory>();
+    std::shared_ptr<CodecDataFilter> codecFilter(new network::CodecDataFilter(codecFactory));
+    filters.push_back(codecFilter);
+
+    m_pool = network::makeAsyncClientPool(filters);
+
+    m_pool->setHandler(this);
+
+    // TODO: Implement connection limit.
+    m_pool->start(addrs, 0);
+
+    auto connectResult = m_initialConnect.get_future();
+
+    connectResult.get();
+}
+
+void ClusterConnection::onConnectionSuccess(const network::EndPoint &addr, uint64_t id)
+{
+    m_logger->logInfo("Established connection with remote host " + addr.toString());
+    m_logger->logDebug("Connection ID: " + std::to_string(id));
+
+    auto protocolCtx = std::make_shared<ProtocolContext>();
+
+    {
+        std::lock_guard<std::recursive_mutex> lock(m_inProgressMutex);
+
+        if (m_inProgress.find(id) != m_inProgress.end())
+            m_logger->logError("Unknown error: connecting is already in progress. Connection ID: " + std::to_string(id));
+
+        m_inProgress[id] = protocolCtx;
+    }
+
+    handshake(id, *protocolCtx);
+}
+
+void ClusterConnection::onConnectionError(const network::EndPoint &addr, const IgniteError &err)
+{
+    m_logger->logWarning("Failed to establish connection with remote host " + addr.toString() +
+        ", reason: " + err.what());
+}
+
+void ClusterConnection::onConnectionClosed(uint64_t id, const IgniteError *err)
+{
+    m_logger->logDebug("Closed Connection ID " + std::to_string(id));
+
+    {
+        std::lock_guard<std::recursive_mutex> lock(m_inProgressMutex);
+
+        auto it = m_inProgress.find(id);
+        if (it != m_inProgress.end())
+        {
+            handshakeFail(id, std::nullopt);
+
+            // No sense in locking connections mutex - connection was not established.
+            // Returning early.
+            return;
+        }
+    }
+
+    {
+        std::lock_guard<std::recursive_mutex> lock(m_connectionsMutex);
+
+        m_connections.erase(id);
+    }
+}
+
+void ClusterConnection::onMessageReceived(uint64_t id, const network::DataBuffer &msg)
+{
+    m_logger->logDebug("Message on Connection ID " + std::to_string(id) +
+        ", size: " + std::to_string(msg.getSize()));
+
+    std::shared_ptr<NodeConnection> connection;
+    {
+        std::lock_guard<std::recursive_mutex> lock(m_inProgressMutex);
+
+        auto it = m_inProgress.find(id);
+        if (it != m_inProgress.end())
+        {
+            try
+            {
+                handshakeRsp(*it->second, msg);
+
+                connection = std::make_shared<NodeConnection>(id, m_pool);
+
+                m_inProgress.erase(it);
+            }
+            catch (const IgniteError& err)
+            {
+                handshakeFail(id, err);
+
+                // No sense in locking connections mutex - connection was not established.
+                // Returning early.
+                return;
+            }
+        }
+    }
+
+    {
+        std::lock_guard<std::recursive_mutex> lock(m_connectionsMutex);
+
+        {
+            auto it = m_connections.find(id);
+            if (connection)
+            {
+                if (it != m_connections.end())
+                    m_logger->logError("Unknown error: connection already established. Connection ID: " + std::to_string(id));
+
+                m_connections[id] = connection;
+                m_initialConnect.set_value();
+            }
+            else
+                connection = it->second;
+        }
+    }
+
+    if (connection)
+        connection->processMessage(msg);
+}
+
+void ClusterConnection::onMessageSent(uint64_t id)
+{
+    m_logger->logDebug("Message sent successfully on Connection ID " + std::to_string(id));
+}
+
+void ClusterConnection::handshake(uint64_t id, ProtocolContext& context)
+{
+    static constexpr int8_t CLIENT_TYPE = 2;
+
+    auto buffer = std::make_shared<protocol::Buffer>();
+    buffer->writeRawData(BytesView(MAGIC_BYTES.data(), MAGIC_BYTES.size()));
+    buffer->reserveLengthHeader();
+
+    protocol::Writer::writeMessageToBuffer(*buffer, [&context](protocol::Writer& writer) {
+        auto ver = context.getVersion();
+
+        writer.write(ver.getMajor());
+        writer.write(ver.getMinor());
+        writer.write(ver.getPatch());
+
+        writer.write(CLIENT_TYPE);
+
+        // Features.
+        writer.writeBinaryEmpty();
+
+        // Extensions.
+        writer.writeMapEmpty();
+    });
+
+    network::DataBuffer dataBuffer(buffer);
+
+    try
+    {
+        m_pool->send(id, dataBuffer);
+    }
+    catch (const IgniteError& err)
+    {
+        handshakeFail(id, std::nullopt);
+    }
+}
+
+void ClusterConnection::handshakeFail(uint64_t id, std::optional<IgniteError> err)
+{
+    std::lock_guard<std::recursive_mutex> lock(m_inProgressMutex);
+
+    m_inProgress.erase(id);
+
+    if (err)
+        m_initialConnect.set_exception(std::make_exception_ptr<IgniteError>(std::move(err.value())));
+}
+
+void ClusterConnection::handshakeRsp(ProtocolContext& protocolCtx, const network::DataBuffer& buffer)
+{
+    protocol::Reader reader(buffer.getBytesView());
+
+    auto verMajor = reader.readInt16();
+    auto verMinor = reader.readInt16();
+    auto verPatch = reader.readInt16();
+
+    ProtocolVersion ver(verMajor, verMinor, verPatch);
+
+    // We now only support a single version
+    if (ver != ProtocolContext::CURRENT_VERSION)
+        throw IgniteError("Unsupported server version: " + ver.toString());
+
+    auto err = readError(reader);
+    if (err)
+        throw IgniteError(err.value());
+
+    (void) reader.readInt64(); // TODO: IGNITE-17606 Implement heartbeats
+    (void) reader.readString(); // Cluster node ID. Needed for partition-aware compute.
+    (void) reader.readString(); // Cluster node name. Needed for partition-aware compute.
+
+    reader.skip(); // Features.
+    reader.skip(); // Extensions.
+
+    protocolCtx.setVersion(ver);
+}
+
+std::optional<IgniteError> ClusterConnection::readError(protocol::Reader &reader)
+{
+    if (reader.tryReadNil())
+        return std::nullopt;
+
+    Guid traceId = reader.tryReadNil() ? makeRandomGuid() : reader.readGuid();
+    int32_t code = reader.tryReadNil() ? 65537 : reader.readInt32();
+    std::string className = reader.readString();
+    std::string message = reader.readString();
+
+    std::stringstream errMsgBuilder;
+
+    errMsgBuilder << className << ": " << message << " (" << code << ", " << traceId << ")";
+
+    return {IgniteError(StatusCode(code), errMsgBuilder.str())};
+}
+
+} // namespace ignite::impl
\ No newline at end of file
diff --git a/modules/platforms/cpp/client/src/cluster_connection.h b/modules/platforms/cpp/client/src/cluster_connection.h
new file mode 100644
index 0000000000..221b989c45
--- /dev/null
+++ b/modules/platforms/cpp/client/src/cluster_connection.h
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <array>
+#include <future>
+#include <memory>
+#include <unordered_map>
+#include <mutex>
+
+#include "ignite/network/async_client_pool.h"
+
+#include "ignite/ignite_client_configuration.h"
+#include "node_connection.h"
+#include "protocol_context.h"
+
+namespace ignite::protocol
+{
+
+class Reader;
+
+}
+
+namespace ignite::impl
+{
+
+/**
+ * Represents connection to the cluster.
+ *
+ * Considered established while there is connection to at least one server.
+ */
+class ClusterConnection : public network::AsyncHandler
+{
+public:
+    /** Default TCP port. */
+    static constexpr uint16_t DEFAULT_TCP_PORT = 10800;
+
+    /** Magic bytes. */
+    static constexpr std::array<std::byte, 4> MAGIC_BYTES =
+            { std::byte('I'), std::byte('G'), std::byte('N'), std::byte('I') };
+
+    // Deleted
+    ClusterConnection() = delete;
+    ClusterConnection(ClusterConnection&&) = delete;
+    ClusterConnection(const ClusterConnection&) = delete;
+    ClusterConnection& operator=(ClusterConnection&&) = delete;
+    ClusterConnection& operator=(const ClusterConnection&) = delete;
+
+    // Default
+    ~ClusterConnection() override = default;
+
+    /**
+     * Constructor.
+     *
+     * @param configuration Configuration.
+     */
+    explicit ClusterConnection(const IgniteClientConfiguration& configuration);
+
+    /**
+     * Start client.
+     */
+    void start();
+
+private:
+    /**
+     * Callback that called on successful connection establishment.
+     *
+     * @param addr Address of the new connection.
+     * @param id Connection ID.
+     */
+    void onConnectionSuccess(const network::EndPoint& addr, uint64_t id) override;
+
+    /**
+     * Callback that called on error during connection establishment.
+     *
+     * @param addr Connection address.
+     * @param err Error.
+     */
+    void onConnectionError(const network::EndPoint& addr, const IgniteError& err) override;
+
+    /**
+     * Callback that called on error during connection establishment.
+     *
+     * @param id Async client ID.
+     * @param err Error. Can be null if connection closed without error.
+     */
+    void onConnectionClosed(uint64_t id, const IgniteError* err) override;
+
+    /**
+     * Callback that called when new message is received.
+     *
+     * @param id Async client ID.
+     * @param msg Received message.
+     */
+    void onMessageReceived(uint64_t id, const network::DataBuffer& msg) override;
+
+    /**
+     * Callback that called when message is sent.
+     *
+     * @param id Async client ID.
+     */
+    void onMessageSent(uint64_t id) override;
+
+    /**
+     * Perform handshake.
+     *
+     * @param id Connection id.
+     * @param context Handshake context.
+     */
+    void handshake(uint64_t id, ProtocolContext &context);
+
+    /**
+     * Process handshake failure.
+     *
+     * @param id Connection ID.
+     * @param err Error. If set, connection is stopped and failed.
+     */
+    void handshakeFail(uint64_t id, std::optional<IgniteError> err);
+
+    /**
+     * Process handshake response.
+     *
+     * @param protocolCtx Handshake context.
+     * @param buffer Message.
+     */
+    static void handshakeRsp(ProtocolContext &protocolCtx, const network::DataBuffer &buffer);
+
+    /**
+     * Read error.
+     *
+     * @param reader Reader.
+     * @return Error.
+     */
+    static std::optional<IgniteError> readError(protocol::Reader& reader);
+
+    /** Configuration. */
+    const IgniteClientConfiguration& m_configuration;
+
+    /** Initial connect promise. */
+    std::promise<void> m_initialConnect;
+
+    /** Connection pool. */
+    std::shared_ptr<network::AsyncClientPool> m_pool;
+
+    /** Logger. */
+    std::shared_ptr<IgniteLogger> m_logger;
+
+    /** Node connections in progress. */
+    std::unordered_map<uint64_t, std::shared_ptr<ProtocolContext>> m_inProgress;
+
+    /** Node connections in progress mutex. */
+    std::recursive_mutex m_inProgressMutex;
+
+    /** Node connections. */
+    std::unordered_map<uint64_t, std::shared_ptr<NodeConnection>> m_connections;
+
+    /** Connections mutex. */
+    std::recursive_mutex m_connectionsMutex;
+};
+
+} // namespace ignite::impl
\ No newline at end of file
diff --git a/modules/platforms/cpp/common/Platform.h b/modules/platforms/cpp/client/src/ignite_client_impl.cpp
similarity index 54%
copy from modules/platforms/cpp/common/Platform.h
copy to modules/platforms/cpp/client/src/ignite_client_impl.cpp
index 7bfcebc447..99f64d6565 100644
--- a/modules/platforms/cpp/common/Platform.h
+++ b/modules/platforms/cpp/client/src/ignite_client_impl.cpp
@@ -15,36 +15,14 @@
  * limitations under the License.
  */
 
-#pragma once
+#include "ignite_client_impl.h"
 
-/**
- * Macro SWITCH_WIN_OTHER that uses first option on Windows and second on any other OS.
- */
-#ifdef WIN32
-#   define SWITCH_WIN_OTHER(x, y) (x)
-#else
-#   define SWITCH_WIN_OTHER(x, y) (y)
-#endif
-
-namespace ignite::platform
+namespace ignite::impl
 {
 
-/**
- * Byte order utility class.
- */
-class ByteOrder
+void IgniteClientImpl::start()
 {
-private:
-    static constexpr uint32_t fourBytes = 0x01020304;
-    static constexpr uint8_t lesserByte = (const uint8_t&)fourBytes;
-
-public:
-    ByteOrder() = delete;
-
-    static constexpr bool littleEndian = lesserByte == 0x04;
-    static constexpr bool bigEndian = lesserByte == 0x01;
-
-    static_assert(littleEndian || bigEndian, "Unknown byte order");
-};
+    m_connection.start();
+}
 
-} // ignite::platform
+} // namespace ignite::impl
\ No newline at end of file
diff --git a/modules/platforms/cpp/client/src/ignite_client_impl.h b/modules/platforms/cpp/client/src/ignite_client_impl.h
index 17be39464f..8d5701a466 100644
--- a/modules/platforms/cpp/client/src/ignite_client_impl.h
+++ b/modules/platforms/cpp/client/src/ignite_client_impl.h
@@ -22,6 +22,8 @@
 
 #include "ignite/ignite_client_configuration.h"
 
+#include "cluster_connection.h"
+
 namespace ignite::impl
 {
 
@@ -47,19 +49,20 @@ public:
      * @param configuration Configuration.
      */
     explicit IgniteClientImpl(IgniteClientConfiguration configuration) :
-        m_configuration(std::move(configuration)) { }
+        m_configuration(std::move(configuration)),
+        m_connection(m_configuration) { }
 
     /**
      * Start client.
      */
-    void start()
-    {
-        // TODO
-    }
+    void start();
 
 private:
     /** Configuration. */
     IgniteClientConfiguration m_configuration;
+
+    /** Cluster connection. */
+    ClusterConnection m_connection;
 };
 
 } // namespace ignite::impl
\ No newline at end of file
diff --git a/modules/platforms/cpp/common/Platform.h b/modules/platforms/cpp/client/src/node_connection.cpp
similarity index 54%
copy from modules/platforms/cpp/common/Platform.h
copy to modules/platforms/cpp/client/src/node_connection.cpp
index 7bfcebc447..3fabe69028 100644
--- a/modules/platforms/cpp/common/Platform.h
+++ b/modules/platforms/cpp/client/src/node_connection.cpp
@@ -15,36 +15,18 @@
  * limitations under the License.
  */
 
-#pragma once
+#include "node_connection.h"
 
-/**
- * Macro SWITCH_WIN_OTHER that uses first option on Windows and second on any other OS.
- */
-#ifdef WIN32
-#   define SWITCH_WIN_OTHER(x, y) (x)
-#else
-#   define SWITCH_WIN_OTHER(x, y) (y)
-#endif
-
-namespace ignite::platform
+namespace ignite::impl
 {
 
-/**
- * Byte order utility class.
- */
-class ByteOrder
-{
-private:
-    static constexpr uint32_t fourBytes = 0x01020304;
-    static constexpr uint8_t lesserByte = (const uint8_t&)fourBytes;
+NodeConnection::NodeConnection(uint64_t id, std::shared_ptr<network::AsyncClientPool> pool) :
+    m_id(id),
+    m_pool(std::move(pool)) { }
 
-public:
-    ByteOrder() = delete;
-
-    static constexpr bool littleEndian = lesserByte == 0x04;
-    static constexpr bool bigEndian = lesserByte == 0x01;
-
-    static_assert(littleEndian || bigEndian, "Unknown byte order");
-};
+void NodeConnection::processMessage(const network::DataBuffer &msg)
+{
+    // TODO:
+}
 
-} // ignite::platform
+} // namespace ignite::impl
\ No newline at end of file
diff --git a/modules/platforms/cpp/client/src/node_connection.h b/modules/platforms/cpp/client/src/node_connection.h
new file mode 100644
index 0000000000..a0cca9981d
--- /dev/null
+++ b/modules/platforms/cpp/client/src/node_connection.h
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <future>
+#include <memory>
+
+#include "ignite/network/async_client_pool.h"
+
+#include "ignite/ignite_client_configuration.h"
+
+namespace ignite::impl
+{
+
+class ClusterConnection;
+
+/**
+ * Represents connection to the cluster.
+ *
+ * Considered established while there is connection to at least one server.
+ */
+class NodeConnection
+{
+    friend class ClusterConnection;
+public:
+    // Deleted
+    NodeConnection() = delete;
+    NodeConnection(const NodeConnection&) = delete;
+    NodeConnection& operator=(NodeConnection&&) = delete;
+    NodeConnection& operator=(const NodeConnection&) = delete;
+
+    // Default
+    ~NodeConnection() = default;
+    NodeConnection(NodeConnection&&) = default;
+
+    /**
+     * Constructor.
+     *
+     * @param id Connection ID.
+     * @param pool Connection pool.
+     */
+    NodeConnection(uint64_t id, std::shared_ptr<network::AsyncClientPool> pool);
+
+private:
+    /**
+     * Callback that called when new message is received.
+     *
+     * @param msg Received message.
+     */
+    void processMessage(const network::DataBuffer& msg);
+
+    /** Connection ID. */
+    uint64_t m_id;
+
+    /** Handshake result. */
+    std::promise<void> handshakeRes;
+
+    /** Connection pool. */
+    std::shared_ptr<network::AsyncClientPool> m_pool;
+};
+
+} // namespace ignite::impl
\ No newline at end of file
diff --git a/modules/platforms/cpp/client/src/ignite_client_impl.h b/modules/platforms/cpp/client/src/protocol_context.h
similarity index 50%
copy from modules/platforms/cpp/client/src/ignite_client_impl.h
copy to modules/platforms/cpp/client/src/protocol_context.h
index 17be39464f..bd7823c8b7 100644
--- a/modules/platforms/cpp/client/src/ignite_client_impl.h
+++ b/modules/platforms/cpp/client/src/protocol_context.h
@@ -17,49 +17,56 @@
 
 #pragma once
 
-#include <future>
 #include <memory>
 
-#include "ignite/ignite_client_configuration.h"
+#include "ignite/network/data_buffer.h"
+#include "protocol_version.h"
 
 namespace ignite::impl
 {
 
 /**
- * Ignite client implementation.
+ * Represents connection to the cluster.
+ *
+ * Considered established while there is connection to at least one server.
  */
-class IgniteClientImpl
+class ProtocolContext
 {
 public:
-    // Deleted
-    IgniteClientImpl(const IgniteClientImpl&) = delete;
-    IgniteClientImpl& operator=(const IgniteClientImpl&) = delete;
+    static constexpr ProtocolVersion CURRENT_VERSION{1, 0, 0};
 
     // Default
-    IgniteClientImpl() = default;
-    ~IgniteClientImpl() = default;
-    IgniteClientImpl(IgniteClientImpl&&) = default;
-    IgniteClientImpl& operator=(IgniteClientImpl&&) = default;
+    ProtocolContext() = default;
+    ~ProtocolContext() = default;
+    ProtocolContext(ProtocolContext&&) = default;
+    ProtocolContext(const ProtocolContext&) = default;
+    ProtocolContext& operator=(ProtocolContext&&) = default;
+    ProtocolContext& operator=(const ProtocolContext&) = default;
 
     /**
-     * Constructor.
+     * Get protocol version.
      *
-     * @param configuration Configuration.
+     * @return protocol version.
      */
-    explicit IgniteClientImpl(IgniteClientConfiguration configuration) :
-        m_configuration(std::move(configuration)) { }
+    [[nodiscard]]
+    ProtocolVersion getVersion() const
+    {
+        return m_version;
+    }
 
     /**
-     * Start client.
+     * Set version.
+     *
+     * @param ver Version to set.
      */
-    void start()
+    void setVersion(ProtocolVersion ver)
     {
-        // TODO
+        m_version = ver;
     }
 
 private:
-    /** Configuration. */
-    IgniteClientConfiguration m_configuration;
+    /** Protocol version. */
+    ProtocolVersion m_version = CURRENT_VERSION;
 };
 
 } // namespace ignite::impl
\ No newline at end of file
diff --git a/modules/platforms/cpp/client/src/protocol_version.h b/modules/platforms/cpp/client/src/protocol_version.h
new file mode 100644
index 0000000000..7dc84b39e0
--- /dev/null
+++ b/modules/platforms/cpp/client/src/protocol_version.h
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include <string>
+#include <sstream>
+
+namespace ignite::impl
+{
+
+/** Protocol version. */
+class ProtocolVersion
+{
+public:
+    // Default
+    ProtocolVersion() = default;
+    ~ProtocolVersion() = default;
+    ProtocolVersion(ProtocolVersion&&) = default;
+    ProtocolVersion(const ProtocolVersion&) = default;
+    ProtocolVersion& operator=(ProtocolVersion&&) = default;
+    ProtocolVersion& operator=(const ProtocolVersion&) = default;
+
+    /**
+     * Constructor.
+     *
+     * @param vmajor Major version part.
+     * @param vminor Minor version part.
+     * @param vpatch Patch version part.
+     */
+    constexpr ProtocolVersion(int16_t vmajor, int16_t vminor, int16_t vpatch) :
+        m_major(vmajor),
+        m_minor(vminor),
+        m_patch(vpatch) { }
+
+    /**
+     * Get major part.
+     *
+     * @return Major part.
+     */
+    [[nodiscard]]
+    int16_t getMajor() const
+    {
+        return m_major;
+    }
+
+    /**
+     * Get minor part.
+     *
+     * @return Minor part.
+     */
+    [[nodiscard]]
+    int16_t getMinor() const
+    {
+        return m_minor;
+    }
+
+    /**
+     * Get patch version part.
+     *
+     * @return Patch version part.
+     */
+    [[nodiscard]]
+    int16_t getPatch() const
+    {
+        return m_patch;
+    }
+
+    /**
+     * Compare to another value.
+     *
+     * @param other Instance to compare to.
+     * @return Zero if equals, negative number if less and positive if more.
+     */
+    [[nodiscard]]
+    int32_t compare(const ProtocolVersion &other) const
+    {
+        int32_t res = m_major - other.m_major;
+        if (res != 0)
+            return res;
+
+        res = m_minor - other.m_minor;
+        if (res != 0)
+            return res;
+
+        return m_patch - other.m_patch;
+    }
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if equal.
+     */
+    friend bool operator==(const ProtocolVersion &val1, const ProtocolVersion &val2)
+    {
+        return val1.compare(val2) == 0;
+    }
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if not equal.
+     */
+    friend bool operator!=(const ProtocolVersion &val1, const ProtocolVersion &val2)
+    {
+        return val1.compare(val2) != 0;
+    }
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if less.
+     */
+    friend bool operator<(const ProtocolVersion &val1, const ProtocolVersion &val2)
+    {
+        return val1.compare(val2) < 0;
+    }
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if less or equal.
+     */
+    friend bool operator<=(const ProtocolVersion &val1, const ProtocolVersion &val2)
+    {
+        return val1.compare(val2) <= 0;
+    }
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if greater.
+     */
+    friend bool operator>(const ProtocolVersion &val1, const ProtocolVersion &val2)
+    {
+        return val1.compare(val2) > 0;
+    }
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if greater or equal.
+     */
+    friend bool operator>=(const ProtocolVersion &val1, const ProtocolVersion &val2)
+    {
+        return val1.compare(val2) >= 0;
+    }
+
+    /**
+     * Convert to string value.
+     *
+     * @return Protocol version.
+     */
+    [[nodiscard]]
+    std::string toString() const
+    {
+        std::stringstream buf;
+        buf << m_major << '.' << m_minor << '.' << m_patch;
+
+        return buf.str();
+    }
+
+private:
+    /** Major part. */
+    int16_t m_major;
+
+    /** Minor part. */
+    int16_t m_minor;
+
+    /** Maintenance part. */
+    int16_t m_patch;
+};
+
+} // namespace ignite::impl
diff --git a/modules/platforms/cpp/common/CMakeLists.txt b/modules/platforms/cpp/common/CMakeLists.txt
index 150b4c73a8..38aa5939a7 100644
--- a/modules/platforms/cpp/common/CMakeLists.txt
+++ b/modules/platforms/cpp/common/CMakeLists.txt
@@ -20,8 +20,9 @@ project(ignite-common)
 set(TARGET ${PROJECT_NAME})
 
 set(HEADERS
+    guid.h
+    ignite_error.h
     Types.h
-    Platform.h
 )
 
 add_library(${TARGET} INTERFACE)
diff --git a/modules/platforms/cpp/common/Platform.h b/modules/platforms/cpp/common/Platform.h
index 7bfcebc447..cbe4218b14 100644
--- a/modules/platforms/cpp/common/Platform.h
+++ b/modules/platforms/cpp/common/Platform.h
@@ -21,9 +21,9 @@
  * Macro SWITCH_WIN_OTHER that uses first option on Windows and second on any other OS.
  */
 #ifdef WIN32
-#   define SWITCH_WIN_OTHER(x, y) (x)
+#   define SWITCH_WIN_OTHER(x, y) x
 #else
-#   define SWITCH_WIN_OTHER(x, y) (y)
+#   define SWITCH_WIN_OTHER(x, y) y
 #endif
 
 namespace ignite::platform
diff --git a/modules/platforms/cpp/common/Platform.h b/modules/platforms/cpp/common/factory.h
similarity index 56%
copy from modules/platforms/cpp/common/Platform.h
copy to modules/platforms/cpp/common/factory.h
index 7bfcebc447..ab41b8edc2 100644
--- a/modules/platforms/cpp/common/Platform.h
+++ b/modules/platforms/cpp/common/factory.h
@@ -17,34 +17,31 @@
 
 #pragma once
 
-/**
- * Macro SWITCH_WIN_OTHER that uses first option on Windows and second on any other OS.
- */
-#ifdef WIN32
-#   define SWITCH_WIN_OTHER(x, y) (x)
-#else
-#   define SWITCH_WIN_OTHER(x, y) (y)
-#endif
+#include <memory>
 
-namespace ignite::platform
+namespace ignite
 {
 
 /**
- * Byte order utility class.
+ * Factory class.
+ *
+ * @tparam T Instances of this type factory builds.
  */
-class ByteOrder
+template<typename T>
+class Factory
 {
-private:
-    static constexpr uint32_t fourBytes = 0x01020304;
-    static constexpr uint8_t lesserByte = (const uint8_t&)fourBytes;
-
 public:
-    ByteOrder() = delete;
-
-    static constexpr bool littleEndian = lesserByte == 0x04;
-    static constexpr bool bigEndian = lesserByte == 0x01;
-
-    static_assert(littleEndian || bigEndian, "Unknown byte order");
+    /**
+     * Destructor.
+     */
+    virtual ~Factory() = default;
+
+    /**
+     * Build instance.
+     *
+     * @return New instance of type @c T.
+     */
+    virtual std::unique_ptr<T> build() = 0;
 };
 
-} // ignite::platform
+} // namespace ignite
diff --git a/modules/platforms/cpp/common/guid.h b/modules/platforms/cpp/common/guid.h
new file mode 100644
index 0000000000..77f6bd2a19
--- /dev/null
+++ b/modules/platforms/cpp/common/guid.h
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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;
+    Guid(Guid&&) = default;
+    Guid(const Guid&) = default;
+    Guid& operator=(Guid&&) = default;
+    Guid& operator=(const 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.
+     */
+    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.
+     */
+    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.
+     */
+    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.
+     */
+    std::int32_t getVariant() const
+    {
+        std::uint64_t 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.
+     */
+    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;
+    }
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if equal.
+     */
+    friend 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.
+     */
+    friend 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.
+     */
+    friend 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.
+     */
+    friend 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.
+     */
+    friend 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.
+     */
+    friend bool operator>=(const Guid& val1, const Guid& val2)
+    {
+        return val1.compare(val2) >= 0;
+    }
+
+private:
+    /** Most significant bits. */
+    std::int64_t m_most{0};
+
+    /** Least significant bits. */
+    std::int64_t m_least{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)
+{
+    uint32_t part1 = static_cast<uint32_t>(guid.getMostSignificantBits() >> 32);
+    uint16_t part2 = static_cast<uint16_t>(guid.getMostSignificantBits() >> 16);
+    uint16_t part3 = static_cast<uint16_t>(guid.getMostSignificantBits());
+    uint16_t part4 = static_cast<uint16_t>(guid.getLeastSignificantBits() >> 48);
+    uint64_t part5 = guid.getLeastSignificantBits() & 0x0000FFFFFFFFFFFFU;
+
+    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;
+
+    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((parts[0] << 32) | (parts[1] << 16) | parts[2], (parts[3] << 48) | parts[4]);
+
+    return is;
+}
+
+} // namespace ignite
diff --git a/modules/platforms/cpp/common/ignite_error.h b/modules/platforms/cpp/common/ignite_error.h
new file mode 100644
index 0000000000..b2224e2903
--- /dev/null
+++ b/modules/platforms/cpp/common/ignite_error.h
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <exception>
+#include <string>
+
+namespace ignite
+{
+
+/**
+ * Status code.
+ */
+enum class StatusCode : std::int32_t
+{
+    SUCCESS = 0,
+
+    GENERIC,
+
+    UNKNOWN,
+
+    NETWORK,
+
+    OS,
+};
+
+/**
+ * Ignite Error.
+ */
+class IgniteError : public std::exception
+{
+public:
+    // Default
+    IgniteError() = default;
+    ~IgniteError() override = default;
+    IgniteError(IgniteError&&) = default;
+    IgniteError(const IgniteError&) = default;
+    IgniteError& operator=(IgniteError&&) = default;
+    IgniteError& operator=(const IgniteError&) = default;
+
+    /**
+     * Constructor.
+     *
+     * @param statusCode Status code.
+     * @param message Message.
+     */
+    explicit IgniteError(StatusCode statusCode, std::string message) :
+        m_statusCode(statusCode),
+        m_message(std::move(message)) { }
+
+    /**
+     * Constructor.
+     *
+     * @param message Message.
+     */
+    explicit IgniteError(std::string message) :
+        m_statusCode(StatusCode::GENERIC),
+        m_message(std::move(message)) { }
+
+    /**
+     * Get error message.
+     */
+    [[nodiscard]]
+    char const* what() const override
+    {
+        return m_message.c_str();
+    }
+
+    /**
+     * Get status code.
+     *
+     * @return Status code.
+     */
+    [[nodiscard]]
+    StatusCode getStatusCode() const
+    {
+        return m_statusCode;
+    }
+
+private:
+    /** Status code. */
+    StatusCode m_statusCode{StatusCode::SUCCESS};
+
+    /** Message. */
+    std::string m_message;
+};
+
+} // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/conanfile.txt b/modules/platforms/cpp/conanfile.txt
index 48b519d8a1..cf328d1504 100644
--- a/modules/platforms/cpp/conanfile.txt
+++ b/modules/platforms/cpp/conanfile.txt
@@ -1,5 +1,6 @@
 [requires]
-msgpack-cxx/4.1.1
+openssl/1.1.1q
+msgpack-c/4.0.0
 gtest/1.12.1
 
 [generators]
diff --git a/modules/platforms/cpp/network/CMakeLists.txt b/modules/platforms/cpp/network/CMakeLists.txt
new file mode 100644
index 0000000000..3c8ad4a1ca
--- /dev/null
+++ b/modules/platforms/cpp/network/CMakeLists.txt
@@ -0,0 +1,70 @@
+#
+# 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.
+#
+
+project(ignite-network)
+
+set(TARGET ${PROJECT_NAME})
+
+find_package(OpenSSL REQUIRED)
+
+include_directories(include src ${OPENSSL_INCLUDE_DIR})
+
+set(SOURCES
+    src/network/async_client_pool_adapter.cpp
+    src/network/error_handling_filter.cpp
+    src/network/codec_data_filter.cpp
+    src/network/data_buffer.cpp
+    src/network/length_prefix_codec.cpp
+    src/network/network.cpp
+    src/network/tcp_range.cpp
+)
+
+if (WIN32)
+    include_directories(os/win/src)
+
+    list(APPEND SOURCES
+        os/win/src/network/sockets.cpp
+        os/win/src/network/utils.cpp
+        os/win/src/network/win_async_client.cpp
+        os/win/src/network/win_async_client_pool.cpp
+        os/win/src/network/win_async_connecting_thread.cpp
+        os/win/src/network/win_async_worker_thread.cpp
+    )
+else()
+    include_directories(os/linux/src)
+
+    list(APPEND SOURCES
+        os/linux/src/network/connecting_context.cpp
+        os/linux/src/network/linux_async_client.cpp
+        os/linux/src/network/linux_async_client_pool.cpp
+        os/linux/src/network/linux_async_worker_thread.cpp
+        os/linux/src/network/sockets.cpp
+    )
+endif()
+
+add_library(${TARGET} OBJECT ${SOURCES})
+
+set_target_properties(${TARGET} PROPERTIES VERSION ${CMAKE_PROJECT_VERSION})
+set_target_properties(${TARGET} PROPERTIES POSITION_INDEPENDENT_CODE 1)
+
+if (WIN32)
+    add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS)
+    target_link_libraries(${TARGET} wsock32 ws2_32 iphlpapi crypt32)
+endif()
+
+target_link_libraries(${TARGET} ignite-common ignite-protocol)
+target_include_directories(${TARGET} INTERFACE include)
diff --git a/modules/platforms/cpp/network/include/ignite/network/async_client_pool.h b/modules/platforms/cpp/network/include/ignite/network/async_client_pool.h
new file mode 100644
index 0000000000..26f23bda93
--- /dev/null
+++ b/modules/platforms/cpp/network/include/ignite/network/async_client_pool.h
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include <vector>
+
+#include <ignite/network/async_handler.h>
+#include <ignite/network/data_sink.h>
+#include <ignite/network/tcp_range.h>
+
+namespace ignite::network
+{
+
+/**
+ * Asynchronous client pool.
+ */
+class AsyncClientPool : public DataSink
+{
+public:
+    // Default
+    ~AsyncClientPool() override = default;
+
+    /**
+     * Start internal thread that establishes connections to provided addresses and asynchronously sends and
+     * receives messages from them. Function returns either when thread is started and first connection is
+     * established or failure happened.
+     *
+     * @param addrs Addresses to connect to.
+     * @param connLimit Connection upper limit. Zero means limit is disabled.
+     *
+     * @throw IgniteError on error.
+     */
+    virtual void start(std::vector<TcpRange> addrs, uint32_t connLimit) = 0;
+
+    /**
+     * Close all established connections and stops handling threads.
+     */
+    virtual void stop() = 0;
+
+    /**
+     * Set handler.
+     *
+     * @param handler Handler to set.
+     */
+    virtual void setHandler(AsyncHandler *handler) = 0;
+};
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/include/ignite/network/async_handler.h b/modules/platforms/cpp/network/include/ignite/network/async_handler.h
new file mode 100644
index 0000000000..6b780e276d
--- /dev/null
+++ b/modules/platforms/cpp/network/include/ignite/network/async_handler.h
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include <common/ignite_error.h>
+#include <ignite/network/end_point.h>
+#include <ignite/network/data_buffer.h>
+
+namespace ignite::network
+{
+
+/**
+ * Asynchronous events handler.
+ */
+class AsyncHandler
+{
+public:
+    /**
+     * Destructor.
+     */
+    virtual ~AsyncHandler() = default;
+
+    /**
+     * Callback that called on successful connection establishment.
+     *
+     * @param addr Address of the new connection.
+     * @param id Connection ID.
+     */
+    virtual void onConnectionSuccess(const EndPoint& addr, uint64_t id) = 0;
+
+    /**
+     * Callback that called on error during connection establishment.
+     *
+     * @param addr Connection address.
+     * @param err Error.
+     */
+    virtual void onConnectionError(const EndPoint& addr, const IgniteError& err) = 0;
+
+    /**
+     * Callback that called on error during connection establishment.
+     *
+     * @param id Async client ID.
+     * @param err Error. Can be null if connection closed without error.
+     */
+    virtual void onConnectionClosed(uint64_t id, const IgniteError* err) = 0;
+
+    /**
+     * Callback that called when new message is received.
+     *
+     * @param id Async client ID.
+     * @param msg Received message.
+     */
+    virtual void onMessageReceived(uint64_t id, const DataBuffer& msg) = 0;
+
+    /**
+     * Callback that called when message is sent.
+     *
+     * @param id Async client ID.
+     */
+    virtual void onMessageSent(uint64_t id) = 0;
+};
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/common/Platform.h b/modules/platforms/cpp/network/include/ignite/network/codec.h
similarity index 52%
copy from modules/platforms/cpp/common/Platform.h
copy to modules/platforms/cpp/network/include/ignite/network/codec.h
index 7bfcebc447..77ba75c21f 100644
--- a/modules/platforms/cpp/common/Platform.h
+++ b/modules/platforms/cpp/network/include/ignite/network/codec.h
@@ -17,34 +17,43 @@
 
 #pragma once
 
-/**
- * Macro SWITCH_WIN_OTHER that uses first option on Windows and second on any other OS.
- */
-#ifdef WIN32
-#   define SWITCH_WIN_OTHER(x, y) (x)
-#else
-#   define SWITCH_WIN_OTHER(x, y) (y)
-#endif
+#include <common/ignite_error.h>
+#include <common/factory.h>
+
+#include <ignite/network/data_buffer.h>
 
-namespace ignite::platform
+namespace ignite::network
 {
 
 /**
- * Byte order utility class.
+ * Codec class.
+ * Encodes and decodes data.
  */
-class ByteOrder
+class Codec
 {
-private:
-    static constexpr uint32_t fourBytes = 0x01020304;
-    static constexpr uint8_t lesserByte = (const uint8_t&)fourBytes;
-
 public:
-    ByteOrder() = delete;
-
-    static constexpr bool littleEndian = lesserByte == 0x04;
-    static constexpr bool bigEndian = lesserByte == 0x01;
-
-    static_assert(littleEndian || bigEndian, "Unknown byte order");
+    // Default
+    virtual ~Codec() = default;
+
+    /**
+     * Encode provided data.
+     *
+     * @param data Data to encode.
+     * @return Encoded data. Returning null is ok.
+     *
+     * @throw IgniteError on error.
+     */
+    virtual DataBuffer encode(DataBuffer& data) = 0;
+
+    /**
+     * Decode provided data.
+     *
+     * @param data Data to decode.
+     * @return Decoded data. Returning null means data is not yet ready.
+     *
+     * @throw IgniteError on error.
+     */
+    virtual DataBuffer decode(DataBuffer& data) = 0;
 };
 
-} // ignite::platform
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/include/ignite/network/codec_data_filter.h b/modules/platforms/cpp/network/include/ignite/network/codec_data_filter.h
new file mode 100644
index 0000000000..0a4de5f789
--- /dev/null
+++ b/modules/platforms/cpp/network/include/ignite/network/codec_data_filter.h
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <map>
+#include <mutex>
+
+#include <ignite/network/codec.h>
+#include <ignite/network/data_filter_adapter.h>
+
+namespace ignite::network
+{
+
+/**
+ * Data filter that uses codecs inside to encode/decode data.
+ */
+class CodecDataFilter : public DataFilterAdapter
+{
+public:
+    //Default
+    ~CodecDataFilter() override = default;
+
+    /**
+     * Constructor.
+     *
+     * @param factory Codec factory.
+     */
+    explicit CodecDataFilter(std::shared_ptr<Factory<Codec>> factory);
+
+    /**
+     * Send data to specific established connection.
+     *
+     * @param id Client ID.
+     * @param data Data to be sent.
+     * @return @c true if connection is present and @c false otherwise.
+     *
+     * @throw IgniteError on error.
+     */
+    bool send(uint64_t id, const DataBuffer& data) override;
+
+    /**
+      * Callback that called on successful connection establishment.
+      *
+      * @param addr Address of the new connection.
+      * @param id Connection ID.
+      */
+    void onConnectionSuccess(const EndPoint& addr, uint64_t id) override;
+
+    /**
+     * Callback that called on error during connection establishment.
+     *
+     * @param id Async client ID.
+     * @param err Error. Can be null if connection closed without error.
+     */
+    void onConnectionClosed(uint64_t id, const IgniteError* err) override;
+
+    /**
+     * Callback that called when new message is received.
+     *
+     * @param id Async client ID.
+     * @param msg Received message.
+     */
+    void onMessageReceived(uint64_t id, const DataBuffer& msg) override;
+
+private:
+    /**
+     * Get codec for connection.
+     *
+     * @param id Connection ID.
+     * @return Codec if found or null.
+     */
+    std::shared_ptr<Codec> FindCodec(uint64_t id);
+
+    /** Codec factory. */
+    std::shared_ptr<Factory<Codec>> m_codecFactory;
+
+    /** Codecs. */
+    std::map<uint64_t, std::shared_ptr<Codec>> m_codecs;
+
+    /** Mutex for secure access to codecs map. */
+    std::mutex m_codecsMutex;
+};
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/include/ignite/network/data_buffer.h b/modules/platforms/cpp/network/include/ignite/network/data_buffer.h
new file mode 100644
index 0000000000..b835d9cda4
--- /dev/null
+++ b/modules/platforms/cpp/network/include/ignite/network/data_buffer.h
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "common/Types.h"
+
+#include "ignite/protocol/buffer.h"
+
+namespace ignite::network
+{
+
+/**
+ * Data buffer.
+ */
+class DataBuffer
+{
+public:
+    /**
+     * Default constructor.
+     */
+    DataBuffer();
+
+    /**
+     * Constructor.
+     *
+     * @param data Data.
+     */
+    explicit DataBuffer(std::shared_ptr<protocol::Buffer> data);
+
+    /**
+     * Constructor.
+     *
+     * @param data Data.
+     * @param pos Start of data.
+     * @param len Length.
+     */
+    DataBuffer(std::shared_ptr<protocol::Buffer> data, int32_t pos, int32_t len);
+
+    /**
+     * Destructor.
+     */
+    ~DataBuffer() = default;
+
+    /**
+     * Consume data from buffer to specified place in memory.
+     *
+     * @param dst Destination in memory.
+     * @param size Number of bytes to copy.
+     */
+    void beConsumed(int8_t* dst, int32_t size);
+
+    /**
+     * Consume data from buffer to the vector.
+     *
+     * @param dst Vector to append data to.
+     * @param size Number of bytes to copy.
+     */
+    void beConsumed(std::vector<std::byte>& dst, int32_t toCopy);
+
+    /**
+     * Get data pointer.
+     *
+     * @return Data.
+     */
+    [[nodiscard]]
+    const int8_t* getData() const;
+
+    /**
+     * Get packet size.
+     *
+     * @return Packet size.
+     */
+    [[nodiscard]]
+    int32_t getSize() const;
+
+    /**
+     * Check whether data buffer was fully consumed.
+     *
+     * @return @c true if consumed and @c false otherwise.
+     */
+    [[nodiscard]]
+    bool isEmpty() const;
+
+    /**
+     * Consume the whole buffer.
+     *
+     * @return Buffer containing consumed data.
+     */
+    DataBuffer consumeEntirely();
+
+    /**
+     * Clone underlying buffer into a new one.
+     *
+     * @return New data buffer.
+     */
+    [[nodiscard]]
+    DataBuffer clone() const;
+
+    /**
+     * Skip specified number of bytes.
+     *
+     * @param bytes Bytes to skip.
+     */
+    void skip(int32_t bytes);
+
+    /**
+     * Get bytes view.
+     *
+     * @return Bytes view.
+     */
+    [[nodiscard]]
+    BytesView getBytesView() const;
+
+private:
+    /**
+     * Advance position in packet by specified value.
+     *
+     * @param val Bytes to advance.
+     */
+    void advance(int32_t val);
+
+    /** Position in current data. */
+    int32_t m_position;
+
+    /** Data length. */
+    int32_t m_length;
+
+    /** Data. */
+    std::shared_ptr<protocol::Buffer> m_data;
+};
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/include/ignite/network/data_filter.h b/modules/platforms/cpp/network/include/ignite/network/data_filter.h
new file mode 100644
index 0000000000..1c8d667ae7
--- /dev/null
+++ b/modules/platforms/cpp/network/include/ignite/network/data_filter.h
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <vector>
+#include <memory>
+
+#include <ignite/network/data_sink.h>
+#include <ignite/network/async_handler.h>
+
+namespace ignite::network
+{
+
+/**
+ * Data buffer.
+ */
+class DataFilter : public DataSink, public AsyncHandler
+{
+public:
+    // Default
+    DataFilter() = default;
+    ~DataFilter() override = default;
+
+    /**
+     * Set sink.
+     *
+     * @param sink Data sink
+     */
+    void setSink(DataSink* sink)
+    {
+        m_sink = sink;
+    }
+
+    /**
+     * Get sink.
+     *
+     * @return Data sink.
+     */
+    DataSink* getSink()
+    {
+        return m_sink;
+    }
+
+    /**
+     * Set handler.
+     *
+     * @param handler Event handler.
+     */
+    void setHandler(AsyncHandler* handler)
+    {
+        m_handler = handler;
+    }
+
+    /**
+     * Get handler.
+     *
+     * @return Event handler.
+     */
+    AsyncHandler* getHandler()
+    {
+        return m_handler;
+    }
+
+protected:
+    /** Sink. */
+    DataSink* m_sink{nullptr};
+
+    /** Handler. */
+    AsyncHandler* m_handler{nullptr};
+};
+
+typedef std::vector<std::shared_ptr<DataFilter>> DataFilters;
+
+} // namespace ignite::network
+
diff --git a/modules/platforms/cpp/network/include/ignite/network/data_filter_adapter.h b/modules/platforms/cpp/network/include/ignite/network/data_filter_adapter.h
new file mode 100644
index 0000000000..fb73f00362
--- /dev/null
+++ b/modules/platforms/cpp/network/include/ignite/network/data_filter_adapter.h
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <ignite/network/data_filter.h>
+
+namespace ignite::network
+{
+
+/**
+ * Data filter adapter.
+ */
+class DataFilterAdapter : public DataFilter
+{
+public:
+    // Default
+    DataFilterAdapter() = default;
+    ~DataFilterAdapter() override = default;
+
+    /**
+     * Send data to specific established connection.
+     *
+     * @param id Client ID.
+     * @param data Data to be sent.
+     * @return @c true if connection is present and @c false otherwise.
+     *
+     * @throw IgniteError on error.
+     */
+    bool send(uint64_t id, const DataBuffer& data) override
+    {
+        DataSink* sink = m_sink;
+        if (sink)
+            return sink->send(id, data);
+
+        return false;
+    }
+
+    /**
+     * Closes specified connection if it's established. Connection to the specified address is planned for
+     * re-connect. Error is reported to handler.
+     *
+     * @param id Client ID.
+     */
+    void close(uint64_t id, const IgniteError* err) override
+    {
+        DataSink* sink = m_sink;
+        if (sink)
+            sink->close(id, err);
+    }
+
+    /**
+      * Callback that called on successful connection establishment.
+      *
+      * @param addr Address of the new connection.
+      * @param id Connection ID.
+      */
+    void onConnectionSuccess(const EndPoint& addr, uint64_t id) override
+    {
+        AsyncHandler* handler = m_handler;
+        if (handler)
+            handler->onConnectionSuccess(addr, id);
+    }
+
+    /**
+     * Callback that called on error during connection establishment.
+     *
+     * @param addr Connection address.
+     * @param err Error.
+     */
+    void onConnectionError(const EndPoint& addr, const IgniteError& err) override
+    {
+        AsyncHandler* handler = m_handler;
+        if (handler)
+            handler->onConnectionError(addr, err);
+    }
+
+    /**
+     * Callback that called on error during connection establishment.
+     *
+     * @param id Async client ID.
+     * @param err Error. Can be null if connection closed without error.
+     */
+    void onConnectionClosed(uint64_t id, const IgniteError* err) override
+    {
+        AsyncHandler* handler = m_handler;
+        if (handler)
+            handler->onConnectionClosed(id, err);
+    }
+
+    /**
+     * Callback that called when new message is received.
+     *
+     * @param id Async client ID.
+     * @param msg Received message.
+     */
+    void onMessageReceived(uint64_t id, const DataBuffer& msg) override
+    {
+        AsyncHandler* handler = m_handler;
+        if (handler)
+            handler->onMessageReceived(id, msg);
+    }
+
+    /**
+     * Callback that called when message is sent.
+     *
+     * @param id Async client ID.
+     */
+    void onMessageSent(uint64_t id) override
+    {
+        AsyncHandler* handler = m_handler;
+        if (handler)
+            handler->onMessageSent(id);
+    }
+};
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/common/Platform.h b/modules/platforms/cpp/network/include/ignite/network/data_sink.h
similarity index 50%
copy from modules/platforms/cpp/common/Platform.h
copy to modules/platforms/cpp/network/include/ignite/network/data_sink.h
index 7bfcebc447..c6788e37a8 100644
--- a/modules/platforms/cpp/common/Platform.h
+++ b/modules/platforms/cpp/network/include/ignite/network/data_sink.h
@@ -17,34 +17,39 @@
 
 #pragma once
 
-/**
- * Macro SWITCH_WIN_OTHER that uses first option on Windows and second on any other OS.
- */
-#ifdef WIN32
-#   define SWITCH_WIN_OTHER(x, y) (x)
-#else
-#   define SWITCH_WIN_OTHER(x, y) (y)
-#endif
+#include <common/ignite_error.h>
+#include <ignite/network/data_buffer.h>
 
-namespace ignite::platform
+namespace ignite::network
 {
 
 /**
- * Byte order utility class.
+ * Data sink. Can consume data.
  */
-class ByteOrder
+class DataSink
 {
-private:
-    static constexpr uint32_t fourBytes = 0x01020304;
-    static constexpr uint8_t lesserByte = (const uint8_t&)fourBytes;
-
 public:
-    ByteOrder() = delete;
-
-    static constexpr bool littleEndian = lesserByte == 0x04;
-    static constexpr bool bigEndian = lesserByte == 0x01;
-
-    static_assert(littleEndian || bigEndian, "Unknown byte order");
+    // Default.
+    virtual ~DataSink() = default;
+
+    /**
+     * Send data to specific established connection.
+     *
+     * @param id Client ID.
+     * @param data Data to be sent.
+     * @return @c true if connection is present and @c false otherwise.
+     *
+     * @throw IgniteError on error.
+     */
+    virtual bool send(uint64_t id, const DataBuffer& data) = 0;
+
+    /**
+     * Closes specified connection if it's established. Connection to the specified address is planned for
+     * re-connect. Error is reported to handler.
+     *
+     * @param id Client ID.
+     */
+    virtual void close(uint64_t id, const IgniteError* err) = 0;
 };
 
-} // ignite::platform
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/include/ignite/network/end_point.h b/modules/platforms/cpp/network/include/ignite/network/end_point.h
new file mode 100644
index 0000000000..e949e81a95
--- /dev/null
+++ b/modules/platforms/cpp/network/include/ignite/network/end_point.h
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include <sstream>
+#include <utility>
+#include <vector>
+
+namespace ignite::network
+{
+
+/**
+ * Connection end point structure.
+ */
+struct EndPoint
+{
+    // Default
+    EndPoint() = default;
+    ~EndPoint() = default;
+    EndPoint(EndPoint&&) = default;
+    EndPoint(const EndPoint&) = default;
+    EndPoint& operator=(EndPoint&&) = default;
+    EndPoint& operator=(const EndPoint&) = default;
+
+    /**
+     * Constructor.
+     *
+     * @param host Host.
+     * @param port Port.
+     */
+    EndPoint(std::string  host, uint16_t port) :
+        host(std::move(host)),
+        port(port) { }
+
+    /**
+     * Convert to string.
+     *
+     * @return String form.
+     */
+    [[nodiscard]]
+    std::string toString() const
+    {
+        std::stringstream ss;
+        ss << host << ':' << port;
+
+        return ss.str();
+    }
+
+    /**
+     * Compare to another instance.
+     *
+     * @param other Another instance.
+     * @return Negative value if less, positive if larger and zero, if equals
+     *   another instance.
+     */
+    [[nodiscard]]
+    int compare(const EndPoint& other) const
+    {
+        if (port < other.port)
+            return -1;
+
+        if (port > other.port)
+            return 1;
+
+        return host.compare(other.host);
+    }
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if equal.
+     */
+    friend bool operator==(const EndPoint& val1, const EndPoint& val2)
+    {
+        return val1.port == val2.port && val1.host == val2.host;
+    }
+
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if not equal.
+     */
+    friend bool operator!=(const EndPoint& val1, const EndPoint& val2)
+    {
+        return !(val1 == val2);
+    }
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if less.
+     */
+    friend bool operator<(const EndPoint& val1, const EndPoint& val2)
+    {
+        return val1.compare(val2) < 0;
+    }
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if less or equal.
+     */
+    friend bool operator<=(const EndPoint& val1, const EndPoint& val2)
+    {
+        return val1.compare(val2) <= 0;
+    }
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if gretter.
+     */
+    friend bool operator>(const EndPoint& val1, const EndPoint& val2)
+    {
+        return val1.compare(val2) > 0;
+    }
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if gretter or equal.
+     */
+    friend bool operator>=(const EndPoint& val1, const EndPoint& val2)
+    {
+        return val1.compare(val2) >= 0;
+    }
+
+    /** Remote host. */
+    std::string host;
+
+    /** TCP port. */
+    uint16_t port = 0;
+};
+
+} // namespace ignite::network
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
new file mode 100644
index 0000000000..93c47fe268
--- /dev/null
+++ b/modules/platforms/cpp/network/include/ignite/network/length_prefix_codec.h
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <vector>
+#include <cstddef>
+
+#include <common/ignite_error.h>
+
+#include <ignite/network/codec.h>
+
+namespace ignite::network
+{
+
+/**
+ * Codec that decodes messages prefixed with int32 length.
+ */
+class LengthPrefixCodec : public Codec
+{
+public:
+    /** Packet header size in bytes. */
+    static constexpr int32_t PACKET_HEADER_SIZE = 4;
+
+    // Default
+    ~LengthPrefixCodec() override = default;
+
+    /**
+     * Constructor.
+     */
+    LengthPrefixCodec();
+
+    /**
+     * Encode provided data.
+     *
+     * @param data Data to encode.
+     * @return Encoded data. Returning null is ok.
+     *
+     * @throw IgniteError on error.
+     */
+    DataBuffer encode(DataBuffer& data) override;
+
+    /**
+     * Decode provided data.
+     *
+     * @param data Data to decode.
+     * @return Decoded data. Returning null means data is not yet ready.
+     *
+     * @throw IgniteError on error.
+     */
+    DataBuffer decode(DataBuffer& data) override;
+
+private:
+    /**
+     * Consume the right amount of provided data to make packet closer to desired size.
+     *
+     * @param data Data to consume.
+     * @param desired Desired resulting size of packet.
+     */
+    void consume(DataBuffer& data, int32_t desired);
+
+    /** Size of the current packet. */
+    int32_t m_packetSize;
+
+    /** Current packet */
+    std::vector<std::byte> m_packet;
+};
+
+/**
+ * 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>();
+    }
+};
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/common/Platform.h b/modules/platforms/cpp/network/include/ignite/network/network.h
similarity index 56%
copy from modules/platforms/cpp/common/Platform.h
copy to modules/platforms/cpp/network/include/ignite/network/network.h
index 7bfcebc447..7a43240678 100644
--- a/modules/platforms/cpp/common/Platform.h
+++ b/modules/platforms/cpp/network/include/ignite/network/network.h
@@ -17,34 +17,20 @@
 
 #pragma once
 
-/**
- * Macro SWITCH_WIN_OTHER that uses first option on Windows and second on any other OS.
- */
-#ifdef WIN32
-#   define SWITCH_WIN_OTHER(x, y) (x)
-#else
-#   define SWITCH_WIN_OTHER(x, y) (y)
-#endif
+#include <string>
 
-namespace ignite::platform
+#include <ignite/network/async_client_pool.h>
+#include <ignite/network/data_filter.h>
+
+namespace ignite::network
 {
 
 /**
- * Byte order utility class.
+ * Make asynchronous client pool.
+ *
+ * @param filters Filters.
+ * @return Async client pool.
  */
-class ByteOrder
-{
-private:
-    static constexpr uint32_t fourBytes = 0x01020304;
-    static constexpr uint8_t lesserByte = (const uint8_t&)fourBytes;
-
-public:
-    ByteOrder() = delete;
-
-    static constexpr bool littleEndian = lesserByte == 0x04;
-    static constexpr bool bigEndian = lesserByte == 0x01;
-
-    static_assert(littleEndian || bigEndian, "Unknown byte order");
-};
+std::shared_ptr<AsyncClientPool> makeAsyncClientPool(DataFilters filters);
 
-} // ignite::platform
+}
diff --git a/modules/platforms/cpp/network/include/ignite/network/tcp_range.h b/modules/platforms/cpp/network/include/ignite/network/tcp_range.h
new file mode 100644
index 0000000000..7afaddda03
--- /dev/null
+++ b/modules/platforms/cpp/network/include/ignite/network/tcp_range.h
@@ -0,0 +1,174 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include <optional>
+
+namespace ignite::network
+{
+
+/**
+ * TCP port range.
+ */
+struct TcpRange
+{
+    // Default
+    TcpRange() = default;
+    ~TcpRange() = default;
+    TcpRange(TcpRange&&) = default;
+    TcpRange(const TcpRange&) = default;
+    TcpRange& operator=(TcpRange&&) = default;
+    TcpRange& operator=(const TcpRange&) = default;
+
+    /**
+     * Parse string and try to get TcpRange.
+     *
+     * @param str String to parse.
+     * @param defPort Default port.
+     * @return TcpRange instance on success and none on failure.
+     */
+    static std::optional<TcpRange> parse(std::string_view str, uint16_t defPort);
+
+    /**
+     * Constructor.
+     *
+     * @param host Host.
+     * @param port Port.
+     * @param range Number of ports after the @c port that
+     *    should be tried if the previous are unavailable.
+     */
+    TcpRange(std::string host, uint16_t port, uint16_t range = 0) :
+        host(std::move(host)),
+        port(port),
+        range(range) { }
+
+    /**
+     * Compare to another instance.
+     *
+     * @param other Another instance.
+     * @return Negative value if less, positive if larger and
+     *    zero, if equals another instance.
+     */
+    [[nodiscard]]
+    int compare(const TcpRange& other) const;
+
+    /**
+     * Check whether empty.
+     *
+     * @return @c true if empty.
+     */
+    [[nodiscard]]
+    bool isEmpty() const
+    {
+        return host.empty();
+    }
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if equal.
+     */
+    friend bool operator==(const TcpRange& val1, const TcpRange& val2)
+    {
+        return val1.port == val2.port && val1.range == val2.range && val1.host == val2.host;
+    }
+
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if not equal.
+     */
+    friend bool operator!=(const TcpRange& val1, const TcpRange& val2)
+    {
+        return !(val1 == val2);
+    }
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if less.
+     */
+    friend bool operator<(const TcpRange& val1, const TcpRange& val2)
+    {
+        return val1.compare(val2) < 0;
+    }
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if less or equal.
+     */
+    friend bool operator<=(const TcpRange& val1, const TcpRange& val2)
+    {
+        return val1.compare(val2) <= 0;
+    }
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if greater.
+     */
+    friend bool operator>(const TcpRange& val1, const TcpRange& val2)
+    {
+        return val1.compare(val2) > 0;
+    }
+
+    /**
+     * Comparison operator.
+     *
+     * @param val1 First value.
+     * @param val2 Second value.
+     * @return True if greater or equal.
+     */
+    friend bool operator>=(const TcpRange& val1, const TcpRange& val2)
+    {
+        return val1.compare(val2) >= 0;
+    }
+
+    /**
+     * Convert to string.
+     *
+     * @return String representation.
+     */
+    [[nodiscard]]
+    std::string toString() const;
+
+    /** Remote host. */
+    std::string host;
+
+    /** TCP port. */
+    uint16_t port{0};
+
+    /** Number of ports after the port that should be tried if the previous are unavailable. */
+    uint16_t range{0};
+};
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/os/linux/src/network/connecting_context.cpp b/modules/platforms/cpp/network/os/linux/src/network/connecting_context.cpp
new file mode 100644
index 0000000000..b22c2e6c3b
--- /dev/null
+++ b/modules/platforms/cpp/network/os/linux/src/network/connecting_context.cpp
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <sys/epoll.h>
+#include <unistd.h>
+
+#include <cstring>
+#include <iterator>
+
+#include <ignite/common/utils.h>
+#include <network/utils.h>
+
+#include "network/connecting_context.h"
+
+namespace ignite
+{
+    namespace network
+    {
+        ConnectingContext::ConnectingContext(const TcpRange &range) :
+            range(range),
+            nextPort(range.port),
+            info(0),
+            currentInfo(0)
+        {
+            // No-op.
+        }
+
+        ConnectingContext::~ConnectingContext()
+        {
+            Reset();
+        }
+
+        void ConnectingContext::Reset()
+        {
+            if (info)
+            {
+                freeaddrinfo(info);
+                info = 0;
+                currentInfo = 0;
+            }
+
+            nextPort = range.port;
+        }
+
+        addrinfo *ConnectingContext::Next()
+        {
+            if (currentInfo)
+                currentInfo = currentInfo->ai_next;
+
+            while (!currentInfo)
+            {
+                if (info)
+                {
+                    freeaddrinfo(info);
+                    info = 0;
+                }
+
+                if (nextPort > range.port + range.range)
+                    return 0;
+
+                addrinfo hints;
+                std::memset(&hints, 0, sizeof(hints));
+
+                hints.ai_family = AF_UNSPEC;
+                hints.ai_socktype = SOCK_STREAM;
+                hints.ai_protocol = IPPROTO_TCP;
+
+                std::string strPort = common::LexicalCast<std::string>(nextPort);
+
+                // Resolve the server address and port
+                int res = getaddrinfo(range.host.c_str(), strPort.c_str(), &hints, &info);
+                if (res != 0)
+                    return 0;
+
+                currentInfo = info;
+                ++nextPort;
+            }
+
+            return currentInfo;
+        }
+
+        EndPoint ConnectingContext::getAddress() const
+        {
+            return EndPoint(range.host, nextPort - 1);
+        }
+
+        SP_LinuxAsyncClient ConnectingContext::ToClient(int fd)
+        {
+            return SP_LinuxAsyncClient(new LinuxAsyncClient(fd, getAddress(), range));
+        }
+    }
+}
diff --git a/modules/platforms/cpp/network/os/linux/src/network/connecting_context.h b/modules/platforms/cpp/network/os/linux/src/network/connecting_context.h
new file mode 100644
index 0000000000..8b7ebcd241
--- /dev/null
+++ b/modules/platforms/cpp/network/os/linux/src/network/connecting_context.h
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+#ifndef _IGNITE_NETWORK_CONNECTING_CONTEXT
+#define _IGNITE_NETWORK_CONNECTING_CONTEXT
+
+#include <netdb.h>
+
+#include <stdint.h>
+#include <memory>
+
+#include <ignite/network/end_point.h>
+#include <ignite/network/tcp_range.h>
+
+#include "network/linux_async_client.h"
+
+namespace ignite
+{
+    namespace network
+    {
+        /**
+         * Connecting context.
+         */
+        class ConnectingContext
+        {
+        public:
+            /**
+             * Constructor.
+             */
+            ConnectingContext(const TcpRange& range);
+
+            /**
+             * Destructor.
+             */
+            ~ConnectingContext();
+
+            /**
+             * Reset connection context to it's initial state.
+             */
+            void Reset();
+
+            /**
+             * Next address in range.
+             *
+             * @return Next addrinfo for connection.
+             */
+            addrinfo* Next();
+
+            /**
+             * Get lastaddress.
+             *
+             * @return Address.
+             */
+            EndPoint getAddress() const;
+
+            /**
+             * Make client.
+             *
+             * @param fd Socket file descriptor.
+             * @return Client instance from current internal state.
+             */
+            SP_LinuxAsyncClient ToClient(int fd);
+
+        private:
+            IGNITE_NO_COPY_ASSIGNMENT(ConnectingContext);
+
+            /** Range. */
+            const TcpRange range;
+
+            /** Next port. */
+            uint16_t nextPort;
+
+            /** Current addrinfo. */
+            addrinfo* info;
+
+            /** Addrinfo which is currently used for connection */
+            addrinfo* currentInfo;
+        };
+    }
+}
+
+#endif //_IGNITE_NETWORK_CONNECTING_CONTEXT
diff --git a/modules/platforms/cpp/network/os/linux/src/network/linux_async_client.cpp b/modules/platforms/cpp/network/os/linux/src/network/linux_async_client.cpp
new file mode 100644
index 0000000000..127d151ffd
--- /dev/null
+++ b/modules/platforms/cpp/network/os/linux/src/network/linux_async_client.cpp
@@ -0,0 +1,198 @@
+/*
+ * 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.
+ */
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <sys/epoll.h>
+#include <unistd.h>
+
+#include <algorithm>
+
+#include <ignite/common/utils.h>
+#include <network/utils.h>
+
+#include "network/sockets.h"
+#include "network/linux_async_client.h"
+
+namespace ignite
+{
+    namespace network
+    {
+        LinuxAsyncClient::LinuxAsyncClient(int fd, const EndPoint &addr, const TcpRange &range) :
+            m_state(State::CONNECTED),
+            fd(fd),
+            epoll(-1),
+            id(0),
+            addr(addr),
+            range(range),
+            m_sendPackets(),
+            m_sendMutex(),
+            m_recvPacket(),
+            m_closeErr(IgniteError::IGNITE_SUCCESS)
+        {
+            // No-op.
+        }
+
+        LinuxAsyncClient::~LinuxAsyncClient()
+        {
+            shutdown(0);
+
+            close();
+        }
+
+        bool LinuxAsyncClient::shutdown(const IgniteError* err)
+        {
+            common::concurrent::CsLockGuard lock(m_sendMutex);
+            if (m_state != State::CONNECTED)
+                return false;
+
+            m_closeErr = err ? *err : IgniteError(IgniteError::IGNITE_ERR_GENERIC, "Connection closed by application");
+            shutdown(fd, SHUT_RDWR);
+            m_state = State::SHUTDOWN;
+
+            return true;
+        }
+
+        bool LinuxAsyncClient::close()
+        {
+            if (State::CLOSED == m_state)
+                return false;
+
+            StopMonitoring();
+            close(fd);
+            fd = -1;
+            m_state = State::CLOSED;
+
+            return true;
+        }
+
+        bool LinuxAsyncClient::send(const DataBuffer& data)
+        {
+            common::concurrent::CsLockGuard lock(m_sendMutex);
+
+            m_sendPackets.push_back(data);
+
+            if (m_sendPackets.size() > 1)
+                return true;
+
+            return sendNextPacketLocked();
+        }
+
+        bool LinuxAsyncClient::sendNextPacketLocked()
+        {
+            if (m_sendPackets.empty())
+                return true;
+
+            DataBuffer& packet = m_sendPackets.front();
+
+            ssize_t ret = send(fd, packet.GetData(), packet.GetSize(), 0);
+            if (ret < 0)
+                return false;
+
+            packet.Skip(static_cast<int32_t>(ret));
+
+            EnableSendNotifications();
+
+            return true;
+        }
+
+        DataBuffer LinuxAsyncClient::receive()
+        {
+            using namespace impl::interop;
+
+            if (!m_recvPacket.IsValid())
+            {
+                m_recvPacket = SP_InteropMemory(new InteropUnpooledMemory(BUFFER_SIZE));
+                m_recvPacket->Length(BUFFER_SIZE);
+            }
+
+            ssize_t res = recv(fd, m_recvPacket->Data(), m_recvPacket->Length(), 0);
+            if (res < 0)
+                return DataBuffer();
+
+            return DataBuffer(m_recvPacket, 0, static_cast<int32_t>(res));
+        }
+
+        bool LinuxAsyncClient::StartMonitoring(int epoll0)
+        {
+            if (epoll0 < 0)
+                return false;
+
+            epoll_event event;
+            std::memset(&event, 0, sizeof(event));
+            event.data.ptr = this;
+            event.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP;
+
+            int res = epoll_ctl(epoll0, EPOLL_CTL_ADD, fd, &event);
+            if (res < 0)
+                return false;
+
+            epoll = epoll0;
+
+            return true;
+        }
+
+        void LinuxAsyncClient::StopMonitoring()
+        {
+            epoll_event event;
+            std::memset(&event, 0, sizeof(event));
+
+            epoll_ctl(epoll, EPOLL_CTL_DEL, fd, &event);
+        }
+
+        void LinuxAsyncClient::EnableSendNotifications()
+        {
+            epoll_event event;
+            std::memset(&event, 0, sizeof(event));
+            event.data.ptr = this;
+            event.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP;
+
+            epoll_ctl(epoll, EPOLL_CTL_MOD, fd, &event);
+        }
+
+        void LinuxAsyncClient::DisableSendNotifications()
+        {
+            epoll_event event;
+            std::memset(&event, 0, sizeof(event));
+            event.data.ptr = this;
+            event.events = EPOLLIN | EPOLLRDHUP;
+
+            epoll_ctl(epoll, EPOLL_CTL_MOD, fd, &event);
+        }
+
+        bool LinuxAsyncClient::processSent()
+        {
+            common::concurrent::CsLockGuard lock(m_sendMutex);
+
+            if (m_sendPackets.empty())
+            {
+                DisableSendNotifications();
+
+                return true;
+            }
+
+            DataBuffer& front = m_sendPackets.front();
+
+            if (front.isEmpty())
+                m_sendPackets.pop_front();
+
+            return sendNextPacketLocked();
+        }
+    }
+}
diff --git a/modules/platforms/cpp/network/os/linux/src/network/linux_async_client.h b/modules/platforms/cpp/network/os/linux/src/network/linux_async_client.h
new file mode 100644
index 0000000000..6191f2ba11
--- /dev/null
+++ b/modules/platforms/cpp/network/os/linux/src/network/linux_async_client.h
@@ -0,0 +1,249 @@
+/*
+ * 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.
+ */
+
+#ifndef _IGNITE_NETWORK_LINUX_ASYNC_CLIENT
+#define _IGNITE_NETWORK_LINUX_ASYNC_CLIENT
+
+#include "network/sockets.h"
+
+#include <stdint.h>
+#include <deque>
+
+#include <ignite/common/concurrent.h>
+#include <ignite/impl/interop/interop_memory.h>
+
+#include <ignite/network/async_handler.h>
+#include <ignite/network/codec.h>
+#include <ignite/network/end_point.h>
+#include <ignite/network/tcp_range.h>
+
+namespace ignite
+{
+    namespace network
+    {
+        /**
+         * Linux-specific implementation of async network client.
+         */
+        class LinuxAsyncClient
+        {
+            /**
+             * State.
+             */
+            struct State
+            {
+                enum Type
+                {
+                    CONNECTED,
+
+                    SHUTDOWN,
+
+                    CLOSED,
+                };
+            };
+
+        public:
+            enum { BUFFER_SIZE = 0x10000 };
+
+            /**
+             * Constructor.
+             *
+             * @param fd Socket file descriptor.
+             * @param addr Address.
+             * @param range Range.
+             */
+            LinuxAsyncClient(int fd, const EndPoint& addr, const TcpRange& range);
+
+            /**
+             * Destructor.
+             *
+             * Should not be destructed from external threads.
+             * Can be destructed from WorkerThread.
+             */
+            ~LinuxAsyncClient();
+
+            /**
+             * Shutdown client.
+             *
+             * Can be called from external threads.
+             * Can be called from WorkerThread.
+             *
+             * @param err Error message. Can be null.
+             * @return @c true if shutdown performed successfully.
+             */
+            bool shutdown(const IgniteError* err);
+
+            /**
+             * Close client.
+             *
+             * Should not be called from external threads.
+             * Can be called from WorkerThread.
+             *
+             * @return @c true if shutdown performed successfully.
+             */
+            bool close();
+
+            /**
+             * Send packet using client.
+             *
+             * @param data Data to send.
+             * @return @c true on success.
+             */
+            bool send(const DataBuffer& data);
+
+            /**
+             * Initiate next receive of data.
+             *
+             * @return @c true on success.
+             */
+            DataBuffer receive();
+
+            /**
+             * Process sent data.
+             *
+             * @return @c true on success.
+             */
+            bool processSent();
+
+            /**
+             * Start monitoring client.
+             *
+             * @param epoll Epoll file descriptor.
+             * @return @c true on success.
+             */
+            bool StartMonitoring(int epoll);
+
+            /**
+             * Stop monitoring client.
+             */
+            void StopMonitoring();
+
+            /**
+             * Enable epoll notifications.
+             */
+            void EnableSendNotifications();
+
+            /**
+             * Disable epoll notifications.
+             */
+            void DisableSendNotifications();
+
+            /**
+             * Get client ID.
+             *
+             * @return Client ID.
+             */
+            uint64_t GetId() const
+            {
+                return id;
+            }
+
+            /**
+             * Set ID.
+             *
+             * @param id ID to set.
+             */
+            void setId(uint64_t id)
+            {
+                this->id = id;
+            }
+
+            /**
+             * Get address.
+             *
+             * @return Address.
+             */
+            const EndPoint& getAddress() const
+            {
+                return addr;
+            }
+
+            /**
+             * Get range.
+             *
+             * @return Range.
+             */
+            const TcpRange& getRange() const
+            {
+                return range;
+            }
+
+            /**
+             * Check whether client is closed.
+             *
+             * @return @c true if closed.
+             */
+            bool isClosed() const
+            {
+                return m_state == State::CLOSED;
+            }
+
+            /**
+             * Get closing error for the connection. Can be IGNITE_SUCCESS.
+             *
+             * @return Connection error.
+             */
+            const IgniteError& getCloseError() const
+            {
+                return m_closeErr;
+            }
+
+        private:
+            /**
+             * Send next packet in queue.
+             *
+             * @warning Can only be called when holding m_sendMutex lock.
+             * @return @c true on success.
+             */
+            bool sendNextPacketLocked();
+
+            /** State. */
+            State::Type m_state;
+
+            /** Socket file descriptor. */
+            int fd;
+
+            /** Epoll file descriptor. */
+            int epoll;
+
+            /** Connection ID. */
+            uint64_t id;
+
+            /** Server end point. */
+            EndPoint addr;
+
+            /** Address range associated with current connection. */
+            TcpRange range;
+
+            /** Packets that should be sent. */
+            std::deque<DataBuffer> m_sendPackets;
+
+            /** Send critical section. */
+            common::concurrent::CriticalSection m_sendMutex;
+
+            /** Packet that is currently received. */
+            impl::interop::SP_InteropMemory m_recvPacket;
+
+            /** Closing error. */
+            IgniteError m_closeErr;
+        };
+
+        /** Shared pointer to async client. */
+        typedef common::concurrent::SharedPointer<LinuxAsyncClient> SP_LinuxAsyncClient;
+    }
+}
+
+#endif //_IGNITE_NETWORK_LINUX_ASYNC_CLIENT
diff --git a/modules/platforms/cpp/network/os/linux/src/network/linux_async_client_pool.cpp b/modules/platforms/cpp/network/os/linux/src/network/linux_async_client_pool.cpp
new file mode 100644
index 0000000000..981b8bd884
--- /dev/null
+++ b/modules/platforms/cpp/network/os/linux/src/network/linux_async_client_pool.cpp
@@ -0,0 +1,212 @@
+/*
+ * 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.
+ */
+
+#include <algorithm>
+
+#include <ignite/common/utils.h>
+#include <network/utils.h>
+
+#include "network/sockets.h"
+#include "network/linux_async_client_pool.h"
+
+namespace ignite
+{
+    namespace network
+    {
+        LinuxAsyncClientPool::LinuxAsyncClientPool() :
+            m_stopping(true),
+            m_asyncHandler(0),
+            m_workerThread(*this),
+            m_idGen(0),
+            m_clientsMutex(),
+            m_clientIdMap()
+        {
+            // No-op.
+        }
+
+        LinuxAsyncClientPool::~LinuxAsyncClientPool()
+        {
+            InternalStop();
+        }
+
+        void LinuxAsyncClientPool::start(const std::vector<TcpRange> &addrs, uint32_t connLimit)
+        {
+            if (!m_stopping)
+                throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, "Client pool is already started");
+
+            m_idGen = 0;
+            m_stopping = false;
+
+            try
+            {
+                m_workerThread.Start0(connLimit, addrs);
+            }
+            catch (...)
+            {
+                stop();
+
+                throw;
+            }
+        }
+
+        void LinuxAsyncClientPool::stop()
+        {
+            InternalStop();
+        }
+
+        bool LinuxAsyncClientPool::send(uint64_t id, const DataBuffer &data)
+        {
+            if (m_stopping)
+                return false;
+
+            SP_LinuxAsyncClient client = FindClient(id);
+            if (!client.IsValid())
+                return false;
+
+            return client->send(data);
+        }
+
+        void LinuxAsyncClientPool::close(uint64_t id, const IgniteError *err)
+        {
+            if (m_stopping)
+                return;
+
+            SP_LinuxAsyncClient client = FindClient(id);
+            if (client.IsValid() && !client->isClosed())
+                client->shutdown(err);
+        }
+
+        void LinuxAsyncClientPool::closeAndRelease(uint64_t id, const IgniteError *err)
+        {
+            if (m_stopping)
+                return;
+
+            SP_LinuxAsyncClient client;
+            {
+                common::concurrent::CsLockGuard lock(m_clientsMutex);
+
+                std::map<uint64_t, SP_LinuxAsyncClient>::iterator it = m_clientIdMap.find(id);
+                if (it == m_clientIdMap.end())
+                    return;
+
+                client = it->second;
+
+                m_clientIdMap.erase(it);
+            }
+
+            bool closed = client->close();
+            if (closed)
+            {
+                IgniteError err0(client->getCloseError());
+                if (err0.GetCode() == IgniteError::IGNITE_SUCCESS)
+                    err0 = IgniteError(IgniteError::IGNITE_ERR_NETWORK_FAILURE, "Connection closed by server");
+
+                if (!err)
+                    err = &err0;
+
+                HandleConnectionClosed(id, err);
+            }
+        }
+
+        bool LinuxAsyncClientPool::addClient(SP_LinuxAsyncClient &client)
+        {
+            if (m_stopping)
+                return false;
+
+            LinuxAsyncClient& clientRef = *client.Get();
+            {
+                common::concurrent::CsLockGuard lock(m_clientsMutex);
+
+                uint64_t id = ++m_idGen;
+                clientRef.setId(id);
+
+                m_clientIdMap[id] = client;
+            }
+
+            handleConnectionSuccess(clientRef.getAddress(), clientRef.GetId());
+
+            return true;
+        }
+
+        void LinuxAsyncClientPool::handleConnectionError(const EndPoint &addr, const IgniteError &err)
+        {
+            AsyncHandler* asyncHandler0 = m_asyncHandler;
+            if (asyncHandler0)
+                asyncHandler0->onConnectionError(addr, err);
+        }
+
+        void LinuxAsyncClientPool::handleConnectionSuccess(const EndPoint &addr, uint64_t id)
+        {
+            AsyncHandler* asyncHandler0 = m_asyncHandler;
+            if (asyncHandler0)
+                asyncHandler0->onConnectionSuccess(addr, id);
+        }
+
+        void LinuxAsyncClientPool::HandleConnectionClosed(uint64_t id, const IgniteError *err)
+        {
+            AsyncHandler* asyncHandler0 = m_asyncHandler;
+            if (asyncHandler0)
+                asyncHandler0->onConnectionClosed(id, err);
+        }
+
+        void LinuxAsyncClientPool::handleMessageReceived(uint64_t id, const DataBuffer &msg)
+        {
+            AsyncHandler* asyncHandler0 = m_asyncHandler;
+            if (asyncHandler0)
+                asyncHandler0->onMessageReceived(id, msg);
+        }
+
+        void LinuxAsyncClientPool::handleMessageSent(uint64_t id)
+        {
+            AsyncHandler* asyncHandler0 = m_asyncHandler;
+            if (asyncHandler0)
+                asyncHandler0->onMessageSent(id);
+        }
+
+        void LinuxAsyncClientPool::InternalStop()
+        {
+            m_stopping = true;
+            m_workerThread.stop();
+
+            {
+                common::concurrent::CsLockGuard lock(m_clientsMutex);
+
+                std::map<uint64_t, SP_LinuxAsyncClient>::iterator it;
+                for (it = m_clientIdMap.begin(); it != m_clientIdMap.end(); ++it)
+                {
+                    LinuxAsyncClient& client = *it->second.Get();
+
+                    IgniteError err(IgniteError::IGNITE_ERR_GENERIC, "Client stopped");
+                    HandleConnectionClosed(client.GetId(), &err);
+                }
+
+                m_clientIdMap.clear();
+            }
+        }
+
+        SP_LinuxAsyncClient LinuxAsyncClientPool::FindClient(uint64_t id) const
+        {
+            common::concurrent::CsLockGuard lock(m_clientsMutex);
+
+            std::map<uint64_t, SP_LinuxAsyncClient>::const_iterator it = m_clientIdMap.find(id);
+            if (it == m_clientIdMap.end())
+                return SP_LinuxAsyncClient();
+
+            return it->second;
+        }
+    }
+}
diff --git a/modules/platforms/cpp/network/os/linux/src/network/linux_async_client_pool.h b/modules/platforms/cpp/network/os/linux/src/network/linux_async_client_pool.h
new file mode 100644
index 0000000000..bb5b633079
--- /dev/null
+++ b/modules/platforms/cpp/network/os/linux/src/network/linux_async_client_pool.h
@@ -0,0 +1,205 @@
+/*
+ * 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.
+ */
+
+#ifndef _IGNITE_NETWORK_LINUX_ASYNC_CLIENT_POOL
+#define _IGNITE_NETWORK_LINUX_ASYNC_CLIENT_POOL
+
+#include <stdint.h>
+#include <map>
+
+#include "common/ignite_error.h"
+
+#include <ignite/common/concurrent.h>
+#include <ignite/impl/interop/interop_memory.h>
+
+#include <ignite/network/async_client_pool.h>
+#include <ignite/network/async_handler.h>
+#include <ignite/network/tcp_range.h>
+
+#include "network/linux_async_worker_thread.h"
+#include "network/linux_async_client.h"
+
+namespace ignite
+{
+    namespace network
+    {
+        /**
+         * Linux-specific implementation of asynchronous client pool.
+         */
+        class LinuxAsyncClientPool : public AsyncClientPool
+        {
+        public:
+            /**
+             * Constructor
+             *
+             * @param handler Upper level event handler.
+             */
+            LinuxAsyncClientPool();
+
+            /**
+             * Destructor.
+             */
+            virtual ~LinuxAsyncClientPool();
+
+            /**
+             * Start internal thread that establishes connections to provided addresses and asynchronously sends and
+             * receives messages from them. Function returns either when thread is started and first connection is
+             * established or failure happened.
+             *
+             * @param addrs Addresses to connect to.
+             * @param connLimit Connection upper limit. Zero means limit is disabled.
+             *
+             * @throw IgniteError on error.
+             */
+            virtual void start(std::vector<TcpRange> addrs, uint32_t connLimit);
+
+            /**
+             * Close all established connections and stops handling thread.
+             */
+            virtual void stop();
+
+            /**
+             * Set handler.
+             *
+             * @param handler Handler to set.
+             */
+            virtual void SetHandler(AsyncHandler *handler)
+            {
+                m_asyncHandler = handler;
+            }
+
+            /**
+             * Send data to specific established connection.
+             *
+             * @param id Client ID.
+             * @param data Data to be sent.
+             * @return @c true if connection is present and @c false otherwise.
+             *
+             * @throw IgniteError on error.
+             */
+            virtual bool send(uint64_t id, const DataBuffer& data);
+
+            /**
+             * Closes specified connection if it's established. Connection to the specified address is planned for
+             * re-connect. Event is issued to the handler with specified error.
+             *
+             * @param id Client ID.
+             */
+            virtual void close(uint64_t id, const IgniteError* err);
+
+            /**
+             * Closes and releases memory allocated for client with specified ID.
+             * Error is reported to handler.
+             *
+             * @param id Client ID.
+             * @param err Error to report. May be null.
+             * @return @c true if connection with specified ID was found.
+             */
+            void closeAndRelease(uint64_t id, const IgniteError* err);
+
+            /**
+             * Add client to connection map. Notify user.
+             *
+             * @param client Client.
+             * @return Client ID.
+             */
+            bool addClient(SP_LinuxAsyncClient& client);
+
+            /**
+             * Handle error during connection establishment.
+             *
+             * @param addr Connection address.
+             * @param err Error.
+             */
+            void handleConnectionError(const EndPoint& addr, const IgniteError& err);
+
+            /**
+             * Handle successful connection establishment.
+             *
+             * @param addr Address of the new connection.
+             * @param id Connection ID.
+             */
+            void handleConnectionSuccess(const EndPoint& addr, uint64_t id);
+
+            /**
+             * Handle error during connection establishment.
+             *
+             * @param id Async client ID.
+             * @param err Error. Can be null if connection closed without error.
+             */
+            void HandleConnectionClosed(uint64_t id, const IgniteError* err);
+
+            /**
+             * Handle new message.
+             *
+             * @param id Async client ID.
+             * @param msg Received message.
+             */
+            void handleMessageReceived(uint64_t id, const DataBuffer& msg);
+
+            /**
+             * Handle sent message event.
+             *
+             * @param id Async client ID.
+             */
+            void handleMessageSent(uint64_t id);
+
+        private:
+             /**
+             * Close all established connections and stops handling threads.
+             */
+            void InternalStop();
+
+            /**
+             * Find client by ID.
+             *
+             * @param id Client ID.
+             * @return Client. Null pointer if is not found.
+             */
+            SP_LinuxAsyncClient FindClient(uint64_t id) const;
+
+            /**
+             * Find client by ID.
+             *
+             * @warning Should only be called with m_clientsMutex lock held.
+             * @param id Client ID.
+             * @return Client. Null pointer if is not found.
+             */
+            SP_LinuxAsyncClient FindClientLocked(uint64_t id) const;
+
+            /** Flag indicating that pool is stopping. */
+            volatile bool m_stopping;
+
+            /** Event handler. */
+            AsyncHandler* m_asyncHandler;
+
+            /** Worker thread. */
+            LinuxAsyncWorkerThread m_workerThread;
+
+            /** ID counter. */
+            uint64_t m_idGen;
+
+            /** Clients critical section. */
+            mutable common::concurrent::CriticalSection m_clientsMutex;
+
+            /** Client mapping ID -> client */
+            std::map<uint64_t, SP_LinuxAsyncClient> m_clientIdMap;
+        };
+    }
+}
+
+#endif //_IGNITE_NETWORK_LINUX_ASYNC_CLIENT_POOL
diff --git a/modules/platforms/cpp/network/os/linux/src/network/linux_async_worker_thread.cpp b/modules/platforms/cpp/network/os/linux/src/network/linux_async_worker_thread.cpp
new file mode 100644
index 0000000000..092ba0e788
--- /dev/null
+++ b/modules/platforms/cpp/network/os/linux/src/network/linux_async_worker_thread.cpp
@@ -0,0 +1,348 @@
+/*
+ * 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.
+ */
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
+#include <netdb.h>
+#include <netinet/tcp.h>
+#include <unistd.h>
+
+#include <cstring>
+
+#include <network/utils.h>
+#include <ignite/common/utils.h>
+
+#include "network/linux_async_worker_thread.h"
+#include "network/linux_async_client_pool.h"
+
+namespace
+{
+    ignite::network::FibonacciSequence<10> fibonacci10;
+}
+
+namespace ignite
+{
+    namespace network
+    {
+        LinuxAsyncWorkerThread::LinuxAsyncWorkerThread(LinuxAsyncClientPool &clientPool) :
+            m_clientPool(clientPool),
+            m_stopping(true),
+            epoll(-1),
+            stopEvent(-1),
+            m_nonConnected(),
+            currentConnection(),
+            currentClient(),
+            m_failedAttempts(0),
+            lastConnectionTime(),
+            m_minAddrs(0)
+        {
+            memset(&lastConnectionTime, 0, sizeof(lastConnectionTime));
+        }
+
+        LinuxAsyncWorkerThread::~LinuxAsyncWorkerThread()
+        {
+            stop();
+        }
+
+        void LinuxAsyncWorkerThread::Start0(size_t limit, const std::vector<TcpRange> &addrs)
+        {
+            epoll = epoll_create(1);
+            if (epoll < 0)
+                common::ThrowLastSystemError("Failed to create epoll instance");
+
+            stopEvent = eventfd(0, EFD_NONBLOCK);
+            if (stopEvent < 0)
+            {
+                std::string msg = common::GetLastSystemError("Failed to create stop event instance");
+                close(stopEvent);
+                common::ThrowSystemError(msg);
+            }
+
+            epoll_event event;
+            memset(&event, 0, sizeof(event));
+
+            event.events = EPOLLIN;
+
+            int res = epoll_ctl(epoll, EPOLL_CTL_ADD, stopEvent, &event);
+            if (res < 0)
+            {
+                std::string msg = common::GetLastSystemError("Failed to create stop event instance");
+                close(stopEvent);
+                close(epoll);
+                common::ThrowSystemError(msg);
+            }
+
+            m_stopping = false;
+            m_failedAttempts = 0;
+            m_nonConnected = addrs;
+
+            currentConnection.reset();
+            currentClient = SP_LinuxAsyncClient();
+
+            if (!limit || limit > addrs.size())
+                m_minAddrs = 0;
+            else
+                m_minAddrs = addrs.size() - limit;
+
+            Thread::start();
+        }
+
+        void LinuxAsyncWorkerThread::stop()
+        {
+            if (m_stopping)
+                return;
+
+            m_stopping = true;
+
+            int64_t value = 1;
+            ssize_t res = write(stopEvent, &value, sizeof(value));
+
+            IGNITE_UNUSED(res);
+            assert(res == sizeof(value));
+
+            Thread::Join();
+
+            close(stopEvent);
+            close(epoll);
+
+            m_nonConnected.clear();
+            currentConnection.reset();
+        }
+
+        void LinuxAsyncWorkerThread::run()
+        {
+            while (!m_stopping)
+            {
+                HandleNewConnections();
+
+                if (m_stopping)
+                    break;
+
+                HandleConnectionEvents();
+            }
+        }
+
+        void LinuxAsyncWorkerThread::HandleNewConnections()
+        {
+            if (!ShouldInitiateNewConnection())
+                return;
+
+            if (CalculateConnectionTimeout() > 0)
+                return;
+
+            addrinfo* addr = 0;
+            if (currentConnection.get())
+                addr = currentConnection->Next();
+
+            if (!addr)
+            {
+                size_t idx = rand() % m_nonConnected.size();
+                const TcpRange& range = m_nonConnected.at(idx);
+
+                currentConnection.reset(new ConnectingContext(range));
+                addr = currentConnection->Next();
+                if (!addr)
+                {
+                    currentConnection.reset();
+                    ReportConnectionError(EndPoint(), "Can not resolve a single address from range: " + range.ToString());
+                    ++m_failedAttempts;
+
+                    return;
+                }
+            }
+
+            // Create a SOCKET for connecting to server
+            int socketFd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
+            if (SOCKET_ERROR == socketFd)
+            {
+                ReportConnectionError(currentConnection->getAddress(),
+                    "Socket creation failed: " + getLastSocketErrorMessage());
+
+                return;
+            }
+
+            TrySetSocketOptions(socketFd, LinuxAsyncClient::BUFFER_SIZE, true, true, true);
+            bool success = SetNonBlockingMode(socketFd, true);
+            if (!success)
+            {
+                ReportConnectionError(currentConnection->getAddress(),
+                    "Can not make non-blocking socket: " + getLastSocketErrorMessage());
+
+                return;
+            }
+
+            currentClient = currentConnection->ToClient(socketFd);
+            bool ok = currentClient->StartMonitoring(epoll);
+            if (!ok)
+                common::ThrowLastSystemError("Can not add file descriptor to epoll");
+
+            // Connect to server.
+            int res = connect(socketFd, addr->ai_addr, addr->ai_addrlen);
+            if (SOCKET_ERROR == res)
+            {
+                int lastError = errno;
+
+                clock_gettime(CLOCK_MONOTONIC, &lastConnectionTime);
+
+                if (lastError != EWOULDBLOCK && lastError != EINPROGRESS)
+                {
+                    HandleConnectionFailed("Failed to establish connection with the host: " +
+                        getSocketErrorMessage(lastError));
+
+                    return;
+                }
+            }
+        }
+
+        void LinuxAsyncWorkerThread::HandleConnectionEvents()
+        {
+            enum { MAX_EVENTS = 16 };
+            epoll_event events[MAX_EVENTS];
+
+            int timeout = CalculateConnectionTimeout();
+
+            int res = epoll_wait(epoll, events, MAX_EVENTS, timeout);
+
+            if (res <= 0)
+                return;
+
+            for (int i = 0; i < res; ++i)
+            {
+                epoll_event& currentEvent = events[i];
+                LinuxAsyncClient* client = static_cast<LinuxAsyncClient*>(currentEvent.data.ptr);
+                if (!client)
+                    continue;
+
+                if (client == currentClient.Get())
+                {
+                    if (currentEvent.events & (EPOLLRDHUP | EPOLLERR))
+                    {
+                        HandleConnectionFailed("Can not establish connection");
+
+                        continue;
+                    }
+
+                    handleConnectionSuccess(client);
+                }
+
+                if (currentEvent.events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP))
+                {
+                    HandleConnectionClosed(client);
+
+                    continue;
+                }
+
+                if (currentEvent.events & EPOLLIN)
+                {
+                    DataBuffer msg = client->receive();
+                    if (msg.isEmpty())
+                    {
+                        HandleConnectionClosed(client);
+
+                        continue;
+                    }
+
+                    m_clientPool.handleMessageReceived(client->GetId(), msg);
+                }
+
+                if (currentEvent.events & EPOLLOUT)
+                {
+                    bool ok = client->processSent();
+                    if (!ok)
+                    {
+                        HandleConnectionClosed(client);
+
+                        continue;
+                    }
+                }
+            }
+        }
+
+        void LinuxAsyncWorkerThread::ReportConnectionError(const EndPoint& addr, const std::string& msg)
+        {
+            IgniteError err(IgniteError::IGNITE_ERR_NETWORK_FAILURE, msg.c_str());
+            m_clientPool.handleConnectionError(addr, err);
+        }
+
+        void LinuxAsyncWorkerThread::HandleConnectionFailed(const std::string& msg)
+        {
+            LinuxAsyncClient* client = currentClient.Get();
+            assert(client != 0);
+
+            client->StopMonitoring();
+            client->close();
+
+            ReportConnectionError(client->getAddress(), msg);
+
+            currentClient = SP_LinuxAsyncClient();
+            ++m_failedAttempts;
+        }
+
+        void LinuxAsyncWorkerThread::HandleConnectionClosed(LinuxAsyncClient *client)
+        {
+            client->StopMonitoring();
+
+            m_nonConnected.push_back(client->getRange());
+
+            m_clientPool.closeAndRelease(client->GetId(), 0);
+        }
+
+        void LinuxAsyncWorkerThread::handleConnectionSuccess(LinuxAsyncClient* client)
+        {
+            m_nonConnected.erase(std::find(m_nonConnected.begin(), m_nonConnected.end(), client->getRange()));
+
+            m_clientPool.addClient(currentClient);
+
+            currentClient = SP_LinuxAsyncClient();
+            currentConnection.reset();
+
+            m_failedAttempts = 0;
+
+            clock_gettime(CLOCK_MONOTONIC, &lastConnectionTime);
+        }
+
+        int LinuxAsyncWorkerThread::CalculateConnectionTimeout() const
+        {
+            if (!ShouldInitiateNewConnection())
+                return -1;
+
+            if (lastConnectionTime.tv_sec == 0)
+                return 0;
+
+            int timeout = fibonacci10.GetValue(m_failedAttempts) * 1000;
+
+            timespec now;
+            clock_gettime(CLOCK_MONOTONIC, &now);
+
+            int passed = (now.tv_sec - lastConnectionTime.tv_sec) * 1000 +
+                         (now.tv_nsec - lastConnectionTime.tv_nsec) / 1000000;
+
+            timeout -= passed;
+            if (timeout < 0)
+                timeout = 0;
+
+            return timeout;
+        }
+
+        bool LinuxAsyncWorkerThread::ShouldInitiateNewConnection() const
+        {
+            return !currentClient.Get() && m_nonConnected.size() > m_minAddrs;
+        }
+    }
+}
diff --git a/modules/platforms/cpp/network/os/linux/src/network/linux_async_worker_thread.h b/modules/platforms/cpp/network/os/linux/src/network/linux_async_worker_thread.h
new file mode 100644
index 0000000000..83d286fc75
--- /dev/null
+++ b/modules/platforms/cpp/network/os/linux/src/network/linux_async_worker_thread.h
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+
+#ifndef _IGNITE_NETWORK_LINUX_ASYNC_WORKER_THREAD
+#define _IGNITE_NETWORK_LINUX_ASYNC_WORKER_THREAD
+
+#include <time.h>
+
+#include <stdint.h>
+#include <memory>
+
+#include <ignite/common/concurrent.h>
+#include <ignite/impl/interop/interop_memory.h>
+
+#include <ignite/network/async_handler.h>
+#include <ignite/network/end_point.h>
+#include <ignite/network/tcp_range.h>
+
+#include "network/linux_async_client.h"
+#include "network/connecting_context.h"
+
+namespace ignite
+{
+    namespace network
+    {
+        class LinuxAsyncClientPool;
+
+        /**
+         * Async pool working thread.
+         */
+        class LinuxAsyncWorkerThread : protected common::concurrent::Thread
+        {
+        public:
+            /**
+             * Default constructor.
+             */
+            LinuxAsyncWorkerThread(LinuxAsyncClientPool& clientPool);
+
+            /**
+             * Destructor.
+             */
+            virtual ~LinuxAsyncWorkerThread();
+
+            /**
+             * Start worker thread.
+             *
+             * @param limit Connection limit.
+             * @param addrs Addresses to connect to.
+             */
+            void Start0(size_t limit, std::vector<TcpRange> addrs);
+
+            /**
+             * Stop thread.
+             */
+            void stop();
+
+        private:
+            /**
+             * Run thread.
+             */
+            virtual void run();
+
+            /**
+             * Initiate new connection process if needed.
+             */
+            void HandleNewConnections();
+
+            /**
+             * Handle epoll events.
+             */
+            void HandleConnectionEvents();
+
+            /**
+             * Handle network error during connection establishment.
+             *
+             * @param addr End point.
+             * @param msg Error message.
+             */
+            void ReportConnectionError(const EndPoint& addr, const std::string& msg);
+
+            /**
+             * Handle failed connection.
+             *
+             * @param msg Error message.
+             */
+            void HandleConnectionFailed(const std::string& msg);
+
+            /**
+             * Handle network error on established connection.
+             *
+             * @param client Client instance.
+             */
+            void HandleConnectionClosed(LinuxAsyncClient* client);
+
+            /**
+             * Handle successfully established connection.
+             *
+             * @param client Client instance.
+             */
+            void handleConnectionSuccess(LinuxAsyncClient* client);
+
+            /**
+             * Calculate connection timeout.
+             *
+             * @return Connection timeout.
+             */
+            int CalculateConnectionTimeout() const;
+
+            /**
+             * Check whether new connection should be initiated.
+             *
+             * @return @c true if new connection should be initiated.
+             */
+            bool ShouldInitiateNewConnection() const;
+
+            /** Client pool. */
+            LinuxAsyncClientPool& m_clientPool;
+
+            /** Flag indicating that thread is stopping. */
+            bool m_stopping;
+
+            /** Client epoll file descriptor. */
+            int epoll;
+
+            /** Stop event file descriptor. */
+            int stopEvent;
+
+            /** Addresses to use for connection establishment. */
+            std::vector<TcpRange> m_nonConnected;
+
+            /** Connection which is currently in connecting process. */
+            std::auto_ptr<ConnectingContext> currentConnection;
+
+            /** Currently connected client. */
+            SP_LinuxAsyncClient currentClient;
+
+            /** Failed connection attempts. */
+            size_t m_failedAttempts;
+
+            /** Last connection time. */
+            timespec lastConnectionTime;
+
+            /** Minimal number of addresses. */
+            size_t m_minAddrs;
+        };
+    }
+}
+
+#endif //_IGNITE_NETWORK_LINUX_ASYNC_WORKER_THREAD
diff --git a/modules/platforms/cpp/network/os/linux/src/network/sockets.cpp b/modules/platforms/cpp/network/os/linux/src/network/sockets.cpp
new file mode 100644
index 0000000000..044e488a2a
--- /dev/null
+++ b/modules/platforms/cpp/network/os/linux/src/network/sockets.cpp
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include <sstream>
+
+#include "network/sockets.h"
+
+namespace ignite
+{
+    namespace network
+    {
+        namespace sockets
+        {
+            int getLastSocketError()
+            {
+                return errno;
+            }
+
+            int getLastSocketError(int handle)
+            {
+                int lastError = 0;
+                socklen_t size = sizeof(lastError);
+                int res = getsockopt(handle, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&lastError), &size);
+
+                return res == SOCKET_ERROR ? 0 : lastError;
+            }
+
+            std::string getSocketErrorMessage(int error)
+            {
+                std::stringstream res;
+
+                res << "error_code=" << error;
+
+                if (error == 0)
+                    return res.str();
+
+                char errBuf[1024] = { 0 };
+
+                const char* errStr = strerror_r(error, errBuf, sizeof(errBuf));
+                if (errStr)
+                    res << ", msg=" << errStr;
+
+                return res.str();
+            }
+
+            std::string getLastSocketErrorMessage()
+            {
+                int lastError = errno;
+
+                return getSocketErrorMessage(lastError);
+            }
+
+            int WaitOnSocket(SOCKET socket, int32_t timeout, bool rd)
+            {
+                int32_t timeout0 = timeout == 0 ? -1 : timeout;
+
+                int lastError = 0;
+                int ret;
+
+                do
+                {
+                    struct pollfd fds[1];
+
+                    fds[0].fd = socket;
+                    fds[0].events = rd ? POLLIN : POLLOUT;
+
+                    ret = poll(fds, 1, timeout0 * 1000);
+
+                    if (ret == SOCKET_ERROR)
+                        lastError = getLastSocketError();
+
+                } while (ret == SOCKET_ERROR && isSocketOperationInterrupted(lastError));
+
+                if (ret == SOCKET_ERROR)
+                    return -lastError;
+
+                socklen_t size = sizeof(lastError);
+                int res = getsockopt(socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&lastError), &size);
+
+                if (res != SOCKET_ERROR && lastError != 0)
+                    return -lastError;
+
+                if (ret == 0)
+                    return SocketClient::WaitResult::TIMEOUT;
+
+                return SocketClient::WaitResult::SUCCESS;
+            }
+
+            bool isSocketOperationInterrupted(int errorCode)
+            {
+                return errorCode == EINTR;
+            }
+
+            void TrySetSocketOptions(int socketFd, int bufSize, bool noDelay, bool outOfBand, bool keepAlive)
+            {
+                setsockopt(socketFd, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<char*>(&bufSize), sizeof(bufSize));
+                setsockopt(socketFd, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<char*>(&bufSize), sizeof(bufSize));
+
+                int iNoDelay = noDelay ? 1 : 0;
+                setsockopt(socketFd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&iNoDelay), sizeof(iNoDelay));
+
+                int iOutOfBand = outOfBand ? 1 : 0;
+                setsockopt(socketFd, SOL_SOCKET, SO_OOBINLINE,
+                    reinterpret_cast<char*>(&iOutOfBand), sizeof(iOutOfBand));
+
+                int iKeepAlive = keepAlive ? 1 : 0;
+                int res = setsockopt(socketFd, SOL_SOCKET, SO_KEEPALIVE,
+                    reinterpret_cast<char*>(&iKeepAlive), sizeof(iKeepAlive));
+
+                if (SOCKET_ERROR == res)
+                {
+                    // There is no sense in configuring keep alive params if we faileed to set up keep alive mode.
+                    return;
+                }
+
+                // The time in seconds the connection needs to remain idle before starts sending keepalive probes.
+                enum { KEEP_ALIVE_IDLE_TIME = 60 };
+
+                // The time in seconds between individual keepalive probes.
+                enum { KEEP_ALIVE_PROBES_PERIOD = 1 };
+
+                int idleOpt = KEEP_ALIVE_IDLE_TIME;
+                int idleRetryOpt = KEEP_ALIVE_PROBES_PERIOD;
+#ifdef __APPLE__
+                setsockopt(socketFd, IPPROTO_TCP, TCP_KEEPALIVE, reinterpret_cast<char*>(&idleOpt), sizeof(idleOpt));
+#else
+                setsockopt(socketFd, IPPROTO_TCP, TCP_KEEPIDLE, reinterpret_cast<char*>(&idleOpt), sizeof(idleOpt));
+#endif
+
+                setsockopt(socketFd, IPPROTO_TCP, TCP_KEEPINTVL,
+                    reinterpret_cast<char*>(&idleRetryOpt), sizeof(idleRetryOpt));
+            }
+
+            bool SetNonBlockingMode(int socketFd, bool nonBlocking)
+            {
+                int flags = fcntl(socketFd, F_GETFL, 0);
+                if (flags == -1)
+                    return false;
+
+                bool currentNonBlocking = flags & O_NONBLOCK;
+                if (nonBlocking == currentNonBlocking)
+                    return true;
+
+                flags ^= O_NONBLOCK;
+                int res = fcntl(socketFd, F_SETFL, flags);
+
+                return res != -1;
+            }
+        }
+    }
+}
diff --git a/modules/platforms/cpp/network/os/linux/src/network/sockets.h b/modules/platforms/cpp/network/os/linux/src/network/sockets.h
new file mode 100644
index 0000000000..507732d5cc
--- /dev/null
+++ b/modules/platforms/cpp/network/os/linux/src/network/sockets.h
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+#ifndef _IGNITE_NETWORK_SOCKETS
+#define _IGNITE_NETWORK_SOCKETS
+
+#include <stdint.h>
+#include <string>
+
+#define SOCKET_ERROR (-1)
+
+namespace ignite
+{
+    namespace network
+    {
+        namespace sockets
+        {
+            /** Socket handle type. */
+            typedef int SOCKET;
+
+            /**
+             * Get socket error.
+             * @return Last socket error.
+             */
+            int getLastSocketError();
+
+            /**
+             * Get socket error.
+             * @param handle Socket handle.
+             * @return Last socket error.
+             */
+            int getLastSocketError(int handle);
+
+            /**
+             * Get socket error message for the error code.
+             * @param error Error code.
+             * @return Socket error message string.
+             */
+            std::string getSocketErrorMessage(int error);
+
+            /**
+             * Get last socket error message.
+             * @return Last socket error message string.
+             */
+            std::string getLastSocketErrorMessage();
+
+            /**
+             * Check whether socket operation was interupted.
+             * @return @c true if the socket operation was interupted.
+             */
+            bool isSocketOperationInterrupted(int errorCode);
+
+            /**
+             * Wait on the socket for any event for specified time.
+             * This function uses poll to achive timeout functionality
+             * for every separate socket operation.
+             *
+             * @param socket Socket handle.
+             * @param timeout Timeout.
+             * @param rd Wait for read if @c true, or for write if @c false.
+             * @return -errno on error, WaitResult::TIMEOUT on timeout and
+             *     WaitResult::SUCCESS on success.
+             */
+            int WaitOnSocket(SOCKET socket, int32_t timeout, bool rd);
+
+            /**
+             * Try and set socket options.
+             *
+             * @param socketFd Socket file descriptor.
+             * @param bufSize Buffer size.
+             * @param noDelay Set no-delay mode.
+             * @param outOfBand Set out-of-Band mode.
+             * @param keepAlive Keep alive mode.
+             */
+            void TrySetSocketOptions(int socketFd, int bufSize, bool noDelay, bool outOfBand, bool keepAlive);
+
+            /**
+             * Set non blocking mode for socket.
+             *
+             * @param socketFd Socket file descriptor.
+             * @param nonBlocking Non-blocking mode.
+             */
+            bool SetNonBlockingMode(int socketFd, bool nonBlocking);
+        }
+    }
+}
+
+#endif //_IGNITE_NETWORK_SOCKETS
diff --git a/modules/platforms/cpp/network/os/win/src/network/sockets.cpp b/modules/platforms/cpp/network/os/win/src/network/sockets.cpp
new file mode 100644
index 0000000000..2565a2b77f
--- /dev/null
+++ b/modules/platforms/cpp/network/os/win/src/network/sockets.cpp
@@ -0,0 +1,164 @@
+/*
+ * 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.
+ */
+
+#include "network/sockets.h"
+
+#include <sstream>
+#include <mutex>
+
+#include "network/utils.h"
+
+// Using NULLs as specified by WinAPI
+#pragma ide diagnostic ignored "modernize-use-nullptr"
+
+namespace ignite::network
+{
+
+std::string getSocketErrorMessage(HRESULT error)
+{
+    std::stringstream res;
+
+    res << "error_code=" << error;
+
+    if (error == 0)
+        return res.str();
+
+    LPTSTR errorText = NULL;
+
+    DWORD len = FormatMessageA(
+        // use system message tables to retrieve error text
+        FORMAT_MESSAGE_FROM_SYSTEM
+        // allocate buffer on local heap for error text
+        | FORMAT_MESSAGE_ALLOCATE_BUFFER
+        // We're not passing insertion parameters
+        | FORMAT_MESSAGE_IGNORE_INSERTS,
+        // unused with FORMAT_MESSAGE_FROM_SYSTEM
+        NULL,
+        error,
+        MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+        // output
+        reinterpret_cast<LPSTR>(&errorText),
+        // minimum size for output buffer
+        0,
+        // arguments - see note
+        NULL);
+
+    if (NULL != errorText && len > 0)
+    {
+        std::string msg(reinterpret_cast<const char*>(errorText), static_cast<size_t>(len));
+
+        res << ", msg=" << msg;
+
+        LocalFree(errorText);
+    }
+
+    return res.str();
+}
+
+std::string getLastSocketErrorMessage()
+{
+    HRESULT lastError = WSAGetLastError();
+
+    return getSocketErrorMessage(lastError);
+}
+
+void TrySetSocketOptions(SOCKET socket, int bufSize, BOOL noDelay, BOOL outOfBand, BOOL keepAlive)
+{
+    setsockopt(socket, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<char*>(&bufSize), sizeof(bufSize));
+    setsockopt(socket, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<char*>(&bufSize), sizeof(bufSize));
+
+    setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&noDelay), sizeof(noDelay));
+
+    setsockopt(socket, SOL_SOCKET, SO_OOBINLINE, reinterpret_cast<char*>(&outOfBand), sizeof(outOfBand));
+
+    int res = setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE,
+        reinterpret_cast<char*>(&keepAlive), sizeof(keepAlive));
+
+    // TODO: IGNITE-17606 Disable keep-alive once heartbeats are implemented.
+    if (keepAlive)
+    {
+        if (SOCKET_ERROR == res)
+        {
+            // There is no sense in configuring keep alive params if we failed to set up keep alive mode.
+            return;
+        }
+
+        // The time in seconds the connection needs to remain idle before starts sending keepalive probes.
+        enum { KEEP_ALIVE_IDLE_TIME = 60 };
+
+        // The time in seconds between individual keepalive probes.
+        enum { KEEP_ALIVE_PROBES_PERIOD = 1 };
+
+#if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
+        // This option is available starting with Windows 10, version 1709.
+        DWORD idleOpt = KEEP_ALIVE_IDLE_TIME;
+        DWORD idleRetryOpt = KEEP_ALIVE_PROBES_PERIOD;
+
+        setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, reinterpret_cast<char*>(&idleOpt), sizeof(idleOpt));
+
+        setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL,
+                   reinterpret_cast<char*>(&idleRetryOpt), sizeof(idleRetryOpt));
+
+#else // use old hardcore WSAIoctl
+        // WinSock structure for KeepAlive timing settings
+        struct tcp_keepalive settings = { 0 };
+        settings.onoff = 1;
+        settings.keepalivetime = KEEP_ALIVE_IDLE_TIME * 1000;
+        settings.keepaliveinterval = KEEP_ALIVE_PROBES_PERIOD * 1000;
+
+        // pointers for WinSock call
+        DWORD bytesReturned;
+        WSAOVERLAPPED overlapped;
+        overlapped.hEvent = NULL;
+
+        // Set KeepAlive settings
+        WSAIoctl(
+            socket,
+            SIO_KEEPALIVE_VALS,
+            &settings,
+            sizeof(struct tcp_keepalive),
+            NULL,
+            0,
+            &bytesReturned,
+            &overlapped,
+            NULL
+        );
+#endif
+    }
+}
+
+void InitWsa()
+{
+    static std::mutex initMutex;
+    static bool networkInited = false;
+
+    if (!networkInited)
+    {
+        std::lock_guard<std::mutex> lock(initMutex);
+        if (!networkInited)
+        {
+            WSADATA wsaData;
+
+            networkInited = WSAStartup(MAKEWORD(2, 2), &wsaData) == 0;
+
+            if (!networkInited)
+                ThrowNetworkError("Networking initialisation failed: " + getLastSocketErrorMessage());
+        }
+    }
+}
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/os/win/src/network/sockets.h b/modules/platforms/cpp/network/os/win/src/network/sockets.h
new file mode 100644
index 0000000000..8daa78d2ad
--- /dev/null
+++ b/modules/platforms/cpp/network/os/win/src/network/sockets.h
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#define WIN32_LEAN_AND_MEAN
+#define _WINSOCKAPI_
+
+#include <windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <mstcpip.h>
+
+#include <cstdint>
+#include <string>
+
+namespace ignite::network
+{
+
+/**
+ * Get socket error message for the error code.
+ * @param error Error code.
+ * @return Socket error message string.
+ */
+std::string getSocketErrorMessage(HRESULT error);
+
+/**
+ * Get last socket error message.
+ * @return Last socket error message string.
+ */
+std::string getLastSocketErrorMessage();
+
+/**
+ * Try and set socket options.
+ *
+ * @param socket Socket.
+ * @param bufSize Buffer size.
+ * @param noDelay Set no-delay mode.
+ * @param outOfBand Set out-of-Band mode.
+ * @param keepAlive Keep alive mode.
+ */
+void TrySetSocketOptions(SOCKET socket, int bufSize, BOOL noDelay, BOOL outOfBand, BOOL keepAlive);
+
+/**
+ * Init windows sockets.
+ *
+ * Thread-safe.
+ */
+void InitWsa();
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/common/Platform.h b/modules/platforms/cpp/network/os/win/src/network/utils.cpp
similarity index 54%
copy from modules/platforms/cpp/common/Platform.h
copy to modules/platforms/cpp/network/os/win/src/network/utils.cpp
index 7bfcebc447..c941dd1e84 100644
--- a/modules/platforms/cpp/common/Platform.h
+++ b/modules/platforms/cpp/network/os/win/src/network/utils.cpp
@@ -15,36 +15,33 @@
  * limitations under the License.
  */
 
-#pragma once
+#include <windows.h>
 
-/**
- * Macro SWITCH_WIN_OTHER that uses first option on Windows and second on any other OS.
- */
-#ifdef WIN32
-#   define SWITCH_WIN_OTHER(x, y) (x)
-#else
-#   define SWITCH_WIN_OTHER(x, y) (y)
-#endif
+#include "network/utils.h"
+
+// Using NULLs as specified by WinAPI
+#pragma ide diagnostic ignored "modernize-use-nullptr"
 
-namespace ignite::platform
+namespace ignite::network
 {
 
-/**
- * Byte order utility class.
- */
-class ByteOrder
+std::string GetLastSystemError()
 {
-private:
-    static constexpr uint32_t fourBytes = 0x01020304;
-    static constexpr uint8_t lesserByte = (const uint8_t&)fourBytes;
+    DWORD errorCode = GetLastError();
+
+    std::string errorDetails;
+    if (errorCode != ERROR_SUCCESS)
+    {
+        char errBuf[1024] = {};
 
-public:
-    ByteOrder() = delete;
+        FormatMessageA(
+                FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorCode,
+                MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), errBuf, sizeof(errBuf), NULL);
 
-    static constexpr bool littleEndian = lesserByte == 0x04;
-    static constexpr bool bigEndian = lesserByte == 0x01;
+        errorDetails.assign(errBuf);
+    }
 
-    static_assert(littleEndian || bigEndian, "Unknown byte order");
-};
+    return errorDetails;
+}
 
-} // ignite::platform
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/os/win/src/network/win_async_client.cpp b/modules/platforms/cpp/network/os/win/src/network/win_async_client.cpp
new file mode 100644
index 0000000000..5f25467316
--- /dev/null
+++ b/modules/platforms/cpp/network/os/win/src/network/win_async_client.cpp
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+
+#include <algorithm>
+
+#include <network/utils.h>
+
+#include "network/sockets.h"
+#include "network/win_async_client.h"
+
+namespace ignite::network
+{
+
+WinAsyncClient::WinAsyncClient(SOCKET socket, EndPoint addr, TcpRange range, int32_t m_bufLen) :
+    m_bufLen(m_bufLen),
+    m_state(State::CONNECTED),
+    m_socket(socket),
+    m_id(0),
+    m_addr(std::move(addr)),
+    m_range(std::move(range)),
+    m_closeErr()
+{
+    memset(&m_currentSend, 0, sizeof(m_currentSend));
+    m_currentSend.kind = IoOperationKind::SEND;
+
+    memset(&m_currentRecv, 0, sizeof(m_currentRecv));
+    m_currentRecv.kind = IoOperationKind::RECEIVE;
+}
+
+WinAsyncClient::~WinAsyncClient()
+{
+    if (State::IN_POOL == m_state)
+        shutdown(nullptr);
+
+    if (State::CLOSED != m_state)
+        close();
+}
+
+bool WinAsyncClient::shutdown(const IgniteError* err)
+{
+    std::lock_guard<std::mutex> lock(m_sendMutex);
+
+    if (State::CONNECTED != m_state && State::IN_POOL != m_state)
+        return false;
+
+    m_closeErr = err ? *err : IgniteError("Connection closed by application");
+
+    ::shutdown(m_socket, SD_BOTH);
+
+    m_state = State::SHUTDOWN;
+
+    return true;
+}
+
+bool WinAsyncClient::close()
+{
+    if (State::CLOSED == m_state)
+        return false;
+
+    ::closesocket(m_socket);
+
+    m_sendPackets.clear();
+    m_recvPacket.clear();
+
+    m_state = State::CLOSED;
+
+    return true;
+}
+
+HANDLE WinAsyncClient::addToIocp(HANDLE iocp)
+{
+    assert(State::CONNECTED == m_state);
+
+    HANDLE res = CreateIoCompletionPort((HANDLE)socket, iocp, reinterpret_cast<DWORD_PTR>(this), 0);
+
+    if (!res)
+        return res;
+
+    m_state = State::IN_POOL;
+
+    return res;
+}
+
+bool WinAsyncClient::send(const DataBuffer& data)
+{
+    std::lock_guard<std::mutex> lock(m_sendMutex);
+
+    if (State::CONNECTED != m_state && State::IN_POOL != m_state)
+        return false;
+
+    m_sendPackets.push_back(data);
+
+    if (m_sendPackets.size() > 1)
+        return true;
+
+    return sendNextPacketLocked();
+}
+
+bool WinAsyncClient::sendNextPacketLocked()
+{
+    if (m_sendPackets.empty())
+        return true;
+
+    const DataBuffer& packet0 = m_sendPackets.front();
+    DWORD flags = 0;
+
+    WSABUF buffer;
+    buffer.buf = (CHAR*)packet0.getData();
+    buffer.len = packet0.getSize();
+
+    int ret = ::WSASend(m_socket, &buffer, 1, NULL, flags, &m_currentSend.overlapped, NULL); // NOLINT(modernize-use-nullptr)
+
+    return ret != SOCKET_ERROR || WSAGetLastError() == ERROR_IO_PENDING;
+}
+
+bool WinAsyncClient::receive()
+{
+    // We do not need locking on receive as we're always reading in a single thread at most.
+    // If this ever changes we'd need to add mutex locking here.
+    if (State::CONNECTED != m_state && State::IN_POOL != m_state)
+        return false;
+
+    if (m_recvPacket.empty())
+        clearReceiveBuffer();
+
+    DWORD flags = 0;
+    WSABUF buffer;
+    buffer.buf = (CHAR*)m_recvPacket.data();
+    buffer.len = (ULONG)m_recvPacket.size();
+
+    int ret = ::WSARecv(m_socket, &buffer, 1, NULL, &flags, &m_currentRecv.overlapped, NULL); // NOLINT(modernize-use-nullptr)
+
+    return ret != SOCKET_ERROR || WSAGetLastError() == ERROR_IO_PENDING;
+}
+
+void WinAsyncClient::clearReceiveBuffer()
+{
+    if (m_recvPacket.empty())
+        m_recvPacket.resize(m_bufLen);
+}
+
+DataBuffer WinAsyncClient::processReceived(size_t bytes)
+{
+    // TODO: Re-factor read-only data buffers
+    return {std::make_shared<protocol::Buffer>(m_recvPacket), 0, static_cast<int32_t>(bytes)};
+}
+
+bool WinAsyncClient::processSent(size_t bytes)
+{
+    std::lock_guard<std::mutex> lock(m_sendMutex);
+
+    DataBuffer& front = m_sendPackets.front();
+
+    front.skip(static_cast<int32_t>(bytes));
+
+    if (front.isEmpty())
+        m_sendPackets.pop_front();
+
+    return sendNextPacketLocked();
+}
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/os/win/src/network/win_async_client.h b/modules/platforms/cpp/network/os/win/src/network/win_async_client.h
new file mode 100644
index 0000000000..d31e4a97c6
--- /dev/null
+++ b/modules/platforms/cpp/network/os/win/src/network/win_async_client.h
@@ -0,0 +1,270 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "network/sockets.h"
+
+#include <cstdint>
+#include <deque>
+#include <memory>
+#include <mutex>
+
+#include <ignite/network/async_handler.h>
+#include <ignite/network/codec.h>
+#include <ignite/network/end_point.h>
+#include <ignite/network/tcp_range.h>
+
+namespace ignite::network
+{
+
+/**
+ * Operation kind.
+ */
+enum class IoOperationKind
+{
+    SEND,
+
+    RECEIVE,
+};
+
+/**
+ * Represents single IO operation.
+ * Needed to be able to distinguish one operation from another.
+ */
+struct IoOperation
+{
+    /** Overlapped structure that should be passed to every IO operation. */
+    WSAOVERLAPPED overlapped;
+
+    /** Operation type. */
+    IoOperationKind kind;
+};
+
+/**
+ * Windows-specific implementation of async network client.
+ */
+class WinAsyncClient
+{
+public:
+    /**
+     * State.
+     */
+    enum class State
+    {
+        CONNECTED,
+
+        IN_POOL,
+
+        SHUTDOWN,
+
+        CLOSED,
+    };
+
+    /**
+     * Constructor.
+     *
+     * @param socket Socket.
+     * @param addr Address.
+     * @param range Range.
+     * @param m_bufLen Buffer length.
+     */
+    WinAsyncClient(SOCKET m_socket, EndPoint addr, TcpRange range, int32_t m_bufLen);
+
+    /**
+     * Destructor.
+     */
+    ~WinAsyncClient();
+
+    /**
+     * Shutdown client.
+     *
+     * Can be called from external threads.
+     * Can be called from WorkerThread.
+     *
+     * @param err Error message. Can be null.
+     * @return @c true if shutdown performed successfully.
+     */
+    bool shutdown(const IgniteError* err);
+
+    /**
+     * Close client.
+     *
+     * Should not be called from external threads.
+     * Can be called from WorkerThread.
+     *
+     * @return @c true if shutdown performed successfully.
+     */
+    bool close();
+
+    /**
+     * Add client to IOCP.
+     *
+     * @return IOCP handle on success and NULL otherwise.
+     */
+    HANDLE addToIocp(HANDLE m_iocp);
+
+    /**
+     * Send packet using client.
+     *
+     * @param data Data to send.
+     * @return @c true on success.
+     */
+    bool send(const DataBuffer& data);
+
+    /**
+     * Initiate next receive of data.
+     *
+     * @return @c true on success.
+     */
+    bool receive();
+
+    /**
+     * Get client ID.
+     *
+     * @return Client ID.
+     */
+    [[nodiscard]]
+    uint64_t GetId() const
+    {
+        return m_id;
+    }
+
+    /**
+     * Set ID.
+     *
+     * @param id ID to set.
+     */
+    void setId(uint64_t id)
+    {
+        m_id = id;
+    }
+
+    /**
+     * Get address.
+     *
+     * @return Address.
+     */
+    [[nodiscard]]
+    const EndPoint& getAddress() const
+    {
+        return m_addr;
+    }
+
+    /**
+     * Get range.
+     *
+     * @return Range.
+     */
+    [[nodiscard]]
+    const TcpRange& getRange() const
+    {
+        return m_range;
+    }
+
+    /**
+     * Check whether client is closed.
+     *
+     * @return @c true if closed.
+     */
+    [[nodiscard]]
+    bool isClosed() const
+    {
+        return m_socket == NULL;
+    }
+
+    /**
+     * Process sent data.
+     *
+     * @param bytes Bytes.
+     * @return @c true on success.
+     */
+    bool processSent(size_t bytes);
+
+    /**
+     * Process received bytes.
+     *
+     * @param bytes Number of received bytes.
+     */
+    DataBuffer processReceived(size_t bytes);
+
+    /**
+     * Get closing error for the connection. Can be IGNITE_SUCCESS.
+     *
+     * @return Connection error.
+     */
+    [[nodiscard]]
+    const IgniteError& getCloseError() const
+    {
+        return m_closeErr;
+    }
+
+private:
+
+    /**
+     * Clears client's receive buffer.
+     *
+     * @return Data received so far.
+     */
+    void clearReceiveBuffer();
+
+    /**
+     * Send next packet in queue.
+     *
+     * @warning Can only be called when holding m_sendMutex lock.
+     * @return @c true on success.
+     */
+    bool sendNextPacketLocked();
+
+    /** Buffer length. */
+    const int32_t m_bufLen;
+
+    /** Client state. */
+    State m_state;
+
+    /** Socket. */
+    SOCKET m_socket;
+
+    /** Connection ID. */
+    uint64_t m_id;
+
+    /** Server end point. */
+    EndPoint m_addr;
+
+    /** Address range associated with current connection. */
+    TcpRange m_range;
+
+    /** Current send operation. */
+    IoOperation m_currentSend{};
+
+    /** Packets that should be sent. */
+    std::deque<DataBuffer> m_sendPackets;
+
+    /** Send critical section. */
+    std::mutex m_sendMutex;
+
+    /** Current receive operation. */
+    IoOperation m_currentRecv{};
+
+    /** Packet that is currently received. */
+    std::vector<std::byte> m_recvPacket;
+
+    /** Closing error. */
+    IgniteError m_closeErr;
+};
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/os/win/src/network/win_async_client_pool.cpp b/modules/platforms/cpp/network/os/win/src/network/win_async_client_pool.cpp
new file mode 100644
index 0000000000..a993613c4c
--- /dev/null
+++ b/modules/platforms/cpp/network/os/win/src/network/win_async_client_pool.cpp
@@ -0,0 +1,234 @@
+/*
+ * 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.
+ */
+
+#include <algorithm>
+
+#include <network/utils.h>
+
+#include "network/sockets.h"
+#include "network/win_async_client_pool.h"
+
+// Using NULLs as specified by WinAPI
+#pragma ide diagnostic ignored "modernize-use-nullptr"
+
+namespace ignite::network
+{
+
+WinAsyncClientPool::WinAsyncClientPool() :
+    m_stopping(true),
+    m_asyncHandler(nullptr),
+    m_connectingThread(),
+    m_workerThread(),
+    m_idGen(0),
+    m_iocp(NULL),
+    m_clientsMutex(),
+    m_clientIdMap() { }
+
+WinAsyncClientPool::~WinAsyncClientPool()
+{
+    internalStop();
+}
+
+void WinAsyncClientPool::start(std::vector<TcpRange> addrs, uint32_t connLimit)
+{
+    if (!m_stopping)
+        throw IgniteError(StatusCode::GENERIC, "Client pool is already started");
+
+    m_stopping = false;
+
+    InitWsa();
+
+    m_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
+    if (!m_iocp)
+        ThrowLastSystemError("Failed to create IOCP instance");
+
+    try
+    {
+        m_connectingThread.start(*this, connLimit, std::move(addrs));
+        m_workerThread.start(*this, m_iocp);
+    }
+    catch (...)
+    {
+        stop();
+
+        throw;
+    }
+}
+
+void WinAsyncClientPool::stop()
+{
+    internalStop();
+}
+
+void WinAsyncClientPool::internalStop()
+{
+    m_stopping = true;
+    m_connectingThread.stop();
+
+    {
+        std::lock_guard<std::mutex> lock(m_clientsMutex);
+
+        for (auto it = m_clientIdMap.begin(); it != m_clientIdMap.end(); ++it)
+        {
+            WinAsyncClient& client = *it->second;
+
+            client.shutdown(nullptr);
+            client.close();
+        }
+    }
+
+    m_workerThread.stop();
+
+    CloseHandle(m_iocp);
+    m_iocp = NULL;
+
+    m_clientIdMap.clear();
+}
+
+bool WinAsyncClientPool::addClient(std::shared_ptr<WinAsyncClient> client)
+{
+    uint64_t id;
+    {
+        std::lock_guard<std::mutex> lock(m_clientsMutex);
+
+        if (m_stopping)
+            return false;
+
+        id = ++m_idGen;
+        client->setId(id);
+
+        HANDLE iocp0 = client->addToIocp(m_iocp);
+        if (iocp0 == NULL)
+            ThrowLastSystemError("Can not add socket to IOCP");
+
+        m_iocp = iocp0;
+
+        m_clientIdMap[id] = std::move(client);
+    }
+
+    PostQueuedCompletionStatus(m_iocp, 0, reinterpret_cast<ULONG_PTR>(client.get()), NULL);
+
+    return true;
+}
+
+void WinAsyncClientPool::handleConnectionError(const EndPoint &addr, const IgniteError &err)
+{
+    AsyncHandler* asyncHandler0 = m_asyncHandler;
+    if (asyncHandler0)
+        asyncHandler0->onConnectionError(addr, err);
+}
+
+void WinAsyncClientPool::handleConnectionSuccess(const EndPoint &addr, uint64_t id)
+{
+    AsyncHandler* asyncHandler0 = m_asyncHandler;
+    if (asyncHandler0)
+        asyncHandler0->onConnectionSuccess(addr, id);
+}
+
+void WinAsyncClientPool::handleConnectionClosed(uint64_t id, const IgniteError *err)
+{
+    AsyncHandler* asyncHandler0 = m_asyncHandler;
+    if (asyncHandler0)
+        asyncHandler0->onConnectionClosed(id, err);
+}
+
+void WinAsyncClientPool::handleMessageReceived(uint64_t id, const DataBuffer &msg)
+{
+    AsyncHandler* asyncHandler0 = m_asyncHandler;
+    if (asyncHandler0)
+        asyncHandler0->onMessageReceived(id, msg);
+}
+
+void WinAsyncClientPool::handleMessageSent(uint64_t id)
+{
+    AsyncHandler* asyncHandler0 = m_asyncHandler;
+    if (asyncHandler0)
+        asyncHandler0->onMessageSent(id);
+}
+
+bool WinAsyncClientPool::send(uint64_t id, const DataBuffer& data)
+{
+    if (m_stopping)
+        return false;
+
+    auto client = findClient(id);
+    if (!client)
+        return false;
+
+    return client->send(data);
+}
+
+void WinAsyncClientPool::closeAndRelease(uint64_t id, const IgniteError* err)
+{
+    std::shared_ptr<WinAsyncClient> client;
+    {
+        std::lock_guard<std::mutex> lock(m_clientsMutex);
+
+        auto it = m_clientIdMap.find(id);
+        if (it == m_clientIdMap.end())
+            return;
+
+        client = it->second;
+
+        m_clientIdMap.erase(it);
+    }
+
+    bool closed = client->close();
+    if (closed)
+    {
+        m_connectingThread.notifyFreeAddress(client->getRange());
+
+        IgniteError err0(client->getCloseError());
+        if (err0.getStatusCode() == StatusCode::SUCCESS)
+            err0 = IgniteError(StatusCode::NETWORK, "Connection closed by server");
+
+        if (!err)
+            err = &err0;
+
+        handleConnectionClosed(id, err);
+    }
+}
+
+void WinAsyncClientPool::close(uint64_t id, const IgniteError* err)
+{
+    auto client = findClient(id);
+    if (client && !client->isClosed())
+        client->shutdown(err);
+}
+
+std::shared_ptr<WinAsyncClient> WinAsyncClientPool::findClient(uint64_t id) const
+{
+    std::lock_guard<std::mutex> lock(m_clientsMutex);
+
+    return findClientLocked(id);
+}
+
+std::shared_ptr<WinAsyncClient> WinAsyncClientPool::findClientLocked(uint64_t id) const
+{
+    auto it = m_clientIdMap.find(id);
+    if (it == m_clientIdMap.end())
+        return {};
+
+    return it->second;
+}
+
+void WinAsyncClientPool::setHandler(AsyncHandler *handler)
+{
+    m_asyncHandler = handler;
+}
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/os/win/src/network/win_async_client_pool.h b/modules/platforms/cpp/network/os/win/src/network/win_async_client_pool.h
new file mode 100644
index 0000000000..9a74a8a42b
--- /dev/null
+++ b/modules/platforms/cpp/network/os/win/src/network/win_async_client_pool.h
@@ -0,0 +1,204 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <map>
+#include <mutex>
+
+#include <common/ignite_error.h>
+
+#include <ignite/network/async_client_pool.h>
+#include <ignite/network/async_handler.h>
+#include <ignite/network/tcp_range.h>
+
+#include "network/win_async_client.h"
+#include "network/win_async_connecting_thread.h"
+#include "network/win_async_worker_thread.h"
+
+namespace ignite::network
+{
+/**
+ * Windows-specific implementation of asynchronous client pool.
+ */
+class WinAsyncClientPool : public AsyncClientPool
+{
+public:
+    /**
+     * Constructor
+     *
+     * @param handler Upper level event handler.
+     */
+    WinAsyncClientPool();
+
+    /**
+     * Destructor.
+     */
+    ~WinAsyncClientPool() override;
+
+    /**
+     * Start internal thread that establishes connections to provided addresses and asynchronously sends and
+     * receives messages from them. Function returns either when thread is started and first connection is
+     * established or failure happened.
+     *
+     * @param addrs Addresses to connect to.
+     * @param connLimit Connection upper limit. Zero means limit is disabled.
+     *
+     * @throw IgniteError on error.
+     */
+    void start(std::vector<TcpRange> addrs, uint32_t connLimit) override;
+
+    /**
+     * Close all established connections and stops handling thread.
+     */
+    void stop() override;
+
+    /**
+     * Set handler.
+     *
+     * @param handler Handler to set.
+     */
+    void setHandler(AsyncHandler *handler) override;
+
+    /**
+     * Send data to specific established connection.
+     *
+     * @param id Client ID.
+     * @param data Data to be sent.
+     * @return @c true if connection is present and @c false otherwise.
+     *
+     * @throw IgniteError on error.
+     */
+    bool send(uint64_t id, const DataBuffer& data) override;
+
+    /**
+     * Closes specified connection if it's established. Connection to the specified address is planned for
+     * re-connect. Event is issued to the handler with specified error.
+     *
+     * @param id Client ID.
+     */
+    void close(uint64_t id, const IgniteError* err) override;
+
+    /**
+     * Closes and releases memory allocated for client with specified ID.
+     * Error is reported to handler.
+     *
+     * @param id Client ID.
+     * @param err Error to report. May be null.
+     * @return @c true if connection with specified ID was found.
+     */
+    void closeAndRelease(uint64_t id, const IgniteError* err);
+
+    /**
+     * Add client to connection map. Notify user.
+     *
+     * @param client Client.
+     * @return Client ID.
+     */
+    bool addClient(std::shared_ptr<WinAsyncClient> client);
+
+    /**
+     * Handle error during connection establishment.
+     *
+     * @param addr Connection address.
+     * @param err Error.
+     */
+    void handleConnectionError(const EndPoint& addr, const IgniteError& err);
+
+    /**
+     * Handle successful connection establishment.
+     *
+     * @param addr Address of the new connection.
+     * @param id Connection ID.
+     */
+    void handleConnectionSuccess(const EndPoint& addr, uint64_t id);
+
+    /**
+     * Handle error during connection establishment.
+     *
+     * @param id Async client ID.
+     * @param err Error. Can be null if connection closed without error.
+     */
+    void handleConnectionClosed(uint64_t id, const IgniteError* err);
+
+    /**
+     * Handle new message.
+     *
+     * @param id Async client ID.
+     * @param msg Received message.
+     */
+    void handleMessageReceived(uint64_t id, const DataBuffer& msg);
+
+    /**
+     * Handle sent message event.
+     *
+     * @param id Async client ID.
+     */
+    void handleMessageSent(uint64_t id);
+
+private:
+     /**
+     * Close all established connections and stops handling threads.
+     */
+    void internalStop();
+
+    /**
+     * Find client by ID.
+     *
+     * @param id Client ID.
+     * @return Client. Null pointer if is not found.
+     */
+    [[nodiscard]]
+    std::shared_ptr<WinAsyncClient> findClient(uint64_t id) const;
+
+    /**
+     * Find client by ID.
+     *
+     * @warning Should only be called with m_clientsMutex lock held.
+     * @param id Client ID.
+     * @return Client. Null pointer if is not found.
+     */
+    [[nodiscard]]
+    std::shared_ptr<WinAsyncClient> findClientLocked(uint64_t id) const;
+
+    /** Flag indicating that pool is stopping. */
+    volatile bool m_stopping;
+
+    /** Event handler. */
+    AsyncHandler* m_asyncHandler;
+
+    /** Connecting thread. */
+    WinAsyncConnectingThread m_connectingThread;
+
+    /** Internal thread. */
+    WinAsyncWorkerThread m_workerThread;
+
+    /** ID counter. */
+    uint64_t m_idGen;
+
+    /** IO Completion Port. Windows-specific primitive for asynchronous IO. */
+    HANDLE m_iocp;
+
+    /** Clients critical section. */
+    mutable std::mutex m_clientsMutex;
+
+    /** Client mapping ID -> client */
+    std::map<uint64_t, std::shared_ptr<WinAsyncClient>> m_clientIdMap;
+};
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/os/win/src/network/win_async_connecting_thread.cpp b/modules/platforms/cpp/network/os/win/src/network/win_async_connecting_thread.cpp
new file mode 100644
index 0000000000..d5bfec7de1
--- /dev/null
+++ b/modules/platforms/cpp/network/os/win/src/network/win_async_connecting_thread.cpp
@@ -0,0 +1,250 @@
+/*
+ * 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.
+ */
+
+#include "network/utils.h"
+
+#include "network/sockets.h"
+#include "network/win_async_client_pool.h"
+#include "network/win_async_connecting_thread.h"
+
+// Using NULLs as specified by WinAPI
+#pragma ide diagnostic ignored "modernize-use-nullptr"
+
+namespace
+{
+    ignite::network::FibonacciSequence<10> fibonacci10;
+}
+
+namespace ignite::network
+{
+
+WinAsyncConnectingThread::WinAsyncConnectingThread() :
+    m_thread(),
+    m_clientPool(nullptr),
+    m_stopping(false),
+    m_failedAttempts(0),
+    m_minAddrs(0),
+    m_addrsMutex(),
+    m_connectNeeded(),
+    m_nonConnected() { }
+
+void WinAsyncConnectingThread::run()
+{
+    assert(m_clientPool != nullptr);
+
+    while (!m_stopping)
+    {
+        TcpRange range = getRandomAddress();
+
+        if (m_stopping || range.isEmpty())
+            break;
+
+        std::shared_ptr<WinAsyncClient> client = tryConnect(range);
+
+        if (!client)
+        {
+            ++m_failedAttempts;
+
+            auto msToWait = static_cast<DWORD>(1000 * fibonacci10.GetValue(m_failedAttempts));
+            if (msToWait)
+                Sleep(msToWait);
+
+            continue;
+        }
+
+        m_failedAttempts = 0;
+
+        if (m_stopping)
+        {
+            client->close();
+
+            return;
+        }
+
+        try
+        {
+            bool added = m_clientPool->addClient(client);
+
+            if (!added)
+            {
+                client->close();
+
+                continue;
+            }
+
+            {
+                std::lock_guard<std::mutex> lock(m_addrsMutex);
+
+                auto it = std::find(m_nonConnected.begin(), m_nonConnected.end(), range);
+                if (it != m_nonConnected.end())
+                    m_nonConnected.erase(it);
+            }
+        }
+        catch (const IgniteError& err)
+        {
+            client->close();
+
+            m_clientPool->handleConnectionError(client->getAddress(), err);
+
+            continue;
+        }
+    }
+}
+
+void WinAsyncConnectingThread::notifyFreeAddress(const TcpRange &range)
+{
+    std::lock_guard<std::mutex> lock(m_addrsMutex);
+
+    m_nonConnected.push_back(range);
+    m_connectNeeded.notify_one();
+}
+
+void WinAsyncConnectingThread::start(WinAsyncClientPool& clientPool, size_t limit, std::vector<TcpRange> addrs)
+{
+    m_stopping = false;
+    m_clientPool = &clientPool;
+    m_failedAttempts = 0;
+    m_nonConnected = std::move(addrs);
+
+    if (!limit || limit > m_nonConnected.size())
+        m_minAddrs = 0;
+    else
+        m_minAddrs = m_nonConnected.size() - limit;
+
+    m_thread = std::thread(&WinAsyncConnectingThread::run, this);
+}
+
+void WinAsyncConnectingThread::stop()
+{
+    m_stopping = true;
+
+    {
+        std::lock_guard<std::mutex> lock(m_addrsMutex);
+        m_connectNeeded.notify_one();
+    }
+
+    m_thread.join();
+    m_nonConnected.clear();
+}
+
+std::shared_ptr<WinAsyncClient> WinAsyncConnectingThread::tryConnect(const TcpRange& range)
+{
+    for (uint16_t port = range.port; port <= (range.port + range.range); ++port)
+    {
+        EndPoint addr(range.host, port);
+        try
+        {
+            SOCKET socket = tryConnect(addr);
+
+            return std::make_shared<WinAsyncClient>(socket, addr, range, BUFFER_SIZE);
+        }
+        catch (const IgniteError&)
+        {
+            // No-op.
+        }
+    }
+
+    return {};
+}
+
+SOCKET WinAsyncConnectingThread::tryConnect(const EndPoint& addr)
+{
+    addrinfo hints{};
+    memset(&hints, 0, sizeof(hints));
+
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = IPPROTO_TCP;
+
+    std::stringstream converter;
+    converter << addr.port;
+    std::string strPort = converter.str();
+
+    // Resolve the server address and port
+    addrinfo *result = NULL;
+    int res = getaddrinfo(addr.host.c_str(), strPort.c_str(), &hints, &result);
+
+    if (res != 0)
+        ThrowNetworkError("Can not resolve host: " + addr.host + ":" + strPort);
+
+    std::string lastErrorMsg = "Failed to resolve host";
+
+    SOCKET socket = INVALID_SOCKET; // NOLINT(modernize-use-auto)
+
+    // Attempt to connect to an address until one succeeds
+    for (addrinfo *it = result; it != NULL; it = it->ai_next)
+    {
+        lastErrorMsg = "Failed to establish connection with the host";
+
+        socket = WSASocket(it->ai_family, it->ai_socktype, it->ai_protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
+
+        if (socket == INVALID_SOCKET)
+            ThrowNetworkError("Socket creation failed: " + getLastSocketErrorMessage());
+
+        TrySetSocketOptions(socket, BUFFER_SIZE, TRUE, TRUE, TRUE);
+
+        // Connect to server.
+        res = WSAConnect(socket, it->ai_addr, static_cast<int>(it->ai_addrlen), NULL, NULL, NULL, NULL);
+        if (SOCKET_ERROR == res)
+        {
+            closesocket(socket);
+            socket = INVALID_SOCKET;
+
+            int lastError = WSAGetLastError();
+
+            if (lastError != WSAEWOULDBLOCK)
+            {
+                lastErrorMsg.append(": ").append(getSocketErrorMessage(lastError));
+
+                continue;
+            }
+        }
+
+        break;
+    }
+
+    freeaddrinfo(result);
+
+    if (socket == INVALID_SOCKET)
+        ThrowNetworkError(lastErrorMsg);
+
+    return socket;
+}
+
+TcpRange WinAsyncConnectingThread::getRandomAddress() const
+{
+    std::unique_lock<std::mutex> lock(m_addrsMutex);
+
+    if (m_stopping)
+        return {};
+
+    while (m_nonConnected.size() <= m_minAddrs)
+    {
+        m_connectNeeded.wait(lock);
+
+        if (m_stopping)
+            return {};
+    }
+
+    // TODO: Re-write to round-robin
+    size_t idx = rand() % m_nonConnected.size();
+    TcpRange range = m_nonConnected.at(idx);
+
+    return range;
+}
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/os/win/src/network/win_async_connecting_thread.h b/modules/platforms/cpp/network/os/win/src/network/win_async_connecting_thread.h
new file mode 100644
index 0000000000..f9fa4be965
--- /dev/null
+++ b/modules/platforms/cpp/network/os/win/src/network/win_async_connecting_thread.h
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+
+#include "common/ignite_error.h"
+
+#include <ignite/network/async_client_pool.h>
+#include <ignite/network/async_handler.h>
+#include <ignite/network/tcp_range.h>
+
+#include "network/win_async_client.h"
+
+namespace ignite::network
+{
+
+class WinAsyncClientPool;
+
+/**
+ * Async pool connecting thread.
+ */
+class WinAsyncConnectingThread
+{
+    /** Send and receive buffers size. */
+    static constexpr size_t BUFFER_SIZE = 0x10000;
+
+public:
+    /**
+     * Constructor.
+     */
+    WinAsyncConnectingThread();
+
+    /**
+     * Start thread.
+     *
+     * @param clientPool Client pool.
+     * @param limit Connection limit.
+     * @param addrs Addresses.
+     */
+    void start(WinAsyncClientPool& clientPool, size_t limit, std::vector<TcpRange> addrs);
+
+    /**
+     * Stop thread.
+     */
+    void stop();
+
+    /**
+     * Notify about new address available for connection.
+     *
+     * @param range Address range.
+     */
+    void notifyFreeAddress(const TcpRange &range);
+
+private:
+    /**
+     * Run thread.
+     */
+    void run();
+
+    /**
+     * Try establish connection to address in the range.
+     * @param range TCP range.
+     * @return New client.
+     */
+    static std::shared_ptr<WinAsyncClient> tryConnect(const TcpRange& range);
+
+    /**
+     * Try establish connection to address.
+     * @param addr Address.
+     * @return Socket.
+     */
+    static SOCKET tryConnect(const EndPoint& addr);
+
+    /**
+     * Get random address.
+     *
+     * @warning Will block if no addresses are available for connect.
+     * @return @c true if a new connection should be established.
+     */
+    TcpRange getRandomAddress() const;
+
+    /** Thread. */
+    std::thread m_thread;
+
+    /** Client pool. */
+    WinAsyncClientPool* m_clientPool;
+
+    /** Flag to signal that thread is stopping. */
+    volatile bool m_stopping;
+
+    /** Failed connection attempts. */
+    size_t m_failedAttempts;
+
+    /** Minimal number of addresses. */
+    size_t m_minAddrs;
+
+    /** Addresses critical section. */
+    mutable std::mutex m_addrsMutex;
+
+    /** Condition variable, which signalled when new connect is needed. */
+    mutable std::condition_variable m_connectNeeded;
+
+    /** Addresses to use for connection establishment. */
+    std::vector<TcpRange> m_nonConnected;
+};
+}
diff --git a/modules/platforms/cpp/network/os/win/src/network/win_async_worker_thread.cpp b/modules/platforms/cpp/network/os/win/src/network/win_async_worker_thread.cpp
new file mode 100644
index 0000000000..8cfda7a45c
--- /dev/null
+++ b/modules/platforms/cpp/network/os/win/src/network/win_async_worker_thread.cpp
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+#include <algorithm>
+
+#include "network/sockets.h"
+#include "network/win_async_client.h"
+#include "network/win_async_client_pool.h"
+#include "network/win_async_worker_thread.h"
+
+// Using NULLs as specified by WinAPI
+#pragma ide diagnostic ignored "modernize-use-nullptr"
+
+namespace ignite::network
+{
+
+WinAsyncWorkerThread::WinAsyncWorkerThread() :
+    m_thread(),
+    m_stopping(false),
+    m_clientPool(nullptr),
+    m_iocp(NULL) { }
+
+void WinAsyncWorkerThread::start(WinAsyncClientPool& clientPool0, HANDLE iocp0)
+{
+    assert(iocp0 != NULL);
+    m_iocp = iocp0;
+    m_clientPool = &clientPool0;
+
+    m_thread = std::thread(&WinAsyncWorkerThread::run, this);
+}
+
+void WinAsyncWorkerThread::run()
+{
+    assert(m_clientPool != nullptr);
+
+    while (!m_stopping)
+    {
+        DWORD bytesTransferred = 0;
+        ULONG_PTR key = NULL;
+        LPOVERLAPPED overlapped = NULL;
+
+        BOOL ok = GetQueuedCompletionStatus(m_iocp, &bytesTransferred, &key, &overlapped, INFINITE);
+
+        if (m_stopping)
+            break;
+
+        if (!key)
+            continue;
+
+        auto client = reinterpret_cast<WinAsyncClient*>(key);
+
+        if (!ok || (NULL != overlapped && 0 == bytesTransferred))
+        {
+            m_clientPool->closeAndRelease(client->GetId(), nullptr);
+
+            continue;
+        }
+
+        if (!overlapped)
+        {
+            // This mean new client is connected.
+            m_clientPool->handleConnectionSuccess(client->getAddress(), client->GetId());
+
+            bool success = client->receive();
+            if (!success)
+                m_clientPool->closeAndRelease(client->GetId(), nullptr);
+
+            continue;
+        }
+
+        try
+        {
+            auto operation = reinterpret_cast<IoOperation*>(overlapped);
+            switch (operation->kind)
+            {
+                case IoOperationKind::SEND:
+                {
+                    bool success = client->processSent(bytesTransferred);
+
+                    if (!success)
+                        m_clientPool->closeAndRelease(client->GetId(), nullptr);
+
+                    m_clientPool->handleMessageSent(client->GetId());
+
+                    break;
+                }
+
+                case IoOperationKind::RECEIVE:
+                {
+                    DataBuffer data = client->processReceived(bytesTransferred);
+
+                    if (!data.isEmpty())
+                        m_clientPool->handleMessageReceived(client->GetId(), data);
+
+                    bool success = client->receive();
+
+                    if (!success)
+                        m_clientPool->closeAndRelease(client->GetId(), nullptr);
+
+                    break;
+                }
+
+                default:
+                    break;
+            }
+        }
+        catch (const IgniteError& err)
+        {
+            m_clientPool->closeAndRelease(client->GetId(), &err);
+        }
+    }
+}
+
+void WinAsyncWorkerThread::stop()
+{
+    m_stopping = true;
+
+    PostQueuedCompletionStatus(m_iocp, 0, 0, NULL);
+
+    m_thread.join();
+}
+
+} // namespace ignite::network
+
diff --git a/modules/platforms/cpp/client/src/ignite_client_impl.h b/modules/platforms/cpp/network/os/win/src/network/win_async_worker_thread.h
similarity index 52%
copy from modules/platforms/cpp/client/src/ignite_client_impl.h
copy to modules/platforms/cpp/network/os/win/src/network/win_async_worker_thread.h
index 17be39464f..93044e7325 100644
--- a/modules/platforms/cpp/client/src/ignite_client_impl.h
+++ b/modules/platforms/cpp/network/os/win/src/network/win_async_worker_thread.h
@@ -17,49 +17,58 @@
 
 #pragma once
 
-#include <future>
-#include <memory>
+#include <cstdint>
+#include <thread>
 
-#include "ignite/ignite_client_configuration.h"
+#include "common/ignite_error.h"
 
-namespace ignite::impl
+namespace ignite::network
 {
 
+/** Windows async client pool. */
+class WinAsyncClientPool;
+
 /**
- * Ignite client implementation.
+ * Async pool worker thread.
  */
-class IgniteClientImpl
+class WinAsyncWorkerThread
 {
 public:
-    // Deleted
-    IgniteClientImpl(const IgniteClientImpl&) = delete;
-    IgniteClientImpl& operator=(const IgniteClientImpl&) = delete;
-
-    // Default
-    IgniteClientImpl() = default;
-    ~IgniteClientImpl() = default;
-    IgniteClientImpl(IgniteClientImpl&&) = default;
-    IgniteClientImpl& operator=(IgniteClientImpl&&) = default;
-
     /**
      * Constructor.
+     */
+    WinAsyncWorkerThread();
+
+    /**
+     * Start thread.
      *
-     * @param configuration Configuration.
+     * @param clientPool Client pool.
+     * @param iocp Valid IOCP instance handle.
      */
-    explicit IgniteClientImpl(IgniteClientConfiguration configuration) :
-        m_configuration(std::move(configuration)) { }
+    void start(WinAsyncClientPool& clientPool, HANDLE iocp);
 
     /**
-     * Start client.
+     * Stop thread.
      */
-    void start()
-    {
-        // TODO
-    }
+    void stop();
 
 private:
-    /** Configuration. */
-    IgniteClientConfiguration m_configuration;
+    /**
+     * Run thread.
+     */
+    void run();
+
+    /** Thread. */
+    std::thread m_thread;
+
+    /** Flag to signal that thread should stop. */
+    volatile bool m_stopping;
+
+    /** Client pool. */
+    WinAsyncClientPool* m_clientPool;
+
+    /** IO Completion Port. Windows-specific primitive for asynchronous IO. */
+    HANDLE m_iocp;
 };
 
-} // namespace ignite::impl
\ No newline at end of file
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/src/network/async_client_pool_adapter.cpp b/modules/platforms/cpp/network/src/network/async_client_pool_adapter.cpp
new file mode 100644
index 0000000000..ad9296ec79
--- /dev/null
+++ b/modules/platforms/cpp/network/src/network/async_client_pool_adapter.cpp
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#include "network/async_client_pool_adapter.h"
+#include "network/error_handling_filter.h"
+
+namespace ignite::network
+{
+
+AsyncClientPoolAdapter::AsyncClientPoolAdapter(DataFilters filters, std::shared_ptr<AsyncClientPool> pool) :
+    m_filters(std::move(filters)),
+    m_pool(std::move(pool)),
+    m_sink(pool.get())
+{
+    m_filters.insert(m_filters.begin(), std::make_shared<ErrorHandlingFilter>());
+
+    for (const auto& filter : m_filters)
+    {
+        filter->setSink(m_sink);
+        m_sink = filter.get();
+    }
+}
+
+void AsyncClientPoolAdapter::start(std::vector<TcpRange> addrs, uint32_t connLimit)
+{
+    m_pool->start(std::move(addrs), connLimit);
+}
+
+void AsyncClientPoolAdapter::stop()
+{
+    m_pool->stop();
+}
+
+void AsyncClientPoolAdapter::setHandler(AsyncHandler* handler)
+{
+    auto handler0 = handler;
+    for (auto it = m_filters.rbegin(); it != m_filters.rend(); ++it)
+    {
+        (*it)->setHandler(handler0);
+        handler0 = it->get();
+    }
+
+    m_pool->setHandler(handler0);
+}
+
+bool AsyncClientPoolAdapter::send(uint64_t id, const DataBuffer& data)
+{
+    return m_sink->send(id, data);
+}
+
+void AsyncClientPoolAdapter::close(uint64_t id, const IgniteError* err)
+{
+    m_sink->close(id, err);
+}
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/src/network/async_client_pool_adapter.h b/modules/platforms/cpp/network/src/network/async_client_pool_adapter.h
new file mode 100644
index 0000000000..5f78d82d02
--- /dev/null
+++ b/modules/platforms/cpp/network/src/network/async_client_pool_adapter.h
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <ignite/network/async_client_pool.h>
+#include <ignite/network/data_filter.h>
+
+namespace ignite::network
+{
+/**
+ * Asynchronous client pool adapter.
+ */
+class AsyncClientPoolAdapter : public AsyncClientPool
+{
+public:
+    /**
+     * Constructor.
+     *
+     * @param filters Filters.
+     * @param pool Client pool.
+     */
+    AsyncClientPoolAdapter(DataFilters filters, std::shared_ptr<AsyncClientPool> pool);
+
+    /**
+     * Destructor.
+     */
+    ~AsyncClientPoolAdapter() override = default;
+
+    /**
+     * Start internal thread that establishes connections to provided addresses and asynchronously sends and
+     * receives messages from them. Function returns either when thread is started and first connection is
+     * established or failure happened.
+     *
+     * @param addrs Addresses to connect to.
+     * @param connLimit Connection upper limit. Zero means limit is disabled.
+     *
+     * @throw IgniteError on error.
+     */
+    void start(std::vector<TcpRange> addrs, uint32_t connLimit) override;
+
+    /**
+     * Close all established connections and stops handling threads.
+     */
+    void stop() override;
+
+    /**
+     * Set handler.
+     *
+     * @param handler Handler to set.
+     */
+    void setHandler(AsyncHandler *handler) override;
+
+    /**
+     * Send data to specific established connection.
+     *
+     * @param id Client ID.
+     * @param data Data to be sent.
+     * @return @c true if connection is present and @c false otherwise.
+     *
+     * @throw IgniteError on error.
+     */
+    bool send(uint64_t id, const DataBuffer& data) override;
+
+    /**
+     * Closes specified connection if it's established. Connection to the specified address is planned for
+     * re-connect. Error is reported to handler.
+     *
+     * @param id Client ID.
+     */
+    void close(uint64_t id, const IgniteError* err) override;
+
+private:
+    /** Filters. */
+    DataFilters m_filters;
+
+    /** Underlying pool. */
+    std::shared_ptr<AsyncClientPool> m_pool;
+
+    /** Lower level data sink. */
+    DataSink* m_sink;
+};
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/src/network/codec_data_filter.cpp b/modules/platforms/cpp/network/src/network/codec_data_filter.cpp
new file mode 100644
index 0000000000..f724e264ea
--- /dev/null
+++ b/modules/platforms/cpp/network/src/network/codec_data_filter.cpp
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+#include <ignite/network/codec_data_filter.h>
+
+namespace ignite::network
+{
+
+CodecDataFilter::CodecDataFilter(std::shared_ptr<Factory<Codec>> factory) :
+    m_codecFactory(std::move(factory)),
+    m_codecs(),
+    m_codecsMutex() { }
+
+bool CodecDataFilter::send(uint64_t id, const DataBuffer &data)
+{
+    std::shared_ptr<Codec> codec = FindCodec(id);
+    if (!codec)
+        return false;
+
+    DataBuffer data0(data);
+    while (true)
+    {
+        DataBuffer out = codec->encode(data0);
+
+        if (out.isEmpty())
+            break;
+
+        DataFilterAdapter::send(id, out);
+    }
+
+    return true;
+}
+
+void CodecDataFilter::onConnectionSuccess(const EndPoint &addr, uint64_t id)
+{
+    {
+        std::lock_guard<std::mutex> lock(m_codecsMutex);
+
+        std::shared_ptr<Codec> codec(m_codecFactory->build());
+        m_codecs.insert(std::make_pair(id, codec));
+    }
+
+    DataFilterAdapter::onConnectionSuccess(addr, id);
+}
+
+void CodecDataFilter::onConnectionClosed(uint64_t id, const IgniteError *err)
+{
+    {
+        std::lock_guard<std::mutex> lock(m_codecsMutex);
+
+        m_codecs.erase(id);
+    }
+
+    DataFilterAdapter::onConnectionClosed(id, err);
+}
+
+void CodecDataFilter::onMessageReceived(uint64_t id, const DataBuffer &msg)
+{
+    std::shared_ptr<Codec> codec = FindCodec(id);
+    if (!codec)
+        return;
+
+    DataBuffer msg0(msg);
+    while (true)
+    {
+        DataBuffer out = codec->decode(msg0);
+
+        if (out.isEmpty())
+            break;
+
+        DataFilterAdapter::onMessageReceived(id, out);
+    }
+}
+
+std::shared_ptr<Codec> CodecDataFilter::FindCodec(uint64_t id)
+{
+    std::lock_guard<std::mutex> lock(m_codecsMutex);
+
+    auto it = m_codecs.find(id);
+    if (it == m_codecs.end())
+        return {};
+
+    return it->second;
+}
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/src/network/data_buffer.cpp b/modules/platforms/cpp/network/src/network/data_buffer.cpp
new file mode 100644
index 0000000000..db8ea21ed0
--- /dev/null
+++ b/modules/platforms/cpp/network/src/network/data_buffer.cpp
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+#include <cstring>
+
+#include "common/ignite_error.h"
+#include "ignite/network/data_buffer.h"
+
+namespace ignite::network
+{
+
+DataBuffer::DataBuffer() :
+    m_position(0),
+    m_length(0),
+    m_data() { }
+
+DataBuffer::DataBuffer(std::shared_ptr<protocol::Buffer> data) :
+    m_position(0),
+    m_length(data->getLength()),
+    m_data(std::move(data)) { }
+
+DataBuffer::DataBuffer(std::shared_ptr<protocol::Buffer> data, int32_t pos, int32_t len) :
+    m_position(pos),
+    m_length(len),
+    m_data(std::move(data)) { }
+
+void DataBuffer::beConsumed(int8_t *dst, int32_t size)
+{
+    if (!size)
+        return;
+
+    if (size < 0)
+        throw IgniteError("Codec error: Can not read negative number of bytes");
+
+    if (getSize() < size)
+        throw IgniteError("Codec error: Not enough data to read data from buffer");
+
+    std::memcpy(dst, getData(), size);
+    advance(size);
+}
+
+void DataBuffer::beConsumed(std::vector<std::byte>& dst, int32_t toCopy)
+{
+    auto bytes = m_data->getBuffer();
+    dst.insert(dst.end(), bytes.begin(), bytes.begin() + toCopy);
+}
+
+const int8_t *DataBuffer::getData() const
+{
+    return m_data->getData() + m_position;
+}
+
+int32_t DataBuffer::getSize() const
+{
+    if (!m_data)
+        return 0;
+
+    return m_length - m_position;
+}
+
+bool DataBuffer::isEmpty() const
+{
+    return getSize() <= 0;
+}
+
+DataBuffer DataBuffer::consumeEntirely()
+{
+    DataBuffer res(*this);
+    advance(getSize());
+
+    return res;
+}
+
+void DataBuffer::advance(int32_t val)
+{
+    m_position += val;
+}
+
+DataBuffer DataBuffer::clone() const
+{
+    if (isEmpty())
+        return {};
+
+    auto copy = std::make_shared<protocol::Buffer>(*m_data);
+
+    return {copy, 0, m_length};
+}
+
+void DataBuffer::skip(int32_t bytes)
+{
+    int32_t toSkip = bytes < getSize() ? bytes : getSize();
+
+    advance(toSkip);
+}
+
+BytesView DataBuffer::getBytesView() const
+{
+    return {reinterpret_cast<const std::byte *>(getData()), std::size_t(getSize())};
+}
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/src/network/error_handling_filter.cpp b/modules/platforms/cpp/network/src/network/error_handling_filter.cpp
new file mode 100644
index 0000000000..86042a6272
--- /dev/null
+++ b/modules/platforms/cpp/network/src/network/error_handling_filter.cpp
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#include "network/error_handling_filter.h"
+
+namespace ignite::network
+{
+
+void ErrorHandlingFilter::onConnectionSuccess(const EndPoint &addr, uint64_t id)
+{
+    closeConnectionOnException(id, [this, &addr, id] { DataFilterAdapter::onConnectionSuccess(addr, id); });
+}
+
+void ErrorHandlingFilter::onConnectionError(const EndPoint &addr, const IgniteError &err)
+{
+    try
+    {
+        DataFilterAdapter::onConnectionError(addr, err);
+    }
+    catch (...)
+    {
+        // No-op.
+    }
+}
+
+void ErrorHandlingFilter::onConnectionClosed(uint64_t id, const IgniteError *err)
+{
+    try
+    {
+        DataFilterAdapter::onConnectionClosed(id, err);
+    }
+    catch (...)
+    {
+        // No-op.
+    }
+}
+
+void ErrorHandlingFilter::onMessageReceived(uint64_t id, const DataBuffer &data)
+{
+    closeConnectionOnException(id, [this, id, &data] { onMessageReceived(id, data); });
+}
+
+void ErrorHandlingFilter::onMessageSent(uint64_t id)
+{
+    closeConnectionOnException(id, [this, id] { DataFilterAdapter::onMessageSent(id); });
+}
+
+void ErrorHandlingFilter::closeConnectionOnException(uint64_t id, const std::function<void()>& func)
+{
+    try
+    {
+        func();
+    }
+    catch (const IgniteError& err)
+    {
+        DataFilterAdapter::close(id, &err);
+    }
+    catch (std::exception& err)
+    {
+        std::string msg("Standard library exception is thrown: ");
+        msg += err.what();
+        IgniteError err0(StatusCode::GENERIC, msg);
+        DataFilterAdapter::close(id, &err0);
+    }
+    catch (...)
+    {
+        IgniteError err0(StatusCode::UNKNOWN,
+            "Unknown error is encountered when processing network event");
+        DataFilterAdapter::close(id, &err0);
+    }
+}
+
+}
diff --git a/modules/platforms/cpp/network/src/network/error_handling_filter.h b/modules/platforms/cpp/network/src/network/error_handling_filter.h
new file mode 100644
index 0000000000..f07f6b686d
--- /dev/null
+++ b/modules/platforms/cpp/network/src/network/error_handling_filter.h
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <functional>
+
+#include <ignite/network/data_filter_adapter.h>
+
+namespace ignite::network
+{
+
+/**
+ * Filter that handles exceptions thrown by upper level handlers.
+ */
+class ErrorHandlingFilter : public DataFilterAdapter
+{
+public:
+    // Default
+    ~ErrorHandlingFilter() override = default;
+
+    /**
+     * Callback that called on successful connection establishment.
+     *
+     * @param addr Address of the new connection.
+     * @param id Connection ID.
+     */
+    void onConnectionSuccess(const EndPoint& addr, uint64_t id) override;
+
+    /**
+     * Callback that called on error during connection establishment.
+     *
+     * @param addr Connection address.
+     * @param err Error.
+     */
+    void onConnectionError(const EndPoint& addr, const IgniteError& err) override;
+
+    /**
+     * Callback that called on error during connection establishment.
+     *
+     * @param id Async client ID.
+     * @param err Error. Can be null if connection closed without error.
+     */
+    void onConnectionClosed(uint64_t id, const IgniteError* err) override;
+
+    /**
+     * Callback that called when new message is received.
+     *
+     * @param id Async client ID.
+     * @param msg Received message.
+     */
+    void onMessageReceived(uint64_t id, const DataBuffer &msg) override;
+
+    /**
+     * Callback that called when message is sent.
+     *
+     * @param id Async client ID.
+     */
+    void onMessageSent(uint64_t id) override;
+
+private:
+    /**
+     * Execute function and handle all possible exceptions.
+     *
+     * @param id Async client ID.
+     * @param func Function to handle;
+     */
+    void closeConnectionOnException(uint64_t id, const std::function<void()>& func);
+};
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/src/network/length_prefix_codec.cpp b/modules/platforms/cpp/network/src/network/length_prefix_codec.cpp
new file mode 100644
index 0000000000..155c674d24
--- /dev/null
+++ b/modules/platforms/cpp/network/src/network/length_prefix_codec.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+#include "ignite/protocol/utils.h"
+
+#include <ignite/network/length_prefix_codec.h>
+
+namespace ignite::network
+{
+
+LengthPrefixCodec::LengthPrefixCodec() :
+    m_packetSize(-1) { }
+
+DataBuffer LengthPrefixCodec::encode(DataBuffer& data)
+{
+    // Just pass data as is, because we encode message size in
+    // the application to avoid unnecessary re-allocations and copying.
+    return data.consumeEntirely();
+}
+
+DataBuffer LengthPrefixCodec::decode(DataBuffer& data)
+{
+    if (m_packet.empty() || m_packet.size() == (PACKET_HEADER_SIZE + m_packetSize))
+    {
+        m_packetSize = -1;
+        m_packet.clear();
+    }
+
+    if (m_packetSize < 0)
+    {
+        consume(data, PACKET_HEADER_SIZE);
+
+        if (m_packet.size() < PACKET_HEADER_SIZE)
+            return {};
+
+        m_packetSize = protocol::readInt32(m_packet.data());
+        m_packet.clear();
+    }
+
+    consume(data, m_packetSize);
+
+    if (m_packet.size() == m_packetSize)
+        return {std::make_shared<protocol::Buffer>(m_packet), 0, m_packetSize};
+
+    return {};
+}
+
+void LengthPrefixCodec::consume(DataBuffer &data, int32_t desired)
+{
+    int32_t toCopy = desired - int32_t(m_packet.size());
+    if (toCopy <= 0)
+        return;
+
+    if (data.getSize() < toCopy)
+        toCopy = data.getSize();
+
+    data.beConsumed(m_packet, toCopy);
+}
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/common/Platform.h b/modules/platforms/cpp/network/src/network/network.cpp
similarity index 55%
copy from modules/platforms/cpp/common/Platform.h
copy to modules/platforms/cpp/network/src/network/network.cpp
index 7bfcebc447..819dc54c3c 100644
--- a/modules/platforms/cpp/common/Platform.h
+++ b/modules/platforms/cpp/network/src/network/network.cpp
@@ -15,36 +15,24 @@
  * limitations under the License.
  */
 
-#pragma once
-
-/**
- * Macro SWITCH_WIN_OTHER that uses first option on Windows and second on any other OS.
- */
-#ifdef WIN32
-#   define SWITCH_WIN_OTHER(x, y) (x)
-#else
-#   define SWITCH_WIN_OTHER(x, y) (y)
+#ifdef _WIN32
+#   include "network/win_async_client_pool.h"
+#else // Other. Assume Linux
+#   include "network/linux_async_client_pool.h"
 #endif
 
-namespace ignite::platform
-{
+#include "common/Platform.h"
 
-/**
- * Byte order utility class.
- */
-class ByteOrder
-{
-private:
-    static constexpr uint32_t fourBytes = 0x01020304;
-    static constexpr uint8_t lesserByte = (const uint8_t&)fourBytes;
+#include "ignite/network/network.h"
+#include "network/async_client_pool_adapter.h"
 
-public:
-    ByteOrder() = delete;
-
-    static constexpr bool littleEndian = lesserByte == 0x04;
-    static constexpr bool bigEndian = lesserByte == 0x01;
-
-    static_assert(littleEndian || bigEndian, "Unknown byte order");
-};
-
-} // ignite::platform
+namespace ignite::network
+{
+    std::shared_ptr<AsyncClientPool> makeAsyncClientPool(DataFilters filters)
+    {
+        auto platformPool = std::make_shared<SWITCH_WIN_OTHER(WinAsyncClientPool, LinuxAsyncClientPool)>();
+        auto pool = std::static_pointer_cast<AsyncClientPool>(platformPool);
+
+        return std::make_shared<AsyncClientPoolAdapter>(std::move(filters), pool);
+    }
+}
diff --git a/modules/platforms/cpp/network/src/network/tcp_range.cpp b/modules/platforms/cpp/network/src/network/tcp_range.cpp
new file mode 100644
index 0000000000..bbc9f2dcb7
--- /dev/null
+++ b/modules/platforms/cpp/network/src/network/tcp_range.cpp
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+
+#include <algorithm>
+#include <limits>
+#include <sstream>
+
+#include "ignite/network/tcp_range.h"
+
+namespace
+{
+
+uint16_t parsePort(std::string_view value)
+{
+    // Stripping whitespaces
+    size_t begin = value.find_first_not_of(' ');
+    size_t end = value.find_last_not_of(' ');
+    if (begin == std::string_view::npos || end == std::string_view::npos)
+        return 0;
+
+    std::string_view port = value.substr(begin, end - begin + 1);
+    if (port.empty())
+        return 0;
+
+    // Checking that all chars are digits
+    if (port.find_first_not_of("1234567890") != std::string_view::npos)
+        return 0;
+
+    // Checking that number is not too big
+    if (port.size() >= sizeof("65535"))
+        return 0;
+
+    int32_t intPort = 0;
+    std::stringstream conv;
+
+    conv << port;
+    conv >> intPort;
+
+    // Checking that number is within TCP port range
+    if (intPort <= 0 || intPort > 0xFFFF)
+        return 0;
+
+    return static_cast<uint16_t>(intPort);
+}
+
+}
+
+
+namespace ignite::network
+{
+
+std::optional<TcpRange> TcpRange::parse(std::string_view str, uint16_t defPort)
+{
+    TcpRange res;
+    size_t colonNum = std::count(str.begin(), str.end(), ':');
+
+    if (colonNum == 0)
+    {
+        res.host = str;
+        res.port = defPort;
+        res.range = 0;
+
+        return {std::move(res)};
+    }
+
+    if (colonNum != 1)
+        return std::nullopt;
+
+    size_t colonPos = str.find(':');
+
+    res.host = str.substr(0, colonPos);
+
+    if (colonPos == str.size() - 1)
+        return std::nullopt;
+
+    std::string_view portRange = str.substr(colonPos + 1);
+
+    size_t sepPos = portRange.find('.');
+    if (sepPos == std::string::npos)
+    {
+        res.range = 0;
+        res.port = parsePort(portRange);
+
+        if (!res.port)
+            return std::nullopt;
+        return {res};
+    }
+
+    if (sepPos + 2 > portRange.size() || portRange[sepPos + 1] != '.')
+        return std::nullopt;
+
+    uint16_t rangeBegin = parsePort(portRange.substr(0, sepPos));
+    if (!rangeBegin)
+        return std::nullopt;
+
+    uint16_t rangeEnd = parsePort(portRange.substr(sepPos + 2));
+    if (!rangeEnd)
+        return std::nullopt;
+
+    if (rangeEnd < rangeBegin)
+        return std::nullopt;
+
+    res.port = rangeBegin;
+    res.range = rangeEnd - rangeBegin;
+
+    return {res};
+}
+
+int TcpRange::compare(const TcpRange &other) const {
+    if (port < other.port)
+        return -1;
+
+    if (port > other.port)
+        return 1;
+
+    if (range < other.range)
+        return -1;
+
+    if (range > other.range)
+        return 1;
+
+    return host.compare(other.host);
+}
+
+std::string TcpRange::toString() const
+{
+    std::stringstream buf;
+    buf << host << ':' << port;
+
+    if (range)
+        buf << ".." << (port + range);
+
+    return buf.str();
+}
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/network/src/network/utils.h b/modules/platforms/cpp/network/src/network/utils.h
new file mode 100644
index 0000000000..959299f7c3
--- /dev/null
+++ b/modules/platforms/cpp/network/src/network/utils.h
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <string>
+#include <string_view>
+#include <sstream>
+
+#include "common/ignite_error.h"
+
+namespace ignite::network
+{
+
+// TODO: Re-factor
+
+/**
+ * Fibonacci sequence iterator.
+ *
+ * @tparam S Sequence length. Should be >= 2.
+ */
+template<size_t S, typename T = size_t>
+class FibonacciSequence
+{
+public:
+    /** Size. */
+    static constexpr size_t size = S > 2 ? S : 2;
+
+    /**
+     * Constructor.
+     */
+    constexpr FibonacciSequence()
+    {
+        for (size_t i = 2; i < size; ++i)
+            sequence[i] = sequence[i - 1] + sequence[i - 2];
+    }
+
+    /**
+     * Get n-th or max member of sequence.
+     *
+     * @param n Member position.
+     * @return N-th member of sequence if n < size, or max member.
+     */
+    [[nodiscard]]
+    constexpr T GetValue(size_t n) const
+    {
+        return n < size ? sequence[n] : sequence[size-1];
+    }
+
+private:
+    /** Sequence of fibonacci numbers */
+    T sequence[size]{0, 1};
+};
+
+/**
+ * Throw connection error.
+ *
+ * @param err Error message.
+ */
+inline void ThrowNetworkError(std::string err)
+{
+    // TODO: Remove me
+    throw IgniteError(StatusCode::NETWORK, std::move(err));
+}
+
+/**
+ * Format error message.
+ *
+ * @param description Error description.
+ * @param description Error details.
+ * @param advice User advice.
+ */
+std::string FormatErrorMessage(std::string_view description, std::string_view details, std::string_view advice)
+{
+    std::stringstream messageBuilder;
+    messageBuilder << description;
+    if (!details.empty())
+        messageBuilder << ": " << details;
+
+    if (!advice.empty())
+        messageBuilder << ". " << advice;
+
+    return messageBuilder.str();
+}
+
+/**
+ * Try extract from system error stack, and return platform-specific error.
+ *
+ * @return Error in human-readable format.
+ */
+std::string GetLastSystemError();
+
+/**
+ * Try extract from system error stack, format and return platform-specific error.
+ *
+ * @param description Error description.
+ * @return Error in human-readable format.
+ */
+std::string GetLastSystemError(std::string_view description, std::string_view advice)
+{
+    return FormatErrorMessage(description, GetLastSystemError(), advice);
+}
+
+/**
+ * Throw platform-specific error.
+ *
+ * @param msg Error message.
+ */
+inline void ThrowSystemError(std::string msg)
+{
+    // TODO: Remove me
+    throw IgniteError(StatusCode::OS, std::move(msg));
+}
+
+/**
+ * Try extract from system error stack and throw platform-specific error.
+ *
+ * @param description Error description.
+ * @param advice User advice.
+ */
+void ThrowLastSystemError(std::string_view description, std::string_view advice)
+{
+    ThrowSystemError(GetLastSystemError(description, advice));
+}
+
+/**
+ * Try extract from system error stack and throw platform-specific error.
+ *
+ * @param description Error description.
+ */
+void ThrowLastSystemError(std::string_view description)
+{
+    ThrowLastSystemError(description, "");
+}
+
+} // namespace ignite::network
diff --git a/modules/platforms/cpp/test-common/CMakeLists.txt b/modules/platforms/cpp/protocol/CMakeLists.txt
similarity index 91%
copy from modules/platforms/cpp/test-common/CMakeLists.txt
copy to modules/platforms/cpp/protocol/CMakeLists.txt
index 92485f7f89..8ff9e3ce22 100644
--- a/modules/platforms/cpp/test-common/CMakeLists.txt
+++ b/modules/platforms/cpp/protocol/CMakeLists.txt
@@ -15,16 +15,16 @@
 # limitations under the License.
 #
 
-project(ignite-test-common)
+project(ignite-protocol)
 
 set(TARGET ${PROJECT_NAME})
 
 include_directories(include)
 
 set(SOURCES
-        src/ignite_node.cpp
-        src/process.cpp
-        src/test_utils.cpp
+    src/buffer.cpp
+    src/reader.cpp
+    src/writer.cpp
 )
 
 add_library(${TARGET} OBJECT ${SOURCES})
diff --git a/modules/platforms/cpp/protocol/include/ignite/protocol/buffer.h b/modules/platforms/cpp/protocol/include/ignite/protocol/buffer.h
new file mode 100644
index 0000000000..caab073ceb
--- /dev/null
+++ b/modules/platforms/cpp/protocol/include/ignite/protocol/buffer.h
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <msgpack.h>
+
+#include "common/Types.h"
+
+namespace ignite::protocol
+{
+
+class Writer;
+
+/**
+ * Buffer.
+ */
+class Buffer
+{
+    friend class Writer;
+public:
+    /** Length header size in bytes. */
+    static constexpr size_t LENGTH_HEADER_SIZE = 4;
+
+    // Default
+    virtual ~Buffer() = default;
+    Buffer(Buffer&&) = default;
+    Buffer(const Buffer& other) = default;
+    Buffer& operator=(Buffer&&) = default;
+    Buffer& operator=(const Buffer&) = default;
+
+    /**
+     * Constructor.
+     */
+    Buffer();
+
+    /**
+     * Constructor.
+     *
+     * @param data Data.
+     */
+    explicit Buffer(std::vector<std::byte> data);
+
+    /**
+     * Write raw data.
+     *
+     * @param data Data to write.
+     */
+    void writeRawData(BytesView data);
+
+    /**
+     * Get buffer.
+     *
+     * @return Underlying buffer.
+     */
+    BytesView getBuffer()
+    {
+        return m_buffer;
+    }
+
+    /**
+     * Reserving space for length header.
+     */
+    void reserveLengthHeader();
+
+    /**
+     * Write buffer length to previously reserved position.
+     */
+    void writeLengthHeader();
+
+    /**
+     * Get length.
+     *
+     * @return Packet length.
+     */
+    [[nodiscard]]
+    std::int32_t getLength() const
+    {
+        return std::int32_t(m_buffer.size());
+    }
+
+    /**
+     * Get data.
+     *
+     * @return Data.
+     */
+    [[nodiscard]]
+    const std::int8_t* getData() const
+    {
+        return reinterpret_cast<const std::int8_t*>(m_buffer.data());
+    }
+
+private:
+    /**
+     * Write callback.
+     *
+     * @param data Pointer to the instance.
+     * @param buf Data to write.
+     * @param len Data length.
+     * @return Write result.
+     */
+    static int writeCallback(void* data, const char* buf, size_t len);
+
+    /** Buffer. */
+    std::vector<std::byte> m_buffer;
+
+    /** Length position. */
+    std::size_t m_lengthPos;
+};
+
+} // namespace ignite::protocol
diff --git a/modules/platforms/cpp/common/Platform.h b/modules/platforms/cpp/protocol/include/ignite/protocol/extension_types.h
similarity index 58%
copy from modules/platforms/cpp/common/Platform.h
copy to modules/platforms/cpp/protocol/include/ignite/protocol/extension_types.h
index 7bfcebc447..47ddf94ecd 100644
--- a/modules/platforms/cpp/common/Platform.h
+++ b/modules/platforms/cpp/protocol/include/ignite/protocol/extension_types.h
@@ -17,34 +17,33 @@
 
 #pragma once
 
-/**
- * Macro SWITCH_WIN_OTHER that uses first option on Windows and second on any other OS.
- */
-#ifdef WIN32
-#   define SWITCH_WIN_OTHER(x, y) (x)
-#else
-#   define SWITCH_WIN_OTHER(x, y) (y)
-#endif
+#include <cstdint>
 
-namespace ignite::platform
+namespace ignite::protocol
 {
 
 /**
- * Byte order utility class.
+ * Extension types.
  */
-class ByteOrder
+enum class ExtensionTypes : std::int8_t
 {
-private:
-    static constexpr uint32_t fourBytes = 0x01020304;
-    static constexpr uint8_t lesserByte = (const uint8_t&)fourBytes;
+    NUMBER = 1,
+
+    DECIMAL = 2,
+
+    GUID = 3,
+
+    DATE = 4,
+
+    TIME = 5,
+
+    DATE_TIME = 6,
 
-public:
-    ByteOrder() = delete;
+    TIMESTAMP = 7,
 
-    static constexpr bool littleEndian = lesserByte == 0x04;
-    static constexpr bool bigEndian = lesserByte == 0x01;
+    BITMASK = 8,
 
-    static_assert(littleEndian || bigEndian, "Unknown byte order");
+    NO_VALUE = 10
 };
 
-} // ignite::platform
+} // namespace ignite::protocol
diff --git a/modules/platforms/cpp/protocol/include/ignite/protocol/reader.h b/modules/platforms/cpp/protocol/include/ignite/protocol/reader.h
new file mode 100644
index 0000000000..7c1f4d1efe
--- /dev/null
+++ b/modules/platforms/cpp/protocol/include/ignite/protocol/reader.h
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <functional>
+
+#include <msgpack.h>
+
+#include "common/guid.h"
+#include "common/Types.h"
+
+namespace ignite::protocol
+{
+
+/**
+ * Reader.
+ */
+class Reader
+{
+public:
+    // Deleted
+    Reader() = delete;
+    Reader(Reader&&) = delete;
+    Reader(const Reader&) = delete;
+    Reader& operator=(Reader&&) = delete;
+    Reader& operator=(const Reader&) = delete;
+
+    /**
+     * Constructor.
+     *
+     * @param buffer Buffer.
+     */
+    explicit Reader(BytesView buffer);
+
+    /**
+     * Destructor.
+     */
+    virtual ~Reader();
+
+    /**
+     * Read int16.
+     *
+     * @return Value.
+     */
+    [[nodiscard]]
+    std::int16_t readInt16();
+
+    /**
+     * Read int32.
+     *
+     * @return Value.
+     */
+    [[nodiscard]]
+    std::int32_t readInt32();
+
+    /**
+     * Read int64 number.
+     *
+     * @return Value.
+     */
+    [[nodiscard]]
+    std::int64_t readInt64();
+
+    /**
+     * Read string.
+     *
+     * @return String value.
+     */
+    [[nodiscard]]
+    std::string readString();
+
+    /**
+     * Read GUID.
+     *
+     * @return GUID value.
+     */
+    [[nodiscard]]
+    Guid readGuid();
+
+    /**
+     * If the next value is Nil, read it and move reader to the next position.
+     *
+     * @return @c true if the value was nil.
+     */
+    bool tryReadNil();
+
+    /**
+     * Skip next value.
+     */
+    void skip();
+
+private:
+    /**
+     * Move to the next value.
+     */
+    void next();
+
+    /** Buffer. */
+    BytesView m_buffer;
+
+    /** Unpacked data. */
+    msgpack_unpacked m_unpacked;
+
+    /** Result of the last move operation. */
+    msgpack_unpack_return m_moveRes;
+};
+
+} // namespace ignite::protocol
diff --git a/modules/platforms/cpp/protocol/include/ignite/protocol/utils.h b/modules/platforms/cpp/protocol/include/ignite/protocol/utils.h
new file mode 100644
index 0000000000..8d179461bc
--- /dev/null
+++ b/modules/platforms/cpp/protocol/include/ignite/protocol/utils.h
@@ -0,0 +1,199 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <cstddef>
+
+#include "common/Types.h"
+
+namespace ignite::protocol
+{
+
+/**
+ * Read uint64 from bytes stream.
+ *
+ * @param data Data.
+ * @param offset Offset.
+ * @return Value
+ */
+inline uint64_t readUint64(const std::byte* data, size_t offset = 0)
+{
+    return std::uint64_t(data[offset]) |
+        (std::uint64_t(data[offset + 1]) << 8) |
+        (std::uint64_t(data[offset + 2]) << 16) |
+        (std::uint64_t(data[offset + 3]) << 24) |
+        (std::uint64_t(data[offset + 4]) << 32) |
+        (std::uint64_t(data[offset + 5]) << 40) |
+        (std::uint64_t(data[offset + 6]) << 48) |
+        (std::uint64_t(data[offset + 7]) << 56);
+}
+
+/**
+ * Read int64 from bytes stream.
+ *
+ * @param data Data.
+ * @param offset Offset.
+ * @return Value
+ */
+inline int64_t readInt64(const std::byte* data, size_t offset = 0)
+{
+    return std::int64_t(readUint64(data, offset));
+}
+
+/**
+ * Read uint32 from bytes stream.
+ *
+ * @param data Data.
+ * @param offset Offset.
+ * @return Value
+ */
+inline uint32_t readUint32(const std::byte* data, size_t offset = 0)
+{
+    return std::uint32_t(data[offset]) |
+       (std::uint32_t(data[offset + 1]) << 8) |
+       (std::uint32_t(data[offset + 2]) << 16) |
+       (std::uint32_t(data[offset + 3]) << 24);
+}
+
+/**
+ * Read int32 from bytes stream.
+ *
+ * @param data Data.
+ * @param offset Offset.
+ * @return Value
+ */
+inline int32_t readInt32(const std::byte* data, size_t offset = 0)
+{
+    return std::int32_t(readUint32(data, offset));
+}
+
+/**
+ * Read uint16 from bytes stream.
+ *
+ * @param data Data.
+ * @param offset Offset.
+ * @return Value
+ */
+inline uint16_t readUint16(const std::byte* data, size_t offset = 0)
+{
+    return std::uint16_t(data[offset]) | (std::uint16_t(data[offset + 1]) << 8);
+}
+
+/**
+ * Read int16 from bytes stream.
+ *
+ * @param data Data.
+ * @param offset Offset.
+ * @return Value
+ */
+inline int16_t readInt16(const std::byte* data, size_t offset = 0)
+{
+    return std::int16_t(readUint16(data, offset));
+}
+
+/**
+ * Write uint64 to byte stream.
+ *
+ * @param value Value to write.
+ * @param buffer Buffer.
+ * @param offset Offset.
+ * @return Value
+ */
+inline void writeUint64(uint64_t value, std::byte* buffer, size_t offset = 0)
+{
+    buffer[offset]     = std::byte( value & 0x00000000'000000FF);
+    buffer[offset + 1] = std::byte((value & 0x00000000'0000FF00) >> 8);
+    buffer[offset + 2] = std::byte((value & 0x00000000'00FF0000) >> 16);
+    buffer[offset + 3] = std::byte((value & 0x00000000'FF000000) >> 24);
+    buffer[offset + 4] = std::byte((value & 0x000000FF'00000000) >> 32);
+    buffer[offset + 5] = std::byte((value & 0x0000FF00'00000000) >> 40);
+    buffer[offset + 6] = std::byte((value & 0x00FF0000'00000000) >> 48);
+    buffer[offset + 7] = std::byte((value & 0xFF000000'00000000) >> 56);
+}
+
+/**
+ * Write int64 to byte stream.
+ *
+ * @param value Value to write.
+ * @param buffer Buffer.
+ * @param offset Offset.
+ * @return Value
+ */
+inline void writeInt64(int64_t value, std::byte* buffer, size_t offset = 0)
+{
+    return writeUint64(std::uint64_t(value), buffer, offset);
+}
+
+/**
+ * Write uint32 to byte stream.
+ *
+ * @param value Value to write.
+ * @param buffer Buffer.
+ * @param offset Offset.
+ * @return Value
+ */
+inline void writeUint32(uint32_t value, std::byte* buffer, size_t offset = 0)
+{
+    buffer[offset]     = std::byte( value & 0x000000FF);
+    buffer[offset + 1] = std::byte((value & 0x0000FF00) >> 8);
+    buffer[offset + 2] = std::byte((value & 0x00FF0000) >> 16);
+    buffer[offset + 3] = std::byte((value & 0xFF000000) >> 24);
+}
+
+/**
+ * Write int32 to byte stream.
+ *
+ * @param value Value to write.
+ * @param buffer Buffer.
+ * @param offset Offset.
+ * @return Value
+ */
+inline void writeInt32(int32_t value, std::byte* buffer, size_t offset = 0)
+{
+    return writeUint32(std::uint32_t(value), buffer, offset);
+}
+
+/**
+ * Write uint16 to byte stream.
+ *
+ * @param value Value to write.
+ * @param buffer Buffer.
+ * @param offset Offset.
+ * @return Value
+ */
+inline void writeUint16(uint16_t value, std::byte* buffer, size_t offset = 0)
+{
+    buffer[offset]     = std::byte( value & 0x00FF);
+    buffer[offset + 1] = std::byte((value & 0xFF00) >> 8);
+}
+
+/**
+ * Write int16 to byte stream.
+ *
+ * @param value Value to write.
+ * @param buffer Buffer.
+ * @param offset Offset.
+ * @return Value
+ */
+inline void writeInt16(int16_t value, std::byte* buffer, size_t offset = 0)
+{
+    return writeUint16(std::uint16_t(value), buffer, offset);
+}
+
+} // namespace ignite::protocol
diff --git a/modules/platforms/cpp/protocol/include/ignite/protocol/writer.h b/modules/platforms/cpp/protocol/include/ignite/protocol/writer.h
new file mode 100644
index 0000000000..a9e72e6c62
--- /dev/null
+++ b/modules/platforms/cpp/protocol/include/ignite/protocol/writer.h
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <functional>
+
+#include <msgpack.h>
+
+#include "common/Types.h"
+#include "ignite/protocol/buffer.h"
+
+namespace ignite::protocol
+{
+
+/**
+ * Writer.
+ */
+class Writer
+{
+public:
+    // Deleted
+    Writer() = delete;
+    Writer(Writer&&) = delete;
+    Writer(const Writer&) = delete;
+    Writer& operator=(Writer&&) = delete;
+    Writer& operator=(const Writer&) = delete;
+
+    /**
+     * Write message to buffer.
+     *
+     * @param buffer Buffer to use.
+     * @param script Function.
+     */
+    static void writeMessageToBuffer(Buffer& buffer, const std::function<void(Writer&)>& script);
+
+    /**
+     * Constructor.
+     *
+     * @param buffer Buffer.
+     */
+    explicit Writer(Buffer& buffer);
+
+    /**
+     * Destructor.
+     */
+    virtual ~Writer();
+
+    /**
+     * Write int value.
+     *
+     * @param value Value to write.
+     */
+    void write(int8_t value);
+
+    /**
+     * Write int value.
+     *
+     * @param value Value to write.
+     */
+    void write(int16_t value);
+
+    /**
+     * Write int value.
+     *
+     * @param value Value to write.
+     */
+    void write(int32_t value);
+
+    /**
+     * Write int value.
+     *
+     * @param value Value to write.
+     */
+    void write(int64_t value);
+
+    /**
+     * Write empty binary data.
+     */
+    void writeBinaryEmpty();
+
+    /**
+     * Write empty map.
+     */
+    void writeMapEmpty();
+
+private:
+    /** Buffer. */
+    Buffer& m_buffer;
+
+    /** Packer. */
+    msgpack_packer* m_packer;
+};
+
+} // namespace ignite::protocol
diff --git a/modules/platforms/cpp/protocol/src/buffer.cpp b/modules/platforms/cpp/protocol/src/buffer.cpp
new file mode 100644
index 0000000000..760fa6affe
--- /dev/null
+++ b/modules/platforms/cpp/protocol/src/buffer.cpp
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+#include <limits>
+
+#include "common/ignite_error.h"
+
+#include "ignite/protocol/buffer.h"
+#include "ignite/protocol/utils.h"
+
+namespace ignite::protocol
+{
+
+Buffer::Buffer() :
+    m_buffer(),
+    m_lengthPos(std::numeric_limits<std::size_t>::max()) { }
+
+Buffer::Buffer(std::vector<std::byte> data) :
+    m_buffer(std::move(data)),
+    m_lengthPos(std::numeric_limits<std::size_t>::max()) { }
+
+void Buffer::writeRawData(BytesView data)
+{
+    m_buffer.insert(m_buffer.end(), data.begin(), data.end());
+}
+
+void Buffer::reserveLengthHeader()
+{
+    static constexpr std::byte empty[] = {std::byte{0}, std::byte{0}, std::byte{0}, std::byte{0}};
+
+    m_lengthPos = m_buffer.size();
+    writeRawData((BytesView)empty);
+}
+
+void Buffer::writeLengthHeader()
+{
+    if (m_lengthPos == std::numeric_limits<std::size_t>::max() || m_lengthPos + LENGTH_HEADER_SIZE > m_buffer.size())
+        throw IgniteError("Length header was not reserved properly in buffer");
+
+    auto length = std::int32_t(m_buffer.size() - (m_lengthPos + LENGTH_HEADER_SIZE));
+
+    writeInt32(length, m_buffer.data(), m_lengthPos);
+}
+
+int Buffer::writeCallback(void *data, const char *buf, size_t len)
+{
+    if (!data)
+        return 0;
+
+    auto self = static_cast<Buffer*>(data);
+
+    // We do not support messages larger than MAX_INT32
+    if (self->m_buffer.size() + len > std::numeric_limits<int32_t>::max())
+        return -1;
+
+    auto bytes = reinterpret_cast<const std::byte*>(buf);
+    self->writeRawData(BytesView{bytes, len});
+
+    return 0;
+}
+
+} // namespace ignite::protocol
diff --git a/modules/platforms/cpp/protocol/src/reader.cpp b/modules/platforms/cpp/protocol/src/reader.cpp
new file mode 100644
index 0000000000..df9fb132b3
--- /dev/null
+++ b/modules/platforms/cpp/protocol/src/reader.cpp
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+#include "common/ignite_error.h"
+
+#include "ignite/protocol/utils.h"
+#include "ignite/protocol/extension_types.h"
+#include "ignite/protocol/reader.h"
+
+namespace ignite::protocol
+{
+
+Reader::Reader(BytesView buffer) :
+    m_buffer(buffer),
+    m_unpacked(),
+    m_moveRes(MSGPACK_UNPACK_SUCCESS)
+{
+    msgpack_unpacked_init(&m_unpacked);
+    next();
+}
+
+Reader::~Reader()
+{
+    msgpack_unpacked_destroy(&m_unpacked);
+}
+
+std::int16_t Reader::readInt16()
+{
+    return std::int16_t(readInt64());
+}
+
+std::int32_t Reader::readInt32()
+{
+    return std::int32_t(readInt64());
+}
+
+std::int64_t Reader::readInt64()
+{
+    if (m_moveRes <= 0)
+        throw IgniteError("No more data in stream");
+
+    msgpack_object object = m_unpacked.data;
+    if (object.type != MSGPACK_OBJECT_NEGATIVE_INTEGER && object.type != MSGPACK_OBJECT_POSITIVE_INTEGER)
+        throw IgniteError("The value in stream is not an integer number");
+
+    auto res = object.via.i64;
+
+    next();
+
+    return res;
+}
+
+std::string Reader::readString()
+{
+    if (m_moveRes <= 0)
+        throw IgniteError("No more data in stream");
+
+    msgpack_object object = m_unpacked.data;
+    if (object.type != MSGPACK_OBJECT_STR)
+        throw IgniteError("The value in stream is not a string");
+
+    std::string res{object.via.str.ptr, object.via.str.size};
+
+    next();
+
+    return res;
+}
+
+Guid Reader::readGuid()
+{
+    if (m_moveRes <= 0)
+        throw IgniteError("No more data in stream");
+
+    if (m_unpacked.data.type != MSGPACK_OBJECT_EXT && m_unpacked.data.via.ext.type != std::int8_t(ExtensionTypes::GUID))
+        throw IgniteError("The value in stream is not a GUID");
+
+    if (m_unpacked.data.via.ext.size != 16)
+        throw IgniteError("Unexpected value size");
+
+    auto data = reinterpret_cast<const std::byte*>(m_unpacked.data.via.ext.ptr);
+
+    int64_t most = protocol::readInt64(data);
+    int64_t least = protocol::readInt64(data, 8);
+
+    Guid res(most, least);
+
+    next();
+    return res;
+}
+
+bool Reader::tryReadNil()
+{
+    if (m_unpacked.data.type != MSGPACK_OBJECT_NIL)
+        return false;
+
+    next();
+    return true;
+}
+
+void Reader::skip()
+{
+    next();
+}
+
+void Reader::next()
+{
+    m_moveRes = msgpack_unpack_next(&m_unpacked, reinterpret_cast<const char *>(m_buffer.data()), m_buffer.size(), NULL);
+}
+
+} // namespace ignite::protocol
diff --git a/modules/platforms/cpp/protocol/src/writer.cpp b/modules/platforms/cpp/protocol/src/writer.cpp
new file mode 100644
index 0000000000..d5b1e12665
--- /dev/null
+++ b/modules/platforms/cpp/protocol/src/writer.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#include "ignite/protocol/writer.h"
+
+namespace ignite::protocol
+{
+
+void Writer::writeMessageToBuffer(Buffer &buffer, const std::function<void(Writer &)> &script)
+{
+    buffer.reserveLengthHeader();
+
+    protocol::Writer writer(buffer);
+    script(writer);
+
+    buffer.writeLengthHeader();
+}
+
+Writer::Writer(Buffer& buffer) :
+    m_buffer(buffer),
+    m_packer(msgpack_packer_new(&m_buffer, Buffer::writeCallback)) { }
+
+Writer::~Writer()
+{
+    msgpack_packer_free(m_packer);
+}
+
+void Writer::write(int8_t value)
+{
+    msgpack_pack_int8(m_packer, value);
+}
+
+void Writer::write(int16_t value)
+{
+    msgpack_pack_int16(m_packer, value);
+}
+
+void Writer::write(int32_t value)
+{
+    msgpack_pack_int32(m_packer, value);
+}
+
+void Writer::write(int64_t value)
+{
+    msgpack_pack_int64(m_packer, value);
+}
+
+void Writer::writeBinaryEmpty()
+{
+    msgpack_pack_bin(m_packer, 0);
+}
+
+void Writer::writeMapEmpty()
+{
+    msgpack_pack_map(m_packer, 0);
+}
+
+} // namespace ignite::protocol
diff --git a/modules/platforms/cpp/test-common/CMakeLists.txt b/modules/platforms/cpp/test-common/CMakeLists.txt
index 92485f7f89..0958b0ae58 100644
--- a/modules/platforms/cpp/test-common/CMakeLists.txt
+++ b/modules/platforms/cpp/test-common/CMakeLists.txt
@@ -22,9 +22,9 @@ set(TARGET ${PROJECT_NAME})
 include_directories(include)
 
 set(SOURCES
-        src/ignite_node.cpp
-        src/process.cpp
-        src/test_utils.cpp
+    src/ignite_node.cpp
+    src/process.cpp
+    src/test_utils.cpp
 )
 
 add_library(${TARGET} OBJECT ${SOURCES})


[ignite-3] 16/17: IGNITE-17424 Links on Windows

Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 5ab37fa54ca9c40f49bced217f2e635b60e80ed9
Author: Igor Sapego <is...@apache.org>
AuthorDate: Wed Sep 7 23:57:57 2022 +0400

    IGNITE-17424 Links on Windows
---
 modules/platforms/cpp/client-test/CMakeLists.txt   |  6 +++---
 .../cpp/client/src/cluster_connection.cpp          |  1 +
 modules/platforms/cpp/common/ignite_error.h        |  8 ++++++++
 modules/platforms/cpp/conanfile.txt                |  4 ++--
 modules/platforms/cpp/network/CMakeLists.txt       |  4 +---
 .../src/network/linux_async_worker_thread.cpp      | 14 +++++++-------
 .../cpp/network/os/win/src/network/sockets.cpp     |  6 ++++--
 .../cpp/network/os/win/src/network/utils.cpp       |  6 ++++--
 .../os/win/src/network/win_async_client_pool.cpp   |  8 +++++---
 .../src/network/win_async_connecting_thread.cpp    | 14 ++++++++------
 .../os/win/src/network/win_async_worker_thread.cpp |  4 +++-
 modules/platforms/cpp/network/src/network/utils.h  | 22 +++++++++++-----------
 modules/platforms/cpp/protocol/CMakeLists.txt      |  4 +++-
 13 files changed, 60 insertions(+), 41 deletions(-)

diff --git a/modules/platforms/cpp/client-test/CMakeLists.txt b/modules/platforms/cpp/client-test/CMakeLists.txt
index 34202f707e..aae4c83c7e 100644
--- a/modules/platforms/cpp/client-test/CMakeLists.txt
+++ b/modules/platforms/cpp/client-test/CMakeLists.txt
@@ -19,11 +19,11 @@ project(ignite-client-test)
 
 set(TARGET ${PROJECT_NAME})
 
-include_directories(include src)
+find_package(GTest REQUIRED)
+
+include_directories(include src ${GTEST_INCLUDE_DIR})
 
 enable_testing()
-find_package(GTest REQUIRED)
-include_directories(${GTEST_INCLUDE_DIR})
 
 set(SOURCES
 	src/ignite_client_test.cpp
diff --git a/modules/platforms/cpp/client/src/cluster_connection.cpp b/modules/platforms/cpp/client/src/cluster_connection.cpp
index fa9f10f8a0..288f005179 100644
--- a/modules/platforms/cpp/client/src/cluster_connection.cpp
+++ b/modules/platforms/cpp/client/src/cluster_connection.cpp
@@ -230,6 +230,7 @@ void ClusterConnection::handshake(uint64_t id, ProtocolContext& context)
     }
     catch (const IgniteError& err)
     {
+        m_logger->logWarning("Failed to send handshake request: " + err.whatStr());
         handshakeFail(id, std::nullopt);
     }
 }
diff --git a/modules/platforms/cpp/common/ignite_error.h b/modules/platforms/cpp/common/ignite_error.h
index b2224e2903..42d2553870 100644
--- a/modules/platforms/cpp/common/ignite_error.h
+++ b/modules/platforms/cpp/common/ignite_error.h
@@ -81,6 +81,14 @@ public:
     {
         return m_message.c_str();
     }
+    /**
+     * Get error message as std::string.
+     */
+    [[nodiscard]]
+    const std::string& whatStr() const
+    {
+        return m_message;
+    }
 
     /**
      * Get status code.
diff --git a/modules/platforms/cpp/conanfile.txt b/modules/platforms/cpp/conanfile.txt
index cf328d1504..d8ef2acd2a 100644
--- a/modules/platforms/cpp/conanfile.txt
+++ b/modules/platforms/cpp/conanfile.txt
@@ -1,7 +1,7 @@
 [requires]
-openssl/1.1.1q
 msgpack-c/4.0.0
 gtest/1.12.1
 
 [generators]
-cmake
\ No newline at end of file
+CMakeDeps
+CMakeToolchain
\ No newline at end of file
diff --git a/modules/platforms/cpp/network/CMakeLists.txt b/modules/platforms/cpp/network/CMakeLists.txt
index 3c8ad4a1ca..13b329b099 100644
--- a/modules/platforms/cpp/network/CMakeLists.txt
+++ b/modules/platforms/cpp/network/CMakeLists.txt
@@ -19,9 +19,7 @@ project(ignite-network)
 
 set(TARGET ${PROJECT_NAME})
 
-find_package(OpenSSL REQUIRED)
-
-include_directories(include src ${OPENSSL_INCLUDE_DIR})
+include_directories(include src)
 
 set(SOURCES
     src/network/async_client_pool_adapter.cpp
diff --git a/modules/platforms/cpp/network/os/linux/src/network/linux_async_worker_thread.cpp b/modules/platforms/cpp/network/os/linux/src/network/linux_async_worker_thread.cpp
index 092ba0e788..34d6e84f3a 100644
--- a/modules/platforms/cpp/network/os/linux/src/network/linux_async_worker_thread.cpp
+++ b/modules/platforms/cpp/network/os/linux/src/network/linux_async_worker_thread.cpp
@@ -64,14 +64,14 @@ namespace ignite
         {
             epoll = epoll_create(1);
             if (epoll < 0)
-                common::ThrowLastSystemError("Failed to create epoll instance");
+                common::throwLastSystemError("Failed to create epoll instance");
 
             stopEvent = eventfd(0, EFD_NONBLOCK);
             if (stopEvent < 0)
             {
-                std::string msg = common::GetLastSystemError("Failed to create stop event instance");
+                std::string msg = common::getLastSystemError("Failed to create stop event instance");
                 close(stopEvent);
-                common::ThrowSystemError(msg);
+                common::throwSystemError(msg);
             }
 
             epoll_event event;
@@ -82,10 +82,10 @@ namespace ignite
             int res = epoll_ctl(epoll, EPOLL_CTL_ADD, stopEvent, &event);
             if (res < 0)
             {
-                std::string msg = common::GetLastSystemError("Failed to create stop event instance");
+                std::string msg = common::getLastSystemError("Failed to create stop event instance");
                 close(stopEvent);
                 close(epoll);
-                common::ThrowSystemError(msg);
+                common::throwSystemError(msg);
             }
 
             m_stopping = false;
@@ -190,7 +190,7 @@ namespace ignite
             currentClient = currentConnection->ToClient(socketFd);
             bool ok = currentClient->StartMonitoring(epoll);
             if (!ok)
-                common::ThrowLastSystemError("Can not add file descriptor to epoll");
+                common::throwLastSystemError("Can not add file descriptor to epoll");
 
             // Connect to server.
             int res = connect(socketFd, addr->ai_addr, addr->ai_addrlen);
@@ -325,7 +325,7 @@ namespace ignite
             if (lastConnectionTime.tv_sec == 0)
                 return 0;
 
-            int timeout = fibonacci10.GetValue(m_failedAttempts) * 1000;
+            int timeout = fibonacci10.getValue(m_failedAttempts) * 1000;
 
             timespec now;
             clock_gettime(CLOCK_MONOTONIC, &now);
diff --git a/modules/platforms/cpp/network/os/win/src/network/sockets.cpp b/modules/platforms/cpp/network/os/win/src/network/sockets.cpp
index 2565a2b77f..3803167d9f 100644
--- a/modules/platforms/cpp/network/os/win/src/network/sockets.cpp
+++ b/modules/platforms/cpp/network/os/win/src/network/sockets.cpp
@@ -23,7 +23,9 @@
 #include "network/utils.h"
 
 // Using NULLs as specified by WinAPI
-#pragma ide diagnostic ignored "modernize-use-nullptr"
+#ifdef __JETBRAINS_IDE__
+#   pragma ide diagnostic ignored "modernize-use-nullptr"
+#endif
 
 namespace ignite::network
 {
@@ -156,7 +158,7 @@ void InitWsa()
             networkInited = WSAStartup(MAKEWORD(2, 2), &wsaData) == 0;
 
             if (!networkInited)
-                ThrowNetworkError("Networking initialisation failed: " + getLastSocketErrorMessage());
+                throwNetworkError("Networking initialisation failed: " + getLastSocketErrorMessage());
         }
     }
 }
diff --git a/modules/platforms/cpp/network/os/win/src/network/utils.cpp b/modules/platforms/cpp/network/os/win/src/network/utils.cpp
index c941dd1e84..15f1ed982f 100644
--- a/modules/platforms/cpp/network/os/win/src/network/utils.cpp
+++ b/modules/platforms/cpp/network/os/win/src/network/utils.cpp
@@ -20,12 +20,14 @@
 #include "network/utils.h"
 
 // Using NULLs as specified by WinAPI
-#pragma ide diagnostic ignored "modernize-use-nullptr"
+#ifdef __JETBRAINS_IDE__
+#   pragma ide diagnostic ignored "modernize-use-nullptr"
+#endif
 
 namespace ignite::network
 {
 
-std::string GetLastSystemError()
+std::string getLastSystemError()
 {
     DWORD errorCode = GetLastError();
 
diff --git a/modules/platforms/cpp/network/os/win/src/network/win_async_client_pool.cpp b/modules/platforms/cpp/network/os/win/src/network/win_async_client_pool.cpp
index a993613c4c..86db983836 100644
--- a/modules/platforms/cpp/network/os/win/src/network/win_async_client_pool.cpp
+++ b/modules/platforms/cpp/network/os/win/src/network/win_async_client_pool.cpp
@@ -23,7 +23,9 @@
 #include "network/win_async_client_pool.h"
 
 // Using NULLs as specified by WinAPI
-#pragma ide diagnostic ignored "modernize-use-nullptr"
+#ifdef __JETBRAINS_IDE__
+#   pragma ide diagnostic ignored "modernize-use-nullptr"
+#endif
 
 namespace ignite::network
 {
@@ -54,7 +56,7 @@ void WinAsyncClientPool::start(std::vector<TcpRange> addrs, uint32_t connLimit)
 
     m_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
     if (!m_iocp)
-        ThrowLastSystemError("Failed to create IOCP instance");
+        throwLastSystemError("Failed to create IOCP instance");
 
     try
     {
@@ -113,7 +115,7 @@ bool WinAsyncClientPool::addClient(std::shared_ptr<WinAsyncClient> client)
 
         HANDLE iocp0 = client->addToIocp(m_iocp);
         if (iocp0 == NULL)
-            ThrowLastSystemError("Can not add socket to IOCP");
+            throwLastSystemError("Can not add socket to IOCP");
 
         m_iocp = iocp0;
 
diff --git a/modules/platforms/cpp/network/os/win/src/network/win_async_connecting_thread.cpp b/modules/platforms/cpp/network/os/win/src/network/win_async_connecting_thread.cpp
index d5bfec7de1..cc678e6237 100644
--- a/modules/platforms/cpp/network/os/win/src/network/win_async_connecting_thread.cpp
+++ b/modules/platforms/cpp/network/os/win/src/network/win_async_connecting_thread.cpp
@@ -22,7 +22,9 @@
 #include "network/win_async_connecting_thread.h"
 
 // Using NULLs as specified by WinAPI
-#pragma ide diagnostic ignored "modernize-use-nullptr"
+#ifdef __JETBRAINS_IDE__
+#   pragma ide diagnostic ignored "modernize-use-nullptr"
+#endif
 
 namespace
 {
@@ -59,7 +61,7 @@ void WinAsyncConnectingThread::run()
         {
             ++m_failedAttempts;
 
-            auto msToWait = static_cast<DWORD>(1000 * fibonacci10.GetValue(m_failedAttempts));
+            auto msToWait = static_cast<DWORD>(1000 * fibonacci10.getValue(m_failedAttempts));
             if (msToWait)
                 Sleep(msToWait);
 
@@ -150,7 +152,7 @@ std::shared_ptr<WinAsyncClient> WinAsyncConnectingThread::tryConnect(const TcpRa
         {
             SOCKET socket = tryConnect(addr);
 
-            return std::make_shared<WinAsyncClient>(socket, addr, range, BUFFER_SIZE);
+            return std::make_shared<WinAsyncClient>(socket, addr, range, int32_t(BUFFER_SIZE));
         }
         catch (const IgniteError&)
         {
@@ -179,7 +181,7 @@ SOCKET WinAsyncConnectingThread::tryConnect(const EndPoint& addr)
     int res = getaddrinfo(addr.host.c_str(), strPort.c_str(), &hints, &result);
 
     if (res != 0)
-        ThrowNetworkError("Can not resolve host: " + addr.host + ":" + strPort);
+        throwNetworkError("Can not resolve host: " + addr.host + ":" + strPort);
 
     std::string lastErrorMsg = "Failed to resolve host";
 
@@ -193,7 +195,7 @@ SOCKET WinAsyncConnectingThread::tryConnect(const EndPoint& addr)
         socket = WSASocket(it->ai_family, it->ai_socktype, it->ai_protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
 
         if (socket == INVALID_SOCKET)
-            ThrowNetworkError("Socket creation failed: " + getLastSocketErrorMessage());
+            throwNetworkError("Socket creation failed: " + getLastSocketErrorMessage());
 
         TrySetSocketOptions(socket, BUFFER_SIZE, TRUE, TRUE, TRUE);
 
@@ -220,7 +222,7 @@ SOCKET WinAsyncConnectingThread::tryConnect(const EndPoint& addr)
     freeaddrinfo(result);
 
     if (socket == INVALID_SOCKET)
-        ThrowNetworkError(lastErrorMsg);
+        throwNetworkError(lastErrorMsg);
 
     return socket;
 }
diff --git a/modules/platforms/cpp/network/os/win/src/network/win_async_worker_thread.cpp b/modules/platforms/cpp/network/os/win/src/network/win_async_worker_thread.cpp
index 8cfda7a45c..a30eb35de9 100644
--- a/modules/platforms/cpp/network/os/win/src/network/win_async_worker_thread.cpp
+++ b/modules/platforms/cpp/network/os/win/src/network/win_async_worker_thread.cpp
@@ -23,7 +23,9 @@
 #include "network/win_async_worker_thread.h"
 
 // Using NULLs as specified by WinAPI
-#pragma ide diagnostic ignored "modernize-use-nullptr"
+#ifdef __JETBRAINS_IDE__
+#   pragma ide diagnostic ignored "modernize-use-nullptr"
+#endif
 
 namespace ignite::network
 {
diff --git a/modules/platforms/cpp/network/src/network/utils.h b/modules/platforms/cpp/network/src/network/utils.h
index 959299f7c3..b87f576dfe 100644
--- a/modules/platforms/cpp/network/src/network/utils.h
+++ b/modules/platforms/cpp/network/src/network/utils.h
@@ -56,7 +56,7 @@ public:
      * @return N-th member of sequence if n < size, or max member.
      */
     [[nodiscard]]
-    constexpr T GetValue(size_t n) const
+    constexpr T getValue(size_t n) const
     {
         return n < size ? sequence[n] : sequence[size-1];
     }
@@ -71,7 +71,7 @@ private:
  *
  * @param err Error message.
  */
-inline void ThrowNetworkError(std::string err)
+inline void throwNetworkError(std::string err)
 {
     // TODO: Remove me
     throw IgniteError(StatusCode::NETWORK, std::move(err));
@@ -84,7 +84,7 @@ inline void ThrowNetworkError(std::string err)
  * @param description Error details.
  * @param advice User advice.
  */
-std::string FormatErrorMessage(std::string_view description, std::string_view details, std::string_view advice)
+inline std::string formatErrorMessage(std::string_view description, std::string_view details, std::string_view advice)
 {
     std::stringstream messageBuilder;
     messageBuilder << description;
@@ -102,7 +102,7 @@ std::string FormatErrorMessage(std::string_view description, std::string_view de
  *
  * @return Error in human-readable format.
  */
-std::string GetLastSystemError();
+std::string getLastSystemError();
 
 /**
  * Try extract from system error stack, format and return platform-specific error.
@@ -110,9 +110,9 @@ std::string GetLastSystemError();
  * @param description Error description.
  * @return Error in human-readable format.
  */
-std::string GetLastSystemError(std::string_view description, std::string_view advice)
+inline std::string getLastSystemError(std::string_view description, std::string_view advice)
 {
-    return FormatErrorMessage(description, GetLastSystemError(), advice);
+    return formatErrorMessage(description, getLastSystemError(), advice);
 }
 
 /**
@@ -120,7 +120,7 @@ std::string GetLastSystemError(std::string_view description, std::string_view ad
  *
  * @param msg Error message.
  */
-inline void ThrowSystemError(std::string msg)
+inline void throwSystemError(std::string msg)
 {
     // TODO: Remove me
     throw IgniteError(StatusCode::OS, std::move(msg));
@@ -132,9 +132,9 @@ inline void ThrowSystemError(std::string msg)
  * @param description Error description.
  * @param advice User advice.
  */
-void ThrowLastSystemError(std::string_view description, std::string_view advice)
+inline void throwLastSystemError(std::string_view description, std::string_view advice)
 {
-    ThrowSystemError(GetLastSystemError(description, advice));
+    throwSystemError(getLastSystemError(description, advice));
 }
 
 /**
@@ -142,9 +142,9 @@ void ThrowLastSystemError(std::string_view description, std::string_view advice)
  *
  * @param description Error description.
  */
-void ThrowLastSystemError(std::string_view description)
+inline void throwLastSystemError(std::string_view description)
 {
-    ThrowLastSystemError(description, "");
+    throwLastSystemError(description, "");
 }
 
 } // namespace ignite::network
diff --git a/modules/platforms/cpp/protocol/CMakeLists.txt b/modules/platforms/cpp/protocol/CMakeLists.txt
index 8ff9e3ce22..08fb9c22b1 100644
--- a/modules/platforms/cpp/protocol/CMakeLists.txt
+++ b/modules/platforms/cpp/protocol/CMakeLists.txt
@@ -19,6 +19,8 @@ project(ignite-protocol)
 
 set(TARGET ${PROJECT_NAME})
 
+find_package(msgpack)
+
 include_directories(include)
 
 set(SOURCES
@@ -32,5 +34,5 @@ add_library(${TARGET} OBJECT ${SOURCES})
 set_target_properties(${TARGET} PROPERTIES VERSION ${CMAKE_PROJECT_VERSION})
 set_target_properties(${TARGET} PROPERTIES POSITION_INDEPENDENT_CODE 1)
 
-target_link_libraries(${TARGET} ignite-common)
+target_link_libraries(${TARGET} ignite-common msgpackc)
 target_include_directories(${TARGET} INTERFACE include)


[ignite-3] 14/17: IGNITE-17424 Add logging support

Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 04b98b5d7afb08e3a1b4b1cf1894df0a819fd8cc
Author: Igor Sapego <is...@apache.org>
AuthorDate: Wed Aug 31 12:36:00 2022 +0400

    IGNITE-17424 Add logging support
---
 .../include/ignite/ignite_client_configuration.h   | 31 +++++++++-
 .../cpp/client/include/ignite/ignite_logger.h      | 72 ++++++++++++++++++++++
 2 files changed, 102 insertions(+), 1 deletion(-)

diff --git a/modules/platforms/cpp/client/include/ignite/ignite_client_configuration.h b/modules/platforms/cpp/client/include/ignite/ignite_client_configuration.h
index 3212a0e9cf..e0073b6641 100644
--- a/modules/platforms/cpp/client/include/ignite/ignite_client_configuration.h
+++ b/modules/platforms/cpp/client/include/ignite/ignite_client_configuration.h
@@ -21,6 +21,8 @@
 #include <string>
 #include <vector>
 
+#include <ignite/ignite_logger.h>
+
 namespace ignite
 {
 
@@ -49,7 +51,8 @@ public:
      * @param endpoint Endpoints list.
      */
     IgniteClientConfiguration(std::initializer_list<std::string> endpoints) :
-        m_endpoints(endpoints) { }
+        m_endpoints(endpoints),
+        m_logger() { }
 
     /**
      * Get endpoints.
@@ -83,9 +86,35 @@ public:
         IgniteClientConfiguration::m_endpoints = endpoints;
     }
 
+    /**
+     * Get logger.
+     *
+     * @return Current logger.
+     */
+    [[nodiscard]]
+    std::shared_ptr<IgniteLogger> getLogger() const
+    {
+        return m_logger;
+    }
+
+    /**
+     * Set logger to be used by client.
+     *
+     * The logger is @c nullptr by default, which means no logging is performed.
+     *
+     * @param logger Logger to use.
+     */
+    void setLogger(std::shared_ptr<IgniteLogger> logger)
+    {
+        m_logger = std::move(logger);
+    }
+
 private:
     /** Endpoints. */
     std::vector<std::string> m_endpoints;
+
+    /** Logger. */
+    std::shared_ptr<IgniteLogger> m_logger;
 };
 
 } // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/client/include/ignite/ignite_logger.h b/modules/platforms/cpp/client/include/ignite/ignite_logger.h
new file mode 100644
index 0000000000..f274775ace
--- /dev/null
+++ b/modules/platforms/cpp/client/include/ignite/ignite_logger.h
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <string_view>
+
+namespace ignite
+{
+
+/**
+ * Ignite logger interface.
+ *
+ * User can implement this class to use preferred logger with Ignite client.
+ */
+class IgniteLogger
+{
+public:
+    // Default
+    IgniteLogger() = default;
+    ~IgniteLogger() = default;
+    IgniteLogger(IgniteLogger&&) = default;
+    IgniteLogger(const IgniteLogger&) = default;
+    IgniteLogger& operator=(IgniteLogger&&) = default;
+    IgniteLogger& operator=(const IgniteLogger&) = default;
+
+    /**
+     * Used to log error messages.
+     *
+     * @param message Error message.
+     */
+    virtual void logError(std::string_view message) = 0;
+
+    /**
+     * Used to log warning messages.
+     *
+     * @param message Warning message.
+     */
+    virtual void logWarning(std::string_view message) = 0;
+
+    /**
+     * Used to log info messages.
+     *
+     * @param message Info message.
+     */
+    virtual void logInfo(std::string_view message) = 0;
+
+    /**
+     * Used to log debug messages.
+     *
+     * It is recommended to disable debug logging by default for the sake of performance.
+     *
+     * @param message Debug message.
+     */
+    virtual void logDebug(std::string_view message) = 0;
+};
+
+} // namespace ignite
\ No newline at end of file


[ignite-3] 12/17: IGNITE-17424 IgniteClient implementation stub

Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 63f137235bd9ec6508d1770c01d612ea1fb878ed
Author: Igor Sapego <is...@apache.org>
AuthorDate: Wed Aug 31 09:01:30 2022 +0400

    IGNITE-17424 IgniteClient implementation stub
---
 .../cpp/client/include/ignite/ignite_client.h      | 15 +++--
 modules/platforms/cpp/client/src/ignite_client.cpp | 15 ++++-
 .../platforms/cpp/client/src/ignite_client_impl.h  | 65 ++++++++++++++++++++++
 3 files changed, 90 insertions(+), 5 deletions(-)

diff --git a/modules/platforms/cpp/client/include/ignite/ignite_client.h b/modules/platforms/cpp/client/include/ignite/ignite_client.h
index 3c47c31641..4a8b45d30e 100644
--- a/modules/platforms/cpp/client/include/ignite/ignite_client.h
+++ b/modules/platforms/cpp/client/include/ignite/ignite_client.h
@@ -37,14 +37,14 @@ class IgniteClient
 {
 public:
     // Deleted
-    IgniteClient() = delete;
+    IgniteClient(const IgniteClient&) = delete;
+    IgniteClient& operator=(const IgniteClient&) = delete;
 
     // Default
+    IgniteClient() = default;
     ~IgniteClient() = default;
     IgniteClient(IgniteClient&&) = default;
-    IgniteClient(const IgniteClient&) = default;
     IgniteClient& operator=(IgniteClient&&) = default;
-    IgniteClient& operator=(const IgniteClient&) = default;
 
     /**
      * Start client asynchronously.
@@ -68,8 +68,15 @@ public:
     static std::future<IgniteClient> startAsync(IgniteClientConfiguration configuration);
 
 private:
+    /**
+     * Constructor
+     *
+     * @param impl Implementation
+     */
+    explicit IgniteClient(std::unique_ptr<impl::IgniteClientImpl> impl);
+
     /** Implementation. */
-    std::shared_ptr<impl::IgniteClientImpl> m_impl;
+    std::unique_ptr<impl::IgniteClientImpl> m_impl;
 };
 
 } // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/client/src/ignite_client.cpp b/modules/platforms/cpp/client/src/ignite_client.cpp
index e94dd89d1e..ddb8975344 100644
--- a/modules/platforms/cpp/client/src/ignite_client.cpp
+++ b/modules/platforms/cpp/client/src/ignite_client.cpp
@@ -17,12 +17,25 @@
 
 #include "ignite/ignite_client.h"
 
+#include "ignite_client_impl.h"
+
 namespace ignite
 {
 
+
 std::future<IgniteClient> IgniteClient::startAsync(IgniteClientConfiguration configuration)
 {
-    return {};
+    return std::async(std::launch::async, [cfg = std::move(configuration)]() {
+
+        auto impl = std::make_unique<impl::IgniteClientImpl>(cfg);
+
+        impl->start();
+
+        return IgniteClient(std::move(impl));
+    });
 }
 
+IgniteClient::IgniteClient(std::unique_ptr<impl::IgniteClientImpl> impl) :
+    m_impl(std::move(impl)) { }
+
 } // namespace ignite
diff --git a/modules/platforms/cpp/client/src/ignite_client_impl.h b/modules/platforms/cpp/client/src/ignite_client_impl.h
new file mode 100644
index 0000000000..17be39464f
--- /dev/null
+++ b/modules/platforms/cpp/client/src/ignite_client_impl.h
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <future>
+#include <memory>
+
+#include "ignite/ignite_client_configuration.h"
+
+namespace ignite::impl
+{
+
+/**
+ * Ignite client implementation.
+ */
+class IgniteClientImpl
+{
+public:
+    // Deleted
+    IgniteClientImpl(const IgniteClientImpl&) = delete;
+    IgniteClientImpl& operator=(const IgniteClientImpl&) = delete;
+
+    // Default
+    IgniteClientImpl() = default;
+    ~IgniteClientImpl() = default;
+    IgniteClientImpl(IgniteClientImpl&&) = default;
+    IgniteClientImpl& operator=(IgniteClientImpl&&) = default;
+
+    /**
+     * Constructor.
+     *
+     * @param configuration Configuration.
+     */
+    explicit IgniteClientImpl(IgniteClientConfiguration configuration) :
+        m_configuration(std::move(configuration)) { }
+
+    /**
+     * Start client.
+     */
+    void start()
+    {
+        // TODO
+    }
+
+private:
+    /** Configuration. */
+    IgniteClientConfiguration m_configuration;
+};
+
+} // namespace ignite::impl
\ No newline at end of file


[ignite-3] 13/17: IGNITE-17424 Re-factoring

Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit ba4e87ea7cd6f939f89565270c0cfdec057250f0
Author: Igor Sapego <is...@apache.org>
AuthorDate: Wed Aug 31 09:06:32 2022 +0400

    IGNITE-17424 Re-factoring
---
 .../cpp/test-common/include/ignite_node.h          |  2 +-
 .../platforms/cpp/test-common/src/ignite_node.cpp  | 14 ++++----
 .../cpp/test-common/src/win/win_process.h          | 40 +++++++++++-----------
 3 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/modules/platforms/cpp/test-common/include/ignite_node.h b/modules/platforms/cpp/test-common/include/ignite_node.h
index 4850e07624..5a34c4c2b1 100644
--- a/modules/platforms/cpp/test-common/include/ignite_node.h
+++ b/modules/platforms/cpp/test-common/include/ignite_node.h
@@ -64,7 +64,7 @@ public:
 
 private:
     /** Underlying process. */
-    std::unique_ptr<Process> process;
+    std::unique_ptr<Process> m_process;
 };
 
 } // namespace ignite
diff --git a/modules/platforms/cpp/test-common/src/ignite_node.cpp b/modules/platforms/cpp/test-common/src/ignite_node.cpp
index 3c6f7ab6a3..8b75cb30b7 100644
--- a/modules/platforms/cpp/test-common/src/ignite_node.cpp
+++ b/modules/platforms/cpp/test-common/src/ignite_node.cpp
@@ -55,10 +55,10 @@ void IgniteNode::start(bool dryRun)
     std::cout << "working dir=" << workDir << std::endl;
     std::cout << "command=" << command << std::endl;
 
-    process = Process::make(command, workDir.string());
-    if (!process->start())
+    m_process = Process::make(command, workDir.string());
+    if (!m_process->start())
     {
-        process.reset();
+        m_process.reset();
 
         throw std::runtime_error("Failed to invoke Ignite command: '" + command + "'");
     }
@@ -66,14 +66,14 @@ void IgniteNode::start(bool dryRun)
 
 void IgniteNode::stop()
 {
-    if (process)
-        process->kill();
+    if (m_process)
+        m_process->kill();
 }
 
 void IgniteNode::join(std::chrono::milliseconds timeout)
 {
-    if (process)
-        process->join(timeout);
+    if (m_process)
+        m_process->join(timeout);
 }
 
 } // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/test-common/src/win/win_process.h b/modules/platforms/cpp/test-common/src/win/win_process.h
index b0c29c5941..b52be1aa73 100644
--- a/modules/platforms/cpp/test-common/src/win/win_process.h
+++ b/modules/platforms/cpp/test-common/src/win/win_process.h
@@ -82,10 +82,10 @@ public:
      * @param workDir Working directory.
      */
     WinProcess(std::string command, std::string workDir) :
-            running(false),
-            command(std::move(command)),
-            workDir(std::move(workDir)),
-            info{}
+            m_running(false),
+            m_command(std::move(command)),
+            m_workDir(std::move(workDir)),
+            m_info{}
     { }
 
     /**
@@ -99,26 +99,26 @@ public:
      */
     bool start() override
     {
-        if (running)
+        if (m_running)
             return false;
 
         STARTUPINFO si;
 
         std::memset(&si, 0, sizeof(si));
         si.cb = sizeof(si);
-        std::memset(&info, 0, sizeof(info));
+        std::memset(&m_info, 0, sizeof(m_info));
 
-        std::vector<char> cmd(command.begin(), command.end());
+        std::vector<char> cmd(m_command.begin(), m_command.end());
         cmd.push_back(0);
 
         BOOL success = CreateProcess(
                 NULL, cmd.data(), NULL, NULL,
-                FALSE, 0, NULL, workDir.c_str(),
-                &si, &info);
+                FALSE, 0, NULL, m_workDir.c_str(),
+                &si, &m_info);
 
-        running = success == TRUE;
+        m_running = success == TRUE;
 
-        return running;
+        return m_running;
     }
 
     /**
@@ -126,7 +126,7 @@ public:
      */
     void kill() override
     {
-        std::vector<DWORD> processTree = getProcessTree(info.dwProcessId);
+        std::vector<DWORD> processTree = getProcessTree(m_info.dwProcessId);
         for (auto procId : processTree)
         {
             HANDLE hChildProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, procId);
@@ -137,10 +137,10 @@ public:
             }
         }
 
-        TerminateProcess(info.hProcess, 1);
+        TerminateProcess(m_info.hProcess, 1);
 
-        CloseHandle( info.hProcess );
-        CloseHandle( info.hThread );
+        CloseHandle(m_info.hProcess );
+        CloseHandle(m_info.hThread );
     }
 
     /**
@@ -152,21 +152,21 @@ public:
     {
         auto msecs = timeout.count() < 0 ? INFINITE : static_cast<DWORD>(timeout.count());
 
-        WaitForSingleObject(info.hProcess, msecs);
+        WaitForSingleObject(m_info.hProcess, msecs);
     }
 
 private:
     /** Running flag. */
-    bool running;
+    bool m_running;
 
     /** Command. */
-    const std::string command;
+    const std::string m_command;
 
     /** Working directory. */
-    const std::string workDir;
+    const std::string m_workDir;
 
     /** Process information. */
-    PROCESS_INFORMATION info;
+    PROCESS_INFORMATION m_info;
 };
 
 } // namespace ignite::win


[ignite-3] 05/17: IGNITE-17424 Start Ignite node

Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit e07dda19358470963d9c41ce9625a0a83f652c44
Author: Igor Sapego <is...@apache.org>
AuthorDate: Mon Aug 29 14:28:49 2022 +0400

    IGNITE-17424 Start Ignite node
---
 modules/platforms/cpp/CMakeLists.txt               |  6 ++--
 .../cpp/client-test/src/ignite_client_test.cpp     | 27 +++++++++++++++-
 .../cpp/test-common/include/ignite_node.h          | 34 +++++++++++++-------
 .../platforms/cpp/test-common/include/test_utils.h | 26 +++++++++++++++
 .../platforms/cpp/test-common/src/ignite_node.cpp  | 31 ++++++++++++++++--
 .../platforms/cpp/test-common/src/test_utils.cpp   | 37 +++++++++++++++++++---
 6 files changed, 139 insertions(+), 22 deletions(-)

diff --git a/modules/platforms/cpp/CMakeLists.txt b/modules/platforms/cpp/CMakeLists.txt
index 54fc4ed113..ca11746ca4 100644
--- a/modules/platforms/cpp/CMakeLists.txt
+++ b/modules/platforms/cpp/CMakeLists.txt
@@ -23,8 +23,10 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
 set(CMAKE_PROJECT_VERSION ${PROJECT_VERSION})
 
-include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
-conan_basic_setup()
+if(EXISTS ${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
+	include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
+	conan_basic_setup()
+endif()
 
 if (UNIX)
 	include(GNUInstallDirs)
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 416ca4af6b..2413b1839b 100644
--- a/modules/platforms/cpp/client-test/src/ignite_client_test.cpp
+++ b/modules/platforms/cpp/client-test/src/ignite_client_test.cpp
@@ -15,8 +15,13 @@
  * limitations under the License.
  */
 
+#include <thread>
+#include <chrono>
+
 #include <gtest/gtest.h>
 
+#include "ignite_node.h"
+
 class ClientTest : public ::testing::Test {
 protected:
     ClientTest() = default;
@@ -37,5 +42,25 @@ protected:
 
 TEST_F(ClientTest, TestTest)
 {
-    EXPECT_EQ(1, 1);
+    std::cout << "Hello" << std::endl;
+
+    ignite::IgniteNode node;
+
+    node.start();
+
+    for (int i = 0; i < 20; ++i)
+    {
+        std::cout << node.getOutput();
+
+        std::this_thread::sleep_for(std::chrono::seconds(1));
+    }
+
+    node.stop();
+
+    for (int i = 0; i < 2; ++i)
+    {
+        std::cout << node.getOutput();
+
+        std::this_thread::sleep_for(std::chrono::seconds(1));
+    }
 }
\ No newline at end of file
diff --git a/modules/platforms/cpp/test-common/include/ignite_node.h b/modules/platforms/cpp/test-common/include/ignite_node.h
index ad0a889336..224aa3e124 100644
--- a/modules/platforms/cpp/test-common/include/ignite_node.h
+++ b/modules/platforms/cpp/test-common/include/ignite_node.h
@@ -15,24 +15,25 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef TEST_COMMON_IGNITE_NODE
+#define TEST_COMMON_IGNITE_NODE
 
-#include <cstdio>
+//#include <cstdio>
 
 namespace ignite
 {
     class IgniteNode
     {
     public:
-        /**
-         * Constructor.
-         */
-        IgniteNode() = default;
+//        /**
+//         * Constructor.
+//         */
+//        IgniteNode() = default;
 
-        /**
-         * Destructor.
-         */
-        ~IgniteNode() = default;
+//        /**
+//         * Destructor.
+//         */
+//        ~IgniteNode() = default;
 
         /**
          * Start node.
@@ -44,7 +45,16 @@ namespace ignite
          */
         void stop();
 
+        /**
+         * Get current node output.
+         *
+         * @param max Max bytes to get.
+         * @return Output.
+         */
+        std::string getOutput(int max = 1024);
     private:
-        FILE* file;
+        FILE* stream;
     };
-} // namespace ignite
\ No newline at end of file
+} // namespace ignite
+
+#endif // TEST_COMMON_IGNITE_NODE
diff --git a/modules/platforms/cpp/test-common/include/test_utils.h b/modules/platforms/cpp/test-common/include/test_utils.h
index 8905bdbc65..ca0d00a51f 100644
--- a/modules/platforms/cpp/test-common/include/test_utils.h
+++ b/modules/platforms/cpp/test-common/include/test_utils.h
@@ -17,6 +17,8 @@
 
 #pragma once
 
+#include <cstdio>
+
 #include <string>
 
 namespace ignite
@@ -33,4 +35,28 @@ namespace ignite
      * @return Resolved Ignite home.
      */
     std::string resolveIgniteHome(const std::string& path = "");
+
+    /**
+     * Get path to maven executable.
+     */
+    std::string getMavenPath();
+
+    /**
+     * Open process.
+     *
+     * @param command System shell command line instruction.
+     * @param type Mode of the returned process output stream. Can be one of the following:
+     *  "r" - The calling process can read the spawned command's standard output using the returned stream.
+     *  "w" - The calling process can write to the spawned command's standard input using the returned stream.
+     * @return File stream for the process.
+     */
+    FILE* processOpen(const char *command, const char *type);
+
+    /**
+     * Waits for the associated process to terminate and returns the exit status of the command.
+     *
+     * @param stream Return value from the previous call to processOpen().
+     * @return Returns the exit status of the terminating command processor, or -1 if an error occurs.
+     */
+    int processClose(FILE* stream);
 } // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/test-common/src/ignite_node.cpp b/modules/platforms/cpp/test-common/src/ignite_node.cpp
index 2c2863c122..1fb4bfb6eb 100644
--- a/modules/platforms/cpp/test-common/src/ignite_node.cpp
+++ b/modules/platforms/cpp/test-common/src/ignite_node.cpp
@@ -16,22 +16,47 @@
  */
 
 #include <iostream>
-#include <memory>
 #include <stdexcept>
-#include <string>
-#include <array>
+#include <vector>
+#include <utility>
 
 #include "ignite_node.h"
+#include "test_utils.h"
 
 namespace ignite
 {
     void IgniteNode::start()
     {
+        std::string home = resolveIgniteHome();
+        if (home.empty())
+            throw std::runtime_error(
+                    "Can not resolve Ignite home directory. Try setting IGNITE_HOME explicitly");
 
+        std::string command =
+#ifdef WIN32
+        "cmd.exe /c ";
+#else
+        "/bin/bash -c ";
+#endif
+
+        command += getMavenPath() + " " + "exec:java@platform-test-node-runner";
+
+        stream = processOpen(command.c_str(), "r");
     }
 
     void IgniteNode::stop()
     {
+        if (stream)
+            processClose(stream);
+    }
+
+    std::string IgniteNode::getOutput(int max)
+    {
+        std::string buffer(max, 0);
+
+        size_t actual = std::fread(buffer.data(), 1, max, stream);
+        buffer.resize(actual);
 
+        return buffer;
     }
 } // namespace ignite
\ No newline at end of file
diff --git a/modules/platforms/cpp/test-common/src/test_utils.cpp b/modules/platforms/cpp/test-common/src/test_utils.cpp
index 3ca15df6d5..65fe5b8975 100644
--- a/modules/platforms/cpp/test-common/src/test_utils.cpp
+++ b/modules/platforms/cpp/test-common/src/test_utils.cpp
@@ -15,14 +15,15 @@
  * limitations under the License.
  */
 
+#include <iostream>
 #include <filesystem>
 #include <functional>
+#include <vector>
 
 #include "test_utils.h"
 
 namespace ignite
 {
-
     /**
      * Checks if the path looks like binary release home directory.
      * Internally checks for presence of core library.
@@ -66,9 +67,13 @@ namespace ignite
         if (!error && std::filesystem::is_directory(path))
             return home.string();
 
-        home = std::filesystem::canonical(std::getenv("IGNITE_HOME"), error);
-        if (!error && std::filesystem::is_directory(home))
-            return home.string();
+        const char *env = std::getenv("IGNITE_HOME");
+        if (env)
+        {
+            home = std::filesystem::canonical(env, error);
+            if (!error && std::filesystem::is_directory(home))
+                return home.string();
+        }
 
         home = std::filesystem::current_path();
         while (!home.empty() && home.has_relative_path())
@@ -80,4 +85,28 @@ namespace ignite
         }
         return home.string();
     }
+
+    std::string getMavenPath()
+    {
+        // Currently, we only support systems with "mvn" command in PATH
+        return "mvn";
+    }
+
+    FILE *processOpen(const char *command, const char *type)
+    {
+#ifdef WIN32
+        return _popen(command, type);
+#else
+        return popen(command, type);
+#endif
+    }
+
+    int processClose(FILE *stream)
+    {
+#ifdef WIN32
+        return _pclose(stream);
+#else
+        return pclose(stream);
+#endif
+    }
 } // namespace ignite
\ No newline at end of file


[ignite-3] 07/17: IGNITE-17424 Cleanup

Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 5b0fc43ef3aa6256cfab4d6f01928c3afa43efa7
Author: Igor Sapego <is...@apache.org>
AuthorDate: Mon Aug 29 23:03:02 2022 +0400

    IGNITE-17424 Cleanup
---
 modules/platforms/cpp/test-common/include/ignite_node.h | 15 ---------------
 modules/platforms/cpp/test-common/src/ignite_node.cpp   | 17 -----------------
 2 files changed, 32 deletions(-)

diff --git a/modules/platforms/cpp/test-common/include/ignite_node.h b/modules/platforms/cpp/test-common/include/ignite_node.h
index 490a7985e0..c72ac06777 100644
--- a/modules/platforms/cpp/test-common/include/ignite_node.h
+++ b/modules/platforms/cpp/test-common/include/ignite_node.h
@@ -46,21 +46,6 @@ namespace ignite
          */
         void stop();
 
-//        /**
-//         * Check whether node is still running.
-//         *
-//         * @return @c true if the node is running.
-//         */
-//        bool isRunning();
-//
-//        /**
-//         * Get current node output.
-//         *
-//         * @param max Max bytes to get.
-//         * @return Output.
-//         */
-//        std::string getOutput(int max = 1024);
-
     private:
         /** Underlying process. */
         std::unique_ptr<Process> process;
diff --git a/modules/platforms/cpp/test-common/src/ignite_node.cpp b/modules/platforms/cpp/test-common/src/ignite_node.cpp
index 47807989a8..c4c7e8a9d1 100644
--- a/modules/platforms/cpp/test-common/src/ignite_node.cpp
+++ b/modules/platforms/cpp/test-common/src/ignite_node.cpp
@@ -17,8 +17,6 @@
 
 #include <filesystem>
 #include <stdexcept>
-#include <vector>
-#include <utility>
 #include <iostream>
 
 #include "ignite_node.h"
@@ -65,19 +63,4 @@ namespace ignite
         if (process)
             process->stop();
     }
-
-//    bool IgniteNode::isRunning()
-//    {
-//        return std::feof(stream) == 0 && std::ferror(stream) == 0;
-//    }
-//
-//    std::string IgniteNode::getOutput(int max)
-//    {
-//        std::string buffer(max, 0);
-//
-//        size_t actual = std::fread(buffer.data(), 1, max, stream);
-//        buffer.resize(actual);
-//
-//        return buffer;
-//    }
 } // namespace ignite
\ No newline at end of file


[ignite-3] 02/17: IGNITE-17424 Fix compilation for MSVC

Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit b26ca7c06fa8f3bed5a66cbf5e2cef3c524fdd0f
Author: Igor Sapego <is...@apache.org>
AuthorDate: Sun Aug 28 15:46:56 2022 +0400

    IGNITE-17424 Fix compilation for MSVC
---
 .gitignore                                         |  2 +-
 modules/platforms/cpp/CMakeLists.txt               |  2 +-
 modules/platforms/cpp/client-test/CMakeLists.txt   |  3 +-
 modules/platforms/cpp/common/CMakeLists.txt        |  5 +++-
 modules/platforms/cpp/common/Platform.h            | 32 ++++++++++++++++++++++
 .../platforms/cpp/schema/BinaryTupleBuilder.cpp    |  3 +-
 modules/platforms/cpp/schema/BinaryTupleBuilder.h  |  3 +-
 modules/platforms/cpp/schema/BinaryTupleParser.cpp |  6 ++--
 modules/platforms/cpp/schema/BinaryTupleParser.h   |  2 +-
 modules/platforms/cpp/schema/BinaryTupleSchema.h   |  2 +-
 modules/platforms/cpp/schema/DataType.cpp          |  1 +
 11 files changed, 51 insertions(+), 10 deletions(-)

diff --git a/.gitignore b/.gitignore
index 316612563b..823c84ef00 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,4 +18,4 @@ build/
 *.ipr
 out/
 
-modules/platforms/cpp/cmake-build-*
\ No newline at end of file
+modules/platforms/cpp/cmake-build-*
diff --git a/modules/platforms/cpp/CMakeLists.txt b/modules/platforms/cpp/CMakeLists.txt
index c4c3b0e195..fd36bf09ab 100644
--- a/modules/platforms/cpp/CMakeLists.txt
+++ b/modules/platforms/cpp/CMakeLists.txt
@@ -18,7 +18,7 @@
 cmake_minimum_required(VERSION 3.10)
 project(Ignite.C++ VERSION 3 LANGUAGES CXX)
 
-set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD 17)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
 set(CMAKE_PROJECT_VERSION ${PROJECT_VERSION})
diff --git a/modules/platforms/cpp/client-test/CMakeLists.txt b/modules/platforms/cpp/client-test/CMakeLists.txt
index 31c54604a6..33601b2175 100644
--- a/modules/platforms/cpp/client-test/CMakeLists.txt
+++ b/modules/platforms/cpp/client-test/CMakeLists.txt
@@ -22,7 +22,7 @@ set(TARGET ${PROJECT_NAME})
 include_directories(include src)
 
 enable_testing()
-find_package(gtest REQUIRED)
+find_package(GTest REQUIRED)
 include_directories(${GTEST_INCLUDE_DIR})
 
 set(SOURCES
@@ -33,4 +33,5 @@ add_executable(${TARGET} ${SOURCES})
 
 target_link_libraries(${TARGET} ignite-test-common ignite-client ${GTEST_LIBRARY_DEBUG} ${GTEST_MAIN_LIBRARY_DEBUG})
 
+set(TEST_TARGET IgniteClientTest)
 add_test(NAME ${TEST_TARGET} COMMAND ${TARGET})
diff --git a/modules/platforms/cpp/common/CMakeLists.txt b/modules/platforms/cpp/common/CMakeLists.txt
index 661910a7ef..150b4c73a8 100644
--- a/modules/platforms/cpp/common/CMakeLists.txt
+++ b/modules/platforms/cpp/common/CMakeLists.txt
@@ -19,7 +19,10 @@ project(ignite-common)
 
 set(TARGET ${PROJECT_NAME})
 
-set(HEADERS Types.h)
+set(HEADERS
+    Types.h
+    Platform.h
+)
 
 add_library(${TARGET} INTERFACE)
 
diff --git a/modules/platforms/cpp/common/Platform.h b/modules/platforms/cpp/common/Platform.h
new file mode 100644
index 0000000000..2901abf986
--- /dev/null
+++ b/modules/platforms/cpp/common/Platform.h
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#define LITTLE_ENDIAN 1
+#define BIG_ENDIAN 2
+
+#ifdef __BYTE_ORDER__
+#   if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#       define BYTE_ORDER LITTLE_ENDIAN
+#   else
+#       define BYTE_ORDER BIG_ENDIAN
+#   endif
+#else
+//TODO: Fix this
+#   define BYTE_ORDER LITTLE_ENDIAN
+#endif
\ No newline at end of file
diff --git a/modules/platforms/cpp/schema/BinaryTupleBuilder.cpp b/modules/platforms/cpp/schema/BinaryTupleBuilder.cpp
index ea1b3a8db3..07cf16dde3 100644
--- a/modules/platforms/cpp/schema/BinaryTupleBuilder.cpp
+++ b/modules/platforms/cpp/schema/BinaryTupleBuilder.cpp
@@ -19,6 +19,7 @@
 #include "BinaryTupleParser.h"
 
 #include <stdexcept>
+#include <string>
 
 namespace ignite {
 
@@ -76,7 +77,7 @@ SizeT BinaryTupleBuilder::sizeOf(DATA_TYPE type, BytesView bytes) {
             return sizeOfDouble(BinaryTupleParser::getDouble(bytes));
         case DATA_TYPE::STRING:
         case DATA_TYPE::BINARY:
-            return bytes.size();
+            return static_cast<SizeT>(bytes.size());
 
         case DATA_TYPE::UUID:
         case DATA_TYPE::DATE:
diff --git a/modules/platforms/cpp/schema/BinaryTupleBuilder.h b/modules/platforms/cpp/schema/BinaryTupleBuilder.h
index 77ea5bb48d..812fc4f954 100644
--- a/modules/platforms/cpp/schema/BinaryTupleBuilder.h
+++ b/modules/platforms/cpp/schema/BinaryTupleBuilder.h
@@ -19,6 +19,7 @@
 
 #include "BinaryTupleSchema.h"
 #include "common/Types.h"
+#include "common/Platform.h"
 
 #include <cassert>
 #include <cstring>
@@ -307,7 +308,7 @@ private:
      * @return Required size.
      */
     static SizeT sizeOfDouble(double value) noexcept {
-        float floatValue = value;
+        float floatValue = static_cast<float>(value);
         return floatValue == value ? sizeOfFloat(floatValue) : sizeof(double);
     }
 
diff --git a/modules/platforms/cpp/schema/BinaryTupleParser.cpp b/modules/platforms/cpp/schema/BinaryTupleParser.cpp
index 73767476e6..4ebb75c5d4 100644
--- a/modules/platforms/cpp/schema/BinaryTupleParser.cpp
+++ b/modules/platforms/cpp/schema/BinaryTupleParser.cpp
@@ -16,6 +16,7 @@
  */
 
 #include "BinaryTupleParser.h"
+#include "common/Platform.h"
 
 #include <cassert>
 #include <cstring>
@@ -62,8 +63,9 @@ BinaryTupleParser::BinaryTupleParser(IntT numElements, BytesView data)
     static_assert(BYTE_ORDER == LITTLE_ENDIAN);
     memcpy(&offset, nextEntry + tableSize - entrySize, entrySize);
     const std::byte *tupleEnd = valueBase + offset;
-    if (binaryTuple.end() > tupleEnd) {
-        binaryTuple.remove_suffix(binaryTuple.end() - tupleEnd);
+    const std::byte *currentEnd = &(*binaryTuple.end());
+    if (currentEnd > tupleEnd) {
+        binaryTuple.remove_suffix(currentEnd - tupleEnd);
     }
 }
 
diff --git a/modules/platforms/cpp/schema/BinaryTupleParser.h b/modules/platforms/cpp/schema/BinaryTupleParser.h
index de949801b4..552e93f6f1 100644
--- a/modules/platforms/cpp/schema/BinaryTupleParser.h
+++ b/modules/platforms/cpp/schema/BinaryTupleParser.h
@@ -70,7 +70,7 @@ public:
      *
      * @return Tuple size.
      */
-    SizeT getSize() const noexcept { return binaryTuple.size(); }
+    SizeT getSize() const noexcept { return static_cast<SizeT>(binaryTuple.size()); }
 
     /**
      * @brief Gets the expected total number of tuple elements.
diff --git a/modules/platforms/cpp/schema/BinaryTupleSchema.h b/modules/platforms/cpp/schema/BinaryTupleSchema.h
index b2b4bf7a18..624dfd0c3b 100644
--- a/modules/platforms/cpp/schema/BinaryTupleSchema.h
+++ b/modules/platforms/cpp/schema/BinaryTupleSchema.h
@@ -72,7 +72,7 @@ public:
      *
      * @return Number of elements.
      */
-    IntT numElements() const noexcept { return elements.size(); }
+    IntT numElements() const noexcept { return static_cast<IntT>(elements.size()); }
 
     /**
      * @brief Gets element info.
diff --git a/modules/platforms/cpp/schema/DataType.cpp b/modules/platforms/cpp/schema/DataType.cpp
index 17d15806cd..77b2a6c61a 100644
--- a/modules/platforms/cpp/schema/DataType.cpp
+++ b/modules/platforms/cpp/schema/DataType.cpp
@@ -18,6 +18,7 @@
 #include "DataType.h"
 
 #include <stdexcept>
+#include <string>
 
 namespace ignite {
 


[ignite-3] 10/17: IGNITE-17424 Re-factoring

Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17424
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 13ec1bbe94f8ab6415b6cb749b703911da8019da
Author: Igor Sapego <is...@apache.org>
AuthorDate: Tue Aug 30 17:34:13 2022 +0400

    IGNITE-17424 Re-factoring
---
 modules/platforms/cpp/common/Platform.h            | 34 +++++++++++++---------
 .../platforms/cpp/schema/BinaryTupleBuilder.cpp    |  6 ++--
 modules/platforms/cpp/schema/BinaryTupleBuilder.h  |  2 +-
 modules/platforms/cpp/schema/BinaryTupleParser.cpp |  4 +--
 4 files changed, 27 insertions(+), 19 deletions(-)

diff --git a/modules/platforms/cpp/common/Platform.h b/modules/platforms/cpp/common/Platform.h
index 4955529660..7bfcebc447 100644
--- a/modules/platforms/cpp/common/Platform.h
+++ b/modules/platforms/cpp/common/Platform.h
@@ -26,17 +26,25 @@
 #   define SWITCH_WIN_OTHER(x, y) (y)
 #endif
 
-#define LITTLE_ENDIAN 1
-#define BIG_ENDIAN 2
-
-#ifdef __BYTE_ORDER__
-#   if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
-#       define BYTE_ORDER LITTLE_ENDIAN
-#   else
-#       define BYTE_ORDER BIG_ENDIAN
-#   endif
-#else
-//TODO: Fix this
-#   define BYTE_ORDER LITTLE_ENDIAN
-#endif
+namespace ignite::platform
+{
+
+/**
+ * Byte order utility class.
+ */
+class ByteOrder
+{
+private:
+    static constexpr uint32_t fourBytes = 0x01020304;
+    static constexpr uint8_t lesserByte = (const uint8_t&)fourBytes;
+
+public:
+    ByteOrder() = delete;
+
+    static constexpr bool littleEndian = lesserByte == 0x04;
+    static constexpr bool bigEndian = lesserByte == 0x01;
+
+    static_assert(littleEndian || bigEndian, "Unknown byte order");
+};
 
+} // ignite::platform
diff --git a/modules/platforms/cpp/schema/BinaryTupleBuilder.cpp b/modules/platforms/cpp/schema/BinaryTupleBuilder.cpp
index e93d6c2f53..37583e9c95 100644
--- a/modules/platforms/cpp/schema/BinaryTupleBuilder.cpp
+++ b/modules/platforms/cpp/schema/BinaryTupleBuilder.cpp
@@ -110,21 +110,21 @@ void BinaryTupleBuilder::putInt8(BytesView bytes) {
 void BinaryTupleBuilder::putInt16(BytesView bytes) {
     SizeT size = sizeOfInt16(BinaryTupleParser::getInt16(bytes));
     assert(size <= bytes.size());
-    static_assert(BYTE_ORDER == LITTLE_ENDIAN);
+    static_assert(platform::ByteOrder::littleEndian);
     putBytes(BytesView{bytes.data(), size});
 }
 
 void BinaryTupleBuilder::putInt32(BytesView bytes) {
     SizeT size = sizeOfInt32(BinaryTupleParser::getInt32(bytes));
     assert(size <= bytes.size());
-    static_assert(BYTE_ORDER == LITTLE_ENDIAN);
+    static_assert(platform::ByteOrder::littleEndian);
     putBytes(BytesView{bytes.data(), size});
 }
 
 void BinaryTupleBuilder::putInt64(BytesView bytes) {
     SizeT size = sizeOfInt64(BinaryTupleParser::getInt64(bytes));
     assert(size <= bytes.size());
-    static_assert(BYTE_ORDER == LITTLE_ENDIAN);
+    static_assert(platform::ByteOrder::littleEndian);
     putBytes(BytesView{bytes.data(), size});
 }
 
diff --git a/modules/platforms/cpp/schema/BinaryTupleBuilder.h b/modules/platforms/cpp/schema/BinaryTupleBuilder.h
index 812fc4f954..e55f35499f 100644
--- a/modules/platforms/cpp/schema/BinaryTupleBuilder.h
+++ b/modules/platforms/cpp/schema/BinaryTupleBuilder.h
@@ -387,7 +387,7 @@ private:
      */
     void appendEntry() {
         uint64_t offset = nextValue - valueBase;
-        static_assert(BYTE_ORDER == LITTLE_ENDIAN);
+        static_assert(platform::ByteOrder::littleEndian);
         assert(nextEntry + entrySize <= valueBase);
         std::memcpy(nextEntry, &offset, entrySize);
         nextEntry += entrySize;
diff --git a/modules/platforms/cpp/schema/BinaryTupleParser.cpp b/modules/platforms/cpp/schema/BinaryTupleParser.cpp
index 4ebb75c5d4..64d3ea19c8 100644
--- a/modules/platforms/cpp/schema/BinaryTupleParser.cpp
+++ b/modules/platforms/cpp/schema/BinaryTupleParser.cpp
@@ -60,7 +60,7 @@ BinaryTupleParser::BinaryTupleParser(IntT numElements, BytesView data)
 
     // Fix tuple size if needed.
     uint64_t offset = 0;
-    static_assert(BYTE_ORDER == LITTLE_ENDIAN);
+    static_assert(platform::ByteOrder::littleEndian);
     memcpy(&offset, nextEntry + tableSize - entrySize, entrySize);
     const std::byte *tupleEnd = valueBase + offset;
     const std::byte *currentEnd = &(*binaryTuple.end());
@@ -75,7 +75,7 @@ ElementView BinaryTupleParser::getNext() {
     ++elementIndex;
 
     uint64_t offset = 0;
-    static_assert(BYTE_ORDER == LITTLE_ENDIAN);
+    static_assert(platform::ByteOrder::littleEndian);
     memcpy(&offset, nextEntry, entrySize);
     nextEntry += entrySize;