Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Refactor main #1555

Merged
merged 22 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
.DS_Store
CMakeUserPresets.json
config.json
src/main/impl/Build.cpp
src/util/build/Build.cpp
7 changes: 4 additions & 3 deletions cmake/Build.cpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@
*/
//==============================================================================

#include "main/Build.hpp"
#include "util/build/Build.hpp"

#include <string>

namespace Build {
namespace util::build {

static constexpr char versionString[] = "@CLIO_VERSION@";

std::string const&
Expand All @@ -38,4 +39,4 @@ getClioFullVersionString()
return value;
}

} // namespace Build
} // namespace util::build
2 changes: 1 addition & 1 deletion cmake/ClioVersion.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ endif ()

message(STATUS "Build version: ${CLIO_VERSION}")

configure_file(${CMAKE_CURRENT_LIST_DIR}/Build.cpp.in ${CMAKE_CURRENT_LIST_DIR}/../src/main/impl/Build.cpp)
configure_file(${CMAKE_CURRENT_LIST_DIR}/Build.cpp.in ${CMAKE_CURRENT_LIST_DIR}/../src/util/build/Build.cpp)
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ add_subdirectory(etl)
add_subdirectory(feed)
add_subdirectory(rpc)
add_subdirectory(web)
add_subdirectory(app)
add_subdirectory(main)
6 changes: 6 additions & 0 deletions src/app/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
add_library(clio_app)
target_sources(clio_app PRIVATE CliArgs.cpp ClioApplication.cpp)

target_link_libraries(clio_app PUBLIC clio_etl clio_feed clio_web clio_rpc)

# target_compile_features(clio_app PUBLIC cxx_std_23)
kuznetsss marked this conversation as resolved.
Show resolved Hide resolved
70 changes: 70 additions & 0 deletions src/app/CliArgs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2024, the clio developers.

Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================

#include "app/CliArgs.hpp"

#include "util/build/Build.hpp"

#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/positional_options.hpp>
#include <boost/program_options/value_semantic.hpp>
#include <boost/program_options/variables_map.hpp>

#include <cstdlib>
#include <iostream>
#include <string>
#include <utility>

namespace app {

CliArgs::Action
CliArgs::parse(int argc, char const* argv[])
{
namespace po = boost::program_options;
// clang-format off
po::options_description description("Options");
description.add_options()
("help,h", "print help message and exit")
("version,v", "print version and exit")
("conf,c", po::value<std::string>()->default_value(defaultConfigPath), "configuration file")
;
// clang-format on
po::positional_options_description positional;
positional.add("conf", 1);

po::variables_map parsed;
po::store(po::command_line_parser(argc, argv).options(description).positional(positional).run(), parsed);
po::notify(parsed);

if (parsed.count("help") != 0u) {
std::cout << "Clio server " << util::build::getClioFullVersionString() << "\n\n" << description;
kuznetsss marked this conversation as resolved.
Show resolved Hide resolved
return Action{Action::Exit{EXIT_SUCCESS}};
}

if (parsed.count("version") != 0u) {
std::cout << util::build::getClioFullVersionString() << '\n';
return Action{Action::Exit{EXIT_SUCCESS}};
}

auto configPath = parsed["conf"].as<std::string>();
return Action{Action::Run{std::move(configPath)}};
}

} // namespace app
96 changes: 96 additions & 0 deletions src/app/CliArgs.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2024, the clio developers.

Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================

#pragma once

#include "util/OverloadSet.hpp"

#include <string>
#include <variant>

namespace app {

/**
* @brief Parsed command line arguments representation.
*/
class CliArgs {
public:
/**
* @brief Default configuration path.
*/
static constexpr char defaultConfigPath[] = "/etc/opt/clio/config.json";

/**
* @brief An action parsed from the command line.
*/
class Action {
public:
/** @brief Run action. */
struct Run {
/** @brief Configuration file path. */
std::string configPath;
};

/** @brief Exit action. */
struct Exit {
/** @brief Exit code. */
int exitCode;
};

/**
* @brief Construct an action from a Run.
*
* @param action Run action.
*/
template <typename ActionType>
requires std::is_same_v<ActionType, Run> or std::is_same_v<ActionType, Exit>
explicit Action(ActionType&& action) : action_(std::forward<ActionType>(action))
{
}

/**
* @brief Apply a function to the action.
*
* @tparam Processors Action processors types. Must be callable with the action type and return int.
* @param processors Action processors.
* @return Exit code.
*/
template <typename... Processors>
int
apply(Processors&&... processors) const
{
return std::visit(util::OverloadSet{std::forward<Processors>(processors)...}, action_);
}

private:
std::variant<Run, Exit> action_;
};

/**
* @brief Parse command line arguments.
*
* @param argc Number of arguments.
* @param argv Array of arguments.
* @return Parsed command line arguments.
*/
static Action
parse(int argc, char const* argv[]);
};

} // namespace app
142 changes: 142 additions & 0 deletions src/app/ClioApplication.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2024, the clio developers.

Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================

#include "app/ClioApplication.hpp"

#include "data/AmendmentCenter.hpp"
#include "data/BackendFactory.hpp"
#include "etl/ETLService.hpp"
#include "etl/LoadBalancer.hpp"
#include "etl/NetworkValidatedLedgers.hpp"
#include "feed/SubscriptionManager.hpp"
#include "rpc/Counters.hpp"
#include "rpc/RPCEngine.hpp"
#include "rpc/WorkQueue.hpp"
#include "rpc/common/impl/HandlerProvider.hpp"
#include "util/build/Build.hpp"
#include "util/config/Config.hpp"
#include "util/log/Logger.hpp"
#include "util/prometheus/Prometheus.hpp"
#include "web/DOSGuard.hpp"
#include "web/IntervalSweepHandler.hpp"
#include "web/RPCServerHandler.hpp"
#include "web/Server.hpp"
#include "web/WhitelistHandler.hpp"

#include <boost/asio/io_context.hpp>

#include <cstdint>
#include <cstdlib>
#include <memory>
#include <thread>
#include <vector>

namespace app {

namespace {

/**
* @brief Start context threads
*
* @param ioc Context
* @param numThreads Number of worker threads to start
*/
void
start(boost::asio::io_context& ioc, std::uint32_t numThreads)

Check warning on line 61 in src/app/ClioApplication.cpp

View check run for this annotation

Codecov / codecov/patch

src/app/ClioApplication.cpp#L61

Added line #L61 was not covered by tests
{
std::vector<std::thread> v;

Check warning on line 63 in src/app/ClioApplication.cpp

View check run for this annotation

Codecov / codecov/patch

src/app/ClioApplication.cpp#L63

Added line #L63 was not covered by tests
v.reserve(numThreads - 1);
for (auto i = numThreads - 1; i > 0; --i)
v.emplace_back([&ioc] { ioc.run(); });

ioc.run();
for (auto& t : v)
t.join();
}

} // namespace

ClioApplication::ClioApplication(util::Config const& config) : config_(config), signalsHandler_{config_}
{
LOG(util::LogService::info()) << "Clio version: " << util::build::getClioFullVersionString();
PrometheusService::init(config);
}

int
ClioApplication::run()

Check warning on line 82 in src/app/ClioApplication.cpp

View check run for this annotation

Codecov / codecov/patch

src/app/ClioApplication.cpp#L82

Added line #L82 was not covered by tests
{
auto const threads = config_.valueOr("io_threads", 2);
if (threads <= 0) {
LOG(util::LogService::fatal()) << "io_threads is less than 1";
return EXIT_FAILURE;

Check warning on line 87 in src/app/ClioApplication.cpp

View check run for this annotation

Codecov / codecov/patch

src/app/ClioApplication.cpp#L87

Added line #L87 was not covered by tests
}
LOG(util::LogService::info()) << "Number of io threads = " << threads;

// IO context to handle all incoming requests, as well as other things.
// This is not the only io context in the application.
boost::asio::io_context ioc{threads};

// Rate limiter, to prevent abuse
auto sweepHandler = web::IntervalSweepHandler{config_, ioc};
auto whitelistHandler = web::WhitelistHandler{config_};
auto dosGuard = web::DOSGuard{config_, whitelistHandler, sweepHandler};

// Interface to the database
auto backend = data::make_Backend(config_);

// Manages clients subscribed to streams
auto subscriptionsRunner = feed::SubscriptionManagerRunner(config_, backend);

auto const subscriptions = subscriptionsRunner.getManager();

Check warning on line 106 in src/app/ClioApplication.cpp

View check run for this annotation

Codecov / codecov/patch

src/app/ClioApplication.cpp#L106

Added line #L106 was not covered by tests

// Tracks which ledgers have been validated by the network
auto ledgers = etl::NetworkValidatedLedgers::make_ValidatedLedgers();

// Handles the connection to one or more rippled nodes.
// ETL uses the balancer to extract data.
// The server uses the balancer to forward RPCs to a rippled node.
// The balancer itself publishes to streams (transactions_proposed and accounts_proposed)
auto balancer = etl::LoadBalancer::make_LoadBalancer(config_, ioc, backend, subscriptions, ledgers);

// ETL is responsible for writing and publishing to streams. In read-only mode, ETL only publishes
auto etl = etl::ETLService::make_ETLService(config_, ioc, backend, subscriptions, balancer, ledgers);

auto workQueue = rpc::WorkQueue::make_WorkQueue(config_);
auto counters = rpc::Counters::make_Counters(workQueue);
auto const amendmentCenter = std::make_shared<data::AmendmentCenter const>(backend);
auto const handlerProvider = std::make_shared<rpc::impl::ProductionHandlerProvider const>(
config_, backend, subscriptions, balancer, etl, amendmentCenter, counters
);
auto const rpcEngine =
rpc::RPCEngine::make_RPCEngine(backend, balancer, dosGuard, workQueue, counters, handlerProvider);

// Init the web server
auto handler =
std::make_shared<web::RPCServerHandler<rpc::RPCEngine, etl::ETLService>>(config_, backend, rpcEngine, etl);
auto const httpServer = web::make_HttpServer(config_, ioc, dosGuard, handler);

// Blocks until stopped.
// When stopped, shared_ptrs fall out of scope
// Calls destructors on all resources, and destructs in order
start(ioc, threads);

return EXIT_SUCCESS;

Check warning on line 139 in src/app/ClioApplication.cpp

View check run for this annotation

Codecov / codecov/patch

src/app/ClioApplication.cpp#L139

Added line #L139 was not covered by tests
}

} // namespace app
Loading
Loading