From fdbf580a2c82078883b79c7572ca3e1d22814ea4 Mon Sep 17 00:00:00 2001
From: Daniel Lyubomirov <daniel.lyubomirov@vereign.com>
Date: Mon, 20 Jul 2020 15:35:55 +0300
Subject: [PATCH] wip

---
 cpp/CMakeLists.txt      |   3 +-
 cpp/cmd/CMakeLists.txt  |  24 ++++++++
 cpp/cmd/service/main.cc | 127 ++++++++++++++++++++++++++++++++++++++++
 cpp/src/csandbox.cc     |  27 ---------
 cpp/vendor/boost.cmake  |   2 +-
 5 files changed, 154 insertions(+), 29 deletions(-)
 create mode 100644 cpp/cmd/CMakeLists.txt
 create mode 100644 cpp/cmd/service/main.cc

diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 35a77a1..2789b5f 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -120,7 +120,7 @@ find_package(
   1.72.0
   EXACT
   REQUIRED
-  COMPONENTS regex thread system date_time filesystem
+  COMPONENTS regex thread system date_time filesystem program_options
 )
 
 find_package(Protobuf CONFIG REQUIRED)
@@ -145,6 +145,7 @@ find_package(nlohmann_json 3.7.3 REQUIRED)
 find_package(SQLite3 REQUIRED)
 
 add_subdirectory("src")
+add_subdirectory("cmd")
 add_subdirectory("tests")
 
 get_target_property(_protobuflib_location protobuf::libprotobuf LOCATION)
diff --git a/cpp/cmd/CMakeLists.txt b/cpp/cmd/CMakeLists.txt
new file mode 100644
index 0000000..a9ca8fe
--- /dev/null
+++ b/cpp/cmd/CMakeLists.txt
@@ -0,0 +1,24 @@
+
+add_definitions(-DBOOST_FILESYSTEM_NO_DEPRECATED)
+
+include_directories(
+  # ${CMAKE_CURRENT_BINARY_DIR}
+  # ${CMAKE_SOURCE_DIR}/src
+  # ${VENDOR_INSTALL_DIR}/include
+  ${Boost_INCLUDE_DIRS}
+  ${CMAKE_SOURCE_DIR}/include
+)
+
+set(VEREIGN_SERVICE_SOURCES
+  service/main.cc
+)
+
+add_executable(vereign-service ${VEREIGN_SERVICE_SOURCES})
+
+target_link_libraries(vereign-service
+  vereign
+  Threads::Threads
+  Boost::program_options
+)
+
+
diff --git a/cpp/cmd/service/main.cc b/cpp/cmd/service/main.cc
new file mode 100644
index 0000000..f7b1a6a
--- /dev/null
+++ b/cpp/cmd/service/main.cc
@@ -0,0 +1,127 @@
+/**
+ * Vereign Client Library Service is a CLI tool that is a tiny wrapper around the vereign library.
+ *
+ * It exists for testing purposes. One can run the `vereign-service` and then use the gRPC
+ * API to communicate with the vereign library the way a real integrator would do.
+ */
+
+#include <vereign/vereign.h>
+#include <boost/program_options.hpp>
+#include <boost/asio/signal_set.hpp>
+
+#include <iostream>
+
+constexpr auto name = std::string_view{"vereign-service"};
+
+struct Config {
+  std::string ListenAddress;
+  std::string VereignHost;
+  std::string VereignPort;
+  std::string StoragePath;
+};
+
+auto parseConfig(int argc, char** argv, Config& config) -> std::string;
+
+auto main(int argc, char** argv) -> int {
+  auto config = std::make_unique<Config>();
+  auto cmd = parseConfig(argc, argv, *config);
+
+  if (cmd == "help") {
+    return 0;
+  }
+
+  vereign_error* err = nullptr;
+  auto service = vereign_service_start(
+    config->ListenAddress.data(),
+    config->VereignHost.data(),
+    config->VereignPort.data(),
+    config->StoragePath.data(),
+    &err
+  );
+
+  if (err != nullptr) {
+    std::cout << "Could not start vereign service, err: " << vereign_error_message(err) << "\n";
+    vereign_error_free(err);
+    return 1;
+  }
+
+  std::cout << "Started Vereign Service.\n"
+    << "Listen address: " << config->ListenAddress << "\n"
+    << "Listen port: " << vereign_service_selected_port(service) << "\n";
+
+  boost::asio::io_context io_ctx;
+
+  boost::asio::signal_set signals(io_ctx, SIGINT, SIGTERM);
+  signals.async_wait([&io_ctx](const boost::system::error_code& /*ec*/, int /*signal*/) {
+    std::cout << "Received Shutdown signal, stopping the service ...\n";
+    io_ctx.stop();
+  });
+
+  io_ctx.run();
+
+  vereign_service_shutdown(service);
+
+  std::cout << "Service stopped.\n";
+
+  return 0;
+}
+
+auto parseConfig(int argc, char** argv, Config& config) -> std::string {
+  namespace po = boost::program_options;
+
+  po::options_description desc("Options");
+  desc.add_options()
+    ("help", "Help for vereign-service.")
+    (
+      "listen-address,l",
+      po::value<std::string>(&config.ListenAddress)->default_value("localhost:3000"),
+      R"(Listen address, for example "localhost:3000.")"
+    )
+    (
+      "vereign-host,h",
+      po::value<std::string>(&config.VereignHost)->default_value("localhost"),
+      R"(Vereign Restful API host, for example "app.vereign.com.")"
+    )
+    (
+      "vereign-port,p",
+      po::value<std::string>(&config.VereignPort)->default_value("443"),
+      R"(Vereign Restful API port.)"
+    )
+    (
+      "storage-path",
+      po::value<std::string>(&config.StoragePath)->default_value(""),
+      R"(Storage path, for example "/home/foo/vereign", if empty it will use a default location. )"
+      R"(Under linux this default is `$HOME/vereign`, and under windows it is )"
+      R"(`C:\Users\<user>\AppData\Local\vereign`.)"
+    )
+  ;
+
+  po::variables_map vm;
+  try {
+    po::store(po::parse_command_line(argc, argv, desc), vm);
+  } catch (std::exception& e) {
+    std::cout << e.what() << "\n";
+    std::exit(1);
+  }
+
+  po::notify(vm);
+
+  if (vm.count("help") > 0) {
+    std::cout << "Vereign Client Library Service"
+      << R"(
+
+Vereign Client Library Service is a CLI tool that is a tiny wrapper around the vereign library.
+
+It exists for testing purposes. One can run the `vereign-service` and then use the gRPC
+API to communicate with the vereign library the way a real integrator would do.
+
+Usage:
+)"
+      << "  " << name << " [options]\n\n"
+      << desc << "\n";
+
+    return "help";
+  }
+
+  return "start";
+}
diff --git a/cpp/src/csandbox.cc b/cpp/src/csandbox.cc
index 5cbbd22..7b4830c 100644
--- a/cpp/src/csandbox.cc
+++ b/cpp/src/csandbox.cc
@@ -27,31 +27,4 @@ auto main(int argc, char** argv) -> int {
   argc = 0;
   argv = nullptr;
 
-  int64_t iterations = int64_t(1000)*1000*1000*10;
-
-  using clock = std::chrono::high_resolution_clock;
-  auto q = vereign::container::BoundedQueue<int>(10);
-
-  auto start = clock::now();
-  int64_t s = 0;
-
-  for (int64_t i = 0; i < iterations; i++) {
-    if (q.IsFull()) {
-      q.PopFront();
-    }
-
-    q.PushBack(i);
-  }
-
-  auto end = clock::now() - start;
-
-  std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end).count() << std::endl;
-  std::cout << std::chrono::duration_cast<std::chrono::nanoseconds>(end).count()/iterations << std::endl;
-
-  while (!q.IsEmpty()) {
-    s += q.Front();
-    q.PopFront();
-  }
-
-  std::cout << s << std::endl;
 }
diff --git a/cpp/vendor/boost.cmake b/cpp/vendor/boost.cmake
index 4d49081..477c579 100644
--- a/cpp/vendor/boost.cmake
+++ b/cpp/vendor/boost.cmake
@@ -1,6 +1,6 @@
 include(ExternalProject)
 
-set(_boost_libs regex system thread date_time filesystem)
+set(_boost_libs regex system thread date_time filesystem program_options)
 
 if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
   list(TRANSFORM _boost_libs PREPEND --with-)
-- 
GitLab