From 5fedbe205c6e00b67a4a31d26af0374b2367b859 Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Wed, 10 May 2023 10:36:16 +0200 Subject: [PATCH 01/17] scord-ctl: Put RPC handlers in correct namespace --- src/scord-ctl/rpc_handlers.cpp | 4 ++-- src/scord-ctl/rpc_handlers.hpp | 4 ++-- src/scord-ctl/scord-ctl.cpp | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/scord-ctl/rpc_handlers.cpp b/src/scord-ctl/rpc_handlers.cpp index c021a466..3db4be92 100644 --- a/src/scord-ctl/rpc_handlers.cpp +++ b/src/scord-ctl/rpc_handlers.cpp @@ -34,7 +34,7 @@ struct remote_procedure { } }; -namespace scord::network::handlers { +namespace scord_ctl::network::handlers { void ping(const scord::network::request& req) { @@ -59,4 +59,4 @@ ping(const scord::network::request& req) { req.respond(resp); } -} // namespace scord::network::handlers +} // namespace scord_ctl::network::handlers diff --git a/src/scord-ctl/rpc_handlers.hpp b/src/scord-ctl/rpc_handlers.hpp index a896d794..085ec9ca 100644 --- a/src/scord-ctl/rpc_handlers.hpp +++ b/src/scord-ctl/rpc_handlers.hpp @@ -29,11 +29,11 @@ #include #include -namespace scord::network::handlers { +namespace scord_ctl::network::handlers { void ping(const scord::network::request& req); -} // namespace scord::network::handlers +} // namespace scord_ctl::network::handlers #endif // SCORD_CTL_RPC_HANDLERS_HPP diff --git a/src/scord-ctl/scord-ctl.cpp b/src/scord-ctl/scord-ctl.cpp index ab2d1e0f..17a03ab2 100644 --- a/src/scord-ctl/scord-ctl.cpp +++ b/src/scord-ctl/scord-ctl.cpp @@ -85,7 +85,8 @@ main(int argc, char* argv[]) { // convenience macro to ensure the names of an RPC and its handler // always match -#define EXPAND(rpc_name) "ADM_" #rpc_name##s, scord::network::handlers::rpc_name +#define EXPAND(rpc_name) \ + "ADM_" #rpc_name##s, scord_ctl::network::handlers::rpc_name srv.set_handler(EXPAND(ping)); -- GitLab From c0807ec10760e1beec782f707132b871f0eab29f Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Thu, 11 May 2023 08:02:39 +0200 Subject: [PATCH 02/17] examples: Fix error processing --- examples/c/ADM_register_job.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/c/ADM_register_job.c b/examples/c/ADM_register_job.c index 36bc1dbb..ebab9efc 100644 --- a/examples/c/ADM_register_job.c +++ b/examples/c/ADM_register_job.c @@ -102,9 +102,9 @@ main(int argc, char* argv[]) { } // 2. Register the adhoc storage - if(ADM_register_adhoc_storage(server, adhoc_name, ADM_ADHOC_STORAGE_GEKKOFS, - adhoc_ctx, adhoc_resources, - &adhoc_storage) != ADM_SUCCESS) { + if((ret = ADM_register_adhoc_storage( + server, adhoc_name, ADM_ADHOC_STORAGE_GEKKOFS, adhoc_ctx, + adhoc_resources, &adhoc_storage)) != ADM_SUCCESS) { fprintf(stderr, "ADM_register_adhoc_storage() failed: %s\n", ADM_strerror(ret)); goto cleanup; @@ -154,8 +154,8 @@ main(int argc, char* argv[]) { // All the information required by the ADM_register_job() API is now ready. // Let's actually contact the server: - if(ADM_register_job(server, job_resources, reqs, slurm_job_id, &job) != - ADM_SUCCESS) { + if((ret = ADM_register_job(server, job_resources, reqs, slurm_job_id, + &job)) != ADM_SUCCESS) { fprintf(stderr, "ADM_register_job() failed: %s\n", ADM_strerror(ret)); goto cleanup; } -- GitLab From 6997821b124026f59fcd6e9521d8be5b2e6a1308 Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Thu, 11 May 2023 08:58:39 +0200 Subject: [PATCH 03/17] scord: Refactor internal types --- src/common/abt_cxx/shared_mutex.hpp | 1 + src/scord/CMakeLists.txt | 3 +- src/scord/internal_types.cpp | 107 ++++++++++++++++++++++++++++ src/scord/internal_types.hpp | 68 +++++------------- 4 files changed, 126 insertions(+), 53 deletions(-) create mode 100644 src/scord/internal_types.cpp diff --git a/src/common/abt_cxx/shared_mutex.hpp b/src/common/abt_cxx/shared_mutex.hpp index 402cfed1..a3d924e9 100644 --- a/src/common/abt_cxx/shared_mutex.hpp +++ b/src/common/abt_cxx/shared_mutex.hpp @@ -23,6 +23,7 @@ *****************************************************************************/ #include +#include #include #include diff --git a/src/scord/CMakeLists.txt b/src/scord/CMakeLists.txt index b79e3fba..5221d3b7 100644 --- a/src/scord/CMakeLists.txt +++ b/src/scord/CMakeLists.txt @@ -27,7 +27,8 @@ add_executable(scord) target_sources(scord PRIVATE scord.cpp rpc_handlers.hpp rpc_handlers.cpp job_manager.hpp adhoc_storage_manager.hpp - pfs_storage_manager.hpp ${CMAKE_CURRENT_BINARY_DIR}/defaults.hpp) + pfs_storage_manager.hpp ${CMAKE_CURRENT_BINARY_DIR}/defaults.hpp + internal_types.hpp internal_types.cpp) configure_file(defaults.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/defaults.hpp @ONLY) diff --git a/src/scord/internal_types.cpp b/src/scord/internal_types.cpp new file mode 100644 index 00000000..0e0f54cc --- /dev/null +++ b/src/scord/internal_types.cpp @@ -0,0 +1,107 @@ +/****************************************************************************** + * Copyright 2021-2023, Barcelona Supercomputing Center (BSC), Spain + * + * This software was partially supported by the EuroHPC-funded project ADMIRE + * (Project ID: 956748, https://www.admire-eurohpc.eu). + * + * This file is part of scord. + * + * scord is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * scord is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with scord. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + *****************************************************************************/ + +#include +#include +#include "internal_types.hpp" + + +namespace scord::internal { + +job_info::job_info(scord::job job, scord::job::resources resources, + scord::job::requirements requirements) + : m_job(std::move(job)), m_resources(std::move(resources)), + m_requirements(std::move(requirements)) {} + +scord::job +job_info::job() const { + return m_job; +} + +std::optional +job_info::resources() const { + return m_resources; +} + +void +job_info::update(scord::job::resources resources) { + m_resources = std::move(resources); +} + +adhoc_storage_info::adhoc_storage_info(scord::adhoc_storage adhoc_storage) + : m_adhoc_storage(std::move(adhoc_storage)) {} + +scord::adhoc_storage +adhoc_storage_info::adhoc_storage() const { + return m_adhoc_storage; +} + +void +adhoc_storage_info::update(scord::adhoc_storage::resources new_resources) { + m_adhoc_storage.update(std::move(new_resources)); +} + +scord::error_code +adhoc_storage_info::add_client_info( + std::shared_ptr job_info) { + + scord::abt::unique_lock lock(m_info_mutex); + + if(m_client_info) { + LOGGER_ERROR("adhoc storage {} already has a client", + m_adhoc_storage.id()); + return error_code::adhoc_in_use; + } + + m_client_info = std::move(job_info); + + return error_code::success; +} + +void +adhoc_storage_info::remove_client_info() { + scord::abt::unique_lock lock(m_info_mutex); + m_client_info.reset(); +} + +std::shared_ptr +adhoc_storage_info::client_info() const { + scord::abt::shared_lock lock(m_info_mutex); + return m_client_info; +} + +pfs_storage_info::pfs_storage_info(scord::pfs_storage pfs_storage) + : m_pfs_storage(std::move(pfs_storage)) {} + +scord::pfs_storage +pfs_storage_info::pfs_storage() const { + return m_pfs_storage; +} + +void +pfs_storage_info::update(scord::pfs_storage::ctx pfs_context) { + m_pfs_storage.update(std::move(pfs_context)); +} + +} // namespace scord::internal diff --git a/src/scord/internal_types.hpp b/src/scord/internal_types.hpp index 72d34e4d..f6b3948f 100644 --- a/src/scord/internal_types.hpp +++ b/src/scord/internal_types.hpp @@ -26,27 +26,22 @@ #ifndef SCORD_INTERNAL_TYPES_HPP #define SCORD_INTERNAL_TYPES_HPP -#include +#include +#include +#include namespace scord::internal { struct job_info { - explicit job_info(scord::job job) : m_job(std::move(job)) {} job_info(scord::job job, scord::job::resources resources, - scord::job::requirements requirements) - : m_job(std::move(job)), m_resources(std::move(resources)), - m_requirements(std::move(requirements)) {} + scord::job::requirements requirements); scord::job - job() const { - return m_job; - } + job() const; std::optional - resources() const { - return m_resources; - } + resources() const; std::optional requirements() const { @@ -54,9 +49,7 @@ struct job_info { } void - update(scord::job::resources resources) { - m_resources = std::move(resources); - } + update(scord::job::resources resources); scord::job m_job; std::optional m_resources; @@ -65,46 +58,22 @@ struct job_info { struct adhoc_storage_info { - explicit adhoc_storage_info(scord::adhoc_storage adhoc_storage) - : m_adhoc_storage(std::move(adhoc_storage)) {} + explicit adhoc_storage_info(scord::adhoc_storage adhoc_storage); scord::adhoc_storage - adhoc_storage() const { - return m_adhoc_storage; - } + adhoc_storage() const; void - update(scord::adhoc_storage::resources new_resources) { - m_adhoc_storage.update(std::move(new_resources)); - } + update(scord::adhoc_storage::resources new_resources); scord::error_code - add_client_info(std::shared_ptr job_info) { - - scord::abt::unique_lock lock(m_info_mutex); - - if(m_client_info) { - LOGGER_ERROR("adhoc storage {} already has a client", - m_adhoc_storage.id()); - return error_code::adhoc_in_use; - } - - m_client_info = std::move(job_info); - - return error_code::success; - } + add_client_info(std::shared_ptr job_info); void - remove_client_info() { - scord::abt::unique_lock lock(m_info_mutex); - m_client_info.reset(); - } + remove_client_info(); std::shared_ptr - client_info() const { - scord::abt::shared_lock lock(m_info_mutex); - return m_client_info; - } + client_info() const; scord::adhoc_storage m_adhoc_storage; std::shared_ptr m_client_info; @@ -113,18 +82,13 @@ struct adhoc_storage_info { struct pfs_storage_info { - explicit pfs_storage_info(scord::pfs_storage pfs_storage) - : m_pfs_storage(std::move(pfs_storage)) {} + explicit pfs_storage_info(scord::pfs_storage pfs_storage); scord::pfs_storage - pfs_storage() const { - return m_pfs_storage; - } + pfs_storage() const; void - update(scord::pfs_storage::ctx pfs_context) { - m_pfs_storage.update(std::move(pfs_context)); - } + update(scord::pfs_storage::ctx pfs_context); scord::pfs_storage m_pfs_storage; std::shared_ptr m_client_info; -- GitLab From 27b91b5fe85a933dd8e7c6fc35b35a6db703316c Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Thu, 11 May 2023 08:09:44 +0200 Subject: [PATCH 04/17] API: Propagate node type between C and C++ APIs Fixes #128 --- src/lib/types.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/types.cpp b/src/lib/types.cpp index 779c1ab8..c725a758 100644 --- a/src/lib/types.cpp +++ b/src/lib/types.cpp @@ -287,7 +287,9 @@ job::resources::resources(ADM_job_resources_t res) { m_nodes.reserve(res->r_nodes->l_length); for(size_t i = 0; i < res->r_nodes->l_length; ++i) { - m_nodes.emplace_back(res->r_nodes->l_nodes[i].n_hostname); + m_nodes.emplace_back(res->r_nodes->l_nodes[i].n_hostname, + static_cast( + res->r_nodes->l_nodes[i].n_type)); } } -- GitLab From d92fbfdd7fb7d867bb7957ea60b80e3dc692a519 Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Thu, 11 May 2023 08:30:41 +0200 Subject: [PATCH 05/17] Fix formatting --- src/lib/scord/types.hpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/lib/scord/types.hpp b/src/lib/scord/types.hpp index 3f0c45e7..923a386a 100644 --- a/src/lib/scord/types.hpp +++ b/src/lib/scord/types.hpp @@ -96,7 +96,7 @@ struct error_code { template void serialize(Archive&& ar) { - ar& m_value; + ar & m_value; } private: @@ -212,7 +212,7 @@ struct adhoc_storage { template void serialize(Archive&& ar) { - ar& m_nodes; + ar & m_nodes; } private: @@ -243,10 +243,10 @@ struct adhoc_storage { template void serialize(Archive&& ar) { - ar& m_exec_mode; - ar& m_access_type; - ar& m_walltime; - ar& m_should_flush; + ar & m_exec_mode; + ar & m_access_type; + ar & m_walltime; + ar & m_should_flush; } private: @@ -326,7 +326,7 @@ struct pfs_storage { template void serialize(Archive&& ar) { - ar& m_mount_point; + ar & m_mount_point; } private: @@ -388,7 +388,7 @@ struct job { template void serialize(Archive&& ar) { - ar& m_nodes; + ar & m_nodes; } private: @@ -417,9 +417,9 @@ struct job { template void serialize(Archive& ar) { - ar& m_inputs; - ar& m_outputs; - ar& m_adhoc_storage; + ar & m_inputs; + ar & m_outputs; + ar & m_adhoc_storage; } private: -- GitLab From 68cf2ee4d8fa9914660ef061577de1ed4d23b9c9 Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Thu, 11 May 2023 08:31:11 +0200 Subject: [PATCH 06/17] scord-ctl: Add handler for deploy_adhoc_storage RPC --- src/scord-ctl/rpc_handlers.cpp | 24 ++++++++++++++++++++++++ src/scord-ctl/rpc_handlers.hpp | 3 +++ 2 files changed, 27 insertions(+) diff --git a/src/scord-ctl/rpc_handlers.cpp b/src/scord-ctl/rpc_handlers.cpp index 3db4be92..65df94ad 100644 --- a/src/scord-ctl/rpc_handlers.cpp +++ b/src/scord-ctl/rpc_handlers.cpp @@ -24,6 +24,7 @@ #include #include +#include #include "rpc_handlers.hpp" struct remote_procedure { @@ -59,4 +60,27 @@ ping(const scord::network::request& req) { req.respond(resp); } +void +deploy_adhoc_storage(const scord::network::request& req) { + + using scord::network::generic_response; + using scord::network::get_address; + + const auto rpc_id = remote_procedure::new_id(); + + LOGGER_INFO("rpc id: {} name: {} from: {} => " + "body: {{}}", + rpc_id, std::quoted(__FUNCTION__), + std::quoted(get_address(req))); + + const auto resp = generic_response{rpc_id, scord::error_code::success}; + + LOGGER_INFO("rpc id: {} name: {} to: {} <= " + "body: {{retval: {}}}", + rpc_id, std::quoted(__FUNCTION__), + std::quoted(get_address(req)), scord::error_code::success); + + req.respond(resp); +} + } // namespace scord_ctl::network::handlers diff --git a/src/scord-ctl/rpc_handlers.hpp b/src/scord-ctl/rpc_handlers.hpp index 085ec9ca..e8f45ca0 100644 --- a/src/scord-ctl/rpc_handlers.hpp +++ b/src/scord-ctl/rpc_handlers.hpp @@ -34,6 +34,9 @@ namespace scord_ctl::network::handlers { void ping(const scord::network::request& req); +void +deploy_adhoc_storage(const scord::network::request& req); + } // namespace scord_ctl::network::handlers #endif // SCORD_CTL_RPC_HANDLERS_HPP -- GitLab From 63f3de48df5350ad55abe1161425f7f4412ffe83 Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Thu, 11 May 2023 08:36:28 +0200 Subject: [PATCH 07/17] Minor fix to error path in `register_job` RPC handler --- src/scord/rpc_handlers.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/scord/rpc_handlers.cpp b/src/scord/rpc_handlers.cpp index 329f4c71..3f2fca05 100644 --- a/src/scord/rpc_handlers.cpp +++ b/src/scord/rpc_handlers.cpp @@ -101,6 +101,10 @@ register_job(const scord::network::request& req, const auto adhoc_id = job_requirements.adhoc_storage()->id(); auto& adhoc_manager = scord::adhoc_storage_manager::instance(); ec = adhoc_manager.add_client_info(adhoc_id, job_info); + + if(!ec) { + goto respond; + } } job_id = job_info->job().id(); @@ -110,6 +114,7 @@ register_job(const scord::network::request& req, ec = jm_result.error(); } +respond: const auto resp = response_with_id{rpc_id, ec, job_id}; LOGGER_INFO("rpc id: {} name: {} to: {} <= " -- GitLab From b8858b10bd6d642cc5ebb48c288cc4eb7c0de2db Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Fri, 12 May 2023 10:06:59 +0200 Subject: [PATCH 08/17] API: Add missing `m_resources` to `adhoc_storage` serialization Fixes #129 --- src/lib/types.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/types.cpp b/src/lib/types.cpp index c725a758..b1798c1f 100644 --- a/src/lib/types.cpp +++ b/src/lib/types.cpp @@ -658,6 +658,7 @@ public: ar(SCORD_SERIALIZATION_NVP(m_name)); ar(SCORD_SERIALIZATION_NVP(m_id)); ar(SCORD_SERIALIZATION_NVP(m_ctx)); + ar(SCORD_SERIALIZATION_NVP(m_resources)); } template @@ -667,6 +668,7 @@ public: ar(SCORD_SERIALIZATION_NVP(m_name)); ar(SCORD_SERIALIZATION_NVP(m_id)); ar(SCORD_SERIALIZATION_NVP(m_ctx)); + ar(SCORD_SERIALIZATION_NVP(m_resources)); } -- GitLab From a9d4eb8f4539027a8d41604af19bb94667b65d68 Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Fri, 12 May 2023 10:17:34 +0200 Subject: [PATCH 09/17] Remove unused code --- src/lib/scord/types.hpp | 6 ------ src/lib/types.cpp | 10 ---------- 2 files changed, 16 deletions(-) diff --git a/src/lib/scord/types.hpp b/src/lib/scord/types.hpp index 923a386a..99c0802a 100644 --- a/src/lib/scord/types.hpp +++ b/src/lib/scord/types.hpp @@ -233,8 +233,6 @@ struct adhoc_storage { exec_mode() const; enum access_type access_type() const; - adhoc_storage::resources - resources() const; std::uint32_t walltime() const; bool @@ -257,10 +255,6 @@ struct adhoc_storage { }; adhoc_storage(); - adhoc_storage(enum adhoc_storage::type type, std::string name, - std::uint64_t id, execution_mode exec_mode, - access_type access_type, adhoc_storage::resources res, - std::uint32_t walltime, bool should_flush); explicit adhoc_storage(ADM_adhoc_storage_t storage); explicit operator ADM_adhoc_storage_t() const; adhoc_storage(enum adhoc_storage::type type, std::string name, diff --git a/src/lib/types.cpp b/src/lib/types.cpp index b1798c1f..f0e33ef3 100644 --- a/src/lib/types.cpp +++ b/src/lib/types.cpp @@ -682,16 +682,6 @@ private: adhoc_storage::adhoc_storage() = default; -adhoc_storage::adhoc_storage(enum adhoc_storage::type type, std::string name, - std::uint64_t id, execution_mode exec_mode, - access_type access_type, - struct adhoc_storage::resources res, - std::uint32_t walltime, bool should_flush) - : m_pimpl(std::make_unique(type, std::move(name), id, - adhoc_storage::ctx{exec_mode, access_type, - walltime, should_flush}, - std::move(res))) {} - adhoc_storage::adhoc_storage(ADM_adhoc_storage_t st) : m_pimpl(std::make_unique( static_cast(st->s_type), st->s_name, -- GitLab From b4e9cbde29550a77fa5acfe52fc866ece0696f3a Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Fri, 12 May 2023 16:53:01 +0200 Subject: [PATCH 10/17] WIP: Add control node address to ADM_adhoc_context_t Update tests to start scord-ctl as needed --- examples/CMakeLists.txt | 24 +++++++++ examples/c/ADM_cancel_transfer.c | 16 ++++-- examples/c/ADM_connect_data_operation.c | 16 ++++-- examples/c/ADM_define_data_operation.c | 16 ++++-- examples/c/ADM_deploy_adhoc_storage.c | 19 ++++--- examples/c/ADM_finalize_data_operation.c | 17 +++--- examples/c/ADM_get_pending_transfers.c | 16 ++++-- examples/c/ADM_get_qos_constraints.c | 16 ++++-- examples/c/ADM_get_statistics.c | 16 ++++-- examples/c/ADM_get_transfer_priority.c | 16 ++++-- .../c/ADM_link_transfer_to_data_operation.c | 17 +++--- examples/c/ADM_ping.c | 14 +++-- examples/c/ADM_register_adhoc_storage.c | 16 ++++-- examples/c/ADM_register_job.c | 16 ++++-- examples/c/ADM_register_pfs_storage.c | 14 +++-- examples/c/ADM_remove_adhoc_storage.c | 16 ++++-- examples/c/ADM_remove_job.c | 16 ++++-- examples/c/ADM_remove_pfs_storage.c | 18 +++++-- examples/c/ADM_set_dataset_information.c | 17 +++--- examples/c/ADM_set_io_resources.c | 16 ++++-- examples/c/ADM_set_qos_constraints.c | 16 ++++-- examples/c/ADM_set_transfer_priority.c | 16 ++++-- examples/c/ADM_tear_down_adhoc_storage.c | 19 ++++--- examples/c/ADM_transfer_datasets.c | 16 ++++-- examples/c/ADM_update_adhoc_storage.c | 19 ++++--- examples/c/ADM_update_job.c | 16 ++++-- examples/c/ADM_update_pfs_storage.c | 14 +++-- examples/c/CMakeLists.txt | 47 ++++++++++++++--- examples/c/common.c | 29 +++++++++++ examples/c/common.h | 18 +++++++ examples/cxx/ADM_cancel_transfer.cpp | 16 +++--- examples/cxx/ADM_connect_data_operation.cpp | 16 +++--- examples/cxx/ADM_define_data_operation.cpp | 17 +++--- examples/cxx/ADM_deploy_adhoc_storage.cpp | 16 +++--- examples/cxx/ADM_finalize_data_operation.cpp | 16 +++--- examples/cxx/ADM_get_pending_transfers.cpp | 17 +++--- examples/cxx/ADM_get_qos_constraints.cpp | 16 +++--- examples/cxx/ADM_get_statistics.cpp | 15 +++--- examples/cxx/ADM_get_transfer_priority.cpp | 17 +++--- examples/cxx/ADM_in_situ_ops.cpp | 18 ++++--- examples/cxx/ADM_in_transit_ops.cpp | 18 ++++--- .../ADM_link_transfer_to_data_operation.cpp | 17 +++--- examples/cxx/ADM_ping.cpp | 15 +++--- examples/cxx/ADM_register_adhoc_storage.cpp | 16 +++--- examples/cxx/ADM_register_job.cpp | 15 +++--- examples/cxx/ADM_register_pfs_storage.cpp | 16 +++--- examples/cxx/ADM_remove_adhoc_storage.cpp | 16 +++--- examples/cxx/ADM_remove_job.cpp | 15 +++--- examples/cxx/ADM_remove_pfs_storage.cpp | 15 +++--- examples/cxx/ADM_set_dataset_information.cpp | 16 +++--- examples/cxx/ADM_set_io_resources.cpp | 15 +++--- examples/cxx/ADM_set_qos_constraints.cpp | 16 +++--- examples/cxx/ADM_set_transfer_priority.cpp | 16 +++--- examples/cxx/ADM_tear_down_adhoc_storage.cpp | 16 +++--- examples/cxx/ADM_transfer_datasets.cpp | 15 +++--- examples/cxx/ADM_update_adhoc_storage.cpp | 16 +++--- examples/cxx/ADM_update_job.cpp | 15 +++--- examples/cxx/ADM_update_pfs_storage.cpp | 15 +++--- examples/cxx/CMakeLists.txt | 52 ++++++++++++++----- examples/cxx/common.cpp | 28 ++++++++++ examples/cxx/common.hpp | 18 +++++++ src/lib/scord/types.h | 5 +- src/lib/scord/types.hpp | 17 +++--- src/lib/types.c | 13 ++++- src/lib/types.cpp | 15 ++++-- src/lib/types_private.h | 2 + 66 files changed, 782 insertions(+), 357 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 0de1b557..ff2512de 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -33,6 +33,9 @@ if(SCORD_BUILD_TESTS) set(TEST_ENV) list(APPEND TEST_ENV SCORD_LOG_OUTPUT=${TEST_DIRECTORY}/scord_daemon.log) + set(SCORD_ADDRESS_STRING + ${SCORD_TRANSPORT_PROTOCOL}://${SCORD_BIND_ADDRESS}:${SCORD_BIND_PORT}) + add_test(start_scord_daemon ${CMAKE_SOURCE_DIR}/scripts/runner.sh start scord.pid ${CMAKE_BINARY_DIR}/src/scord/scord -f @@ -48,6 +51,27 @@ if(SCORD_BUILD_TESTS) set_tests_properties(stop_scord_daemon PROPERTIES FIXTURES_CLEANUP scord_daemon) + + set(SCORD_CTL_TRANSPORT_PROTOCOL ${SCORD_TRANSPORT_PROTOCOL}) + set(SCORD_CTL_BIND_ADDRESS ${SCORD_BIND_ADDRESS}) + math(EXPR SCORD_CTL_BIND_PORT "${SCORD_BIND_PORT} + 1") + set(SCORD_CTL_ADDRESS_STRING + ${SCORD_CTL_TRANSPORT_PROTOCOL}://${SCORD_CTL_BIND_ADDRESS}:${SCORD_CTL_BIND_PORT}) + + add_test(start_scord_ctl + ${CMAKE_SOURCE_DIR}/scripts/runner.sh start scord-ctl.pid + ${CMAKE_BINARY_DIR}/src/scord-ctl/scord-ctl -l ${SCORD_CTL_ADDRESS_STRING} -o ${TEST_DIRECTORY}/scord_ctl.log + ) + + set_tests_properties(start_scord_ctl + PROPERTIES FIXTURES_SETUP scord_ctl) + + add_test(stop_scord_ctl + ${CMAKE_SOURCE_DIR}/scripts/runner.sh stop TERM scord-ctl.pid + ) + + set_tests_properties(stop_scord_ctl PROPERTIES FIXTURES_CLEANUP scord_ctl) + endif() add_subdirectory(c) diff --git a/examples/c/ADM_cancel_transfer.c b/examples/c/ADM_cancel_transfer.c index 8a3bc88d..77bb2a0b 100644 --- a/examples/c/ADM_cancel_transfer.c +++ b/examples/c/ADM_cancel_transfer.c @@ -36,14 +36,19 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_cancel_transfer \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + ADM_server_t server = ADM_server_create("tcp", cli_args.server_address); ADM_job_t job = NULL; ADM_node_t* job_nodes = prepare_nodes(NJOB_NODES); @@ -64,7 +69,8 @@ main(int argc, char* argv[]) { assert(adhoc_resources); ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); + cli_args.controller_address, ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, 100, false); assert(ctx); const char* name = "adhoc_storage_42"; diff --git a/examples/c/ADM_connect_data_operation.c b/examples/c/ADM_connect_data_operation.c index 10398544..8ae8f55e 100644 --- a/examples/c/ADM_connect_data_operation.c +++ b/examples/c/ADM_connect_data_operation.c @@ -36,14 +36,19 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no server address provided\n"); - fprintf(stderr, "Usage: ADM_connect_data_operation \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + ADM_server_t server = ADM_server_create("tcp", cli_args.server_address); ADM_job_t job; ADM_node_t* job_nodes = prepare_nodes(NJOB_NODES); @@ -60,7 +65,8 @@ main(int argc, char* argv[]) { assert(adhoc_resources); ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); + cli_args.controller_address, ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, 100, false); assert(ctx); const char* name = "adhoc_storage_42"; diff --git a/examples/c/ADM_define_data_operation.c b/examples/c/ADM_define_data_operation.c index 8b4fa0ca..04a151c4 100644 --- a/examples/c/ADM_define_data_operation.c +++ b/examples/c/ADM_define_data_operation.c @@ -36,15 +36,20 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_define_data_operation \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + ADM_server_t server = ADM_server_create("tcp", cli_args.server_address); ADM_job_t job = NULL; ADM_node_t* job_nodes = prepare_nodes(NJOB_NODES); @@ -65,7 +70,8 @@ main(int argc, char* argv[]) { assert(adhoc_resources); ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); + cli_args.controller_address, ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, 100, false); assert(ctx); const char* name = "adhoc_storage_42"; diff --git a/examples/c/ADM_deploy_adhoc_storage.c b/examples/c/ADM_deploy_adhoc_storage.c index 1dc7c035..4d6d91dd 100644 --- a/examples/c/ADM_deploy_adhoc_storage.c +++ b/examples/c/ADM_deploy_adhoc_storage.c @@ -34,9 +34,14 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_deploy_adhoc_storage \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } @@ -76,7 +81,8 @@ main(int argc, char* argv[]) { } // 3. the adhoc storage execution context - adhoc_ctx = ADM_adhoc_context_create(ADM_ADHOC_MODE_SEPARATE_NEW, + adhoc_ctx = ADM_adhoc_context_create(cli_args.controller_address, + ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); if(adhoc_ctx == NULL) { @@ -89,7 +95,7 @@ main(int argc, char* argv[]) { // now ready. Let's actually contact the server: // 1. Find the server endpoint - if((server = ADM_server_create("tcp", argv[1])) == NULL) { + if((server = ADM_server_create("tcp", cli_args.server_address)) == NULL) { fprintf(stderr, "Fatal error creating server\n"); goto cleanup; } @@ -108,7 +114,8 @@ main(int argc, char* argv[]) { // system, let's prepare a new execution context for the adhoc // storage system - new_adhoc_ctx = ADM_adhoc_context_create(ADM_ADHOC_MODE_SEPARATE_NEW, + new_adhoc_ctx = ADM_adhoc_context_create(cli_args.controller_address, + ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 200, false); if(new_adhoc_ctx == NULL) { diff --git a/examples/c/ADM_finalize_data_operation.c b/examples/c/ADM_finalize_data_operation.c index 9851326e..89c421ea 100644 --- a/examples/c/ADM_finalize_data_operation.c +++ b/examples/c/ADM_finalize_data_operation.c @@ -36,15 +36,19 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, - "Usage: ADM_finalize_data_operation \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + ADM_server_t server = ADM_server_create("tcp", cli_args.server_address); ADM_job_t job = NULL; ADM_node_t* job_nodes = prepare_nodes(NJOB_NODES); @@ -61,7 +65,8 @@ main(int argc, char* argv[]) { assert(adhoc_resources); ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); + cli_args.controller_address, ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, 100, false); assert(ctx); const char* name = "adhoc_storage_42"; diff --git a/examples/c/ADM_get_pending_transfers.c b/examples/c/ADM_get_pending_transfers.c index e2c109bf..6789136c 100644 --- a/examples/c/ADM_get_pending_transfers.c +++ b/examples/c/ADM_get_pending_transfers.c @@ -36,14 +36,19 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_get_pending_transfers \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + ADM_server_t server = ADM_server_create("tcp", cli_args.server_address); ADM_job_t job = NULL; ADM_node_t* job_nodes = prepare_nodes(NJOB_NODES); @@ -64,7 +69,8 @@ main(int argc, char* argv[]) { assert(adhoc_resources); ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); + cli_args.controller_address, ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, 100, false); assert(ctx); const char* name = "adhoc_storage_42"; diff --git a/examples/c/ADM_get_qos_constraints.c b/examples/c/ADM_get_qos_constraints.c index 6644c99b..be8498ee 100644 --- a/examples/c/ADM_get_qos_constraints.c +++ b/examples/c/ADM_get_qos_constraints.c @@ -36,14 +36,19 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_get_qos_constraints \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + ADM_server_t server = ADM_server_create("tcp", cli_args.server_address); ADM_job_t job = NULL; ADM_node_t* job_nodes = prepare_nodes(NJOB_NODES); @@ -60,7 +65,8 @@ main(int argc, char* argv[]) { assert(adhoc_resources); ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); + cli_args.controller_address, ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, 100, false); assert(ctx); const char* name = "adhoc_storage_42"; diff --git a/examples/c/ADM_get_statistics.c b/examples/c/ADM_get_statistics.c index 9686246b..4f0c7db5 100644 --- a/examples/c/ADM_get_statistics.c +++ b/examples/c/ADM_get_statistics.c @@ -36,14 +36,19 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_get_statistics \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + ADM_server_t server = ADM_server_create("tcp", cli_args.server_address); ADM_job_t job = NULL; ADM_node_t* job_nodes = prepare_nodes(NJOB_NODES); @@ -60,7 +65,8 @@ main(int argc, char* argv[]) { assert(adhoc_resources); ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); + cli_args.controller_address, ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, 100, false); assert(ctx); const char* name = "adhoc_storage_42"; diff --git a/examples/c/ADM_get_transfer_priority.c b/examples/c/ADM_get_transfer_priority.c index 2be2ac0f..5a5957bd 100644 --- a/examples/c/ADM_get_transfer_priority.c +++ b/examples/c/ADM_get_transfer_priority.c @@ -36,14 +36,19 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_get_transfer_priority \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + ADM_server_t server = ADM_server_create("tcp", cli_args.server_address); ADM_job_t job = NULL; ADM_node_t* job_nodes = prepare_nodes(NJOB_NODES); @@ -64,7 +69,8 @@ main(int argc, char* argv[]) { assert(adhoc_resources); ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); + cli_args.controller_address, ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, 100, false); assert(ctx); const char* name = "adhoc_storage_42"; diff --git a/examples/c/ADM_link_transfer_to_data_operation.c b/examples/c/ADM_link_transfer_to_data_operation.c index 66bd656b..bfab8b6b 100644 --- a/examples/c/ADM_link_transfer_to_data_operation.c +++ b/examples/c/ADM_link_transfer_to_data_operation.c @@ -36,15 +36,19 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, - "Usage: ADM_link_transfer_to_data_operation \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + ADM_server_t server = ADM_server_create("tcp", cli_args.server_address); ADM_job_t job = NULL; ADM_node_t* job_nodes = prepare_nodes(NJOB_NODES); @@ -61,7 +65,8 @@ main(int argc, char* argv[]) { assert(adhoc_resources); ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); + cli_args.controller_address, ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, 100, false); assert(ctx); const char* name = "adhoc_storage_42"; diff --git a/examples/c/ADM_ping.c b/examples/c/ADM_ping.c index a197642f..7ec29720 100644 --- a/examples/c/ADM_ping.c +++ b/examples/c/ADM_ping.c @@ -26,17 +26,23 @@ #include #include #include +#include "common.h" int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_ping \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = false, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } - ADM_server_t server = ADM_server_create("tcp", argv[1]); + ADM_server_t server = ADM_server_create("tcp", cli_args.server_address); ADM_return_t ret = ADM_ping(server); diff --git a/examples/c/ADM_register_adhoc_storage.c b/examples/c/ADM_register_adhoc_storage.c index 5f2a86dc..0d2ff17e 100644 --- a/examples/c/ADM_register_adhoc_storage.c +++ b/examples/c/ADM_register_adhoc_storage.c @@ -34,9 +34,14 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_register_adhoc_storage \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } @@ -73,7 +78,8 @@ main(int argc, char* argv[]) { } // 3. define the adhoc execution context - adhoc_ctx = ADM_adhoc_context_create(ADM_ADHOC_MODE_SEPARATE_NEW, + adhoc_ctx = ADM_adhoc_context_create(cli_args.controller_address, + ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); if(adhoc_ctx == NULL) { @@ -85,7 +91,7 @@ main(int argc, char* argv[]) { // now ready. Let's actually contact the server: // 1. Find the server endpoint - if((server = ADM_server_create("tcp", argv[1])) == NULL) { + if((server = ADM_server_create("tcp", cli_args.server_address)) == NULL) { fprintf(stderr, "Fatal error creating server\n"); goto cleanup; } diff --git a/examples/c/ADM_register_job.c b/examples/c/ADM_register_job.c index ebab9efc..e4be4153 100644 --- a/examples/c/ADM_register_job.c +++ b/examples/c/ADM_register_job.c @@ -35,9 +35,14 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_register_job \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } @@ -83,7 +88,8 @@ main(int argc, char* argv[]) { } // 3. the adhoc storage execution context - adhoc_ctx = ADM_adhoc_context_create(ADM_ADHOC_MODE_SEPARATE_NEW, + adhoc_ctx = ADM_adhoc_context_create(cli_args.controller_address, + ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); if(adhoc_ctx == NULL) { @@ -96,7 +102,7 @@ main(int argc, char* argv[]) { // now ready. Let's actually contact the server: // 1. Find the server endpoint - if((server = ADM_server_create("tcp", argv[1])) == NULL) { + if((server = ADM_server_create("tcp", cli_args.server_address)) == NULL) { fprintf(stderr, "Fatal error creating server\n"); goto cleanup; } diff --git a/examples/c/ADM_register_pfs_storage.c b/examples/c/ADM_register_pfs_storage.c index 8510bfc3..5c7ecc2f 100644 --- a/examples/c/ADM_register_pfs_storage.c +++ b/examples/c/ADM_register_pfs_storage.c @@ -25,13 +25,19 @@ #include #include #include +#include "common.h" int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no server address provided\n"); - fprintf(stderr, "Usage: ADM_register_pfs_storage \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = false, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } @@ -62,7 +68,7 @@ main(int argc, char* argv[]) { // now ready. Let's actually contact the server: // 1. Find the server endpoint - if((server = ADM_server_create("tcp", argv[1])) == NULL) { + if((server = ADM_server_create("tcp", cli_args.server_address)) == NULL) { fprintf(stderr, "Fatal error creating server\n"); goto cleanup; } diff --git a/examples/c/ADM_remove_adhoc_storage.c b/examples/c/ADM_remove_adhoc_storage.c index 23e404bb..17d8cf78 100644 --- a/examples/c/ADM_remove_adhoc_storage.c +++ b/examples/c/ADM_remove_adhoc_storage.c @@ -34,9 +34,14 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_remove_adhoc_storage \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } @@ -75,7 +80,8 @@ main(int argc, char* argv[]) { } // 3. the adhoc storage execution context - adhoc_ctx = ADM_adhoc_context_create(ADM_ADHOC_MODE_SEPARATE_NEW, + adhoc_ctx = ADM_adhoc_context_create(cli_args.controller_address, + ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); if(adhoc_ctx == NULL) { @@ -88,7 +94,7 @@ main(int argc, char* argv[]) { // now ready. Let's actually contact the server: // 1. Find the server endpoint - if((server = ADM_server_create("tcp", argv[1])) == NULL) { + if((server = ADM_server_create("tcp", cli_args.server_address)) == NULL) { fprintf(stderr, "Fatal error creating server\n"); goto cleanup; } diff --git a/examples/c/ADM_remove_job.c b/examples/c/ADM_remove_job.c index c4d0a7c8..ddf7a2d6 100644 --- a/examples/c/ADM_remove_job.c +++ b/examples/c/ADM_remove_job.c @@ -36,14 +36,19 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_remove_job \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + ADM_server_t server = ADM_server_create("tcp", cli_args.server_address); ADM_job_t job = NULL; ADM_node_t* job_nodes = prepare_nodes(NJOB_NODES); @@ -64,7 +69,8 @@ main(int argc, char* argv[]) { assert(adhoc_resources); ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); + cli_args.controller_address, ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, 100, false); assert(ctx); const char* name = "adhoc_storage_42"; diff --git a/examples/c/ADM_remove_pfs_storage.c b/examples/c/ADM_remove_pfs_storage.c index d2bc0017..34423b8e 100644 --- a/examples/c/ADM_remove_pfs_storage.c +++ b/examples/c/ADM_remove_pfs_storage.c @@ -18,7 +18,9 @@ * * You should have received a copy of the GNU General Public License * along with scord. If not, see . - * + if(test_info.requires_server) { + } +* * SPDX-License-Identifier: GPL-3.0-or-later *****************************************************************************/ @@ -26,13 +28,19 @@ #include #include #include +#include "common.h" int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no server address provided\n"); - fprintf(stderr, "Usage: ADM_remove_pfs_storage \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = false, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } @@ -63,7 +71,7 @@ main(int argc, char* argv[]) { // now ready. Let's actually contact the server: // 1. Find the server endpoint - if((server = ADM_server_create("tcp", argv[1])) == NULL) { + if((server = ADM_server_create("tcp", cli_args.server_address)) == NULL) { fprintf(stderr, "Fatal error creating server\n"); goto cleanup; } diff --git a/examples/c/ADM_set_dataset_information.c b/examples/c/ADM_set_dataset_information.c index ddeefe0c..548befd8 100644 --- a/examples/c/ADM_set_dataset_information.c +++ b/examples/c/ADM_set_dataset_information.c @@ -36,15 +36,19 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, - "Usage: ADM_set_dataset_information \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + ADM_server_t server = ADM_server_create("tcp", cli_args.server_address); ADM_job_t job = NULL; ADM_node_t* job_nodes = prepare_nodes(NJOB_NODES); @@ -61,7 +65,8 @@ main(int argc, char* argv[]) { assert(adhoc_resources); ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); + cli_args.controller_address, ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, 100, false); assert(ctx); const char* name = "adhoc_storage_42"; diff --git a/examples/c/ADM_set_io_resources.c b/examples/c/ADM_set_io_resources.c index 37989fa5..cdf07a3b 100644 --- a/examples/c/ADM_set_io_resources.c +++ b/examples/c/ADM_set_io_resources.c @@ -36,14 +36,19 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_set_io_resources \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + ADM_server_t server = ADM_server_create("tcp", cli_args.server_address); ADM_job_t job = NULL; ADM_node_t* job_nodes = prepare_nodes(NJOB_NODES); @@ -60,7 +65,8 @@ main(int argc, char* argv[]) { assert(adhoc_resources); ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); + cli_args.controller_address, ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, 100, false); assert(ctx); const char* name = "adhoc_storage_42"; diff --git a/examples/c/ADM_set_qos_constraints.c b/examples/c/ADM_set_qos_constraints.c index dec01f69..a7f07bc1 100644 --- a/examples/c/ADM_set_qos_constraints.c +++ b/examples/c/ADM_set_qos_constraints.c @@ -36,14 +36,19 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_set_qos_constraints \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + ADM_server_t server = ADM_server_create("tcp", cli_args.server_address); ADM_job_t job = NULL; ADM_node_t* job_nodes = prepare_nodes(NJOB_NODES); @@ -64,7 +69,8 @@ main(int argc, char* argv[]) { assert(adhoc_resources); ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); + cli_args.controller_address, ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, 100, false); assert(ctx); const char* name = "adhoc_storage_42"; diff --git a/examples/c/ADM_set_transfer_priority.c b/examples/c/ADM_set_transfer_priority.c index 60e33761..8ba26be5 100644 --- a/examples/c/ADM_set_transfer_priority.c +++ b/examples/c/ADM_set_transfer_priority.c @@ -36,14 +36,19 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_set_transfer_priority \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + ADM_server_t server = ADM_server_create("tcp", cli_args.server_address); ADM_job_t job = NULL; ADM_node_t* job_nodes = prepare_nodes(NJOB_NODES); @@ -64,7 +69,8 @@ main(int argc, char* argv[]) { assert(adhoc_resources); ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); + cli_args.controller_address, ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, 100, false); assert(ctx); const char* name = "adhoc_storage_42"; diff --git a/examples/c/ADM_tear_down_adhoc_storage.c b/examples/c/ADM_tear_down_adhoc_storage.c index 10e6546c..996d03e1 100644 --- a/examples/c/ADM_tear_down_adhoc_storage.c +++ b/examples/c/ADM_tear_down_adhoc_storage.c @@ -34,9 +34,14 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_deploy_adhoc_storage \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } @@ -76,7 +81,8 @@ main(int argc, char* argv[]) { } // 3. the adhoc storage execution context - adhoc_ctx = ADM_adhoc_context_create(ADM_ADHOC_MODE_SEPARATE_NEW, + adhoc_ctx = ADM_adhoc_context_create(cli_args.controller_address, + ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); if(adhoc_ctx == NULL) { @@ -89,7 +95,7 @@ main(int argc, char* argv[]) { // now ready. Let's actually contact the server: // 1. Find the server endpoint - if((server = ADM_server_create("tcp", argv[1])) == NULL) { + if((server = ADM_server_create("tcp", cli_args.server_address)) == NULL) { fprintf(stderr, "Fatal error creating server\n"); goto cleanup; } @@ -108,7 +114,8 @@ main(int argc, char* argv[]) { // system, let's prepare a new execution context for the adhoc // storage system - new_adhoc_ctx = ADM_adhoc_context_create(ADM_ADHOC_MODE_SEPARATE_NEW, + new_adhoc_ctx = ADM_adhoc_context_create(cli_args.controller_address, + ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 200, false); if(new_adhoc_ctx == NULL) { diff --git a/examples/c/ADM_transfer_datasets.c b/examples/c/ADM_transfer_datasets.c index 73af36c5..343c603e 100644 --- a/examples/c/ADM_transfer_datasets.c +++ b/examples/c/ADM_transfer_datasets.c @@ -39,14 +39,19 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_transfer_datasets \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + ADM_server_t server = ADM_server_create("tcp", cli_args.server_address); ADM_job_t job = NULL; ADM_node_t* job_nodes = prepare_nodes(NJOB_NODES); @@ -67,7 +72,8 @@ main(int argc, char* argv[]) { assert(adhoc_resources); ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); + cli_args.controller_address, ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, 100, false); assert(ctx); const char* name = "adhoc_storage_42"; diff --git a/examples/c/ADM_update_adhoc_storage.c b/examples/c/ADM_update_adhoc_storage.c index f8f06397..823f5504 100644 --- a/examples/c/ADM_update_adhoc_storage.c +++ b/examples/c/ADM_update_adhoc_storage.c @@ -35,9 +35,14 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_update_adhoc_storage \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } @@ -79,7 +84,8 @@ main(int argc, char* argv[]) { } // 3. the adhoc storage execution context - adhoc_ctx = ADM_adhoc_context_create(ADM_ADHOC_MODE_SEPARATE_NEW, + adhoc_ctx = ADM_adhoc_context_create(cli_args.controller_address, + ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); if(adhoc_ctx == NULL) { @@ -92,7 +98,7 @@ main(int argc, char* argv[]) { // now ready. Let's actually contact the server: // 1. Find the server endpoint - if((server = ADM_server_create("tcp", argv[1])) == NULL) { + if((server = ADM_server_create("tcp", cli_args.server_address)) == NULL) { fprintf(stderr, "Fatal error creating server\n"); goto cleanup; } @@ -118,7 +124,8 @@ main(int argc, char* argv[]) { goto cleanup; } - new_adhoc_ctx = ADM_adhoc_context_create(ADM_ADHOC_MODE_SEPARATE_NEW, + new_adhoc_ctx = ADM_adhoc_context_create(cli_args.controller_address, + ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 200, false); if(new_adhoc_ctx == NULL) { diff --git a/examples/c/ADM_update_job.c b/examples/c/ADM_update_job.c index 2e94dded..25ca6735 100644 --- a/examples/c/ADM_update_job.c +++ b/examples/c/ADM_update_job.c @@ -36,14 +36,19 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no location provided\n"); - fprintf(stderr, "Usage: ADM_update_job \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + ADM_server_t server = ADM_server_create("tcp", cli_args.server_address); ADM_job_t job; ADM_node_t* job_nodes = prepare_nodes(NJOB_NODES); @@ -64,7 +69,8 @@ main(int argc, char* argv[]) { assert(adhoc_resources); ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, 100, false); + cli_args.controller_address, ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, 100, false); assert(ctx); const char* name = "adhoc_storage_42"; diff --git a/examples/c/ADM_update_pfs_storage.c b/examples/c/ADM_update_pfs_storage.c index 95aea01c..dce5f27e 100644 --- a/examples/c/ADM_update_pfs_storage.c +++ b/examples/c/ADM_update_pfs_storage.c @@ -26,13 +26,19 @@ #include #include #include +#include "common.h" int main(int argc, char* argv[]) { - if(argc != 2) { - fprintf(stderr, "ERROR: no server address provided\n"); - fprintf(stderr, "Usage: ADM_update_pfs_storage \n"); + test_info_t test_info = { + .name = TESTNAME, + .requires_server = true, + .requires_controller = false, + }; + + cli_args_t cli_args; + if(process_args(argc, argv, test_info, &cli_args)) { exit(EXIT_FAILURE); } @@ -65,7 +71,7 @@ main(int argc, char* argv[]) { // now ready. Let's actually contact the server: // 1. Find the server endpoint - if((server = ADM_server_create("tcp", argv[1])) == NULL) { + if((server = ADM_server_create("tcp", cli_args.server_address)) == NULL) { fprintf(stderr, "Fatal error creating server\n"); goto cleanup; } diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt index ce29ffbd..d2a25be8 100644 --- a/examples/c/CMakeLists.txt +++ b/examples/c/CMakeLists.txt @@ -22,16 +22,12 @@ # SPDX-License-Identifier: GPL-3.0-or-later # ################################################################################ -list(APPEND examples_c - # ping - ADM_ping +list(APPEND c_examples_with_controller # job ADM_register_job ADM_update_job ADM_remove_job # adhoc storage ADM_register_adhoc_storage ADM_update_adhoc_storage ADM_remove_adhoc_storage ADM_deploy_adhoc_storage ADM_tear_down_adhoc_storage - # pfs storage - ADM_register_pfs_storage ADM_update_pfs_storage ADM_remove_pfs_storage # transfers ADM_transfer_datasets ADM_get_transfer_priority ADM_set_transfer_priority ADM_cancel_transfer ADM_get_pending_transfers @@ -45,11 +41,18 @@ list(APPEND examples_c ADM_get_statistics ADM_set_dataset_information ADM_set_io_resources ) +list(APPEND c_examples_without_controller + # ping + ADM_ping + # pfs storage + ADM_register_pfs_storage ADM_update_pfs_storage ADM_remove_pfs_storage + ) + add_library(c_examples_common STATIC) target_sources(c_examples_common PUBLIC common.h PRIVATE common.c) target_link_libraries(c_examples_common libscord_c_types) -foreach(example IN LISTS examples_c) +foreach(example IN LISTS c_examples_with_controller c_examples_without_controller) add_executable(${example}_c) target_sources(${example}_c PRIVATE ${example}.c) target_link_libraries(${example}_c PUBLIC libscord c_examples_common) @@ -57,7 +60,7 @@ foreach(example IN LISTS examples_c) endforeach() if(SCORD_BUILD_TESTS) - foreach(example IN LISTS examples_c) + foreach(example IN LISTS c_examples_with_controller) # prepare environment for the RPC test itself and its validation test set(TEST_NAME "${example}_c_test") @@ -69,7 +72,35 @@ if(SCORD_BUILD_TESTS) list(APPEND TEST_ENV LIBSCORD_LOG_OUTPUT=${TEST_DIRECTORY}/libscord.log) add_test(run_${TEST_NAME} ${example} - ${SCORD_TRANSPORT_PROTOCOL}://${SCORD_BIND_ADDRESS}:${SCORD_BIND_PORT}) + ${SCORD_ADDRESS_STRING} + ${SCORD_CTL_ADDRESS_STRING}) + set_tests_properties(run_${TEST_NAME} + PROPERTIES FIXTURES_REQUIRED "scord_daemon;scord_ctl" + ENVIRONMENT "${TEST_ENV}") + + add_test(validate_${TEST_NAME} + ${CMAKE_SOURCE_DIR}/ci/check_rpcs.py + ${TEST_DIRECTORY}/libscord.log + ${SCORD_TESTS_DIRECTORY}/scord_daemon/scord_daemon.log + ${example} + ) + set_tests_properties(validate_${TEST_NAME} + PROPERTIES DEPENDS stop_scord_daemon + ) + endforeach() + + foreach(example IN LISTS c_examples_without_controller) + + # prepare environment for the RPC test itself and its validation test + set(TEST_NAME "${example}_c_test") + set(TEST_DIRECTORY "${SCORD_TESTS_DIRECTORY}/${TEST_NAME}") + file(MAKE_DIRECTORY ${TEST_DIRECTORY}) + + set(TEST_ENV) + list(APPEND TEST_ENV LIBSCORD_LOG=1) + list(APPEND TEST_ENV LIBSCORD_LOG_OUTPUT=${TEST_DIRECTORY}/libscord.log) + + add_test(run_${TEST_NAME} ${example} ${SCORD_ADDRESS_STRING}) set_tests_properties(run_${TEST_NAME} PROPERTIES FIXTURES_REQUIRED scord_daemon ENVIRONMENT "${TEST_ENV}") diff --git a/examples/c/common.c b/examples/c/common.c index c5b97ae4..b1993598 100644 --- a/examples/c/common.c +++ b/examples/c/common.c @@ -2,8 +2,37 @@ #define SCORD_COMMON_H #include +#include #include "common.h" +int +process_args(int argc, char* argv[], test_info_t test_info, cli_args_t* args) { + + int required_args = 1; + + if(test_info.requires_server) { + ++required_args; + } + + if(test_info.requires_controller) { + ++required_args; + } + + if(argc != required_args) { + fprintf(stderr, "ERROR: missing arguments\n"); + fprintf(stderr, "Usage: %s%s%s\n", test_info.name, + test_info.requires_server ? " " : "", + test_info.requires_controller ? " " : ""); + return -1; + } + + args->server_address = test_info.requires_server ? argv[1] : NULL; + args->controller_address = test_info.requires_controller ? argv[2] : NULL; + + return 0; +} + + ADM_node_t* prepare_nodes(size_t n) { diff --git a/examples/c/common.h b/examples/c/common.h index 0aeab9c9..53d47211 100644 --- a/examples/c/common.h +++ b/examples/c/common.h @@ -3,6 +3,24 @@ #include +#define TESTNAME \ + (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 \ + : __FILE__) + +typedef struct { + const char* name; + bool requires_server; + bool requires_controller; +} test_info_t; + +typedef struct { + const char* server_address; + const char* controller_address; +} cli_args_t; + +int +process_args(int argc, char* argv[], test_info_t test_info, cli_args_t* args); + ADM_node_t* prepare_nodes(size_t n); diff --git a/examples/cxx/ADM_cancel_transfer.cpp b/examples/cxx/ADM_cancel_transfer.cpp index 1abff9ca..d2791147 100644 --- a/examples/cxx/ADM_cancel_transfer.cpp +++ b/examples/cxx/ADM_cancel_transfer.cpp @@ -24,18 +24,20 @@ #include #include - +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, "Usage: ADM_cancel_transfer \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; ADM_job_t job{}; ADM_transfer_t tx{}; diff --git a/examples/cxx/ADM_connect_data_operation.cpp b/examples/cxx/ADM_connect_data_operation.cpp index 5ff68267..d3bc9ac1 100644 --- a/examples/cxx/ADM_connect_data_operation.cpp +++ b/examples/cxx/ADM_connect_data_operation.cpp @@ -24,18 +24,20 @@ #include #include +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, - "Usage: ADM_connect_data_operation \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; ADM_job_t job{}; ADM_dataset_t input{}; diff --git a/examples/cxx/ADM_define_data_operation.cpp b/examples/cxx/ADM_define_data_operation.cpp index bf087508..e34a8d05 100644 --- a/examples/cxx/ADM_define_data_operation.cpp +++ b/examples/cxx/ADM_define_data_operation.cpp @@ -24,19 +24,20 @@ #include #include - +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, - "Usage: ADM_define_data_operation \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; ADM_job_t job{}; const char* path = "/tmpxxxxx"; diff --git a/examples/cxx/ADM_deploy_adhoc_storage.cpp b/examples/cxx/ADM_deploy_adhoc_storage.cpp index 38077cca..ac37c49f 100644 --- a/examples/cxx/ADM_deploy_adhoc_storage.cpp +++ b/examples/cxx/ADM_deploy_adhoc_storage.cpp @@ -34,14 +34,15 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, - "Usage: ADM_deploy_adhoc_storage \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; const auto adhoc_nodes = prepare_nodes(NADHOC_NODES); const auto inputs = prepare_datasets("input-dataset-{}", NINPUTS); @@ -49,6 +50,7 @@ main(int argc, char* argv[]) { std::string name = "adhoc_storage_42"; const auto adhoc_storage_ctx = scord::adhoc_storage::ctx{ + cli_args.controller_address, scord::adhoc_storage::execution_mode::separate_new, scord::adhoc_storage::access_type::read_write, 100, false}; const auto adhoc_resources = scord::adhoc_storage::resources{adhoc_nodes}; diff --git a/examples/cxx/ADM_finalize_data_operation.cpp b/examples/cxx/ADM_finalize_data_operation.cpp index 147ae686..a9148a19 100644 --- a/examples/cxx/ADM_finalize_data_operation.cpp +++ b/examples/cxx/ADM_finalize_data_operation.cpp @@ -24,18 +24,20 @@ #include #include +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, - "Usage: ADM_finalize_data_operation \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; ADM_job_t job{}; ADM_data_operation_t op{}; diff --git a/examples/cxx/ADM_get_pending_transfers.cpp b/examples/cxx/ADM_get_pending_transfers.cpp index f60be4b2..60f7d9eb 100644 --- a/examples/cxx/ADM_get_pending_transfers.cpp +++ b/examples/cxx/ADM_get_pending_transfers.cpp @@ -24,19 +24,20 @@ #include #include - +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, - "Usage: ADM_get_pending_transfers \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; ADM_job_t job{}; ADM_transfer_t** tx = nullptr; diff --git a/examples/cxx/ADM_get_qos_constraints.cpp b/examples/cxx/ADM_get_qos_constraints.cpp index ba34766c..389ac2b1 100644 --- a/examples/cxx/ADM_get_qos_constraints.cpp +++ b/examples/cxx/ADM_get_qos_constraints.cpp @@ -24,18 +24,20 @@ #include #include - +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, "Usage: ADM_get_qos_constraints \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; ADM_job_t job{}; ADM_qos_entity_t entity{}; diff --git a/examples/cxx/ADM_get_statistics.cpp b/examples/cxx/ADM_get_statistics.cpp index cb8c0cdc..a19e506b 100644 --- a/examples/cxx/ADM_get_statistics.cpp +++ b/examples/cxx/ADM_get_statistics.cpp @@ -24,17 +24,20 @@ #include #include +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, "Usage: ADM_get_statistics \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; ADM_job_t job{}; ADM_job_stats_t* stats = nullptr; diff --git a/examples/cxx/ADM_get_transfer_priority.cpp b/examples/cxx/ADM_get_transfer_priority.cpp index 7dbd585b..983c39c1 100644 --- a/examples/cxx/ADM_get_transfer_priority.cpp +++ b/examples/cxx/ADM_get_transfer_priority.cpp @@ -24,19 +24,20 @@ #include #include - +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, - "Usage: ADM_get_transfer_priority \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; ADM_job_t job{}; ADM_transfer_t tx{}; diff --git a/examples/cxx/ADM_in_situ_ops.cpp b/examples/cxx/ADM_in_situ_ops.cpp index 517b0fd6..563cf0bc 100644 --- a/examples/cxx/ADM_in_situ_ops.cpp +++ b/examples/cxx/ADM_in_situ_ops.cpp @@ -24,26 +24,28 @@ #include #include - +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, "Usage: ADM_in_situ_ops \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); scord::network::rpc_client rpc_client{"tcp"}; rpc_client.register_rpcs(); - auto endp = rpc_client.lookup(argv[1]); + auto endp = rpc_client.lookup(cli_args.server_address); fmt::print( stdout, "Calling ADM_in_situ_ops remote procedure on {} -> access method: {} ...\n", - argv[1], argv[2]); + cli_args.controller_address, argv[2]); ADM_in_situ_ops_in_t in; in.in_situ = argv[2]; ADM_in_situ_ops_out_t out; diff --git a/examples/cxx/ADM_in_transit_ops.cpp b/examples/cxx/ADM_in_transit_ops.cpp index bf3ce2b0..8e743799 100644 --- a/examples/cxx/ADM_in_transit_ops.cpp +++ b/examples/cxx/ADM_in_transit_ops.cpp @@ -24,26 +24,28 @@ #include #include - +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, "Usage: ADM_in_transit_ops \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); scord::network::rpc_client rpc_client{"tcp"}; rpc_client.register_rpcs(); - auto endp = rpc_client.lookup(argv[1]); + auto endp = rpc_client.lookup(cli_args.server_address); fmt::print( stdout, "Calling ADM_in_transit_ops remote procedure on {} -> access method: {} ...\n", - argv[1], argv[2]); + cli_args.controller_address, argv[2]); ADM_in_transit_ops_in_t in; in.in_transit = argv[2]; ADM_in_transit_ops_out_t out; diff --git a/examples/cxx/ADM_link_transfer_to_data_operation.cpp b/examples/cxx/ADM_link_transfer_to_data_operation.cpp index 9c993c08..2227afd1 100644 --- a/examples/cxx/ADM_link_transfer_to_data_operation.cpp +++ b/examples/cxx/ADM_link_transfer_to_data_operation.cpp @@ -24,19 +24,20 @@ #include #include +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print( - stderr, - "Usage: ADM_link_transfer_to_data_operation \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; ADM_job_t job{}; ADM_data_operation_t op{}; diff --git a/examples/cxx/ADM_ping.cpp b/examples/cxx/ADM_ping.cpp index 8570c17b..ef796074 100644 --- a/examples/cxx/ADM_ping.cpp +++ b/examples/cxx/ADM_ping.cpp @@ -24,17 +24,20 @@ #include #include +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no server address provided\n"); - fmt::print(stderr, "Usage: ADM_ping \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = false, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; try { scord::ping(server); diff --git a/examples/cxx/ADM_register_adhoc_storage.cpp b/examples/cxx/ADM_register_adhoc_storage.cpp index 98b00c56..0dfd0f9b 100644 --- a/examples/cxx/ADM_register_adhoc_storage.cpp +++ b/examples/cxx/ADM_register_adhoc_storage.cpp @@ -34,14 +34,15 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, - "Usage: ADM_register_adhoc_storage \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; const auto adhoc_nodes = prepare_nodes(NADHOC_NODES); const auto inputs = prepare_datasets("input-dataset-{}", NINPUTS); @@ -49,6 +50,7 @@ main(int argc, char* argv[]) { std::string name = "adhoc_storage_42"; const auto adhoc_storage_ctx = scord::adhoc_storage::ctx{ + cli_args.controller_address, scord::adhoc_storage::execution_mode::separate_new, scord::adhoc_storage::access_type::read_write, 100, false}; const auto adhoc_resources = scord::adhoc_storage::resources{adhoc_nodes}; diff --git a/examples/cxx/ADM_register_job.cpp b/examples/cxx/ADM_register_job.cpp index 267f56ad..55ac84d6 100644 --- a/examples/cxx/ADM_register_job.cpp +++ b/examples/cxx/ADM_register_job.cpp @@ -34,13 +34,15 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no server address provided\n"); - fmt::print(stderr, "Usage: ADM_register_job \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; const auto job_nodes = prepare_nodes(NJOB_NODES); const auto adhoc_nodes = prepare_nodes(NADHOC_NODES); @@ -49,6 +51,7 @@ main(int argc, char* argv[]) { std::string name = "adhoc_storage_42"; const auto adhoc_storage_ctx = scord::adhoc_storage::ctx{ + cli_args.controller_address, scord::adhoc_storage::execution_mode::separate_new, scord::adhoc_storage::access_type::read_write, 100, false}; const auto adhoc_resources = scord::adhoc_storage::resources{adhoc_nodes}; diff --git a/examples/cxx/ADM_register_pfs_storage.cpp b/examples/cxx/ADM_register_pfs_storage.cpp index 712409dc..1078262c 100644 --- a/examples/cxx/ADM_register_pfs_storage.cpp +++ b/examples/cxx/ADM_register_pfs_storage.cpp @@ -24,19 +24,21 @@ #include #include +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no server address provided\n"); - fmt::print(stderr, - "Usage: ADM_register_pfs_storage \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = false, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; std::string pfs_name = "gpfs_scratch"; std::string pfs_mount = "/gpfs/scratch"; diff --git a/examples/cxx/ADM_remove_adhoc_storage.cpp b/examples/cxx/ADM_remove_adhoc_storage.cpp index 9459663b..aa496ee6 100644 --- a/examples/cxx/ADM_remove_adhoc_storage.cpp +++ b/examples/cxx/ADM_remove_adhoc_storage.cpp @@ -34,14 +34,15 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, - "Usage: ADM_remove_adhoc_storage \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; const auto adhoc_nodes = prepare_nodes(NADHOC_NODES); const auto inputs = prepare_datasets("input-dataset-{}", NINPUTS); @@ -49,6 +50,7 @@ main(int argc, char* argv[]) { std::string name = "adhoc_storage_42"; const auto adhoc_storage_ctx = scord::adhoc_storage::ctx{ + cli_args.controller_address, scord::adhoc_storage::execution_mode::separate_new, scord::adhoc_storage::access_type::read_write, 100, false}; const auto adhoc_resources = scord::adhoc_storage::resources{adhoc_nodes}; diff --git a/examples/cxx/ADM_remove_job.cpp b/examples/cxx/ADM_remove_job.cpp index 37498e12..4a3ae71c 100644 --- a/examples/cxx/ADM_remove_job.cpp +++ b/examples/cxx/ADM_remove_job.cpp @@ -34,13 +34,15 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no server address provided\n"); - fmt::print(stderr, "Usage: ADM_remove_job \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; const auto job_nodes = prepare_nodes(NJOB_NODES); const auto adhoc_nodes = prepare_nodes(NADHOC_NODES); @@ -49,6 +51,7 @@ main(int argc, char* argv[]) { std::string name = "adhoc_storage_42"; const auto adhoc_storage_ctx = scord::adhoc_storage::ctx{ + cli_args.controller_address, scord::adhoc_storage::execution_mode::separate_new, scord::adhoc_storage::access_type::read_write, 100, false}; diff --git a/examples/cxx/ADM_remove_pfs_storage.cpp b/examples/cxx/ADM_remove_pfs_storage.cpp index c2cdaeec..8e5bd527 100644 --- a/examples/cxx/ADM_remove_pfs_storage.cpp +++ b/examples/cxx/ADM_remove_pfs_storage.cpp @@ -24,18 +24,21 @@ #include #include +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no server address provided\n"); - fmt::print(stderr, "Usage: ADM_remove_pfs_storage \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = false, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; std::string pfs_name = "gpfs_scratch"; std::string pfs_mount = "/gpfs/scratch"; diff --git a/examples/cxx/ADM_set_dataset_information.cpp b/examples/cxx/ADM_set_dataset_information.cpp index 9f7b7d33..863e6774 100644 --- a/examples/cxx/ADM_set_dataset_information.cpp +++ b/examples/cxx/ADM_set_dataset_information.cpp @@ -24,19 +24,21 @@ #include #include +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, - "Usage: ADM_set_dataset_information \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; ADM_job_t job{}; ADM_dataset_t target{}; diff --git a/examples/cxx/ADM_set_io_resources.cpp b/examples/cxx/ADM_set_io_resources.cpp index c36f2c65..425b4642 100644 --- a/examples/cxx/ADM_set_io_resources.cpp +++ b/examples/cxx/ADM_set_io_resources.cpp @@ -24,18 +24,21 @@ #include #include +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, "Usage: ADM_set_io_resources \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; ADM_job_t job{}; ADM_adhoc_storage_t tier{}; diff --git a/examples/cxx/ADM_set_qos_constraints.cpp b/examples/cxx/ADM_set_qos_constraints.cpp index 65b798f1..d487b576 100644 --- a/examples/cxx/ADM_set_qos_constraints.cpp +++ b/examples/cxx/ADM_set_qos_constraints.cpp @@ -24,18 +24,20 @@ #include #include - +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, "Usage: ADM_set_qos_constraints \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; ADM_job_t job{}; ADM_qos_entity_t entity{}; diff --git a/examples/cxx/ADM_set_transfer_priority.cpp b/examples/cxx/ADM_set_transfer_priority.cpp index 040cde0e..39819b47 100644 --- a/examples/cxx/ADM_set_transfer_priority.cpp +++ b/examples/cxx/ADM_set_transfer_priority.cpp @@ -24,19 +24,21 @@ #include #include +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, - "Usage: ADM_set_transfer_priority \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; ADM_job_t job{}; ADM_transfer_t tx{}; diff --git a/examples/cxx/ADM_tear_down_adhoc_storage.cpp b/examples/cxx/ADM_tear_down_adhoc_storage.cpp index 22924274..561676ed 100644 --- a/examples/cxx/ADM_tear_down_adhoc_storage.cpp +++ b/examples/cxx/ADM_tear_down_adhoc_storage.cpp @@ -34,14 +34,15 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, - "Usage: ADM_tear_down_adhoc_storage \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; const auto adhoc_nodes = prepare_nodes(NADHOC_NODES); const auto inputs = prepare_datasets("input-dataset-{}", NINPUTS); @@ -49,6 +50,7 @@ main(int argc, char* argv[]) { std::string name = "adhoc_storage_42"; const auto adhoc_storage_ctx = scord::adhoc_storage::ctx{ + cli_args.controller_address, scord::adhoc_storage::execution_mode::separate_new, scord::adhoc_storage::access_type::read_write, 100, false}; const auto adhoc_resources = scord::adhoc_storage::resources{adhoc_nodes}; diff --git a/examples/cxx/ADM_transfer_datasets.cpp b/examples/cxx/ADM_transfer_datasets.cpp index d13cc8ad..2b4e6f02 100644 --- a/examples/cxx/ADM_transfer_datasets.cpp +++ b/examples/cxx/ADM_transfer_datasets.cpp @@ -37,13 +37,15 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no server address provided\n"); - fmt::print(stderr, "Usage: ADM_transfer_datasets \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; const auto job_nodes = prepare_nodes(NJOB_NODES); const auto adhoc_nodes = prepare_nodes(NADHOC_NODES); @@ -57,6 +59,7 @@ main(int argc, char* argv[]) { std::string name = "adhoc_storage_42"; const auto adhoc_storage_ctx = scord::adhoc_storage::ctx{ + cli_args.controller_address, scord::adhoc_storage::execution_mode::separate_new, scord::adhoc_storage::access_type::read_write, 100, false}; const auto adhoc_resources = scord::adhoc_storage::resources{adhoc_nodes}; diff --git a/examples/cxx/ADM_update_adhoc_storage.cpp b/examples/cxx/ADM_update_adhoc_storage.cpp index 36cdaf55..dbb2ac93 100644 --- a/examples/cxx/ADM_update_adhoc_storage.cpp +++ b/examples/cxx/ADM_update_adhoc_storage.cpp @@ -33,14 +33,15 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no location provided\n"); - fmt::print(stderr, - "Usage: ADM_update_adhoc_storage \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; const auto adhoc_nodes = prepare_nodes(NADHOC_NODES); const auto new_adhoc_nodes = prepare_nodes(NADHOC_NODES * 2); @@ -49,6 +50,7 @@ main(int argc, char* argv[]) { std::string name = "adhoc_storage_42"; const auto adhoc_storage_ctx = scord::adhoc_storage::ctx{ + cli_args.controller_address, scord::adhoc_storage::execution_mode::separate_new, scord::adhoc_storage::access_type::read_write, 100, false}; const auto adhoc_resources = scord::adhoc_storage::resources{adhoc_nodes}; diff --git a/examples/cxx/ADM_update_job.cpp b/examples/cxx/ADM_update_job.cpp index 72c82031..1ee22d58 100644 --- a/examples/cxx/ADM_update_job.cpp +++ b/examples/cxx/ADM_update_job.cpp @@ -34,13 +34,15 @@ int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no server address provided\n"); - fmt::print(stderr, "Usage: ADM_update_job \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = true, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; const auto job_nodes = prepare_nodes(NJOB_NODES); const auto new_job_nodes = prepare_nodes(NJOB_NODES * 2); @@ -51,6 +53,7 @@ main(int argc, char* argv[]) { const auto gkfs_storage = scord::register_adhoc_storage( server, "foobar", scord::adhoc_storage::type::gekkofs, scord::adhoc_storage::ctx{ + cli_args.controller_address, scord::adhoc_storage::execution_mode::separate_new, scord::adhoc_storage::access_type::read_write, 100, false}, scord::adhoc_storage::resources{adhoc_nodes}); diff --git a/examples/cxx/ADM_update_pfs_storage.cpp b/examples/cxx/ADM_update_pfs_storage.cpp index 74fea88b..019fe110 100644 --- a/examples/cxx/ADM_update_pfs_storage.cpp +++ b/examples/cxx/ADM_update_pfs_storage.cpp @@ -24,18 +24,21 @@ #include #include +#include "common.hpp" int main(int argc, char* argv[]) { - if(argc != 2) { - fmt::print(stderr, "ERROR: no server address provided\n"); - fmt::print(stderr, "Usage: ADM_update_pfs_storage \n"); - exit(EXIT_FAILURE); - } + test_info test_info{ + .name = TESTNAME, + .requires_server = true, + .requires_controller = false, + }; + + const auto cli_args = process_args(argc, argv, test_info); - scord::server server{"tcp", argv[1]}; + scord::server server{"tcp", cli_args.server_address}; std::string pfs_name = "gpfs_scratch"; std::string pfs_mount = "/gpfs/scratch"; diff --git a/examples/cxx/CMakeLists.txt b/examples/cxx/CMakeLists.txt index 0b4ca746..efb0258e 100644 --- a/examples/cxx/CMakeLists.txt +++ b/examples/cxx/CMakeLists.txt @@ -22,16 +22,12 @@ # SPDX-License-Identifier: GPL-3.0-or-later # ################################################################################ -list(APPEND examples_cxx - # ping - ADM_ping +list(APPEND cxx_examples_with_controller # job ADM_register_job ADM_update_job ADM_remove_job # adhoc storage ADM_register_adhoc_storage ADM_update_adhoc_storage ADM_remove_adhoc_storage ADM_deploy_adhoc_storage ADM_tear_down_adhoc_storage - # pfs storage - ADM_register_pfs_storage ADM_update_pfs_storage ADM_remove_pfs_storage # transfers ADM_transfer_datasets ADM_get_transfer_priority ADM_set_transfer_priority ADM_cancel_transfer ADM_get_pending_transfers @@ -45,11 +41,18 @@ list(APPEND examples_cxx ADM_get_statistics ADM_set_dataset_information ADM_set_io_resources ) +list(APPEND cxx_examples_without_controller + # ping + ADM_ping + # pfs storage + ADM_register_pfs_storage ADM_update_pfs_storage ADM_remove_pfs_storage + ) + add_library(cxx_examples_common STATIC) target_sources(cxx_examples_common PUBLIC common.hpp PRIVATE common.cpp) target_link_libraries(cxx_examples_common libscord_cxx_types) -foreach(example IN LISTS examples_cxx) +foreach(example IN LISTS cxx_examples_with_controller cxx_examples_without_controller) add_executable(${example}_cxx) target_sources(${example}_cxx PRIVATE ${example}.cpp) target_link_libraries(${example}_cxx @@ -57,10 +60,8 @@ foreach(example IN LISTS examples_cxx) set_target_properties(${example}_cxx PROPERTIES OUTPUT_NAME ${example}) endforeach() -set(CXX_TEST_ID 0) - if(SCORD_BUILD_TESTS) - foreach(example IN LISTS examples_cxx) + foreach(example IN LISTS cxx_examples_with_controller) # prepare environment for the RPC test itself and its validation test set(TEST_NAME "${example}_cxx_test") @@ -72,11 +73,38 @@ if(SCORD_BUILD_TESTS) list(APPEND TEST_ENV LIBSCORD_LOG_OUTPUT=${TEST_DIRECTORY}/libscord.log) add_test(run_${TEST_NAME} ${example} - ${SCORD_TRANSPORT_PROTOCOL}://${SCORD_BIND_ADDRESS}:${SCORD_BIND_PORT}) + ${SCORD_ADDRESS_STRING} + ${SCORD_CTL_ADDRESS_STRING}) set_tests_properties(run_${TEST_NAME} - PROPERTIES FIXTURES_REQUIRED scord_daemon - ENVIRONMENT "${TEST_ENV}" + PROPERTIES FIXTURES_REQUIRED "scord_daemon;scord_ctl" + ENVIRONMENT "${TEST_ENV}") + + add_test(validate_${TEST_NAME} + ${CMAKE_SOURCE_DIR}/ci/check_rpcs.py + ${TEST_DIRECTORY}/libscord.log + ${SCORD_TESTS_DIRECTORY}/scord_daemon/scord_daemon.log + ${example} ) + set_tests_properties(validate_${TEST_NAME} + PROPERTIES DEPENDS stop_scord_daemon + ) + endforeach() + + foreach(example IN LISTS cxx_examples_without_controller) + + # prepare environment for the RPC test itself and its validation test + set(TEST_NAME "${example}_cxx_test") + set(TEST_DIRECTORY "${SCORD_TESTS_DIRECTORY}/${TEST_NAME}") + file(MAKE_DIRECTORY ${TEST_DIRECTORY}) + + set(TEST_ENV) + list(APPEND TEST_ENV LIBSCORD_LOG=1) + list(APPEND TEST_ENV LIBSCORD_LOG_OUTPUT=${TEST_DIRECTORY}/libscord.log) + + add_test(run_${TEST_NAME} ${example} ${SCORD_ADDRESS_STRING}) + set_tests_properties(run_${TEST_NAME} + PROPERTIES FIXTURES_REQUIRED scord_daemon + ENVIRONMENT "${TEST_ENV}") add_test(validate_${TEST_NAME} ${CMAKE_SOURCE_DIR}/ci/check_rpcs.py diff --git a/examples/cxx/common.cpp b/examples/cxx/common.cpp index d0acaafc..cf83a8a9 100644 --- a/examples/cxx/common.cpp +++ b/examples/cxx/common.cpp @@ -1,5 +1,33 @@ #include "common.hpp" +using std::string_literals::operator""s; + +cli_args +process_args(int argc, char* argv[], const test_info& test_info) { + + int required_args = 1; + + if(test_info.requires_server) { + ++required_args; + } + + if(test_info.requires_controller) { + ++required_args; + } + + if(argc != required_args) { + fmt::print(stderr, "ERROR: missing arguments\n"); + fmt::print(stderr, "Usage: {}{}{}\n", test_info.name, + test_info.requires_server ? " " : "", + test_info.requires_controller ? " " + : ""); + exit(EXIT_FAILURE); + } + + return cli_args{test_info.requires_server ? std::string{argv[1]} : ""s, + test_info.requires_controller ? std::string{argv[2]} : ""s}; +} + std::vector prepare_nodes(size_t n) { std::vector nodes; diff --git a/examples/cxx/common.hpp b/examples/cxx/common.hpp index ee76624c..374ad264 100644 --- a/examples/cxx/common.hpp +++ b/examples/cxx/common.hpp @@ -4,6 +4,24 @@ #include #include +#define TESTNAME \ + (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 \ + : __FILE__) + +struct test_info { + std::string name; + bool requires_server; + bool requires_controller; +}; + +struct cli_args { + std::string server_address; + std::string controller_address; +}; + +cli_args +process_args(int argc, char* argv[], const test_info& test_info); + std::vector prepare_nodes(size_t n); diff --git a/src/lib/scord/types.h b/src/lib/scord/types.h index ed5bc8e0..badda31d 100644 --- a/src/lib/scord/types.h +++ b/src/lib/scord/types.h @@ -485,6 +485,8 @@ ADM_adhoc_resources_destroy(ADM_adhoc_resources_t res); * @remark ADM_ADHOC_CONTEXTs need to be freed by calling * ADM_adhoc_context_destroy(). * + * @param[in] ctl_address The address of the control node for the + * adhoc storage system * @param[in] exec_mode The adhoc storage system execution mode * @param[in] access_type The adhoc storage system execution type * @param[in] walltime The adhoc storage system walltime @@ -493,7 +495,8 @@ ADM_adhoc_resources_destroy(ADM_adhoc_resources_t res); * @return A valid ADM_ADHOC_CONTEXT if successful. NULL otherwise. */ ADM_adhoc_context_t -ADM_adhoc_context_create(ADM_adhoc_mode_t exec_mode, +ADM_adhoc_context_create(const char* ctl_address, + ADM_adhoc_mode_t exec_mode, ADM_adhoc_access_t access_type, uint32_t walltime, bool should_flush); diff --git a/src/lib/scord/types.hpp b/src/lib/scord/types.hpp index 99c0802a..a1002f49 100644 --- a/src/lib/scord/types.hpp +++ b/src/lib/scord/types.hpp @@ -223,12 +223,14 @@ struct adhoc_storage { ctx() = default; - ctx(execution_mode exec_mode, access_type access_type, - std::uint32_t walltime, bool should_flush); + ctx(std::string controller_address, execution_mode exec_mode, + access_type access_type, std::uint32_t walltime, bool should_flush); explicit ctx(ADM_adhoc_context_t ctx); explicit operator ADM_adhoc_context_t() const; + std::string + controller_address() const; execution_mode exec_mode() const; enum access_type @@ -241,6 +243,7 @@ struct adhoc_storage { template void serialize(Archive&& ar) { + ar & m_controller_address; ar & m_exec_mode; ar & m_access_type; ar & m_walltime; @@ -248,6 +251,7 @@ struct adhoc_storage { } private: + std::string m_controller_address; execution_mode m_exec_mode; enum access_type m_access_type; std::uint32_t m_walltime; @@ -814,10 +818,11 @@ struct fmt::formatter : formatter { auto format(const scord::adhoc_storage::ctx& c, FormatContext& ctx) const { - const auto str = fmt::format("{{execution_mode: {}, access_type: {}, " - "walltime: {}, should_flush: {}}}", - c.exec_mode(), c.access_type(), - c.walltime(), c.should_flush()); + const auto str = + fmt::format("{{controller: {}, execution_mode: {}, " + "access_type: {}, walltime: {}, should_flush: {}}}", + std::quoted(c.controller_address()), c.exec_mode(), + c.access_type(), c.walltime(), c.should_flush()); return formatter::format(str, ctx); } diff --git a/src/lib/types.c b/src/lib/types.c index b7480a97..97c9ae12 100644 --- a/src/lib/types.c +++ b/src/lib/types.c @@ -657,10 +657,15 @@ ADM_data_operation_destroy(ADM_data_operation_t op) { } ADM_adhoc_context_t -ADM_adhoc_context_create(ADM_adhoc_mode_t exec_mode, +ADM_adhoc_context_create(const char* ctl_address, ADM_adhoc_mode_t exec_mode, ADM_adhoc_access_t access_type, uint32_t walltime, bool should_flush) { + if(!ctl_address) { + LOGGER_ERROR("The address to the controller cannot be NULL"); + return NULL; + } + struct adm_adhoc_context* adm_adhoc_context = (struct adm_adhoc_context*) malloc(sizeof(*adm_adhoc_context)); @@ -669,6 +674,12 @@ ADM_adhoc_context_create(ADM_adhoc_mode_t exec_mode, return NULL; } + + size_t n = strlen(ctl_address); + adm_adhoc_context->c_ctl_address = + (const char*) calloc(n + 1, sizeof(char)); + strcpy((char*) adm_adhoc_context->c_ctl_address, ctl_address); + adm_adhoc_context->c_mode = exec_mode; adm_adhoc_context->c_access = access_type; adm_adhoc_context->c_walltime = walltime; diff --git a/src/lib/types.cpp b/src/lib/types.cpp index f0e33ef3..ba584bf3 100644 --- a/src/lib/types.cpp +++ b/src/lib/types.cpp @@ -561,24 +561,33 @@ adhoc_storage::resources::nodes() const { return m_nodes; } -adhoc_storage::ctx::ctx(adhoc_storage::execution_mode exec_mode, +adhoc_storage::ctx::ctx(std::string controller_address, + adhoc_storage::execution_mode exec_mode, adhoc_storage::access_type access_type, std::uint32_t walltime, bool should_flush) - : m_exec_mode(exec_mode), m_access_type(access_type), m_walltime(walltime), + : m_controller_address(std::move(controller_address)), + m_exec_mode(exec_mode), m_access_type(access_type), m_walltime(walltime), m_should_flush(should_flush) {} adhoc_storage::ctx::ctx(ADM_adhoc_context_t ctx) - : adhoc_storage::ctx(static_cast(ctx->c_mode), + : adhoc_storage::ctx(ctx->c_ctl_address, + static_cast(ctx->c_mode), static_cast(ctx->c_access), ctx->c_walltime, ctx->c_should_bg_flush) {} adhoc_storage::ctx::operator ADM_adhoc_context_t() const { return ADM_adhoc_context_create( + m_controller_address.c_str(), static_cast(m_exec_mode), static_cast(m_access_type), m_walltime, m_should_flush); } +std::string +adhoc_storage::ctx::controller_address() const { + return m_controller_address; +} + adhoc_storage::execution_mode adhoc_storage::ctx::exec_mode() const { return m_exec_mode; diff --git a/src/lib/types_private.h b/src/lib/types_private.h index b66b0b72..3fda9e61 100644 --- a/src/lib/types_private.h +++ b/src/lib/types_private.h @@ -76,6 +76,8 @@ struct adm_dataset_info { }; struct adm_adhoc_context { + /** The address to the node responsible for this adhoc storage system */ + const char* c_ctl_address; /** The adhoc storage system execution mode */ ADM_adhoc_mode_t c_mode; /** The adhoc storage system access type */ -- GitLab From 0ad18d7958d8789c955bd74d780b0d9bae662d84 Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Wed, 17 May 2023 12:11:19 +0200 Subject: [PATCH 11/17] RPC handlers can now access server context Our network interface now relies on Thallium's support for `providers` (https://mochi.readthedocs.io/en/latest/thallium/09_providers.html). This allows using the member functions from a class as RPC handlers, which in turn allows RPC handers to access the class' data members. Thus, we have heavily refactored `scord`: - Create a new `scord::rpc_server` class that inherits both from `network::server` and `network::provider`. This enables the aforementioned functionality. - The RPC handlers for `scord` are now member functions of `scord::rpc_server` instead of free functions. - The managers used by `scord` (i.e. the `job_manager`, `adhoc_storage_manager`, and `pfs_storage_manager` are now members of `scord::rpc_server` instead of singletons, since they no longer need to be accessed globally. Similarly for `scord-ctl`: - Create a new `scord_ctl::rpc_server` class that inherits both from `network::server` and `network::provider`. This enables the aforementioned functionality. - The RPC handlers for `scord-ctl` are now member functions of `scord_ctl::rpc_server` instead of free functions. Additionally, we have also moved the `network` and `logger` namespaces outside of `scord`, since this code is shared by both `scord` and `scord-ctl`. --- src/common/logger/logger.cpp | 18 +- src/common/logger/logger.hpp | 67 +++---- src/common/logger/macros.h | 8 +- src/common/net/client.cpp | 4 +- src/common/net/client.hpp | 10 +- src/common/net/endpoint.cpp | 4 +- src/common/net/endpoint.hpp | 10 +- src/common/net/request.hpp | 10 +- src/common/net/serialization.hpp | 10 +- src/common/net/server.cpp | 23 +-- src/common/net/server.hpp | 25 ++- src/lib/detail/impl.cpp | 52 ++--- src/lib/libscord.cpp | 8 +- src/lib/types.cpp | 112 +++++------ src/scord-ctl/CMakeLists.txt | 2 +- .../{rpc_handlers.cpp => rpc_server.cpp} | 47 +++-- .../{rpc_handlers.hpp => rpc_server.hpp} | 34 ++-- .../{scord-ctl.cpp => scord_ctl.cpp} | 21 +- src/scord/CMakeLists.txt | 6 +- src/scord/adhoc_storage_manager.hpp | 6 +- src/scord/job_manager.hpp | 7 +- src/scord/pfs_storage_manager.hpp | 6 +- src/scord/rpc_handlers.hpp | 89 --------- .../{rpc_handlers.cpp => rpc_server.cpp} | 187 ++++++++++-------- src/scord/rpc_server.hpp | 106 ++++++++++ src/scord/scord.cpp | 41 +--- 26 files changed, 466 insertions(+), 447 deletions(-) rename src/scord-ctl/{rpc_handlers.cpp => rpc_server.cpp} (63%) rename src/scord-ctl/{rpc_handlers.hpp => rpc_server.hpp} (63%) rename src/scord-ctl/{scord-ctl.cpp => scord_ctl.cpp} (83%) delete mode 100644 src/scord/rpc_handlers.hpp rename src/scord/{rpc_handlers.cpp => rpc_server.cpp} (74%) create mode 100644 src/scord/rpc_server.hpp diff --git a/src/common/logger/logger.cpp b/src/common/logger/logger.cpp index e46b295f..974874b1 100644 --- a/src/common/logger/logger.cpp +++ b/src/common/logger/logger.cpp @@ -32,24 +32,24 @@ logger_setup(const char* ident, logger_type type, const char* log_file) { constexpr auto get_cxx_type = [](logger_type t) { switch(t) { case CONSOLE_LOGGER: - return scord::logger_type::console; + return logger::logger_type::console; case CONSOLE_COLOR_LOGGER: - return scord::logger_type::console_color; + return logger::logger_type::console_color; case FILE_LOGGER: - return scord::logger_type::file; + return logger::logger_type::file; case SYSLOG_LOGGER: - return scord::logger_type::syslog; + return logger::logger_type::syslog; default: - return scord::logger_type::console; + return logger::logger_type::console; } }; - scord::logger::create_global_logger(ident, get_cxx_type(type), log_file); + logger::create_global_logger(ident, get_cxx_type(type), log_file); } void logger_log(enum logger_level level, const char* fmt, ...) { - if(const auto logger = scord::logger::get_global_logger(); logger) { + if(const auto logger = logger::get_global_logger(); logger) { std::array msg; // NOLINT va_list args; @@ -79,7 +79,7 @@ logger_log(enum logger_level level, const char* fmt, ...) { void logger_destroy() { - if(scord::logger::get_global_logger()) { - scord::logger::destroy_global_logger(); + if(logger::get_global_logger()) { + logger::destroy_global_logger(); } } diff --git a/src/common/logger/logger.hpp b/src/common/logger/logger.hpp index df565cfa..b9b67439 100644 --- a/src/common/logger/logger.hpp +++ b/src/common/logger/logger.hpp @@ -50,7 +50,7 @@ ptr(const T* p) { namespace fs = std::filesystem; -namespace scord { +namespace logger { enum logger_type { console, @@ -64,7 +64,7 @@ class logger_config { public: logger_config() = default; - explicit logger_config(std::string ident, scord::logger_type type, + explicit logger_config(std::string ident, logger_type type, std::optional log_file = {}) : m_ident(std::move(ident)), m_type(type), m_log_file(std::move(log_file)) {} @@ -74,7 +74,7 @@ public: return m_ident; } - scord::logger_type + logger_type type() const { return m_type; } @@ -86,7 +86,7 @@ public: private: std::string m_ident; - scord::logger_type m_type = console_color; + logger_type m_type = console_color; std::optional m_log_file; }; @@ -165,30 +165,6 @@ public: spdlog::shutdown(); } - // the following static functions can be used to interact - // with a globally registered logger instance - - template - static inline void - create_global_logger(Args&&... args) { - global_logger() = std::make_shared(args...); - } - - static inline void - register_global_logger(logger&& lg) { - global_logger() = std::make_shared(std::move(lg)); - } - - static inline std::shared_ptr& - get_global_logger() { - return global_logger(); - } - - static inline void - destroy_global_logger() { - global_logger().reset(); - } - // the following member functions can be used to interact // with a specific logger instance inline void @@ -307,18 +283,37 @@ public: return ss.str(); } -private: - static std::shared_ptr& - global_logger() { - static std::shared_ptr s_global_logger; - return s_global_logger; - } - private: std::shared_ptr m_internal_logger; std::string m_type; }; -} // namespace scord +// the following static functions can be used to interact +// with a globally registered logger instance + +static inline std::shared_ptr& +get_global_logger() { + static std::shared_ptr s_global_logger; + return s_global_logger; +} + +template +static inline void +create_global_logger(Args&&... args) { + get_global_logger() = std::make_shared(args...); +} + +static inline void +register_global_logger(logger&& lg) { + get_global_logger() = std::make_shared(std::move(lg)); +} + +static inline void +destroy_global_logger() { + get_global_logger().reset(); +} + + +} // namespace logger #endif /* SCORD_LOGGER_HPP */ diff --git a/src/common/logger/macros.h b/src/common/logger/macros.h index f4ee6ac6..7df5f965 100644 --- a/src/common/logger/macros.h +++ b/src/common/logger/macros.h @@ -31,7 +31,6 @@ #define LOGGER_INFO(...) \ do { \ - using scord::logger; \ if(logger::get_global_logger()) { \ logger::get_global_logger()->info(__VA_ARGS__); \ } \ @@ -42,7 +41,6 @@ #define LOGGER_DEBUG(...) \ do { \ - using scord::logger; \ if(logger::get_global_logger()) { \ logger::get_global_logger()->debug(__VA_ARGS__); \ } \ @@ -50,7 +48,6 @@ #define LOGGER_FLUSH() \ do { \ - using scord::logger; \ if(logger::get_global_logger()) { \ logger::get_global_logger()->flush(); \ } \ @@ -69,7 +66,6 @@ #define LOGGER_WARN(...) \ do { \ - using scord::logger; \ if(logger::get_global_logger()) { \ logger::get_global_logger()->warn(__VA_ARGS__); \ } \ @@ -77,7 +73,6 @@ #define LOGGER_ERROR(...) \ do { \ - using scord::logger; \ if(logger::get_global_logger()) { \ logger::get_global_logger()->error(__VA_ARGS__); \ } \ @@ -85,7 +80,6 @@ #define LOGGER_ERRNO(...) \ do { \ - using scord::logger; \ if(logger::get_global_logger()) { \ logger::get_global_logger()->error_errno(__VA_ARGS__); \ } \ @@ -93,7 +87,7 @@ #define LOGGER_CRITICAL(...) \ do { \ - using scord::logger; \ + using logger::logger; \ if(logger::get_global_logger()) { \ logger::get_global_logger()->critical(__VA_ARGS__); \ } \ diff --git a/src/common/net/client.cpp b/src/common/net/client.cpp index 6617beac..969b5a3f 100644 --- a/src/common/net/client.cpp +++ b/src/common/net/client.cpp @@ -29,7 +29,7 @@ using namespace std::literals; -namespace scord::network { +namespace network { client::client(const std::string& protocol) @@ -56,4 +56,4 @@ client::self_address() const noexcept { } } -} // namespace scord::network +} // namespace network diff --git a/src/common/net/client.hpp b/src/common/net/client.hpp index c5877350..5e207149 100644 --- a/src/common/net/client.hpp +++ b/src/common/net/client.hpp @@ -22,13 +22,13 @@ * SPDX-License-Identifier: GPL-3.0-or-later *****************************************************************************/ -#ifndef SCORD_CLIENT_HPP -#define SCORD_CLIENT_HPP +#ifndef NETWORK_CLIENT_HPP +#define NETWORK_CLIENT_HPP #include #include -namespace scord::network { +namespace network { class endpoint; @@ -45,6 +45,6 @@ private: std::shared_ptr m_engine; }; -} // namespace scord::network +} // namespace network -#endif // SCORD_CLIENT_HPP +#endif // NETWORK_CLIENT_HPP diff --git a/src/common/net/endpoint.cpp b/src/common/net/endpoint.cpp index 81ec5204..2637037e 100644 --- a/src/common/net/endpoint.cpp +++ b/src/common/net/endpoint.cpp @@ -26,7 +26,7 @@ #include -namespace scord::network { +namespace network { endpoint::endpoint(std::shared_ptr engine, thallium::endpoint endpoint) @@ -37,4 +37,4 @@ endpoint::address() const { return m_endpoint; } -} // namespace scord::network +} // namespace network diff --git a/src/common/net/endpoint.hpp b/src/common/net/endpoint.hpp index 208498ea..5c640da1 100644 --- a/src/common/net/endpoint.hpp +++ b/src/common/net/endpoint.hpp @@ -22,14 +22,14 @@ * SPDX-License-Identifier: GPL-3.0-or-later *****************************************************************************/ -#ifndef SCORD_ENDPOINT_HPP -#define SCORD_ENDPOINT_HPP +#ifndef NETWORK_ENDPOINT_HPP +#define NETWORK_ENDPOINT_HPP #include #include #include -namespace scord::network { +namespace network { class endpoint { @@ -69,6 +69,6 @@ private: thallium::endpoint m_endpoint; }; -} // namespace scord::network +} // namespace network -#endif // SCORD_ENDPOINT_HPP +#endif // NETWORK_ENDPOINT_HPP diff --git a/src/common/net/request.hpp b/src/common/net/request.hpp index 0f4ad7c5..3154db26 100644 --- a/src/common/net/request.hpp +++ b/src/common/net/request.hpp @@ -22,13 +22,13 @@ * SPDX-License-Identifier: GPL-3.0-or-later *****************************************************************************/ -#ifndef SCORD_NET_REQUEST_HPP -#define SCORD_NET_REQUEST_HPP +#ifndef NETWORK_REQUEST_HPP +#define NETWORK_REQUEST_HPP #include #include -namespace scord::network { +namespace network { using request = thallium::request; @@ -100,6 +100,6 @@ private: using response_with_id = response_with_value; -} // namespace scord::network +} // namespace network -#endif // SCORD_NET_REQUEST_HPP +#endif // NETWORK_REQUEST_HPP diff --git a/src/common/net/serialization.hpp b/src/common/net/serialization.hpp index fbca80d6..1e013560 100644 --- a/src/common/net/serialization.hpp +++ b/src/common/net/serialization.hpp @@ -22,8 +22,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later *****************************************************************************/ -#ifndef SCORD_SERIALIZATION_HPP -#define SCORD_SERIALIZATION_HPP +#ifndef NETWORK_SERIALIZATION_HPP +#define NETWORK_SERIALIZATION_HPP #include #include @@ -57,13 +57,13 @@ CEREAL_SAVE_FUNCTION_NAME(Archive& ar, const std::filesystem::path& in) { } // namespace cereal -namespace scord::network::serialization { +namespace network::serialization { #define SCORD_SERIALIZATION_NVP CEREAL_NVP using input_archive = thallium::proc_input_archive<>; using output_archive = thallium::proc_output_archive<>; -} // namespace scord::network::serialization +} // namespace network::serialization -#endif // SCORD_SERIALIZATION_HPP +#endif // NETWORK_SERIALIZATION_HPP diff --git a/src/common/net/server.cpp b/src/common/net/server.cpp index 616dc90c..00401b82 100644 --- a/src/common/net/server.cpp +++ b/src/common/net/server.cpp @@ -40,10 +40,11 @@ #include #include #include "server.hpp" +#include "endpoint.hpp" using namespace std::literals; -namespace scord::network { +namespace network { server::server(std::string name, std::string address, bool daemonize, fs::path rundir) @@ -51,7 +52,7 @@ server::server(std::string name, std::string address, bool daemonize, m_daemonize(daemonize), m_rundir(std::move(rundir)), m_pidfile(daemonize ? std::make_optional(m_rundir / (m_name + ".pid")) : std::nullopt), - m_logger_config(m_name, scord::logger_type::console_color), + m_logger_config(m_name, logger::logger_type::console_color), m_network_engine(m_address, THALLIUM_SERVER_MODE) {} server::~server() = default; @@ -224,25 +225,25 @@ void server::init_logger() { switch(m_logger_config.type()) { - case console_color: + case logger::logger_type::console_color: logger::create_global_logger(m_logger_config.ident(), - logger_type::console_color); + logger::logger_type::console_color); break; - case syslog: + case logger::logger_type::syslog: logger::create_global_logger(m_logger_config.ident(), - logger_type::syslog); + logger::logger_type::syslog); break; - case file: + case logger::logger_type::file: if(m_logger_config.log_file().has_value()) { logger::create_global_logger(m_logger_config.ident(), - logger_type::file, + logger::logger_type::file, *m_logger_config.log_file()); break; } [[fallthrough]]; - case console: + case logger::logger_type::console: logger::create_global_logger(m_logger_config.ident(), - logger_type::console); + logger::logger_type::console); break; } } @@ -380,4 +381,4 @@ server::shutdown() { m_network_engine.finalize(); } -} // namespace scord::network +} // namespace network diff --git a/src/common/net/server.hpp b/src/common/net/server.hpp index a36a07b4..01d6210f 100644 --- a/src/common/net/server.hpp +++ b/src/common/net/server.hpp @@ -22,8 +22,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later *****************************************************************************/ -#ifndef SCORD_SERVER_HPP -#define SCORD_SERVER_HPP +#ifndef SCORD_RPC_SERVER +#define SCORD_RPC_SERVER #include #include @@ -33,10 +33,13 @@ #include #include -namespace scord::network { +namespace network { using request = thallium::request; +template +using provider = thallium::provider; + class server { public: @@ -47,9 +50,9 @@ public: template void - configure_logger(scord::logger_type type, Args&&... args) { - m_logger_config = - logger_config(m_name, type, std::forward(args)...); + configure_logger(logger::logger_type type, Args&&... args) { + m_logger_config = logger::logger_config(m_name, type, + std::forward(args)...); } int @@ -93,11 +96,15 @@ private: bool m_daemonize; fs::path m_rundir; std::optional m_pidfile; - logger_config m_logger_config; + logger::logger_config m_logger_config; + +protected: thallium::engine m_network_engine; + +private: scord::utils::signal_listener m_signal_listener; }; -} // namespace scord::network +} // namespace network -#endif // SCORD_SERVER_HPP +#endif // SCORD_RPC_SERVER diff --git a/src/lib/detail/impl.cpp b/src/lib/detail/impl.cpp index ec28bcb7..8cc989b0 100644 --- a/src/lib/detail/impl.cpp +++ b/src/lib/detail/impl.cpp @@ -49,7 +49,7 @@ namespace scord::detail { scord::error_code ping(const server& srv) { - scord::network::client rpc_client{srv.protocol()}; + network::client rpc_client{srv.protocol()}; const auto rpc_id = ::api::remote_procedure::new_id(); @@ -65,7 +65,7 @@ ping(const server& srv) { if(const auto call_rv = endp.call("ADM_"s + __FUNCTION__); call_rv.has_value()) { - const scord::network::generic_response resp{call_rv.value()}; + const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, "rpc id: {} name: {} from: {} <= " @@ -87,7 +87,7 @@ register_job(const server& srv, const job::resources& job_resources, const job::requirements& job_requirements, scord::slurm_job_id slurm_id) { - scord::network::client rpc_client{srv.protocol()}; + network::client rpc_client{srv.protocol()}; const auto rpc_id = ::api::remote_procedure::new_id(); @@ -107,7 +107,7 @@ register_job(const server& srv, const job::resources& job_resources, job_requirements, slurm_id); call_rv.has_value()) { - const scord::network::response_with_id resp{call_rv.value()}; + const network::response_with_id resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, "rpc id: {} name: {} from: {} <= " @@ -132,7 +132,7 @@ scord::error_code update_job(const server& srv, const job& job, const job::resources& new_resources) { - scord::network::client rpc_client{srv.protocol()}; + network::client rpc_client{srv.protocol()}; const auto rpc_id = ::api::remote_procedure::new_id(); @@ -150,7 +150,7 @@ update_job(const server& srv, const job& job, endp.call("ADM_"s + __FUNCTION__, job.id(), new_resources); call_rv.has_value()) { - const scord::network::generic_response resp{call_rv.value()}; + const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, "rpc id: {} name: {} from: {} <= " @@ -169,7 +169,7 @@ update_job(const server& srv, const job& job, scord::error_code remove_job(const server& srv, const job& job) { - scord::network::client rpc_client{srv.protocol()}; + network::client rpc_client{srv.protocol()}; const auto rpc_id = ::api::remote_procedure::new_id(); @@ -185,7 +185,7 @@ remove_job(const server& srv, const job& job) { if(const auto& call_rv = endp.call("ADM_"s + __FUNCTION__, job.id()); call_rv.has_value()) { - const scord::network::generic_response resp{call_rv.value()}; + const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, "rpc id: {} name: {} from: {} <= " @@ -207,7 +207,7 @@ register_adhoc_storage(const server& srv, const std::string& name, const adhoc_storage::ctx& ctx, const adhoc_storage::resources& resources) { - scord::network::client rpc_client{srv.protocol()}; + network::client rpc_client{srv.protocol()}; const auto rpc_id = ::api::remote_procedure::new_id(); @@ -226,7 +226,7 @@ register_adhoc_storage(const server& srv, const std::string& name, ctx, resources); call_rv.has_value()) { - const scord::network::response_with_id resp{call_rv.value()}; + const network::response_with_id resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, "rpc id: {} name: {} from: {} <= " @@ -252,7 +252,7 @@ scord::error_code update_adhoc_storage(const server& srv, const adhoc_storage& adhoc_storage, const adhoc_storage::resources& new_resources) { - scord::network::client rpc_client{srv.protocol()}; + network::client rpc_client{srv.protocol()}; const auto rpc_id = ::api::remote_procedure::new_id(); @@ -270,7 +270,7 @@ update_adhoc_storage(const server& srv, const adhoc_storage& adhoc_storage, adhoc_storage.id(), new_resources); call_rv.has_value()) { - const scord::network::generic_response resp{call_rv.value()}; + const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, "rpc id: {} name: {} from: {} <= " @@ -290,7 +290,7 @@ update_adhoc_storage(const server& srv, const adhoc_storage& adhoc_storage, scord::error_code remove_adhoc_storage(const server& srv, const adhoc_storage& adhoc_storage) { - scord::network::client rpc_client{srv.protocol()}; + network::client rpc_client{srv.protocol()}; const auto rpc_id = ::api::remote_procedure::new_id(); @@ -307,7 +307,7 @@ remove_adhoc_storage(const server& srv, const adhoc_storage& adhoc_storage) { endp.call("ADM_"s + __FUNCTION__, adhoc_storage.id()); call_rv.has_value()) { - const scord::network::generic_response resp{call_rv.value()}; + const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, "rpc id: {} name: {} from: {} <= " @@ -328,7 +328,7 @@ tl::expected register_pfs_storage(const server& srv, const std::string& name, enum pfs_storage::type type, const pfs_storage::ctx& ctx) { - scord::network::client rpc_client{srv.protocol()}; + network::client rpc_client{srv.protocol()}; const auto rpc_id = ::api::remote_procedure::new_id(); @@ -345,7 +345,7 @@ register_pfs_storage(const server& srv, const std::string& name, endp.call("ADM_"s + __FUNCTION__, name, type, ctx); call_rv.has_value()) { - const scord::network::response_with_id resp{call_rv.value()}; + const network::response_with_id resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, "rpc id: {} name: {} from: {} <= " @@ -370,7 +370,7 @@ scord::error_code update_pfs_storage(const server& srv, const pfs_storage& pfs_storage, const scord::pfs_storage::ctx& new_ctx) { - scord::network::client rpc_client{srv.protocol()}; + network::client rpc_client{srv.protocol()}; const auto rpc_id = ::api::remote_procedure::new_id(); @@ -388,7 +388,7 @@ update_pfs_storage(const server& srv, const pfs_storage& pfs_storage, endp.call("ADM_"s + __FUNCTION__, pfs_storage.id(), new_ctx); call_rv.has_value()) { - const scord::network::generic_response resp{call_rv.value()}; + const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, "rpc id: {} name: {} from: {} <= " @@ -408,7 +408,7 @@ update_pfs_storage(const server& srv, const pfs_storage& pfs_storage, scord::error_code remove_pfs_storage(const server& srv, const pfs_storage& pfs_storage) { - scord::network::client rpc_client{srv.protocol()}; + network::client rpc_client{srv.protocol()}; const auto rpc_id = ::api::remote_procedure::new_id(); @@ -425,7 +425,7 @@ remove_pfs_storage(const server& srv, const pfs_storage& pfs_storage) { endp.call("ADM_"s + __FUNCTION__, pfs_storage.id()); call_rv.has_value()) { - const scord::network::generic_response resp{call_rv.value()}; + const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, "rpc id: {} name: {} from: {} <= " @@ -445,7 +445,7 @@ remove_pfs_storage(const server& srv, const pfs_storage& pfs_storage) { scord::error_code deploy_adhoc_storage(const server& srv, const adhoc_storage& adhoc_storage) { - scord::network::client rpc_client{srv.protocol()}; + network::client rpc_client{srv.protocol()}; const auto rpc_id = ::api::remote_procedure::new_id(); @@ -462,7 +462,7 @@ deploy_adhoc_storage(const server& srv, const adhoc_storage& adhoc_storage) { endp.call("ADM_"s + __FUNCTION__, adhoc_storage.id()); call_rv.has_value()) { - const scord::network::generic_response resp{call_rv.value()}; + const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, "rpc id: {} name: {} from: {} <= " @@ -482,7 +482,7 @@ deploy_adhoc_storage(const server& srv, const adhoc_storage& adhoc_storage) { scord::error_code tear_down_adhoc_storage(const server& srv, const adhoc_storage& adhoc_storage) { - scord::network::client rpc_client{srv.protocol()}; + network::client rpc_client{srv.protocol()}; const auto rpc_id = ::api::remote_procedure::new_id(); @@ -499,7 +499,7 @@ tear_down_adhoc_storage(const server& srv, const adhoc_storage& adhoc_storage) { endp.call("ADM_"s + __FUNCTION__, adhoc_storage.id()); call_rv.has_value()) { - const scord::network::generic_response resp{call_rv.value()}; + const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, "rpc id: {} name: {} from: {} <= " @@ -523,7 +523,7 @@ transfer_datasets(const server& srv, const job& job, const std::vector& limits, transfer::mapping mapping) { - scord::network::client rpc_client{srv.protocol()}; + network::client rpc_client{srv.protocol()}; const auto rpc_id = ::api::remote_procedure::new_id(); @@ -542,7 +542,7 @@ transfer_datasets(const server& srv, const job& job, sources, targets, limits, mapping); call_rv.has_value()) { - const scord::network::response_with_id resp{call_rv.value()}; + const network::response_with_id resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, "rpc id: {} name: {} from: {} <= " diff --git a/src/lib/libscord.cpp b/src/lib/libscord.cpp index ebc0c206..909c270c 100644 --- a/src/lib/libscord.cpp +++ b/src/lib/libscord.cpp @@ -53,11 +53,11 @@ init_logger() { if(const auto p = std::getenv(scord::env::LOG); p && !std::string{p}.empty() && std::string{p} != "0") { if(const auto log_file = std::getenv(scord::env::LOG_OUTPUT)) { - scord::logger::create_global_logger( - "libscord", scord::logger_type::file, log_file); + logger::create_global_logger( + "libscord", logger::logger_type::file, log_file); } else { - scord::logger::create_global_logger( - "libscord", scord::logger_type::console_color); + logger::create_global_logger( + "libscord", logger::logger_type::console_color); } } } catch(const std::exception& ex) { diff --git a/src/lib/types.cpp b/src/lib/types.cpp index ba584bf3..b9ea9136 100644 --- a/src/lib/types.cpp +++ b/src/lib/types.cpp @@ -173,20 +173,20 @@ node::serialize(Archive& ar) { // we must also explicitly instantiate our template functions for // serialization in the desired archives template void -node::impl::save( - scord::network::serialization::output_archive&) const; +node::impl::save( + network::serialization::output_archive&) const; template void -node::impl::load( - scord::network::serialization::input_archive&); +node::impl::load( + network::serialization::input_archive&); template void -node::serialize( - scord::network::serialization::output_archive&); +node::serialize( + network::serialization::output_archive&); template void -node::serialize( - scord::network::serialization::input_archive&); +node::serialize( + network::serialization::input_archive&); class job::impl { @@ -426,20 +426,20 @@ transfer::serialize(Archive& ar) { // we must also explicitly instantiate our template functions for // serialization in the desired archives template void -transfer::impl::save( - scord::network::serialization::output_archive&) const; +transfer::impl::save( + network::serialization::output_archive&) const; template void -transfer::impl::load( - scord::network::serialization::input_archive&); +transfer::impl::load( + network::serialization::input_archive&); template void -transfer::serialize( - scord::network::serialization::output_archive&); +transfer::serialize( + network::serialization::output_archive&); template void -transfer::serialize( - scord::network::serialization::input_archive&); +transfer::serialize( + network::serialization::input_archive&); class dataset::impl { public: @@ -513,20 +513,20 @@ dataset::serialize(Archive& ar) { // we must also explicitly instantiate our template functions for // serialization in the desired archives template void -dataset::impl::save( - scord::network::serialization::output_archive&) const; +dataset::impl::save( + network::serialization::output_archive&) const; template void -dataset::impl::load( - scord::network::serialization::input_archive&); +dataset::impl::load( + network::serialization::input_archive&); template void -dataset::serialize( - scord::network::serialization::output_archive&); +dataset::serialize( + network::serialization::output_archive&); template void -dataset::serialize( - scord::network::serialization::input_archive&); +dataset::serialize( + network::serialization::input_archive&); adhoc_storage::resources::resources(std::vector nodes) : m_nodes(std::move(nodes)) {} @@ -771,20 +771,20 @@ adhoc_storage::serialize(Archive& ar) { // we must also explicitly instantiate our template functions for // serialization in the desired archives template void -adhoc_storage::impl::save( - scord::network::serialization::output_archive&) const; +adhoc_storage::impl::save( + network::serialization::output_archive&) const; template void -adhoc_storage::impl::load( - scord::network::serialization::input_archive&); +adhoc_storage::impl::load( + network::serialization::input_archive&); template void -adhoc_storage::serialize( - scord::network::serialization::output_archive&); +adhoc_storage::serialize( + network::serialization::output_archive&); template void -adhoc_storage::serialize( - scord::network::serialization::input_archive&); +adhoc_storage::serialize( + network::serialization::input_archive&); adhoc_storage::~adhoc_storage() = default; @@ -944,20 +944,20 @@ pfs_storage::serialize(Archive& ar) { // we must also explicitly instantiate our template functions for // serialization in the desired archives template void -pfs_storage::impl::save( - scord::network::serialization::output_archive&) const; +pfs_storage::impl::save( + network::serialization::output_archive&) const; template void -pfs_storage::impl::load( - scord::network::serialization::input_archive&); +pfs_storage::impl::load( + network::serialization::input_archive&); template void -pfs_storage::serialize( - scord::network::serialization::output_archive&); +pfs_storage::serialize( + network::serialization::output_archive&); template void -pfs_storage::serialize( - scord::network::serialization::input_archive&); +pfs_storage::serialize( + network::serialization::input_archive&); namespace qos { @@ -1093,20 +1093,20 @@ entity::serialize(Archive& ar) { // we must also explicitly instantiate our template functions for // serialization in the desired archives template void -entity::impl::save( - scord::network::serialization::output_archive&) const; +entity::impl::save( + network::serialization::output_archive&) const; template void -entity::impl::load( - scord::network::serialization::input_archive&); +entity::impl::load( + network::serialization::input_archive&); template void -entity::serialize( - scord::network::serialization::output_archive&); +entity::serialize( + network::serialization::output_archive&); template void -entity::serialize( - scord::network::serialization::input_archive&); +entity::serialize( + network::serialization::input_archive&); class limit::impl { @@ -1221,20 +1221,20 @@ limit::serialize(Archive& ar) { // we must also explicitly instantiate our template functions for // serialization in the desired archives template void -limit::impl::save( - scord::network::serialization::output_archive&) const; +limit::impl::save( + network::serialization::output_archive&) const; template void -limit::impl::load( - scord::network::serialization::input_archive&); +limit::impl::load( + network::serialization::input_archive&); template void -limit::serialize( - scord::network::serialization::output_archive&); +limit::serialize( + network::serialization::output_archive&); template void -limit::serialize( - scord::network::serialization::input_archive&); +limit::serialize( + network::serialization::input_archive&); } // namespace qos diff --git a/src/scord-ctl/CMakeLists.txt b/src/scord-ctl/CMakeLists.txt index c3663918..9654c6e3 100644 --- a/src/scord-ctl/CMakeLists.txt +++ b/src/scord-ctl/CMakeLists.txt @@ -26,7 +26,7 @@ add_executable(scord-ctl) target_sources( - scord-ctl PRIVATE scord-ctl.cpp rpc_handlers.hpp rpc_handlers.cpp + scord-ctl PRIVATE scord_ctl.cpp rpc_server.cpp rpc_server.hpp ) target_include_directories( diff --git a/src/scord-ctl/rpc_handlers.cpp b/src/scord-ctl/rpc_server.cpp similarity index 63% rename from src/scord-ctl/rpc_handlers.cpp rename to src/scord-ctl/rpc_server.cpp index 65df94ad..b3b0e586 100644 --- a/src/scord-ctl/rpc_handlers.cpp +++ b/src/scord-ctl/rpc_server.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright 2021-2022, Barcelona Supercomputing Center (BSC), Spain + * Copyright 2021-2023, Barcelona Supercomputing Center (BSC), Spain * * This software was partially supported by the EuroHPC-funded project ADMIRE * (Project ID: 956748, https://www.admire-eurohpc.eu). @@ -22,10 +22,11 @@ * SPDX-License-Identifier: GPL-3.0-or-later *****************************************************************************/ -#include #include -#include -#include "rpc_handlers.hpp" +#include +#include "rpc_server.hpp" + +using namespace std::literals; struct remote_procedure { static std::uint64_t @@ -35,36 +36,50 @@ struct remote_procedure { } }; -namespace scord_ctl::network::handlers { +namespace scord_ctl { + +rpc_server::rpc_server(std::string name, std::string address, bool daemonize, + std::filesystem::path rundir) + : server::server(std::move(name), std::move(address), std::move(daemonize), + std::move(rundir)), + provider::provider(m_network_engine, 0) { + +#define EXPAND(rpc_name) "ADM_" #rpc_name##s, &rpc_server::rpc_name + + provider::define(EXPAND(ping)); + provider::define(EXPAND(deploy_adhoc_storage)); + +#undef EXPAND +} void -ping(const scord::network::request& req) { +rpc_server::ping(const network::request& req) { - using scord::network::generic_response; - using scord::network::get_address; + using network::generic_response; + using network::get_address; + const auto rpc_name = "ADM_"s + __FUNCTION__; const auto rpc_id = remote_procedure::new_id(); LOGGER_INFO("rpc id: {} name: {} from: {} => " "body: {{}}", - rpc_id, std::quoted(__FUNCTION__), - std::quoted(get_address(req))); + rpc_id, std::quoted(rpc_name), std::quoted(get_address(req))); const auto resp = generic_response{rpc_id, scord::error_code::success}; LOGGER_INFO("rpc id: {} name: {} to: {} <= " "body: {{retval: {}}}", - rpc_id, std::quoted(__FUNCTION__), - std::quoted(get_address(req)), scord::error_code::success); + rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), + scord::error_code::success); req.respond(resp); } void -deploy_adhoc_storage(const scord::network::request& req) { +rpc_server::deploy_adhoc_storage(const network::request& req) { - using scord::network::generic_response; - using scord::network::get_address; + using network::generic_response; + using network::get_address; const auto rpc_id = remote_procedure::new_id(); @@ -83,4 +98,4 @@ deploy_adhoc_storage(const scord::network::request& req) { req.respond(resp); } -} // namespace scord_ctl::network::handlers +} // namespace scord_ctl diff --git a/src/scord-ctl/rpc_handlers.hpp b/src/scord-ctl/rpc_server.hpp similarity index 63% rename from src/scord-ctl/rpc_handlers.hpp rename to src/scord-ctl/rpc_server.hpp index e8f45ca0..8c01273d 100644 --- a/src/scord-ctl/rpc_handlers.hpp +++ b/src/scord-ctl/rpc_server.hpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright 2021-2022, Barcelona Supercomputing Center (BSC), Spain + * Copyright 2021-2023, Barcelona Supercomputing Center (BSC), Spain * * This software was partially supported by the EuroHPC-funded project ADMIRE * (Project ID: 956748, https://www.admire-eurohpc.eu). @@ -22,21 +22,29 @@ * SPDX-License-Identifier: GPL-3.0-or-later *****************************************************************************/ -#ifndef SCORD_CTL_RPC_HANDLERS_HPP -#define SCORD_CTL_RPC_HANDLERS_HPP -#include -#include -#include +#ifndef SCORD_CTL_RPC_SERVER_HPP +#define SCORD_CTL_RPC_SERVER_HPP -namespace scord_ctl::network::handlers { +#include -void -ping(const scord::network::request& req); +namespace scord_ctl { -void -deploy_adhoc_storage(const scord::network::request& req); +class rpc_server : public network::server, + public network::provider { -} // namespace scord_ctl::network::handlers +public: + rpc_server(std::string name, std::string address, bool daemonize, + std::filesystem::path rundir); -#endif // SCORD_CTL_RPC_HANDLERS_HPP +private: + void + ping(const network::request& req); + + void + deploy_adhoc_storage(const network::request& req); +}; + +} // namespace scord_ctl + +#endif // SCORD_SCORD_CTL_RPC_SERVER_HPP diff --git a/src/scord-ctl/scord-ctl.cpp b/src/scord-ctl/scord_ctl.cpp similarity index 83% rename from src/scord-ctl/scord-ctl.cpp rename to src/scord-ctl/scord_ctl.cpp index 17a03ab2..b9c0286b 100644 --- a/src/scord-ctl/scord-ctl.cpp +++ b/src/scord-ctl/scord_ctl.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright 2021, Barcelona Supercomputing Center (BSC), Spain + * Copyright 2021-2023, Barcelona Supercomputing Center (BSC), Spain * * This software was partially supported by the EuroHPC-funded project ADMIRE * (Project ID: 956748, https://www.admire-eurohpc.eu). @@ -31,8 +31,7 @@ #include #include -#include -#include "rpc_handlers.hpp" +#include "rpc_server.hpp" namespace fs = std::filesystem; using namespace std::literals; @@ -76,22 +75,12 @@ main(int argc, char* argv[]) { CLI11_PARSE(app, argc, argv); try { - scord::network::server srv(progname, cli_args.address, false, - fs::current_path()); + scord_ctl::rpc_server srv(progname, cli_args.address, false, + fs::current_path()); if(cli_args.output_file) { - srv.configure_logger(scord::logger_type::file, + srv.configure_logger(logger::logger_type::file, *cli_args.output_file); } - -// convenience macro to ensure the names of an RPC and its handler -// always match -#define EXPAND(rpc_name) \ - "ADM_" #rpc_name##s, scord_ctl::network::handlers::rpc_name - - srv.set_handler(EXPAND(ping)); - -#undef EXPAND - return srv.run(); } catch(const std::exception& ex) { fmt::print(stderr, diff --git a/src/scord/CMakeLists.txt b/src/scord/CMakeLists.txt index 5221d3b7..5ccfb19e 100644 --- a/src/scord/CMakeLists.txt +++ b/src/scord/CMakeLists.txt @@ -25,10 +25,10 @@ # scord daemon add_executable(scord) -target_sources(scord PRIVATE scord.cpp rpc_handlers.hpp - rpc_handlers.cpp job_manager.hpp adhoc_storage_manager.hpp +target_sources(scord PRIVATE scord.cpp + job_manager.hpp adhoc_storage_manager.hpp pfs_storage_manager.hpp ${CMAKE_CURRENT_BINARY_DIR}/defaults.hpp - internal_types.hpp internal_types.cpp) + internal_types.hpp internal_types.cpp rpc_server.hpp rpc_server.cpp) configure_file(defaults.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/defaults.hpp @ONLY) diff --git a/src/scord/adhoc_storage_manager.hpp b/src/scord/adhoc_storage_manager.hpp index 381991a6..848248b2 100644 --- a/src/scord/adhoc_storage_manager.hpp +++ b/src/scord/adhoc_storage_manager.hpp @@ -28,7 +28,6 @@ #include #include -#include #include #include #include @@ -38,7 +37,7 @@ namespace scord { -struct adhoc_storage_manager : scord::utils::singleton { +struct adhoc_storage_manager { tl::expected, scord::error_code> @@ -144,9 +143,6 @@ struct adhoc_storage_manager : scord::utils::singleton { private: - friend class scord::utils::singleton; - adhoc_storage_manager() = default; - mutable abt::shared_mutex m_adhoc_storages_mutex; std::unordered_map> diff --git a/src/scord/job_manager.hpp b/src/scord/job_manager.hpp index cf9da9c2..17feef77 100644 --- a/src/scord/job_manager.hpp +++ b/src/scord/job_manager.hpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -37,8 +36,7 @@ namespace scord { - -struct job_manager : scord::utils::singleton { +struct job_manager { tl::expected, scord::error_code> create(scord::slurm_job_id slurm_id, scord::job::resources job_resources, @@ -112,9 +110,6 @@ struct job_manager : scord::utils::singleton { } private: - friend class scord::utils::singleton; - job_manager() = default; - mutable abt::shared_mutex m_jobs_mutex; std::unordered_map> diff --git a/src/scord/pfs_storage_manager.hpp b/src/scord/pfs_storage_manager.hpp index de021848..a5bb0548 100644 --- a/src/scord/pfs_storage_manager.hpp +++ b/src/scord/pfs_storage_manager.hpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -37,7 +36,7 @@ namespace scord { -struct pfs_storage_manager : scord::utils::singleton { +struct pfs_storage_manager { tl::expected, scord::error_code> @@ -117,9 +116,6 @@ struct pfs_storage_manager : scord::utils::singleton { } private: - friend class scord::utils::singleton; - pfs_storage_manager() = default; - mutable abt::shared_mutex m_pfs_storages_mutex; std::unordered_map> diff --git a/src/scord/rpc_handlers.hpp b/src/scord/rpc_handlers.hpp deleted file mode 100644 index 1ccc493d..00000000 --- a/src/scord/rpc_handlers.hpp +++ /dev/null @@ -1,89 +0,0 @@ -/****************************************************************************** - * Copyright 2021, Barcelona Supercomputing Center (BSC), Spain - * - * This software was partially supported by the EuroHPC-funded project ADMIRE - * (Project ID: 956748, https://www.admire-eurohpc.eu). - * - * This file is part of scord. - * - * scord is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * scord is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with scord. If not, see . - * - * SPDX-License-Identifier: GPL-3.0-or-later - *****************************************************************************/ - -#ifndef SCORD_RPC_HANDLERS_HPP -#define SCORD_RPC_HANDLERS_HPP - -#include -#include -#include - -namespace scord::network::handlers { - -void -ping(const scord::network::request& req); - -void -register_job(const scord::network::request& req, - const scord::job::resources& job_resources, - const scord::job::requirements& job_requirements, - scord::slurm_job_id slurm_id); - -void -update_job(const request& req, scord::job_id job_id, - const scord::job::resources& new_resources); - -void -remove_job(const request& req, scord::job_id job_id); - -void -register_adhoc_storage(const request& req, const std::string& name, - enum scord::adhoc_storage::type type, - const scord::adhoc_storage::ctx& ctx, - const scord::adhoc_storage::resources& resources); -void -update_adhoc_storage(const request& req, std::uint64_t adhoc_id, - const scord::adhoc_storage::resources& new_resources); - -void -remove_adhoc_storage(const request& req, std::uint64_t adhoc_id); - -void -deploy_adhoc_storage(const request& req, std::uint64_t adhoc_id); - -void -tear_down_adhoc_storage(const request& req, std::uint64_t adhoc_id); - -void -register_pfs_storage(const request& req, const std::string& name, - enum scord::pfs_storage::type type, - const scord::pfs_storage::ctx& ctx); - -void -update_pfs_storage(const request& req, std::uint64_t pfs_id, - const scord::pfs_storage::ctx& new_ctx); - -void -remove_pfs_storage(const request& req, std::uint64_t pfs_id); - -void -transfer_datasets(const request& req, scord::job_id job_id, - const std::vector& sources, - const std::vector& targets, - const std::vector& limits, - enum scord::transfer::mapping mapping); - -} // namespace scord::network::handlers - -#endif // SCORD_RPC_HANDLERS_HPP diff --git a/src/scord/rpc_handlers.cpp b/src/scord/rpc_server.cpp similarity index 74% rename from src/scord/rpc_handlers.cpp rename to src/scord/rpc_server.cpp index 3f2fca05..dc8f343b 100644 --- a/src/scord/rpc_handlers.cpp +++ b/src/scord/rpc_server.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright 2021-2022, Barcelona Supercomputing Center (BSC), Spain + * Copyright 2021-2023, Barcelona Supercomputing Center (BSC), Spain * * This software was partially supported by the EuroHPC-funded project ADMIRE * (Project ID: 956748, https://www.admire-eurohpc.eu). @@ -22,15 +22,13 @@ * SPDX-License-Identifier: GPL-3.0-or-later *****************************************************************************/ -#include +#include #include -#include "rpc_handlers.hpp" -#include "job_manager.hpp" -#include "adhoc_storage_manager.hpp" -#include "pfs_storage_manager.hpp" +#include +#include "rpc_server.hpp" -// Process running -#include +// required for ::waitpid() +#include #include using namespace std::literals; @@ -43,13 +41,38 @@ struct remote_procedure { } }; -namespace scord::network::handlers { +namespace scord { + +rpc_server::rpc_server(std::string name, std::string address, bool daemonize, + std::filesystem::path rundir) + : server::server(std::move(name), std::move(address), std::move(daemonize), + std::move(rundir)), + provider::provider(m_network_engine, 0) { + +#define EXPAND(rpc_name) "ADM_" #rpc_name##s, &rpc_server::rpc_name + + provider::define(EXPAND(ping)); + provider::define(EXPAND(register_job)); + provider::define(EXPAND(update_job)); + provider::define(EXPAND(remove_job)); + provider::define(EXPAND(register_adhoc_storage)); + provider::define(EXPAND(update_adhoc_storage)); + provider::define(EXPAND(remove_adhoc_storage)); + provider::define(EXPAND(deploy_adhoc_storage)); + provider::define(EXPAND(tear_down_adhoc_storage)); + provider::define(EXPAND(register_pfs_storage)); + provider::define(EXPAND(update_pfs_storage)); + provider::define(EXPAND(remove_pfs_storage)); + provider::define(EXPAND(transfer_datasets)); + +#undef EXPAND +} void -ping(const scord::network::request& req) { +rpc_server::ping(const network::request& req) { - using scord::network::generic_response; - using scord::network::get_address; + using network::generic_response; + using network::get_address; const auto rpc_name = "ADM_"s + __FUNCTION__; const auto rpc_id = remote_procedure::new_id(); @@ -69,12 +92,13 @@ ping(const scord::network::request& req) { } void -register_job(const scord::network::request& req, - const scord::job::resources& job_resources, - const scord::job::requirements& job_requirements, - scord::slurm_job_id slurm_id) { +rpc_server::register_job(const network::request& req, + const scord::job::resources& job_resources, + const scord::job::requirements& job_requirements, + scord::slurm_job_id slurm_id) { - using scord::network::get_address; + using network::get_address; + using network::response_with_id; const auto rpc_name = "ADM_"s + __FUNCTION__; const auto rpc_id = remote_procedure::new_id(); @@ -87,10 +111,9 @@ register_job(const scord::network::request& req, scord::error_code ec; std::optional job_id; - auto& jm = scord::job_manager::instance(); if(const auto jm_result = - jm.create(slurm_id, job_resources, job_requirements); + m_job_manager.create(slurm_id, job_resources, job_requirements); jm_result.has_value()) { const auto& job_info = jm_result.value(); @@ -99,8 +122,7 @@ register_job(const scord::network::request& req, // adhoc_storage instance (if registered) if(job_requirements.adhoc_storage()) { const auto adhoc_id = job_requirements.adhoc_storage()->id(); - auto& adhoc_manager = scord::adhoc_storage_manager::instance(); - ec = adhoc_manager.add_client_info(adhoc_id, job_info); + ec = m_adhoc_manager.add_client_info(adhoc_id, job_info); if(!ec) { goto respond; @@ -126,10 +148,11 @@ respond: } void -update_job(const request& req, scord::job_id job_id, - const scord::job::resources& new_resources) { +rpc_server::update_job(const network::request& req, scord::job_id job_id, + const scord::job::resources& new_resources) { - using scord::network::get_address; + using network::generic_response; + using network::get_address; const auto rpc_name = "ADM_"s + __FUNCTION__; const auto rpc_id = remote_procedure::new_id(); @@ -139,8 +162,7 @@ update_job(const request& req, scord::job_id job_id, rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), job_id, new_resources); - auto& jm = scord::job_manager::instance(); - const auto ec = jm.update(job_id, new_resources); + const auto ec = m_job_manager.update(job_id, new_resources); if(!ec) { LOGGER_ERROR("rpc id: {} error_msg: \"Error updating job: {}\"", rpc_id, @@ -158,9 +180,10 @@ update_job(const request& req, scord::job_id job_id, } void -remove_job(const request& req, scord::job_id job_id) { +rpc_server::remove_job(const network::request& req, scord::job_id job_id) { - using scord::network::get_address; + using network::generic_response; + using network::get_address; const auto rpc_name = "ADM_"s + __FUNCTION__; const auto rpc_id = remote_procedure::new_id(); @@ -171,8 +194,7 @@ remove_job(const request& req, scord::job_id job_id) { job_id); scord::error_code ec; - auto& jm = scord::job_manager::instance(); - const auto jm_result = jm.remove(job_id); + const auto jm_result = m_job_manager.remove(job_id); if(jm_result) { // if the job was using an adhoc storage instance, inform the @@ -181,8 +203,7 @@ remove_job(const request& req, scord::job_id job_id) { if(const auto adhoc_storage = job_info->requirements()->adhoc_storage(); adhoc_storage.has_value()) { - auto& adhoc_manager = scord::adhoc_storage_manager::instance(); - ec = adhoc_manager.remove_client_info(adhoc_storage->id()); + ec = m_adhoc_manager.remove_client_info(adhoc_storage->id()); } } else { LOGGER_ERROR("rpc id: {} error_msg: \"Error removing job: {}\"", rpc_id, @@ -201,12 +222,14 @@ remove_job(const request& req, scord::job_id job_id) { } void -register_adhoc_storage(const request& req, const std::string& name, - enum scord::adhoc_storage::type type, - const scord::adhoc_storage::ctx& ctx, - const scord::adhoc_storage::resources& resources) { +rpc_server::register_adhoc_storage( + const network::request& req, const std::string& name, + enum scord::adhoc_storage::type type, + const scord::adhoc_storage::ctx& ctx, + const scord::adhoc_storage::resources& resources) { - using scord::network::get_address; + using network::get_address; + using network::response_with_id; const auto rpc_name = "ADM_"s + __FUNCTION__; const auto rpc_id = remote_procedure::new_id(); @@ -219,9 +242,9 @@ register_adhoc_storage(const request& req, const std::string& name, scord::error_code ec; std::optional adhoc_id; - auto& adhoc_manager = scord::adhoc_storage_manager::instance(); - if(const auto am_result = adhoc_manager.create(type, name, ctx, resources); + if(const auto am_result = + m_adhoc_manager.create(type, name, ctx, resources); am_result.has_value()) { const auto& adhoc_storage_info = am_result.value(); adhoc_id = adhoc_storage_info->adhoc_storage().id(); @@ -243,10 +266,12 @@ register_adhoc_storage(const request& req, const std::string& name, } void -update_adhoc_storage(const request& req, std::uint64_t adhoc_id, - const scord::adhoc_storage::resources& new_resources) { +rpc_server::update_adhoc_storage( + const network::request& req, std::uint64_t adhoc_id, + const scord::adhoc_storage::resources& new_resources) { - using scord::network::get_address; + using network::generic_response; + using network::get_address; const auto rpc_name = "ADM_"s + __FUNCTION__; const auto rpc_id = remote_procedure::new_id(); @@ -256,8 +281,7 @@ update_adhoc_storage(const request& req, std::uint64_t adhoc_id, rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), adhoc_id, new_resources); - auto& adhoc_manager = scord::adhoc_storage_manager::instance(); - const auto ec = adhoc_manager.update(adhoc_id, new_resources); + const auto ec = m_adhoc_manager.update(adhoc_id, new_resources); if(!ec) { LOGGER_ERROR( @@ -276,9 +300,11 @@ update_adhoc_storage(const request& req, std::uint64_t adhoc_id, } void -remove_adhoc_storage(const request& req, std::uint64_t adhoc_id) { +rpc_server::remove_adhoc_storage(const network::request& req, + std::uint64_t adhoc_id) { - using scord::network::get_address; + using network::generic_response; + using network::get_address; const auto rpc_name = "ADM_"s + __FUNCTION__; const auto rpc_id = remote_procedure::new_id(); @@ -288,8 +314,7 @@ remove_adhoc_storage(const request& req, std::uint64_t adhoc_id) { rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), adhoc_id); - auto& adhoc_manager = scord::adhoc_storage_manager::instance(); - scord::error_code ec = adhoc_manager.remove(adhoc_id); + scord::error_code ec = m_adhoc_manager.remove(adhoc_id); if(!ec) { LOGGER_ERROR("rpc id: {} error_msg: \"Error removing job: {}\"", rpc_id, @@ -307,9 +332,11 @@ remove_adhoc_storage(const request& req, std::uint64_t adhoc_id) { } void -deploy_adhoc_storage(const request& req, std::uint64_t adhoc_id) { +rpc_server::deploy_adhoc_storage(const network::request& req, + std::uint64_t adhoc_id) { - using scord::network::get_address; + using network::generic_response; + using network::get_address; const auto rpc_name = "ADM_"s + __FUNCTION__; const auto rpc_id = remote_procedure::new_id(); @@ -320,9 +347,8 @@ deploy_adhoc_storage(const request& req, std::uint64_t adhoc_id) { adhoc_id); auto ec = scord::error_code::success; - auto& adhoc_manager = scord::adhoc_storage_manager::instance(); - if(const auto am_result = adhoc_manager.find(adhoc_id); + if(const auto am_result = m_adhoc_manager.find(adhoc_id); am_result.has_value()) { const auto& storage_info = am_result.value(); const auto adhoc_storage = storage_info->adhoc_storage(); @@ -370,7 +396,7 @@ deploy_adhoc_storage(const request& req, std::uint64_t adhoc_id) { } default: { int wstatus = 0; - pid_t retwait = waitpid(pid, &wstatus, 0); + pid_t retwait = ::waitpid(pid, &wstatus, 0); if(retwait == -1) { LOGGER_ERROR( "rpc id: {} error_msg: \"Error waitpid code: {}\"", @@ -407,10 +433,11 @@ deploy_adhoc_storage(const request& req, std::uint64_t adhoc_id) { } void -tear_down_adhoc_storage(const request& req, std::uint64_t adhoc_id) { +rpc_server::tear_down_adhoc_storage(const network::request& req, + std::uint64_t adhoc_id) { - using scord::network::generic_response; - using scord::network::get_address; + using network::generic_response; + using network::get_address; const auto rpc_name = "ADM_"s + __FUNCTION__; const auto rpc_id = remote_procedure::new_id(); @@ -433,11 +460,13 @@ tear_down_adhoc_storage(const request& req, std::uint64_t adhoc_id) { } void -register_pfs_storage(const request& req, const std::string& name, - enum scord::pfs_storage::type type, - const scord::pfs_storage::ctx& ctx) { +rpc_server::register_pfs_storage(const network::request& req, + const std::string& name, + enum scord::pfs_storage::type type, + const scord::pfs_storage::ctx& ctx) { - using scord::network::get_address; + using network::get_address; + using network::response_with_id; const auto rpc_name = "ADM_"s + __FUNCTION__; const auto rpc_id = remote_procedure::new_id(); @@ -449,9 +478,8 @@ register_pfs_storage(const request& req, const std::string& name, scord::error_code ec; std::optional pfs_id = 0; - auto& pfs_manager = scord::pfs_storage_manager::instance(); - if(const auto pm_result = pfs_manager.create(type, name, ctx); + if(const auto pm_result = m_pfs_manager.create(type, name, ctx); pm_result.has_value()) { const auto& adhoc_storage_info = pm_result.value(); pfs_id = adhoc_storage_info->pfs_storage().id(); @@ -472,10 +500,12 @@ register_pfs_storage(const request& req, const std::string& name, } void -update_pfs_storage(const request& req, std::uint64_t pfs_id, - const scord::pfs_storage::ctx& new_ctx) { +rpc_server::update_pfs_storage(const network::request& req, + std::uint64_t pfs_id, + const scord::pfs_storage::ctx& new_ctx) { - using scord::network::get_address; + using network::generic_response; + using network::get_address; const auto rpc_name = "ADM_"s + __FUNCTION__; const auto rpc_id = remote_procedure::new_id(); @@ -485,8 +515,7 @@ update_pfs_storage(const request& req, std::uint64_t pfs_id, rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), pfs_id, new_ctx); - auto& pfs_manager = scord::pfs_storage_manager::instance(); - const auto ec = pfs_manager.update(pfs_id, new_ctx); + const auto ec = m_pfs_manager.update(pfs_id, new_ctx); if(!ec) { LOGGER_ERROR("rpc id: {} error_msg: \"Error updating pfs_storage: {}\"", @@ -504,9 +533,11 @@ update_pfs_storage(const request& req, std::uint64_t pfs_id, } void -remove_pfs_storage(const request& req, std::uint64_t pfs_id) { +rpc_server::remove_pfs_storage(const network::request& req, + std::uint64_t pfs_id) { - using scord::network::get_address; + using network::generic_response; + using network::get_address; const auto rpc_name = "ADM_"s + __FUNCTION__; const auto rpc_id = remote_procedure::new_id(); @@ -516,8 +547,7 @@ remove_pfs_storage(const request& req, std::uint64_t pfs_id) { rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), pfs_id); - auto& pfs_manager = scord::pfs_storage_manager::instance(); - scord::error_code ec = pfs_manager.remove(pfs_id); + scord::error_code ec = m_pfs_manager.remove(pfs_id); if(!ec) { LOGGER_ERROR("rpc id: {} error_msg: \"Error removing pfs storage: {}\"", @@ -535,13 +565,14 @@ remove_pfs_storage(const request& req, std::uint64_t pfs_id) { } void -transfer_datasets(const request& req, scord::job_id job_id, - const std::vector& sources, - const std::vector& targets, - const std::vector& limits, - enum scord::transfer::mapping mapping) { +rpc_server::transfer_datasets(const network::request& req, scord::job_id job_id, + const std::vector& sources, + const std::vector& targets, + const std::vector& limits, + enum scord::transfer::mapping mapping) { - using scord::network::get_address; + using network::get_address; + using network::response_with_id; const auto rpc_name = "ADM_"s + __FUNCTION__; const auto rpc_id = remote_procedure::new_id(); @@ -570,4 +601,4 @@ transfer_datasets(const request& req, scord::job_id job_id, req.respond(resp); } -} // namespace scord::network::handlers +} // namespace scord diff --git a/src/scord/rpc_server.hpp b/src/scord/rpc_server.hpp new file mode 100644 index 00000000..5a0df6f9 --- /dev/null +++ b/src/scord/rpc_server.hpp @@ -0,0 +1,106 @@ +/****************************************************************************** + * Copyright 2021-2023, Barcelona Supercomputing Center (BSC), Spain + * + * This software was partially supported by the EuroHPC-funded project ADMIRE + * (Project ID: 956748, https://www.admire-eurohpc.eu). + * + * This file is part of scord. + * + * scord is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * scord is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with scord. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + *****************************************************************************/ + +#ifndef SCORD_RPC_SERVER_HPP +#define SCORD_RPC_SERVER_HPP + +#include +#include +#include +#include "job_manager.hpp" +#include "adhoc_storage_manager.hpp" +#include "pfs_storage_manager.hpp" + +namespace scord { + +class rpc_server : public network::server, + public network::provider { + +public: + rpc_server(std::string name, std::string address, bool daemonize, + std::filesystem::path rundir); + +private: + void + ping(const network::request& req); + + void + register_job(const network::request& req, + const scord::job::resources& job_resources, + const scord::job::requirements& job_requirements, + scord::slurm_job_id slurm_id); + + void + update_job(const network::request& req, scord::job_id job_id, + const scord::job::resources& new_resources); + + void + remove_job(const network::request& req, scord::job_id job_id); + + void + register_adhoc_storage(const network::request& req, const std::string& name, + enum scord::adhoc_storage::type type, + const scord::adhoc_storage::ctx& ctx, + const scord::adhoc_storage::resources& resources); + void + update_adhoc_storage(const network::request& req, std::uint64_t adhoc_id, + const scord::adhoc_storage::resources& new_resources); + + void + remove_adhoc_storage(const network::request& req, std::uint64_t adhoc_id); + + void + deploy_adhoc_storage(const network::request& req, std::uint64_t adhoc_id); + + void + tear_down_adhoc_storage(const network::request& req, + std::uint64_t adhoc_id); + + void + register_pfs_storage(const network::request& req, const std::string& name, + enum scord::pfs_storage::type type, + const scord::pfs_storage::ctx& ctx); + + void + update_pfs_storage(const network::request& req, std::uint64_t pfs_id, + const scord::pfs_storage::ctx& new_ctx); + + void + remove_pfs_storage(const network::request& req, std::uint64_t pfs_id); + + void + transfer_datasets(const network::request& req, scord::job_id job_id, + const std::vector& sources, + const std::vector& targets, + const std::vector& limits, + enum scord::transfer::mapping mapping); + + job_manager m_job_manager; + adhoc_storage_manager m_adhoc_manager; + pfs_storage_manager m_pfs_manager; +}; + +} // namespace scord + +#endif // SCORD_RPC_SERVER_HPP diff --git a/src/scord/scord.cpp b/src/scord/scord.cpp index a11a93c8..5d87e3e5 100644 --- a/src/scord/scord.cpp +++ b/src/scord/scord.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright 2021, Barcelona Supercomputing Center (BSC), Spain + * Copyright 2021-2023, Barcelona Supercomputing Center (BSC), Spain * * This software was partially supported by the EuroHPC-funded project ADMIRE * (Project ID: 956748, https://www.admire-eurohpc.eu). @@ -31,8 +31,7 @@ #include #include -#include -#include "rpc_handlers.hpp" +#include "rpc_server.hpp" #include "defaults.hpp" #include @@ -108,13 +107,12 @@ public: } }; - int main(int argc, char* argv[]) { struct { bool foreground = !scord::config::defaults::daemonize; - scord::logger_type log_type = scord::logger_type::console_color; + logger::logger_type log_type = logger::logger_type::console_color; std::optional output_file; std::optional rundir; std::optional address; @@ -129,7 +127,7 @@ main(int argc, char* argv[]) { app.add_flag_callback( "-C,--force-console", [&]() { - cli_args.log_type = scord::logger_type::console_color; + cli_args.log_type = logger::logger_type::console_color; cli_args.output_file = std::nullopt; }, "Override any logging options defined in the configuration file " @@ -146,7 +144,7 @@ main(int argc, char* argv[]) { app.add_option_function( "-o,--output", [&](const std::string& val) { - cli_args.log_type = scord::logger_type::file; + cli_args.log_type = logger::logger_type::file; cli_args.output_file = fs::path{val}; }, "Write any output to FILENAME console") @@ -168,7 +166,7 @@ main(int argc, char* argv[]) { ->group(""); global_settings->add_option_function( "--logfile", [&](const std::string& val) { - cli_args.log_type = scord::logger_type::file; + cli_args.log_type = logger::logger_type::file; cli_args.output_file = fs::path{val}; }); global_settings->add_option("--rundir", cli_args.rundir); @@ -186,32 +184,9 @@ main(int argc, char* argv[]) { } try { - scord::network::server srv( - progname, *cli_args.address, !cli_args.foreground, - cli_args.rundir.value_or(fs::current_path())); - + scord::rpc_server srv(progname, *cli_args.address, !cli_args.foreground, + cli_args.rundir.value_or(fs::current_path())); srv.configure_logger(cli_args.log_type, cli_args.output_file); - - // convenience macro to ensure the names of an RPC and - // its handler always match -#define EXPAND(rpc_name) "ADM_" #rpc_name##s, scord::network::handlers::rpc_name - - srv.set_handler(EXPAND(ping)); - srv.set_handler(EXPAND(register_job)); - srv.set_handler(EXPAND(update_job)); - srv.set_handler(EXPAND(remove_job)); - srv.set_handler(EXPAND(register_adhoc_storage)); - srv.set_handler(EXPAND(update_adhoc_storage)); - srv.set_handler(EXPAND(remove_adhoc_storage)); - srv.set_handler(EXPAND(deploy_adhoc_storage)); - srv.set_handler(EXPAND(tear_down_adhoc_storage)); - srv.set_handler(EXPAND(register_pfs_storage)); - srv.set_handler(EXPAND(update_pfs_storage)); - srv.set_handler(EXPAND(remove_pfs_storage)); - srv.set_handler(EXPAND(transfer_datasets)); - -#undef EXPAND - return srv.run(); } catch(const std::exception& ex) { fmt::print(stderr, -- GitLab From e1c57a55f70c5b462515324e988e6138fdac8e0a Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Tue, 16 May 2023 14:07:34 +0200 Subject: [PATCH 12/17] WIP: fix logger (merge with previous) --- src/common/logger/logger.cpp | 6 +++++- src/common/logger/logger.hpp | 25 ++++++++++++++++--------- src/common/logger/macros.h | 7 +++++++ src/common/net/server.cpp | 2 +- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/common/logger/logger.cpp b/src/common/logger/logger.cpp index 974874b1..391dd300 100644 --- a/src/common/logger/logger.cpp +++ b/src/common/logger/logger.cpp @@ -49,6 +49,8 @@ logger_setup(const char* ident, logger_type type, const char* log_file) { void logger_log(enum logger_level level, const char* fmt, ...) { + using logger::logger; + if(const auto logger = logger::get_global_logger(); logger) { std::array msg; // NOLINT @@ -79,7 +81,9 @@ logger_log(enum logger_level level, const char* fmt, ...) { void logger_destroy() { + using logger::logger; + if(logger::get_global_logger()) { - logger::destroy_global_logger(); + ::logger::destroy_global_logger(); } } diff --git a/src/common/logger/logger.hpp b/src/common/logger/logger.hpp index b9b67439..09611fb2 100644 --- a/src/common/logger/logger.hpp +++ b/src/common/logger/logger.hpp @@ -165,6 +165,12 @@ public: spdlog::shutdown(); } + static std::shared_ptr& + get_global_logger() { + static std::shared_ptr s_global_logger; + return s_global_logger; + } + // the following member functions can be used to interact // with a specific logger instance inline void @@ -291,26 +297,27 @@ private: // the following static functions can be used to interact // with a globally registered logger instance -static inline std::shared_ptr& -get_global_logger() { - static std::shared_ptr s_global_logger; - return s_global_logger; -} - template static inline void create_global_logger(Args&&... args) { - get_global_logger() = std::make_shared(args...); + logger::get_global_logger() = std::make_shared(args...); } static inline void register_global_logger(logger&& lg) { - get_global_logger() = std::make_shared(std::move(lg)); + logger::get_global_logger() = std::make_shared(std::move(lg)); } static inline void destroy_global_logger() { - get_global_logger().reset(); + logger::get_global_logger().reset(); +} + +static inline void +flush_global_logger() { + if(logger::get_global_logger()) { + logger::get_global_logger()->flush(); + } } diff --git a/src/common/logger/macros.h b/src/common/logger/macros.h index 7df5f965..1da2c6d3 100644 --- a/src/common/logger/macros.h +++ b/src/common/logger/macros.h @@ -31,6 +31,7 @@ #define LOGGER_INFO(...) \ do { \ + using logger::logger; \ if(logger::get_global_logger()) { \ logger::get_global_logger()->info(__VA_ARGS__); \ } \ @@ -41,6 +42,7 @@ #define LOGGER_DEBUG(...) \ do { \ + using logger::logger; \ if(logger::get_global_logger()) { \ logger::get_global_logger()->debug(__VA_ARGS__); \ } \ @@ -48,6 +50,7 @@ #define LOGGER_FLUSH() \ do { \ + using logger::logger; \ if(logger::get_global_logger()) { \ logger::get_global_logger()->flush(); \ } \ @@ -66,6 +69,7 @@ #define LOGGER_WARN(...) \ do { \ + using logger::logger; \ if(logger::get_global_logger()) { \ logger::get_global_logger()->warn(__VA_ARGS__); \ } \ @@ -73,6 +77,7 @@ #define LOGGER_ERROR(...) \ do { \ + using logger::logger; \ if(logger::get_global_logger()) { \ logger::get_global_logger()->error(__VA_ARGS__); \ } \ @@ -80,6 +85,7 @@ #define LOGGER_ERRNO(...) \ do { \ + using logger::logger; \ if(logger::get_global_logger()) { \ logger::get_global_logger()->error_errno(__VA_ARGS__); \ } \ @@ -87,6 +93,7 @@ #define LOGGER_CRITICAL(...) \ do { \ + using logger::logger; \ using logger::logger; \ if(logger::get_global_logger()) { \ logger::get_global_logger()->critical(__VA_ARGS__); \ diff --git a/src/common/net/server.cpp b/src/common/net/server.cpp index 00401b82..27f1154b 100644 --- a/src/common/net/server.cpp +++ b/src/common/net/server.cpp @@ -213,7 +213,7 @@ server::signal_handler(int signum) { case SIGHUP: LOGGER_WARN("A signal (SIGHUP) occurred."); - logger::get_global_logger()->flush(); + logger::flush_global_logger(); break; default: -- GitLab From bd901bccb4c826050abce67ae558bf97c0ee3082 Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Wed, 17 May 2023 11:34:04 +0200 Subject: [PATCH 13/17] Improve network::server API - Add `endpoint lookup(std::string address)` so that a RPC server can lookup peers for RPC forwarding. - Add `std::string self_address()` so that a RPC server can determine its own address string. --- src/common/net/CMakeLists.txt | 4 ++-- src/common/net/client.cpp | 7 +++---- src/common/net/client.hpp | 2 +- src/common/net/endpoint.cpp | 5 ++--- src/common/net/endpoint.hpp | 7 +++---- src/common/net/server.cpp | 20 ++++++++++++++++++++ src/common/net/server.hpp | 8 ++++++++ 7 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/common/net/CMakeLists.txt b/src/common/net/CMakeLists.txt index 68c5658e..f73ca886 100644 --- a/src/common/net/CMakeLists.txt +++ b/src/common/net/CMakeLists.txt @@ -35,8 +35,8 @@ set_property(TARGET _rpc_client PROPERTY POSITION_INDEPENDENT_CODE ON) add_library(_rpc_server STATIC) target_sources( _rpc_server - INTERFACE server.hpp request.hpp serialization.hpp - PRIVATE server.cpp + INTERFACE endpoint.hpp server.hpp request.hpp serialization.hpp + PRIVATE server.cpp endpoint.cpp ) target_link_libraries(_rpc_server PUBLIC common::logger thallium) diff --git a/src/common/net/client.cpp b/src/common/net/client.cpp index 969b5a3f..1c56a4aa 100644 --- a/src/common/net/client.cpp +++ b/src/common/net/client.cpp @@ -33,13 +33,12 @@ namespace network { client::client(const std::string& protocol) - : m_engine(std::make_shared(protocol, - THALLIUM_CLIENT_MODE)) {} + : m_engine(protocol, THALLIUM_CLIENT_MODE) {} std::optional client::lookup(const std::string& address) noexcept { try { - return endpoint{m_engine, m_engine->lookup(address)}; + return endpoint{m_engine, m_engine.lookup(address)}; } catch(const std::exception& ex) { LOGGER_ERROR("client::lookup() failed: {}", ex.what()); return std::nullopt; @@ -49,7 +48,7 @@ client::lookup(const std::string& address) noexcept { std::string client::self_address() const noexcept { try { - return m_engine->self(); + return m_engine.self(); } catch(const std::exception& ex) { LOGGER_ERROR("client::self_address() failed: {}", ex.what()); return "unknown"s; diff --git a/src/common/net/client.hpp b/src/common/net/client.hpp index 5e207149..c371ffb6 100644 --- a/src/common/net/client.hpp +++ b/src/common/net/client.hpp @@ -42,7 +42,7 @@ public: self_address() const noexcept; private: - std::shared_ptr m_engine; + thallium::engine m_engine; }; } // namespace network diff --git a/src/common/net/endpoint.cpp b/src/common/net/endpoint.cpp index 2637037e..25ed4edd 100644 --- a/src/common/net/endpoint.cpp +++ b/src/common/net/endpoint.cpp @@ -28,9 +28,8 @@ namespace network { -endpoint::endpoint(std::shared_ptr engine, - thallium::endpoint endpoint) - : m_engine(std::move(engine)), m_endpoint(std::move(endpoint)) {} +endpoint::endpoint(thallium::engine& engine, thallium::endpoint endpoint) + : m_engine(engine), m_endpoint(std::move(endpoint)) {} std::string endpoint::address() const { diff --git a/src/common/net/endpoint.hpp b/src/common/net/endpoint.hpp index 5c640da1..1c8db2aa 100644 --- a/src/common/net/endpoint.hpp +++ b/src/common/net/endpoint.hpp @@ -34,8 +34,7 @@ namespace network { class endpoint { public: - endpoint(std::shared_ptr engine, - thallium::endpoint endpoint); + endpoint(thallium::engine& engine, thallium::endpoint endpoint); std::string address() const; @@ -45,7 +44,7 @@ public: call(const std::string& rpc_name, Args&&... args) const { try { - const auto rpc = m_engine->define(rpc_name); + const auto rpc = m_engine.define(rpc_name); return std::make_optional( rpc.on(m_endpoint)(std::forward(args)...)); } catch(const std::exception& ex) { @@ -65,7 +64,7 @@ public: } private: - std::shared_ptr m_engine; + mutable thallium::engine m_engine; thallium::endpoint m_endpoint; }; diff --git a/src/common/net/server.cpp b/src/common/net/server.cpp index 27f1154b..494bc219 100644 --- a/src/common/net/server.cpp +++ b/src/common/net/server.cpp @@ -303,6 +303,26 @@ server::print_farewell() { LOGGER_INFO("{:=>{}}", "", farewell.size()); } +std::optional +server::lookup(const std::string& address) noexcept { + try { + return endpoint{m_network_engine, m_network_engine.lookup(address)}; + } catch(const std::exception& ex) { + LOGGER_ERROR("server::lookup() failed: {}", ex.what()); + return std::nullopt; + } +} + +std::string +server::self_address() const noexcept { + try { + return m_network_engine.self(); + } catch(const std::exception& ex) { + LOGGER_ERROR("server::self_address() failed: {}", ex.what()); + return "unknown"s; + } +} + int server::run() { diff --git a/src/common/net/server.hpp b/src/common/net/server.hpp index 01d6210f..bafa8b82 100644 --- a/src/common/net/server.hpp +++ b/src/common/net/server.hpp @@ -35,6 +35,8 @@ namespace network { +class endpoint; + using request = thallium::request; template @@ -55,6 +57,12 @@ public: std::forward(args)...); } + std::optional + lookup(const std::string& address) noexcept; + + std::string + self_address() const noexcept; + int run(); void -- GitLab From 4f2d492fde0b7465760f9efc08ef0c9c32da704b Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Wed, 17 May 2023 11:43:27 +0200 Subject: [PATCH 14/17] Move `deploy_adhoc_storage` logic to `scord-ctl` `scord` now just forwards the request to the appropriate `scord-ctl` instance. --- src/scord-ctl/rpc_server.cpp | 83 ++++++++++++++++++++++++++++--- src/scord-ctl/rpc_server.hpp | 7 ++- src/scord/rpc_server.cpp | 95 +++++++++++------------------------- 3 files changed, 112 insertions(+), 73 deletions(-) diff --git a/src/scord-ctl/rpc_server.cpp b/src/scord-ctl/rpc_server.cpp index b3b0e586..f8c9f4e4 100644 --- a/src/scord-ctl/rpc_server.cpp +++ b/src/scord-ctl/rpc_server.cpp @@ -26,6 +26,10 @@ #include #include "rpc_server.hpp" +// required for ::waitpid() +#include +#include + using namespace std::literals; struct remote_procedure { @@ -76,24 +80,91 @@ rpc_server::ping(const network::request& req) { } void -rpc_server::deploy_adhoc_storage(const network::request& req) { +rpc_server::deploy_adhoc_storage( + const network::request& req, + const enum scord::adhoc_storage::type adhoc_type, + const scord::adhoc_storage::ctx& adhoc_ctx, + const scord::adhoc_storage::resources& adhoc_resources) { using network::generic_response; using network::get_address; + const auto rpc_name = "ADM_"s + __FUNCTION__; const auto rpc_id = remote_procedure::new_id(); LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{}}", + "body: {{type: {}, ctx: {}, resources: {}}}", rpc_id, std::quoted(__FUNCTION__), - std::quoted(get_address(req))); + std::quoted(get_address(req)), adhoc_type, adhoc_ctx, + adhoc_resources); + + auto ec = scord::error_code::success; + + if(adhoc_type == scord::adhoc_storage::type::gekkofs) { + /* Number of nodes */ + const std::string nodes = + std::to_string(adhoc_resources.nodes().size()); + + /* Walltime */ + const std::string walltime = std::to_string(adhoc_ctx.walltime()); + + /* Launch script */ + switch(const auto pid = fork()) { + case 0: { + std::vector args; + args.push_back("gkfs"); + // args.push_back("-c"); + // args.push_back("gkfs.conf"); + args.push_back("-n"); + args.push_back(nodes.c_str()); + // args.push_back("-w"); + // args.push_back(walltime.c_str()); + args.push_back("--srun"); + args.push_back("start"); + args.push_back(NULL); + std::vector env; + env.push_back(NULL); + + execvpe("gkfs", const_cast(args.data()), + const_cast(env.data())); + LOGGER_INFO("ADM_deploy_adhoc_storage() script didn't execute"); + exit(EXIT_FAILURE); + break; + } + case -1: { + ec = scord::error_code::other; + LOGGER_ERROR("rpc id: {} name: {} to: {} <= " + "body: {{retval: {}}}", + rpc_id, std::quoted(rpc_name), + std::quoted(get_address(req)), ec); + break; + } + default: { + int wstatus = 0; + pid_t retwait = ::waitpid(pid, &wstatus, 0); + if(retwait == -1) { + LOGGER_ERROR( + "rpc id: {} error_msg: \"Error waitpid code: {}\"", + rpc_id, retwait); + ec = scord::error_code::other; + } else { + if(WEXITSTATUS(wstatus) != 0) { + ec = scord::error_code::other; + } else { + ec = scord::error_code::success; + } + } + break; + } + } + } - const auto resp = generic_response{rpc_id, scord::error_code::success}; + const auto resp = generic_response{rpc_id, ec}; LOGGER_INFO("rpc id: {} name: {} to: {} <= " "body: {{retval: {}}}", - rpc_id, std::quoted(__FUNCTION__), - std::quoted(get_address(req)), scord::error_code::success); + rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), + ec); req.respond(resp); } diff --git a/src/scord-ctl/rpc_server.hpp b/src/scord-ctl/rpc_server.hpp index 8c01273d..2988a1c4 100644 --- a/src/scord-ctl/rpc_server.hpp +++ b/src/scord-ctl/rpc_server.hpp @@ -27,6 +27,7 @@ #define SCORD_CTL_RPC_SERVER_HPP #include +#include namespace scord_ctl { @@ -42,7 +43,11 @@ private: ping(const network::request& req); void - deploy_adhoc_storage(const network::request& req); + deploy_adhoc_storage( + const network::request& req, + enum scord::adhoc_storage::type adhoc_type, + const scord::adhoc_storage::ctx& adhoc_ctx, + const scord::adhoc_storage::resources& adhoc_resources); }; } // namespace scord_ctl diff --git a/src/scord/rpc_server.cpp b/src/scord/rpc_server.cpp index dc8f343b..6055a7ad 100644 --- a/src/scord/rpc_server.cpp +++ b/src/scord/rpc_server.cpp @@ -24,13 +24,10 @@ #include #include +#include #include #include "rpc_server.hpp" -// required for ::waitpid() -#include -#include - using namespace std::literals; struct remote_procedure { @@ -348,72 +345,38 @@ rpc_server::deploy_adhoc_storage(const network::request& req, auto ec = scord::error_code::success; + // contact the adhoc controller and ask it to deploy the adhoc storage if(const auto am_result = m_adhoc_manager.find(adhoc_id); am_result.has_value()) { - const auto& storage_info = am_result.value(); - const auto adhoc_storage = storage_info->adhoc_storage(); - - if(adhoc_storage.type() == scord::adhoc_storage::type::gekkofs) { - const auto adhoc_ctx = adhoc_storage.context(); - /* Number of nodes */ - const std::string nodes = std::to_string( - adhoc_storage.get_resources().nodes().size()); - - /* Walltime */ - const std::string walltime = std::to_string(adhoc_ctx.walltime()); - - /* Launch script */ - switch(const auto pid = fork()) { - case 0: { - std::vector args; - args.push_back("gkfs"); - // args.push_back("-c"); - // args.push_back("gkfs.conf"); - args.push_back("-n"); - args.push_back(nodes.c_str()); - // args.push_back("-w"); - // args.push_back(walltime.c_str()); - args.push_back("--srun"); - args.push_back("start"); - args.push_back(NULL); - std::vector env; - env.push_back(NULL); - - execvpe("gkfs", const_cast(args.data()), - const_cast(env.data())); - LOGGER_INFO( - "ADM_deploy_adhoc_storage() script didn't execute"); - exit(EXIT_FAILURE); - break; - } - case -1: { - ec = scord::error_code::other; - LOGGER_ERROR("rpc id: {} name: {} to: {} <= " - "body: {{retval: {}}}", - rpc_id, std::quoted(rpc_name), - std::quoted(get_address(req)), ec); - break; - } - default: { - int wstatus = 0; - pid_t retwait = ::waitpid(pid, &wstatus, 0); - if(retwait == -1) { - LOGGER_ERROR( - "rpc id: {} error_msg: \"Error waitpid code: {}\"", - rpc_id, retwait); - ec = scord::error_code::other; - } else { - if(WEXITSTATUS(wstatus) != 0) { - ec = scord::error_code::other; - } else { - ec = scord::error_code::success; - } - } - break; - } + const auto& adhoc_info = am_result.value(); + const auto adhoc_storage = adhoc_info->adhoc_storage(); + + if(const auto lookup_rv = + lookup(adhoc_storage.context().controller_address()); + lookup_rv.has_value()) { + const auto& endp = lookup_rv.value(); + + LOGGER_INFO("rpc id: {} name: {} from: {} => " + "body: {{type: {}, ctx: {}, resources: {}}}", + rpc_id, std::quoted("ADM_"s + __FUNCTION__), + std::quoted(self_address()), adhoc_storage.type(), + adhoc_storage.context(), adhoc_storage.get_resources()); + + if(const auto call_rv = endp.call( + "ADM_"s + __FUNCTION__, adhoc_storage.type(), + adhoc_storage.context(), adhoc_storage.get_resources()); + call_rv.has_value()) { + + const network::generic_response resp{call_rv.value()}; + ec = resp.error_code(); + + LOGGER_EVAL(resp.error_code(), INFO, ERROR, + "rpc id: {} name: {} from: {} <= " + "body: {{retval: {}}} [op_id: {}]", + rpc_id, std::quoted("ADM_"s + __FUNCTION__), + std::quoted(endp.address()), ec, resp.op_id()); } } - } else { ec = am_result.error(); LOGGER_ERROR("rpc id: {} name: {} to: {} <= " -- GitLab From 2389ad6931703cac7a27a12450c9ae9414dc0db3 Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Mon, 22 May 2023 16:16:50 +0200 Subject: [PATCH 15/17] logging: Refactor RPC formatting --- src/common/net/CMakeLists.txt | 4 +- src/common/net/utilities.hpp | 135 ++++++++++++++++ src/lib/detail/impl.cpp | 245 ++++++++++------------------- src/scord-ctl/rpc_server.cpp | 50 ++---- src/scord/rpc_server.cpp | 281 +++++++++++++--------------------- 5 files changed, 339 insertions(+), 376 deletions(-) create mode 100644 src/common/net/utilities.hpp diff --git a/src/common/net/CMakeLists.txt b/src/common/net/CMakeLists.txt index f73ca886..983e7df3 100644 --- a/src/common/net/CMakeLists.txt +++ b/src/common/net/CMakeLists.txt @@ -25,7 +25,7 @@ add_library(_rpc_client STATIC) target_sources( _rpc_client - INTERFACE endpoint.hpp client.hpp request.hpp serialization.hpp + INTERFACE endpoint.hpp client.hpp request.hpp serialization.hpp utilities.hpp PRIVATE endpoint.cpp client.cpp ) @@ -35,7 +35,7 @@ set_property(TARGET _rpc_client PROPERTY POSITION_INDEPENDENT_CODE ON) add_library(_rpc_server STATIC) target_sources( _rpc_server - INTERFACE endpoint.hpp server.hpp request.hpp serialization.hpp + INTERFACE endpoint.hpp server.hpp request.hpp serialization.hpp utilities.hpp PRIVATE server.cpp endpoint.cpp ) diff --git a/src/common/net/utilities.hpp b/src/common/net/utilities.hpp new file mode 100644 index 00000000..cc1dda42 --- /dev/null +++ b/src/common/net/utilities.hpp @@ -0,0 +1,135 @@ +/****************************************************************************** + * Copyright 2021-2023, Barcelona Supercomputing Center (BSC), Spain + * + * This software was partially supported by the EuroHPC-funded project ADMIRE + * (Project ID: 956748, https://www.admire-eurohpc.eu). + * + * This file is part of scord. + * + * scord is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * scord is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with scord. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + *****************************************************************************/ + + +#ifndef NETWORK_UTILITIES_HPP +#define NETWORK_UTILITIES_HPP + +#include +#include +#include +#include +#include +#include + +namespace network { + +class rpc_info { +private: + static std::uint64_t + new_id() { + static std::atomic_uint64_t s_current_id; + return s_current_id++; + } + +public: + rpc_info(std::uint64_t id, std::string name, std::string address) + : m_id(id), m_children(0), m_name(std::move(name)), + m_address(std::move(address)) {} + + rpc_info(std::uint64_t id, std::uint64_t pid, std::string name, + std::string address) + : m_id(id), m_pid(pid), m_children(0), m_name(std::move(name)), + m_address(std::move(address)) {} + + template + static rpc_info + create(Args&&... args) { + return {new_id(), std::forward(args)...}; + } + + template + rpc_info + add_child(std::string address) const { + return {m_children, m_id, m_name, std::move(address)}; + } + + constexpr std::uint64_t + id() const { + return m_id; + } + + constexpr std::optional + pid() const { + return m_pid; + } + + const std::string& + name() const { + return m_name; + } + + const std::string& + address() const { + return m_address; + } + +private: + std::uint64_t m_id; + std::optional m_pid; + std::uint64_t m_children; + std::string m_name; + std::string m_address; +}; + +} // namespace network + +template <> +struct fmt::formatter { + + // RPC direction format: + // '<': from self to target (outbound) + // '>': from target to self (inbound) + bool m_outbound = true; + + // Parses format specifications in the form: + constexpr auto + parse(format_parse_context& ctx) { + auto it = ctx.begin(), end = ctx.end(); + + if(it != end && (*it == '<' || *it == '>')) { + m_outbound = *it++ == '<'; + } + + if(it != end && *it != '}') { + ctx.on_error("invalid format"); + } + + return it; + } + + template + constexpr auto + format(const network::rpc_info& rpc, FormatContext& ctx) const { + format_to(ctx.out(), "{}{} id: {} name: {} ", m_outbound ? "<=" : "=>", + rpc.pid() ? fmt::format(" pid: {}", *rpc.pid()) : "", + rpc.id(), std::quoted(rpc.name())); + return m_outbound ? format_to(ctx.out(), "to: {}", + std::quoted(rpc.address())) + : format_to(ctx.out(), "from: {}", + std::quoted(rpc.address())); + } +}; + +#endif // NETWORK_UTILITIES_HPP diff --git a/src/lib/detail/impl.cpp b/src/lib/detail/impl.cpp index 8cc989b0..4ffb890d 100644 --- a/src/lib/detail/impl.cpp +++ b/src/lib/detail/impl.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "impl.hpp" @@ -46,33 +47,28 @@ struct remote_procedure { namespace scord::detail { +#define RPC_NAME() ("ADM_"s + __FUNCTION__) + scord::error_code ping(const server& srv) { network::client rpc_client{srv.protocol()}; - const auto rpc_id = ::api::remote_procedure::new_id(); + const auto rpc = network::rpc_info::create(RPC_NAME(), srv.address()); if(const auto lookup_rv = rpc_client.lookup(srv.address()); lookup_rv.has_value()) { const auto& endp = lookup_rv.value(); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{}}", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(rpc_client.self_address())); + LOGGER_INFO("rpc {:<} body: {{}}", rpc); - if(const auto call_rv = endp.call("ADM_"s + __FUNCTION__); - call_rv.has_value()) { + if(const auto call_rv = endp.call(rpc.name()); call_rv.has_value()) { const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, - "rpc id: {} name: {} from: {} <= " - "body: {{retval: {}}} [op_id: {}]", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(endp.address()), resp.error_code(), - resp.op_id()); + "rpc {:>} body: {{retval: {}}} [op_id: {}]", rpc, + resp.error_code(), resp.op_id()); return resp.error_code(); } @@ -89,32 +85,25 @@ register_job(const server& srv, const job::resources& job_resources, network::client rpc_client{srv.protocol()}; - const auto rpc_id = ::api::remote_procedure::new_id(); + const auto rpc = network::rpc_info::create(RPC_NAME(), srv.address()); if(const auto lookup_rv = rpc_client.lookup(srv.address()); lookup_rv.has_value()) { const auto& endp = lookup_rv.value(); - LOGGER_INFO( - "rpc id: {} name: {} from: {} => " - "body: {{job_resources: {}, job_requirements: {}, slurm_id: " - "{}}}", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(rpc_client.self_address()), job_resources, - job_requirements, slurm_id); + LOGGER_INFO("rpc {:<} body: {{job_resources: {}, job_requirements: {}, " + "slurm_id: {}}}", + rpc, job_resources, job_requirements, slurm_id); - if(const auto call_rv = endp.call("ADM_"s + __FUNCTION__, job_resources, + if(const auto call_rv = endp.call(rpc.name(), job_resources, job_requirements, slurm_id); call_rv.has_value()) { const network::response_with_id resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, - "rpc id: {} name: {} from: {} <= " - "body: {{retval: {}, job_id: {}}} [op_id: {}]", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(endp.address()), resp.error_code(), - resp.value(), resp.op_id()); + "rpc {:>} body: {{retval: {}, job_id: {}}} [op_id: {}]", + rpc, resp.error_code(), resp.value(), resp.op_id()); if(const auto ec = resp.error_code(); !ec) { return tl::make_unexpected(resp.error_code()); @@ -134,30 +123,23 @@ update_job(const server& srv, const job& job, network::client rpc_client{srv.protocol()}; - const auto rpc_id = ::api::remote_procedure::new_id(); + const auto rpc = network::rpc_info::create(RPC_NAME(), srv.address()); if(const auto& lookup_rv = rpc_client.lookup(srv.address()); lookup_rv.has_value()) { const auto& endp = lookup_rv.value(); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{job_id: {}, new_resources: {}}}", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(rpc_client.self_address()), job.id(), - new_resources); + LOGGER_INFO("rpc {:<} body: {{job_id: {}, new_resources: {}}}", rpc, + job.id(), new_resources); - if(const auto& call_rv = - endp.call("ADM_"s + __FUNCTION__, job.id(), new_resources); + if(const auto& call_rv = endp.call(rpc.name(), job.id(), new_resources); call_rv.has_value()) { const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, - "rpc id: {} name: {} from: {} <= " - "body: {{retval: {}}} [op_id: {}]", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(endp.address()), resp.error_code(), - resp.op_id()); + "rpc {:>} body: {{retval: {}}} [op_id: {}]", rpc, + resp.error_code(), resp.op_id()); return resp.error_code(); } } @@ -171,28 +153,22 @@ remove_job(const server& srv, const job& job) { network::client rpc_client{srv.protocol()}; - const auto rpc_id = ::api::remote_procedure::new_id(); + const auto rpc = network::rpc_info::create(RPC_NAME(), srv.address()); if(const auto& lookup_rv = rpc_client.lookup(srv.address()); lookup_rv.has_value()) { const auto& endp = lookup_rv.value(); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{job_id: {}}}", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(rpc_client.self_address()), job.id()); + LOGGER_INFO("rpc {:<} body: {{job_id: {}}}", rpc, job.id()); - if(const auto& call_rv = endp.call("ADM_"s + __FUNCTION__, job.id()); + if(const auto& call_rv = endp.call(rpc.name(), job.id()); call_rv.has_value()) { const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, - "rpc id: {} name: {} from: {} <= " - "body: {{retval: {}}} [op_id: {}]", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(endp.address()), resp.error_code(), - resp.op_id()); + "rpc {:>} body: {{retval: {}}} [op_id: {}]", rpc, + resp.error_code(), resp.op_id()); return resp.error_code(); } } @@ -209,31 +185,26 @@ register_adhoc_storage(const server& srv, const std::string& name, network::client rpc_client{srv.protocol()}; - const auto rpc_id = ::api::remote_procedure::new_id(); + const auto rpc = network::rpc_info::create(RPC_NAME(), srv.address()); if(const auto& lookup_rv = rpc_client.lookup(srv.address()); lookup_rv.has_value()) { const auto& endp = lookup_rv.value(); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{name: {}, type: {}, adhoc_ctx: {}, " + LOGGER_INFO("rpc {:<} body: {{name: {}, type: {}, adhoc_ctx: {}, " "adhoc_resources: {}}}", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(rpc_client.self_address()), name, type, ctx, - resources); + rpc, name, type, ctx, resources); - if(const auto& call_rv = endp.call("ADM_"s + __FUNCTION__, name, type, - ctx, resources); + if(const auto& call_rv = + endp.call(rpc.name(), name, type, ctx, resources); call_rv.has_value()) { const network::response_with_id resp{call_rv.value()}; - LOGGER_EVAL(resp.error_code(), INFO, ERROR, - "rpc id: {} name: {} from: {} <= " - "body: {{retval: {}, adhoc_id: {}}} [op_id: {}]", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(endp.address()), resp.error_code(), - resp.value(), resp.op_id()); + LOGGER_EVAL( + resp.error_code(), INFO, ERROR, + "rpc {:>} body: {{retval: {}, adhoc_id: {}}} [op_id: {}]", + rpc, resp.error_code(), resp.value(), resp.op_id()); if(const auto ec = resp.error_code(); !ec) { return tl::make_unexpected(ec); @@ -254,30 +225,24 @@ update_adhoc_storage(const server& srv, const adhoc_storage& adhoc_storage, network::client rpc_client{srv.protocol()}; - const auto rpc_id = ::api::remote_procedure::new_id(); + const auto rpc = network::rpc_info::create(RPC_NAME(), srv.address()); if(const auto& lookup_rv = rpc_client.lookup(srv.address()); lookup_rv.has_value()) { const auto& endp = lookup_rv.value(); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{adhoc_id: {}, new_resources: {}}}", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(rpc_client.self_address()), adhoc_storage.id(), - new_resources); + LOGGER_INFO("rpc {:<} body: {{adhoc_id: {}, new_resources: {}}}", rpc, + adhoc_storage.id(), new_resources); - if(const auto& call_rv = endp.call("ADM_"s + __FUNCTION__, - adhoc_storage.id(), new_resources); + if(const auto& call_rv = + endp.call(rpc.name(), adhoc_storage.id(), new_resources); call_rv.has_value()) { const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, - "rpc id: {} name: {} from: {} <= " - "body: {{retval: {}}} [op_id: {}]", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(endp.address()), resp.error_code(), - resp.op_id()); + "rpc {:>} body: {{retval: {}}} [op_id: {}]", rpc, + resp.error_code(), resp.op_id()); return resp.error_code(); } @@ -292,29 +257,22 @@ remove_adhoc_storage(const server& srv, const adhoc_storage& adhoc_storage) { network::client rpc_client{srv.protocol()}; - const auto rpc_id = ::api::remote_procedure::new_id(); + const auto rpc = network::rpc_info::create(RPC_NAME(), srv.address()); if(const auto& lookup_rv = rpc_client.lookup(srv.address()); lookup_rv.has_value()) { const auto& endp = lookup_rv.value(); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{adhoc_id: {}}}", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(rpc_client.self_address()), adhoc_storage.id()); + LOGGER_INFO("rpc {:<} body: {{adhoc_id: {}}}", rpc, adhoc_storage.id()); - if(const auto& call_rv = - endp.call("ADM_"s + __FUNCTION__, adhoc_storage.id()); + if(const auto& call_rv = endp.call(rpc.name(), adhoc_storage.id()); call_rv.has_value()) { const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, - "rpc id: {} name: {} from: {} <= " - "body: {{retval: {}}} [op_id: {}]", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(endp.address()), resp.error_code(), - resp.op_id()); + "rpc {:>} body: {{retval: {}}} [op_id: {}]", rpc, + resp.error_code(), resp.op_id()); return resp.error_code(); } @@ -330,29 +288,23 @@ register_pfs_storage(const server& srv, const std::string& name, network::client rpc_client{srv.protocol()}; - const auto rpc_id = ::api::remote_procedure::new_id(); + const auto rpc = network::rpc_info::create(RPC_NAME(), srv.address()); if(const auto& lookup_rv = rpc_client.lookup(srv.address()); lookup_rv.has_value()) { const auto& endp = lookup_rv.value(); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{name: {}, type: {}, pfs_ctx: {}}}", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(rpc_client.self_address()), name, type, ctx); + LOGGER_INFO("rpc {:<} body: {{name: {}, type: {}, pfs_ctx: {}}}", rpc, + name, type, ctx); - if(const auto& call_rv = - endp.call("ADM_"s + __FUNCTION__, name, type, ctx); + if(const auto& call_rv = endp.call(rpc.name(), name, type, ctx); call_rv.has_value()) { const network::response_with_id resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, - "rpc id: {} name: {} from: {} <= " - "body: {{retval: {}, pfs_id: {}}} [op_id: {}]", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(endp.address()), resp.error_code(), - resp.value(), resp.op_id()); + "rpc {:>} body: {{retval: {}, pfs_id: {}}} [op_id: {}]", + rpc, resp.error_code(), resp.value(), resp.op_id()); if(const auto ec = resp.error_code(); !ec) { return tl::make_unexpected(ec); @@ -372,30 +324,24 @@ update_pfs_storage(const server& srv, const pfs_storage& pfs_storage, network::client rpc_client{srv.protocol()}; - const auto rpc_id = ::api::remote_procedure::new_id(); + const auto rpc = network::rpc_info::create(RPC_NAME(), srv.address()); if(const auto& lookup_rv = rpc_client.lookup(srv.address()); lookup_rv.has_value()) { const auto& endp = lookup_rv.value(); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{pfs_id: {}, new_ctx: {}}}", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(rpc_client.self_address()), pfs_storage.id(), - new_ctx); + LOGGER_INFO("rpc {:<} body: {{pfs_id: {}, new_ctx: {}}}", rpc, + pfs_storage.id(), new_ctx); if(const auto& call_rv = - endp.call("ADM_"s + __FUNCTION__, pfs_storage.id(), new_ctx); + endp.call(rpc.name(), pfs_storage.id(), new_ctx); call_rv.has_value()) { const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, - "rpc id: {} name: {} from: {} <= " - "body: {{retval: {}}} [op_id: {}]", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(endp.address()), resp.error_code(), - resp.op_id()); + "rpc {:>} body: {{retval: {}}} [op_id: {}]", rpc, + resp.error_code(), resp.op_id()); return resp.error_code(); } @@ -410,29 +356,22 @@ remove_pfs_storage(const server& srv, const pfs_storage& pfs_storage) { network::client rpc_client{srv.protocol()}; - const auto rpc_id = ::api::remote_procedure::new_id(); + const auto rpc = network::rpc_info::create(RPC_NAME(), srv.address()); if(const auto& lookup_rv = rpc_client.lookup(srv.address()); lookup_rv.has_value()) { const auto& endp = lookup_rv.value(); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{pfs_id: {}}}", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(rpc_client.self_address()), pfs_storage.id()); + LOGGER_INFO("rpc {:<} body: {{pfs_id: {}}}", rpc, pfs_storage.id()); - if(const auto& call_rv = - endp.call("ADM_"s + __FUNCTION__, pfs_storage.id()); + if(const auto& call_rv = endp.call(rpc.name(), pfs_storage.id()); call_rv.has_value()) { const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, - "rpc id: {} name: {} from: {} <= " - "body: {{retval: {}}} [op_id: {}]", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(endp.address()), resp.error_code(), - resp.op_id()); + "rpc {:>} body: {{retval: {}}} [op_id: {}]", rpc, + resp.error_code(), resp.op_id()); return resp.error_code(); } @@ -447,29 +386,22 @@ deploy_adhoc_storage(const server& srv, const adhoc_storage& adhoc_storage) { network::client rpc_client{srv.protocol()}; - const auto rpc_id = ::api::remote_procedure::new_id(); + const auto rpc = network::rpc_info::create(RPC_NAME(), srv.address()); if(const auto& lookup_rv = rpc_client.lookup(srv.address()); lookup_rv.has_value()) { const auto& endp = lookup_rv.value(); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{adhoc_id: {}}}", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(rpc_client.self_address()), adhoc_storage.id()); + LOGGER_INFO("rpc {:<} body: {{adhoc_id: {}}}", rpc, adhoc_storage.id()); - if(const auto& call_rv = - endp.call("ADM_"s + __FUNCTION__, adhoc_storage.id()); + if(const auto& call_rv = endp.call(rpc.name(), adhoc_storage.id()); call_rv.has_value()) { const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, - "rpc id: {} name: {} from: {} <= " - "body: {{retval: {}}} [op_id: {}]", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(endp.address()), resp.error_code(), - resp.op_id()); + "rpc {:>} body: {{retval: {}}} [op_id: {}]", rpc, + resp.error_code(), resp.op_id()); return resp.error_code(); } @@ -484,29 +416,22 @@ tear_down_adhoc_storage(const server& srv, const adhoc_storage& adhoc_storage) { network::client rpc_client{srv.protocol()}; - const auto rpc_id = ::api::remote_procedure::new_id(); + const auto rpc = network::rpc_info::create(RPC_NAME(), srv.address()); if(const auto lookup_rv = rpc_client.lookup(srv.address()); lookup_rv.has_value()) { const auto& endp = lookup_rv.value(); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{adhoc_id: {}}}", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(rpc_client.self_address()), adhoc_storage.id()); + LOGGER_INFO("rpc {:<} body: {{adhoc_id: {}}}", rpc, adhoc_storage.id()); - if(const auto call_rv = - endp.call("ADM_"s + __FUNCTION__, adhoc_storage.id()); + if(const auto call_rv = endp.call(rpc.name(), adhoc_storage.id()); call_rv.has_value()) { const network::generic_response resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, - "rpc id: {} name: {} from: {} <= " - "body: {{retval: {}}} [op_id: {}]", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(endp.address()), resp.error_code(), - resp.op_id()); + "rpc {:>} body: {{retval: {}}} [op_id: {}]", rpc, + resp.error_code(), resp.op_id()); return resp.error_code(); } @@ -525,31 +450,25 @@ transfer_datasets(const server& srv, const job& job, network::client rpc_client{srv.protocol()}; - const auto rpc_id = ::api::remote_procedure::new_id(); + const auto rpc = network::rpc_info::create(RPC_NAME(), srv.address()); if(const auto& lookup_rv = rpc_client.lookup(srv.address()); lookup_rv.has_value()) { const auto& endp = lookup_rv.value(); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{job_id: {}, sources: {}, targets: {}, limits: {}, " - "mapping: {}}}", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(rpc_client.self_address()), job.id(), sources, - targets, limits, mapping); + LOGGER_INFO("rpc {:<} body: {{job_id: {}, sources: {}, targets: {}, " + "limits: {}, mapping: {}}}", + rpc, job.id(), sources, targets, limits, mapping); - if(const auto& call_rv = endp.call("ADM_"s + __FUNCTION__, job.id(), - sources, targets, limits, mapping); + if(const auto& call_rv = endp.call(rpc.name(), job.id(), sources, + targets, limits, mapping); call_rv.has_value()) { const network::response_with_id resp{call_rv.value()}; LOGGER_EVAL(resp.error_code(), INFO, ERROR, - "rpc id: {} name: {} from: {} <= " - "body: {{retval: {}, tx_id: {}}} [op_id: {}]", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(endp.address()), resp.error_code(), - resp.value(), resp.op_id()); + "rpc {:>} body: {{retval: {}, tx_id: {}}} [op_id: {}]", + rpc, resp.error_code(), resp.value(), resp.op_id()); if(const auto ec = resp.error_code(); !ec) { return tl::make_unexpected(ec); diff --git a/src/scord-ctl/rpc_server.cpp b/src/scord-ctl/rpc_server.cpp index f8c9f4e4..bb7da914 100644 --- a/src/scord-ctl/rpc_server.cpp +++ b/src/scord-ctl/rpc_server.cpp @@ -24,6 +24,7 @@ #include #include +#include #include "rpc_server.hpp" // required for ::waitpid() @@ -32,14 +33,6 @@ using namespace std::literals; -struct remote_procedure { - static std::uint64_t - new_id() { - static std::atomic_uint64_t current_id; - return current_id++; - } -}; - namespace scord_ctl { rpc_server::rpc_server(std::string name, std::string address, bool daemonize, @@ -56,24 +49,22 @@ rpc_server::rpc_server(std::string name, std::string address, bool daemonize, #undef EXPAND } +#define RPC_NAME() ("ADM_"s + __FUNCTION__) + void rpc_server::ping(const network::request& req) { using network::generic_response; using network::get_address; + using network::rpc_info; - const auto rpc_name = "ADM_"s + __FUNCTION__; - const auto rpc_id = remote_procedure::new_id(); + const auto rpc = rpc_info::create(RPC_NAME(), get_address(req)); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req))); + LOGGER_INFO("rpc {:>} body: {{}}", rpc); - const auto resp = generic_response{rpc_id, scord::error_code::success}; + const auto resp = generic_response{rpc.id(), scord::error_code::success}; - LOGGER_INFO("rpc id: {} name: {} to: {} <= " - "body: {{retval: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), + LOGGER_INFO("rpc {:<} body: {{retval: {}}}", rpc, scord::error_code::success); req.respond(resp); @@ -88,15 +79,12 @@ rpc_server::deploy_adhoc_storage( using network::generic_response; using network::get_address; + using network::rpc_info; - const auto rpc_name = "ADM_"s + __FUNCTION__; - const auto rpc_id = remote_procedure::new_id(); + const auto rpc = rpc_info::create(RPC_NAME(), get_address(req)); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{type: {}, ctx: {}, resources: {}}}", - rpc_id, std::quoted(__FUNCTION__), - std::quoted(get_address(req)), adhoc_type, adhoc_ctx, - adhoc_resources); + LOGGER_INFO("rpc {:>} body: {{type: {}, ctx: {}, resources: {}}}", rpc, + adhoc_type, adhoc_ctx, adhoc_resources); auto ec = scord::error_code::success; @@ -133,10 +121,7 @@ rpc_server::deploy_adhoc_storage( } case -1: { ec = scord::error_code::other; - LOGGER_ERROR("rpc id: {} name: {} to: {} <= " - "body: {{retval: {}}}", - rpc_id, std::quoted(rpc_name), - std::quoted(get_address(req)), ec); + LOGGER_ERROR("rpc {:<} body: {{retval: {}}}", rpc, ec); break; } default: { @@ -145,7 +130,7 @@ rpc_server::deploy_adhoc_storage( if(retwait == -1) { LOGGER_ERROR( "rpc id: {} error_msg: \"Error waitpid code: {}\"", - rpc_id, retwait); + rpc.id(), retwait); ec = scord::error_code::other; } else { if(WEXITSTATUS(wstatus) != 0) { @@ -159,12 +144,9 @@ rpc_server::deploy_adhoc_storage( } } - const auto resp = generic_response{rpc_id, ec}; + const auto resp = generic_response{rpc.id(), ec}; - LOGGER_INFO("rpc id: {} name: {} to: {} <= " - "body: {{retval: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - ec); + LOGGER_INFO("rpc {:<} body: {{retval: {}}}", rpc, ec); req.respond(resp); } diff --git a/src/scord/rpc_server.cpp b/src/scord/rpc_server.cpp index 6055a7ad..fd63ea01 100644 --- a/src/scord/rpc_server.cpp +++ b/src/scord/rpc_server.cpp @@ -26,18 +26,11 @@ #include #include #include +#include #include "rpc_server.hpp" using namespace std::literals; -struct remote_procedure { - static std::uint64_t - new_id() { - static std::atomic_uint64_t current_id; - return current_id++; - } -}; - namespace scord { rpc_server::rpc_server(std::string name, std::string address, bool daemonize, @@ -65,24 +58,22 @@ rpc_server::rpc_server(std::string name, std::string address, bool daemonize, #undef EXPAND } +#define RPC_NAME() ("ADM_"s + __FUNCTION__) + void rpc_server::ping(const network::request& req) { using network::generic_response; using network::get_address; + using network::rpc_info; - const auto rpc_name = "ADM_"s + __FUNCTION__; - const auto rpc_id = remote_procedure::new_id(); + const auto rpc = rpc_info::create(RPC_NAME(), get_address(req)); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req))); + LOGGER_INFO("rpc {:>} body: {{}}", rpc); - const auto resp = generic_response{rpc_id, scord::error_code::success}; + const auto resp = generic_response{rpc.id(), scord::error_code::success}; - LOGGER_INFO("rpc id: {} name: {} to: {} <= " - "body: {{retval: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), + LOGGER_INFO("rpc {:<} body: {{retval: {}}}", rpc, scord::error_code::success); req.respond(resp); @@ -96,15 +87,13 @@ rpc_server::register_job(const network::request& req, using network::get_address; using network::response_with_id; + using network::rpc_info; - const auto rpc_name = "ADM_"s + __FUNCTION__; - const auto rpc_id = remote_procedure::new_id(); + const auto rpc = rpc_info::create(RPC_NAME(), get_address(req)); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{job_resources: {}, job_requirements: {}, slurm_id: " - "{}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - job_resources, job_requirements, slurm_id); + LOGGER_INFO("rpc {:>} body: {{job_resources: {}, job_requirements: {}, " + "slurm_id: {}}}", + rpc, job_resources, job_requirements, slurm_id); scord::error_code ec; std::optional job_id; @@ -128,18 +117,15 @@ rpc_server::register_job(const network::request& req, job_id = job_info->job().id(); } else { - LOGGER_ERROR("rpc id: {} error_msg: \"Error creating job: {}\"", rpc_id, - jm_result.error()); + LOGGER_ERROR("rpc id: {} error_msg: \"Error creating job: {}\"", + rpc.id(), jm_result.error()); ec = jm_result.error(); } respond: - const auto resp = response_with_id{rpc_id, ec, job_id}; + const auto resp = response_with_id{rpc.id(), ec, job_id}; - LOGGER_INFO("rpc id: {} name: {} to: {} <= " - "body: {{retval: {}, job_id: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - ec, job_id); + LOGGER_INFO("rpc {:<} body: {{retval: {}, job_id: {}}}", rpc, ec, job_id); req.respond(resp); } @@ -150,28 +136,23 @@ rpc_server::update_job(const network::request& req, scord::job_id job_id, using network::generic_response; using network::get_address; + using network::rpc_info; - const auto rpc_name = "ADM_"s + __FUNCTION__; - const auto rpc_id = remote_procedure::new_id(); + const auto rpc = rpc_info::create(RPC_NAME(), get_address(req)); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{job_id: {}, new_resources: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - job_id, new_resources); + LOGGER_INFO("rpc {:>} body: {{job_id: {}, new_resources: {}}}", rpc, job_id, + new_resources); const auto ec = m_job_manager.update(job_id, new_resources); if(!ec) { - LOGGER_ERROR("rpc id: {} error_msg: \"Error updating job: {}\"", rpc_id, - ec); + LOGGER_ERROR("rpc id: {} error_msg: \"Error updating job: {}\"", + rpc.id(), ec); } - const auto resp = generic_response{rpc_id, ec}; + const auto resp = generic_response{rpc.id(), ec}; - LOGGER_INFO("rpc id: {} name: {} to: {} <= " - "body: {{retval: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - ec); + LOGGER_INFO("rpc {:<} body: {{retval: {}}}", rpc, ec); req.respond(resp); } @@ -181,14 +162,11 @@ rpc_server::remove_job(const network::request& req, scord::job_id job_id) { using network::generic_response; using network::get_address; + using network::rpc_info; - const auto rpc_name = "ADM_"s + __FUNCTION__; - const auto rpc_id = remote_procedure::new_id(); + const auto rpc = rpc_info::create(RPC_NAME(), get_address(req)); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{job_id: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - job_id); + LOGGER_INFO("rpc {:>} body: {{job_id: {}}}", rpc, job_id); scord::error_code ec; const auto jm_result = m_job_manager.remove(job_id); @@ -203,17 +181,14 @@ rpc_server::remove_job(const network::request& req, scord::job_id job_id) { ec = m_adhoc_manager.remove_client_info(adhoc_storage->id()); } } else { - LOGGER_ERROR("rpc id: {} error_msg: \"Error removing job: {}\"", rpc_id, - job_id); + LOGGER_ERROR("rpc id: {} error_msg: \"Error removing job: {}\"", + rpc.id(), job_id); ec = jm_result.error(); } - const auto resp = generic_response{rpc_id, ec}; + const auto resp = generic_response{rpc.id(), ec}; - LOGGER_INFO("rpc id: {} name: {} to: {} <= " - "body: {{retval: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - ec); + LOGGER_INFO("rpc {:<} body: {{retval: {}}}", rpc, ec); req.respond(resp); } @@ -227,15 +202,13 @@ rpc_server::register_adhoc_storage( using network::get_address; using network::response_with_id; + using network::rpc_info; - const auto rpc_name = "ADM_"s + __FUNCTION__; - const auto rpc_id = remote_procedure::new_id(); + const auto rpc = rpc_info::create(RPC_NAME(), get_address(req)); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{name: {}, type: {}, adhoc_ctx: {}, " + LOGGER_INFO("rpc {:>} body: {{name: {}, type: {}, adhoc_ctx: {}, " "adhoc_resources: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - name, type, ctx, resources); + rpc, name, type, ctx, resources); scord::error_code ec; std::optional adhoc_id; @@ -248,16 +221,14 @@ rpc_server::register_adhoc_storage( } else { LOGGER_ERROR("rpc id: {} error_msg: \"Error creating adhoc_storage: " "{}\"", - rpc_id, am_result.error()); + rpc.id(), am_result.error()); ec = am_result.error(); } - const auto resp = response_with_id{rpc_id, ec, adhoc_id}; + const auto resp = response_with_id{rpc.id(), ec, adhoc_id}; - LOGGER_INFO("rpc id: {} name: {} to: {} <= " - "body: {{retval: {}, adhoc_id: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - ec, adhoc_id); + LOGGER_INFO("rpc {:<} body: {{retval: {}, adhoc_id: {}}}", rpc, ec, + adhoc_id); req.respond(resp); } @@ -269,13 +240,11 @@ rpc_server::update_adhoc_storage( using network::generic_response; using network::get_address; + using network::rpc_info; - const auto rpc_name = "ADM_"s + __FUNCTION__; - const auto rpc_id = remote_procedure::new_id(); + const auto rpc = rpc_info::create(RPC_NAME(), get_address(req)); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{adhoc_id: {}, new_resources: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), + LOGGER_INFO("rpc {:>} body: {{adhoc_id: {}, new_resources: {}}}", rpc, adhoc_id, new_resources); const auto ec = m_adhoc_manager.update(adhoc_id, new_resources); @@ -283,15 +252,12 @@ rpc_server::update_adhoc_storage( if(!ec) { LOGGER_ERROR( "rpc id: {} error_msg: \"Error updating adhoc_storage: {}\"", - rpc_id, ec); + rpc.id(), ec); } - const auto resp = generic_response{rpc_id, ec}; + const auto resp = generic_response{rpc.id(), ec}; - LOGGER_INFO("rpc id: {} name: {} to: {} <= " - "body: {{retval: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - ec); + LOGGER_INFO("rpc {:<} body: {{retval: {}}}", rpc, ec); req.respond(resp); } @@ -302,28 +268,22 @@ rpc_server::remove_adhoc_storage(const network::request& req, using network::generic_response; using network::get_address; + using network::rpc_info; - const auto rpc_name = "ADM_"s + __FUNCTION__; - const auto rpc_id = remote_procedure::new_id(); + const auto rpc = rpc_info::create(RPC_NAME(), get_address(req)); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{adhoc_id: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - adhoc_id); + LOGGER_INFO("rpc {:>} body: {{adhoc_id: {}}}", rpc, adhoc_id); scord::error_code ec = m_adhoc_manager.remove(adhoc_id); if(!ec) { - LOGGER_ERROR("rpc id: {} error_msg: \"Error removing job: {}\"", rpc_id, - adhoc_id); + LOGGER_ERROR("rpc id: {} error_msg: \"Error removing job: {}\"", + rpc.id(), adhoc_id); } - const auto resp = generic_response{rpc_id, ec}; + const auto resp = generic_response{rpc.id(), ec}; - LOGGER_INFO("rpc id: {} name: {} to: {} <= " - "body: {{retval: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - ec); + LOGGER_INFO("rpc {:<} body: {{retval: {}}}", rpc, ec); req.respond(resp); } @@ -334,14 +294,11 @@ rpc_server::deploy_adhoc_storage(const network::request& req, using network::generic_response; using network::get_address; + using network::rpc_info; - const auto rpc_name = "ADM_"s + __FUNCTION__; - const auto rpc_id = remote_procedure::new_id(); + const auto rpc = rpc_info::create(RPC_NAME(), get_address(req)); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{adhoc_id: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - adhoc_id); + LOGGER_INFO("rpc {:>} body: {{adhoc_id: {}}}", rpc, adhoc_id); auto ec = scord::error_code::success; @@ -356,41 +313,37 @@ rpc_server::deploy_adhoc_storage(const network::request& req, lookup_rv.has_value()) { const auto& endp = lookup_rv.value(); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{type: {}, ctx: {}, resources: {}}}", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(self_address()), adhoc_storage.type(), + const auto child_rpc = + rpc.add_child(adhoc_storage.context().controller_address()); + + LOGGER_INFO("rpc {:<} body: {{type: {}, ctx: {}, resources: {}}}", + child_rpc, adhoc_storage.type(), adhoc_storage.context(), adhoc_storage.get_resources()); - if(const auto call_rv = endp.call( - "ADM_"s + __FUNCTION__, adhoc_storage.type(), - adhoc_storage.context(), adhoc_storage.get_resources()); + if(const auto call_rv = endp.call(rpc.name(), adhoc_storage.type(), + adhoc_storage.context(), + adhoc_storage.get_resources()); call_rv.has_value()) { const network::generic_response resp{call_rv.value()}; ec = resp.error_code(); LOGGER_EVAL(resp.error_code(), INFO, ERROR, - "rpc id: {} name: {} from: {} <= " - "body: {{retval: {}}} [op_id: {}]", - rpc_id, std::quoted("ADM_"s + __FUNCTION__), - std::quoted(endp.address()), ec, resp.op_id()); + "rpc {:>} body: {{retval: {}}} [op_id: {}]", + child_rpc, ec, resp.op_id()); + } else { + ec = error_code::snafu; + LOGGER_ERROR("rpc call failed"); } } } else { ec = am_result.error(); - LOGGER_ERROR("rpc id: {} name: {} to: {} <= " - "body: {{retval: {}}}", - rpc_id, std::quoted(rpc_name), - std::quoted(get_address(req)), ec); + LOGGER_ERROR("rpc {:<} body: {{retval: {}}}", rpc, ec); } - const auto resp = generic_response{rpc_id, ec}; + const auto resp = generic_response{rpc.id(), ec}; - LOGGER_INFO("rpc id: {} name: {} to: {} <= " - "body: {{retval: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - ec); + LOGGER_INFO("rpc {:<} body: {{retval: {}}}", rpc, ec); req.respond(resp); } @@ -401,22 +354,17 @@ rpc_server::tear_down_adhoc_storage(const network::request& req, using network::generic_response; using network::get_address; + using network::rpc_info; - const auto rpc_name = "ADM_"s + __FUNCTION__; - const auto rpc_id = remote_procedure::new_id(); + const auto rpc = rpc_info::create(RPC_NAME(), get_address(req)); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{adhoc_id: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - adhoc_id); + LOGGER_INFO("rpc {:>} body: {{adhoc_id: {}}}", rpc, adhoc_id); // TODO: actually tear down the adhoc storage instance - const auto resp = generic_response{rpc_id, scord::error_code::success}; + const auto resp = generic_response{rpc.id(), scord::error_code::success}; - LOGGER_INFO("rpc id: {} name: {} to: {} <= " - "body: {{retval: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), + LOGGER_INFO("rpc {:<} body: {{retval: {}}}", rpc, scord::error_code::success); req.respond(resp); @@ -430,14 +378,12 @@ rpc_server::register_pfs_storage(const network::request& req, using network::get_address; using network::response_with_id; + using network::rpc_info; - const auto rpc_name = "ADM_"s + __FUNCTION__; - const auto rpc_id = remote_procedure::new_id(); + const auto rpc = rpc_info::create(RPC_NAME(), get_address(req)); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{name: {}, type: {}, pfs_ctx: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - name, type, ctx); + LOGGER_INFO("rpc {:>} body: {{name: {}, type: {}, pfs_ctx: {}}}", rpc, name, + type, ctx); scord::error_code ec; std::optional pfs_id = 0; @@ -448,16 +394,13 @@ rpc_server::register_pfs_storage(const network::request& req, pfs_id = adhoc_storage_info->pfs_storage().id(); } else { LOGGER_ERROR("rpc id: {} error_msg: \"Error creating pfs_storage: {}\"", - rpc_id, pm_result.error()); + rpc.id(), pm_result.error()); ec = pm_result.error(); } - const auto resp = response_with_id{rpc_id, ec, pfs_id}; + const auto resp = response_with_id{rpc.id(), ec, pfs_id}; - LOGGER_INFO("rpc id: {} name: {} to: {} => " - "body: {{retval: {}, pfs_id: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - ec, pfs_id); + LOGGER_INFO("rpc {:<} body: {{retval: {}, pfs_id: {}}}", rpc, ec, pfs_id); req.respond(resp); } @@ -469,28 +412,23 @@ rpc_server::update_pfs_storage(const network::request& req, using network::generic_response; using network::get_address; + using network::rpc_info; - const auto rpc_name = "ADM_"s + __FUNCTION__; - const auto rpc_id = remote_procedure::new_id(); + const auto rpc = rpc_info::create(RPC_NAME(), get_address(req)); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{pfs_id: {}, new_ctx: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - pfs_id, new_ctx); + LOGGER_INFO("rpc {:>} body: {{pfs_id: {}, new_ctx: {}}}", rpc, pfs_id, + new_ctx); const auto ec = m_pfs_manager.update(pfs_id, new_ctx); if(!ec) { LOGGER_ERROR("rpc id: {} error_msg: \"Error updating pfs_storage: {}\"", - rpc_id, ec); + rpc.id(), ec); } - const auto resp = generic_response{rpc_id, ec}; + const auto resp = generic_response{rpc.id(), ec}; - LOGGER_INFO("rpc id: {} name: {} to: {} => " - "body: {{retval: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - ec); + LOGGER_INFO("rpc {:<} body: {{retval: {}}}", rpc, ec); req.respond(resp); } @@ -501,28 +439,22 @@ rpc_server::remove_pfs_storage(const network::request& req, using network::generic_response; using network::get_address; + using network::rpc_info; - const auto rpc_name = "ADM_"s + __FUNCTION__; - const auto rpc_id = remote_procedure::new_id(); + const auto rpc = rpc_info::create(RPC_NAME(), get_address(req)); - LOGGER_INFO("rpc id: {} name: {} from: {} => " - "body: {{pfs_id: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - pfs_id); + LOGGER_INFO("rpc {:>} body: {{pfs_id: {}}}", rpc, pfs_id); scord::error_code ec = m_pfs_manager.remove(pfs_id); if(!ec) { LOGGER_ERROR("rpc id: {} error_msg: \"Error removing pfs storage: {}\"", - rpc_id, pfs_id); + rpc.id(), pfs_id); } - const auto resp = generic_response{rpc_id, ec}; + const auto resp = generic_response{rpc.id(), ec}; - LOGGER_INFO("rpc id: {} name: {} to: {} <= " - "body: {{retval: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - ec); + LOGGER_INFO("rpc {:<} body: {{retval: {}}}", rpc, ec); req.respond(resp); } @@ -536,15 +468,13 @@ rpc_server::transfer_datasets(const network::request& req, scord::job_id job_id, using network::get_address; using network::response_with_id; + using network::rpc_info; - const auto rpc_name = "ADM_"s + __FUNCTION__; - const auto rpc_id = remote_procedure::new_id(); + const auto rpc = rpc_info::create(RPC_NAME(), get_address(req)); - LOGGER_INFO( - "rpc id: {} name: {} from: {} => " - "body: {{job_id: {}, sources: {}, targets: {}, limits: {}, mapping: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - job_id, sources, targets, limits, mapping); + LOGGER_INFO("rpc {:>} body: {{job_id: {}, sources: {}, targets: {}, " + "limits: {}, mapping: {}}}", + rpc, job_id, sources, targets, limits, mapping); scord::error_code ec; @@ -554,12 +484,9 @@ rpc_server::transfer_datasets(const network::request& req, scord::job_id job_id, // actually request it tx_id = 42; - const auto resp = response_with_id{rpc_id, ec, tx_id}; + const auto resp = response_with_id{rpc.id(), ec, tx_id}; - LOGGER_INFO("rpc id: {} name: {} to: {} <= " - "body: {{retval: {}, tx_id: {}}}", - rpc_id, std::quoted(rpc_name), std::quoted(get_address(req)), - ec, tx_id); + LOGGER_INFO("rpc {:<} body: {{retval: {}, tx_id: {}}}", rpc, ec, tx_id); req.respond(resp); } -- GitLab From 89753c3ee83725024a0122a6f2ed154aaecb96c5 Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Mon, 22 May 2023 16:20:49 +0200 Subject: [PATCH 16/17] Update & bug fixes for check_rpcs.py --- ci/check_rpcs.py | 318 +++++++++++++++++++++++++++--------- examples/c/CMakeLists.txt | 8 +- examples/cxx/CMakeLists.txt | 8 +- 3 files changed, 249 insertions(+), 85 deletions(-) diff --git a/ci/check_rpcs.py b/ci/check_rpcs.py index 5055a07e..fed1f1de 100755 --- a/ci/check_rpcs.py +++ b/ci/check_rpcs.py @@ -1,11 +1,13 @@ #!/usr/bin/env python3 -from loguru import logger +import argparse +import itertools import re import sys from pathlib import Path -from typing import Dict +from typing import Dict, Iterable, Any, Optional from lark import Lark, Transformer +from loguru import logger RPC_NAMES = { 'ADM_ping', @@ -40,7 +42,7 @@ class Meta: @property def line(self): - return self._line + return self._line.replace('{', '{{').replace('}', '}}') @property def lineno(self): @@ -75,22 +77,21 @@ class RemoteProcedure: EXPR = re.compile(r""" ^(?P \[(?P\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\.\d+)]\s - \[(?P\w+)]\s + \[(?P\w+(?:-\w+)*?)]\s \[(?P\d+)]\s \[(?P\w+)]\s rpc\s + (?P<=|=>)\s + (?:pid:\s(?P\d+)\s)? id:\s(?P\d+)\s name:\s"(?P\w+)"\s (?:from|to):\s"(?P
.*?)"\s - (?P<=|=>)\s ) body:\s(?P.*)$ """, re.VERBOSE) - def __init__(self, is_client: bool, meta: Dict, body: Dict, - opts: Dict): + def __init__(self, meta: Dict, body: Dict, opts: Dict): - self._is_client = is_client self._meta = Meta( meta['line'], meta['lineno'], @@ -99,30 +100,26 @@ class RemoteProcedure: meta['pid'], meta['log_level']) + self._pid = int(meta['rpc_pid']) if meta['rpc_pid'] else None self._id = int(meta['rpc_id']) self._name = meta['rpc_name'] - self._is_request = meta['direction'] == '=>' + self._is_inbound = meta['direction'] == '<=' self._address = meta['address'] if opts: - assert self.is_client and self.is_reply self._op_id = opts['op_id'] else: - self._op_id = self.id + _, self._op_id = self.id self._body = body - @property - def is_client(self): - return self._is_client - @property def meta(self): return self._meta @property def id(self): - return self._id + return self._pid, self._id @property def op_id(self): @@ -141,16 +138,21 @@ class RemoteProcedure: return self._address @property - def is_request(self): - return self._is_request + def is_inbound(self): + return self._is_inbound @property - def is_reply(self): - return not self._is_request + def is_outbound(self): + return not self._is_inbound def __eq__(self, other): assert self.name == other.name + if self.name != other.name: + logger.critical("Attempting to compare RPCs with different names:\n" + f" self: {self}\n" + f" other: {other}\n") + sys.exit(1) # first, check that there are no extra keys in the body of the RPCs self_keys = set(self._body.keys()) @@ -165,8 +167,8 @@ class RemoteProcedure: logger.error( "\nExtra fields were found when comparing an rpc " "to its counterpart\n" - f" extra fields: {extra_keys}" - f" line number: {rpc.meta.lineno}" + f" extra fields: {extra_keys}\n" + f" line number: {rpc.meta.lineno}\n" f" line contents: {rpc.meta.line}", file=sys.stderr) return False @@ -185,18 +187,18 @@ class RemoteProcedure: def __repr__(self): return f'RemoteProcedure(' \ - f'is_client={self.is_client}, ' \ f'meta={self.meta}, ' \ f'op_id={self.op_id}, ' \ f'id={self.id}, ' \ f'name={self.name}, ' \ - f'is_request={self.is_request}, ' \ + f'is_inbound={self.is_inbound}, ' \ f'address="{self.address}", ' \ f'body="{self._body}"' \ f')' class Operation: + # noinspection PyShadowingBuiltins def __init__(self, id, request, reply): self._id = id self._request = request @@ -257,14 +259,16 @@ class BodyTransformer(Transformer): pair = tuple opts = dict dict = dict - true = lambda self, _: True - false = lambda self, _: False + true = lambda self, _: True # noqa + false = lambda self, _: False # noqa + # noinspection PyMethodMayBeStatic def start(self, items): body = dict(items[0]) opts = dict(items[1]) if len(items) == 2 else dict() return body, opts + # noinspection PyMethodMayBeStatic def number(self, n): (n,) = n try: @@ -272,14 +276,17 @@ class BodyTransformer(Transformer): except ValueError: return float(n) + # noinspection PyMethodMayBeStatic def escaped_string(self, s): (s,) = s return str(s[1:-1]) + # noinspection PyMethodMayBeStatic def string(self, s): (s,) = s return str(s) + # noinspection PyMethodMayBeStatic def ident(self, ident): (ident,) = ident return str(ident) @@ -291,85 +298,234 @@ def process_body(d): return BodyTransformer().transform(tree) -def find_rpcs(filename, is_client, rpc_name): +def sanitize(address): + if address and "://" in address: + return address.split("://")[1] + return address + + +def find_rpcs(filename, rpc_name): with open(filename, 'r') as f: for ln, line in enumerate(f, start=1): + + logger.trace(f"Processing line {ln}:") + logger.trace(f" {repr(line)}") + if m := RemoteProcedure.EXPR.match(line): tmp = m.groupdict() + # We found a line with a valid RPC format, but its name is not + # known to us. This can happen if the user has defined a new + # RPC and forgot to add it to RPC_NAMES, or if the user has + # made a typo. In any case, we should warn the user about this. + if (n := tmp['rpc_name']) not in RPC_NAMES: + logger.warning(f"Found RPC with unknown name '{n}', " + f"line ignored", file=sys.stderr) + continue + + # We found a line with a valid RPC format and its name is the + # one we are looking for. We can now parse the body of the RPC + # and yield it. if tmp['rpc_name'] == rpc_name: + logger.info( + f"Searching rpc name '{tmp['rpc_name']}' in " + f"line {ln} -- found") tmp['lineno'] = ln tmp['line'] = line body, opts = process_body(tmp['body']) del tmp['body'] - yield RemoteProcedure(is_client, tmp, body, opts) + yield RemoteProcedure(tmp, body, opts), ln + else: + logger.trace( + f"Searching rpc name '{tmp['rpc_name']}' in " + f"line {ln} -- not found") + else: + logger.warning(f"Failed to parse line {ln} in {filename}", + file=sys.stderr) -if __name__ == "__main__": +def process_file(file: Path, rpc_name: str, self_address: Optional[str], + targets: Optional[Iterable[str]] = None) -> Dict[ + int, Operation]: + """Extract information about RPCs from a logfile and create the necessary + Operation descriptors. Within one logfile, RPCs belonging to an operation + can be identified by their id (i.e. an RPC request and an RPC response + will share the same id). - if len(sys.argv) != 4: - print("ERROR: Invalid number of arguments", file=sys.stderr) - print( - f"Usage: {Path(sys.argv[0]).name} CLIENT_LOGFILE SERVER_LOGFILE RPC_NAME", - file=sys.stderr) - sys.exit(1) + Across logfiles, RPCs belonging to an operation can be identified by their + operation id, which corresponds to the rpc id in the server side and is + sent back to the client to allow matching. + + Example: + * client logfile: + [...] rpc <= id: 10 name: "ADM_ping" [args...] + [...] rpc => id: 10 name: "ADM_ping" [retval...] [op_id: 42] + + * server logfile: + [...] rpc => id: 42 name: "ADM_ping" [args...] + [...] rpc <= id: 42 name: "ADM_ping" [retval...] + + :param file: The path to logfile + :param rpc_name: The name of the RPC to search for + :param self_address: The address of the server that generated the logfile + (or None if unknown) + :return: A dict of Operations + """ + + ops = {} + file_rpcs = {} + valid_targets = targets or [] + + logger.info(f"Searching for RPC \"{rpc_name}\" in {file}\n" + f" self address: {self_address}") + + for rpc, lineno in find_rpcs(file, rpc_name): + + prefix, direction = ("in", "from") if rpc.is_outbound else ("out", "to") - client_logfile = Path(sys.argv[1]) - server_logfile = Path(sys.argv[2]) + logger.debug(f"Found {prefix}bound RPC to '{rpc.address}' with " + f"id '{rpc.id}' at line {lineno}") - for lf, n in zip([client_logfile, server_logfile], ['CLIENT_LOGFILE', - 'SERVER_LOGFILE']): - if not lf.is_file(): - logger.error(f"{n} '{lf}' is not a file", file=sys.stderr) + if sanitize(rpc.address) == sanitize(self_address): + logger.error(f"Found {prefix}bound RPC {direction} own address" + f" {rpc.meta.lineno}\n" + f" raw: '{rpc.meta.line}'", + file=sys.stderr) sys.exit(1) - rpc_name = sys.argv[3] + if rpc.id not in file_rpcs: + file_rpcs[rpc.id] = rpc + else: + req_rpc = file_rpcs[rpc.id] + del file_rpcs[rpc.id] + logger.debug(f"Creating new operation with id '{rpc.op_id}'") + ops[rpc.op_id] = Operation(rpc.op_id, req_rpc, rpc) + + return ops + + +def match_ops(origin_ops, target_ops, strict=True): + ec = True + + for op_id in origin_ops.keys(): + + if op_id not in target_ops: + logger.warning( + f"An operation with id '{op_id}' was found in origin's " + f"operations but is missing from target's operations") + if strict: + ec = False + continue + + if origin_ops[op_id] != target_ops[op_id]: + ec = False + + return ec + + +def configure_logging(verbosity): + logger.remove() + + if verbosity == 0: + log_level = "SUCCESS" + elif verbosity == 1: + log_level = "INFO" + elif verbosity == 2: + log_level = "DEBUG" + else: + log_level = "TRACE" + + logger.add(sys.stderr, level=log_level) + + +def group_by_pairs(it: Iterable[Any]): + for e1, e2 in zip(itertools.islice(it, 0, None, 1), + itertools.islice(it, 1, None, 1)): + yield e1, e2 + + +def main(): + parser = argparse.ArgumentParser( + description="Check that client and server logs match for a given RPC " + "name") + + parser.add_argument("RPC_NAME", + help="the name of the RPC to check") + parser.add_argument("LIBSCORD_LOGFILE", + type=Path, + help="the path to the scord client's logfile") + parser.add_argument("SCORD_LOGFILE", + type=Path, + help="the path to the scord server's logfile") + parser.add_argument("SCORD_ADDRESS", + type=str, + help="the address of the scord server") + parser.add_argument("SCORD_CTL_LOGFILE", + type=Path, + nargs='?', + help="the path to the scord server's logfile") + parser.add_argument("SCORD_CTL_ADDRESS", + type=str, + nargs='?', + help="the address of the scord-ctl server") + parser.add_argument( + "-v", + "--verbose", + help="enable verbose output (additional flags increase verbosity)", + action="count", + dest='verbosity') + + parser.set_defaults(verbosity=0) + args = parser.parse_args() + configure_logging(args.verbosity) + + logfiles = [args.LIBSCORD_LOGFILE, args.SCORD_LOGFILE] + argnames = ["LIBSCORD_LOGFILE", "SCORD_LOGFILE"] + origins = [None] + targets = [None, args.SCORD_ADDRESS] + + if args.SCORD_CTL_LOGFILE: + logfiles.append(args.SCORD_CTL_LOGFILE) + argnames.append("SCORD_CTL_LOGFILE") + + if not args.SCORD_CTL_ADDRESS: + parser.error( + "the following arguments are required: SCORD_CTL_ADDRESS") + origins.append(args.SCORD_ADDRESS) + targets.append(args.SCORD_CTL_ADDRESS) + + rpc_name = args.RPC_NAME + + for file, name in zip(logfiles, argnames): + if not file.is_file(): + logger.critical(f"{name} '{file}' is not a file", file=sys.stderr) + sys.exit(1) if rpc_name not in RPC_NAMES: - logger.error(f"'{rpc_name}' is not a valid rpc name", - file=sys.stderr) - logger.error(f" Valid names: {', '.join(sorted(RPC_NAMES))}", - file=sys.stderr) + logger.critical(f"'{rpc_name}' is not a valid rpc name", + file=sys.stderr) + logger.critical(f" Valid names: {', '.join(sorted(RPC_NAMES))}", + file=sys.stderr) sys.exit(1) - logfiles = [client_logfile, server_logfile] - client_side = [True, False] - client_ops = {} - server_ops = {} + file_ops = [] - # extract information about RPCs from logfiles and create - # the necessary Operation - for lf, is_client, ops in zip(logfiles, client_side, [client_ops, - server_ops]): + for file, self_address in zip(logfiles, targets): + ops = process_file(file, rpc_name, self_address) + file_ops.append((file, ops)) - found_rpcs = {} + for (origin_file, origin_ops), (target_file, target_ops) in \ + group_by_pairs(file_ops): - for rpc in find_rpcs(lf, is_client, rpc_name): - if rpc.id not in found_rpcs: - if rpc.is_request: - found_rpcs[rpc.id] = rpc - else: - logger.error(f"\nFound server reply for RPC without " - f"a corresponding client request at line" - f" {rpc.meta.lineno}\n" - f" raw: '{rpc.meta.line}'", file=sys.stderr) - sys.exit(1) - else: - req_rpc = found_rpcs[rpc.id] - req_rpc.op_id = rpc.op_id - ops[rpc.op_id] = Operation(rpc.op_id, req_rpc, rpc) - del found_rpcs[rpc.id] - - ec = 0 - for k in client_ops.keys(): + logger.info(f"Matching operations in '{origin_file.name}' and " + f"'{target_file.name}'") + if not match_ops(origin_ops, target_ops, False): + logger.critical("Not all operations match") + sys.exit(1) - if k not in server_ops: - logger.error( - f"Operation ID '{k}' found in client log but missing " - f"in server log") - ec = 1 + logger.success("All operations match") + sys.exit(0) - if client_ops[k] != server_ops[k]: - ec = 1 - sys.exit(ec) +if __name__ == "__main__": + main() diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt index d2a25be8..cbc590b5 100644 --- a/examples/c/CMakeLists.txt +++ b/examples/c/CMakeLists.txt @@ -80,9 +80,12 @@ if(SCORD_BUILD_TESTS) add_test(validate_${TEST_NAME} ${CMAKE_SOURCE_DIR}/ci/check_rpcs.py + ${example} ${TEST_DIRECTORY}/libscord.log ${SCORD_TESTS_DIRECTORY}/scord_daemon/scord_daemon.log - ${example} + ${SCORD_ADDRESS_STRING} + ${SCORD_TESTS_DIRECTORY}/scord_daemon/scord_ctl.log + ${SCORD_CTL_ADDRESS_STRING} ) set_tests_properties(validate_${TEST_NAME} PROPERTIES DEPENDS stop_scord_daemon @@ -107,9 +110,10 @@ if(SCORD_BUILD_TESTS) add_test(validate_${TEST_NAME} ${CMAKE_SOURCE_DIR}/ci/check_rpcs.py + ${example} ${TEST_DIRECTORY}/libscord.log ${SCORD_TESTS_DIRECTORY}/scord_daemon/scord_daemon.log - ${example} + ${SCORD_ADDRESS_STRING} ) set_tests_properties(validate_${TEST_NAME} PROPERTIES DEPENDS stop_scord_daemon diff --git a/examples/cxx/CMakeLists.txt b/examples/cxx/CMakeLists.txt index efb0258e..9b828a7a 100644 --- a/examples/cxx/CMakeLists.txt +++ b/examples/cxx/CMakeLists.txt @@ -81,9 +81,12 @@ if(SCORD_BUILD_TESTS) add_test(validate_${TEST_NAME} ${CMAKE_SOURCE_DIR}/ci/check_rpcs.py + ${example} ${TEST_DIRECTORY}/libscord.log ${SCORD_TESTS_DIRECTORY}/scord_daemon/scord_daemon.log - ${example} + ${SCORD_ADDRESS_STRING} + ${SCORD_TESTS_DIRECTORY}/scord_daemon/scord_ctl.log + ${SCORD_CTL_ADDRESS_STRING} ) set_tests_properties(validate_${TEST_NAME} PROPERTIES DEPENDS stop_scord_daemon @@ -108,9 +111,10 @@ if(SCORD_BUILD_TESTS) add_test(validate_${TEST_NAME} ${CMAKE_SOURCE_DIR}/ci/check_rpcs.py + ${example} ${TEST_DIRECTORY}/libscord.log ${SCORD_TESTS_DIRECTORY}/scord_daemon/scord_daemon.log - ${example} + ${SCORD_ADDRESS_STRING} ) set_tests_properties(validate_${TEST_NAME} PROPERTIES DEPENDS stop_scord_daemon -- GitLab From c3ef654b094d96388b10268b7a3e070433fde6fe Mon Sep 17 00:00:00 2001 From: Alberto Miranda Date: Tue, 23 May 2023 13:23:22 +0200 Subject: [PATCH 17/17] Fix build issues with GCC-10 --- src/scord/internal_types.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scord/internal_types.cpp b/src/scord/internal_types.cpp index 0e0f54cc..599edae1 100644 --- a/src/scord/internal_types.cpp +++ b/src/scord/internal_types.cpp @@ -22,8 +22,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later *****************************************************************************/ +#include #include -#include #include "internal_types.hpp" -- GitLab