diff --git a/CMakeLists.txt b/CMakeLists.txt index 48de84a31f0506fa5f224b98f3442610aeb7962e..07ea2346b198fca89882619717aa1f45a7fbf01e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,6 +83,8 @@ set(CMAKE_SHARED_LINKER_FLAGS_ASAN set_property(GLOBAL APPEND PROPERTY DEBUG_CONFIGURATIONS Debug) set_property(GLOBAL APPEND PROPERTY DEBUG_CONFIGURATIONS ASan) +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt index d9c9d94868505964164bf63bf50b4c41e3abfdee..61cf9d67225e192ec87f37830de19ca8d7b56717 100644 --- a/examples/c/CMakeLists.txt +++ b/examples/c/CMakeLists.txt @@ -47,7 +47,7 @@ list(APPEND examples_c add_library(c_examples_common STATIC) target_sources(c_examples_common PUBLIC common.h PRIVATE common.c) -target_link_libraries(c_examples_common common::api::types) +target_link_libraries(c_examples_common libscord_c_types) foreach(example IN LISTS examples_c) add_executable(${example}_c) diff --git a/examples/cxx/CMakeLists.txt b/examples/cxx/CMakeLists.txt index a06c06b3e4014fa966201144ed4b4e5d9727ff5c..ead7d2515034d2eec8eff6e63d9ac87387c2f84f 100644 --- a/examples/cxx/CMakeLists.txt +++ b/examples/cxx/CMakeLists.txt @@ -47,7 +47,7 @@ list(APPEND examples_cxx add_library(cxx_examples_common STATIC) target_sources(cxx_examples_common PUBLIC common.hpp PRIVATE common.cpp) -target_link_libraries(cxx_examples_common common::api::types) +target_link_libraries(cxx_examples_common libscord_cxx_types) foreach(example IN LISTS examples_cxx) add_executable(${example}_cxx) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 1ce1ad4bc02ff043d480396a01fcc010b3ec4fd0..9aecbf56880f7b9c62bfbf48a644d128e49b6be7 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -45,15 +45,6 @@ target_include_directories(_rpc_client INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) add_library(common::network::rpc_client ALIAS _rpc_client) -target_include_directories(_rpc_types INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR}) -add_library(common::network::rpc_types ALIAS _rpc_types) - -add_subdirectory(api) -target_include_directories(_api_types INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR}) -add_library(common::api::types ALIAS _api_types) - add_subdirectory(abt_cxx) target_include_directories(_abt_cxx INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/common/api/CMakeLists.txt b/src/common/api/CMakeLists.txt deleted file mode 100644 index 99d81b70b73db3ac2c745b4510d3fde8716f3685..0000000000000000000000000000000000000000 --- a/src/common/api/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -################################################################################ -# Copyright 2021-2022, 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 # -################################################################################ - -add_library(_api_types STATIC) - -target_sources(_api_types PUBLIC scord/types.h scord/types.hpp PRIVATE - types.cpp convert.hpp convert.cpp scord/internal_types.hpp errors.c) - -target_include_directories(_api_types PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - -target_link_libraries(_api_types PRIVATE - Margo::Margo common::logger PUBLIC fmt::fmt common::abt_cxx) - -set_property(TARGET _api_types PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/src/common/api/convert.cpp b/src/common/api/convert.cpp deleted file mode 100644 index ab24eb409813153d2d54029d7c3827468a90a653..0000000000000000000000000000000000000000 --- a/src/common/api/convert.cpp +++ /dev/null @@ -1,337 +0,0 @@ -/****************************************************************************** - * Copyright 2021-2022, 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 "convert.hpp" - -// forward declarations -ADM_job_t -ADM_job_create(uint64_t id, uint64_t slurm_id); - -ADM_transfer_t -ADM_transfer_create(uint64_t id); - -namespace { - -scord::api::managed_ctype_array -as_ctype_array(const std::vector& nodes) { - - std::vector tmp; - - std::transform(nodes.cbegin(), nodes.cend(), std::back_inserter(tmp), - [](const scord::node& n) { - return ADM_node_create(n.hostname().c_str()); - }); - - return scord::api::managed_ctype_array{std::move(tmp)}; -} - -scord::api::managed_ctype_array -as_ctype_array(const std::vector& datasets) { - - std::vector tmp; - - std::transform(datasets.cbegin(), datasets.cend(), std::back_inserter(tmp), - [](const scord::dataset& d) { - return ADM_dataset_create(d.id().c_str()); - }); - - return scord::api::managed_ctype_array{std::move(tmp)}; -} - -} // namespace - -namespace scord::api { - -managed_ctype -convert(const node& node) { - return managed_ctype(ADM_node_create(node.hostname().c_str())); -} - -managed_ctype -convert(const adhoc_storage::resources& res) { - - auto managed_nodes = as_ctype_array(res.nodes()); - - ADM_adhoc_resources_t c_res = ADM_adhoc_resources_create( - managed_nodes.data(), managed_nodes.size()); - - return managed_ctype{c_res, - std::move(managed_nodes)}; -} - -managed_ctype -convert(const adhoc_storage::ctx& ctx) { - - auto managed_adhoc_resources = convert(ctx.resources()); - - return managed_ctype{ - ADM_adhoc_context_create( - static_cast(ctx.exec_mode()), - static_cast(ctx.access_type()), - managed_adhoc_resources.get(), ctx.walltime(), - ctx.should_flush()), - std::move(managed_adhoc_resources)}; -} - -managed_ctype -convert(const std::optional& adhoc_storage) { - - if(!adhoc_storage) { - return managed_ctype{}; - } - - return convert(adhoc_storage.value()); -} - -managed_ctype -convert(const scord::adhoc_storage& st) { - - auto managed_ctx = convert(st.context()); - ADM_adhoc_storage_t c_st = ADM_adhoc_storage_create( - st.name().c_str(), static_cast(st.type()), - st.id(), managed_ctx.get()); - - return managed_ctype{c_st, std::move(managed_ctx)}; -} - -managed_ctype -convert(const pfs_storage::ctx& ctx) { - return managed_ctype{ - ADM_pfs_context_create(ctx.mount_point().c_str())}; -} - -managed_ctype -convert(const std::optional& pfs_storage) { - - if(!pfs_storage) { - return managed_ctype{}; - } - - return convert(pfs_storage.value()); -} - -managed_ctype -convert(const scord::pfs_storage& st) { - - auto managed_ctx = convert(st.context()); - ADM_pfs_storage_t c_st = ADM_pfs_storage_create( - st.name().c_str(), static_cast(st.type()), - st.id(), managed_ctx.get()); - - return managed_ctype{c_st, std::move(managed_ctx)}; -} - -managed_ctype -convert(const scord::dataset& dataset) { - return managed_ctype( - ADM_dataset_create(dataset.id().c_str())); -} - -managed_ctype -convert(const std::vector& datasets) { - - std::vector tmp; - - std::transform(datasets.cbegin(), datasets.cend(), std::back_inserter(tmp), - [](const scord::dataset& d) { - return ADM_dataset_create(d.id().c_str()); - }); - - auto rv = managed_ctype{ - ADM_dataset_list_create(tmp.data(), tmp.size())}; - - std::for_each(tmp.cbegin(), tmp.cend(), - [](ADM_dataset_t d) { ADM_dataset_destroy(d); }); - - return rv; -} - -std::vector -convert(ADM_dataset_t datasets[], size_t datasets_len) { - - std::vector rv; - rv.reserve(datasets_len); - - for(size_t i = 0; i < datasets_len; ++i) { - rv.emplace_back(datasets[i]); - } - - return rv; -} - -std::vector -convert(ADM_dataset_list_t list) { - - std::vector rv; - rv.reserve(list->l_length); - - for(size_t i = 0; i < list->l_length; ++i) { - rv.emplace_back(&list->l_datasets[i]); - } - - return rv; -} - -managed_ctype -convert(const job::resources& res) { - - auto managed_nodes = as_ctype_array(res.nodes()); - - ADM_job_resources_t c_res = ADM_job_resources_create(managed_nodes.data(), - managed_nodes.size()); - - return managed_ctype{c_res, std::move(managed_nodes)}; -} - -managed_ctype -convert(const scord::job_requirements& reqs) { - - const auto& adhoc_storage = reqs.adhoc_storage(); - - auto managed_storage = convert(adhoc_storage); - auto managed_inputs = as_ctype_array(reqs.inputs()); - auto managed_outputs = as_ctype_array(reqs.outputs()); - - ADM_job_requirements_t c_reqs = ADM_job_requirements_create( - managed_inputs.data(), managed_inputs.size(), - managed_outputs.data(), managed_outputs.size(), - managed_storage.get()); - - return managed_ctype{ - c_reqs, std::move(managed_inputs), std::move(managed_outputs), - std::move(managed_storage)}; -} - - -managed_ctype -convert(const job& j) { - return managed_ctype(ADM_job_create(j.id(), j.slurm_id())); -} - -job -convert(ADM_job_t j) { - return scord::job{j}; -} - -managed_ctype -convert(const transfer& tx) { - return managed_ctype(ADM_transfer_create(tx.id())); -} - -transfer -convert(ADM_transfer_t tx) { - return transfer{tx}; -} - -managed_ctype -convert(const std::vector& limits) { - - std::vector tmp; - - std::transform( - limits.cbegin(), limits.cend(), std::back_inserter(tmp), - [](const scord::qos::limit& l) { - ADM_qos_entity_t e = nullptr; - - if(l.entity()) { - - switch(const auto s = l.entity()->scope()) { - case qos::scope::dataset: { - e = ADM_qos_entity_create( - static_cast(s), - convert(l.entity()->data()) - .release()); - break; - } - - case qos::scope::node: { - e = ADM_qos_entity_create( - static_cast(s), - convert(l.entity()->data()) - .release()); - break; - } - - case qos::scope::job: { - e = ADM_qos_entity_create( - static_cast(s), - convert(l.entity()->data()) - .release()); - break; - } - - case qos::scope::transfer: { - e = ADM_qos_entity_create( - static_cast(s), - convert(l.entity()->data()) - .release()); - break; - } - } - } - - return ADM_qos_limit_create( - e, static_cast(l.subclass()), - l.value()); - }); - - auto rv = managed_ctype{ - ADM_qos_limit_list_create(tmp.data(), tmp.size())}; - - std::for_each(tmp.cbegin(), tmp.cend(), - [](ADM_qos_limit_t l) { ADM_qos_limit_destroy_all(l); }); - - return rv; -} - -std::vector -convert(ADM_qos_limit_t limits[], size_t limits_len) { - - std::vector rv; - rv.reserve(limits_len); - - for(size_t i = 0; i < limits_len; ++i) { - rv.emplace_back(limits[i]); - } - - return rv; -} - -std::vector -convert(ADM_qos_limit_list_t list) { - - std::vector rv; - rv.reserve(list->l_length); - - for(size_t i = 0; i < list->l_length; ++i) { - rv.emplace_back(&list->l_limits[i]); - } - - return rv; -} - - -} // namespace scord::api diff --git a/src/common/api/convert.hpp b/src/common/api/convert.hpp deleted file mode 100644 index db9e92f445111a8f33bb65aaa5ed436e165504d0..0000000000000000000000000000000000000000 --- a/src/common/api/convert.hpp +++ /dev/null @@ -1,500 +0,0 @@ -/****************************************************************************** - * Copyright 2021-2022, 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_CONVERT_HPP -#define SCORD_CONVERT_HPP - -#include "scord/types.h" -#include "scord/types.hpp" - -namespace scord::api { - -// convenience types for managing the types from the C API in a RAII fashion -template -struct managed_ctype; - -template -struct managed_ctype_array; - -// conversion functions between C API and CXX API types - -managed_ctype -convert(const node& node); - -managed_ctype -convert(const adhoc_storage::resources& res); - -managed_ctype -convert(const adhoc_storage::ctx& ctx); - -managed_ctype -convert(const scord::adhoc_storage& st); - -managed_ctype -convert(const pfs_storage::ctx& ctx); - -managed_ctype -convert(const scord::pfs_storage& st); - -managed_ctype -convert(const scord::dataset& dataset); - -managed_ctype -convert(const std::vector& datasets); - -std::vector -convert(ADM_dataset_t datasets[], size_t datasets_len); - -std::vector -convert(ADM_dataset_list_t list); - -managed_ctype -convert(const job::resources& res); - -managed_ctype -convert(const scord::job_requirements& reqs); - -managed_ctype -convert(const job& j); - -job -convert(ADM_job_t j); - -managed_ctype -convert(const transfer& t); - -transfer -convert(ADM_transfer_t j); - -managed_ctype -convert(const std::vector& limits); - -std::vector -convert(ADM_qos_limit_t limits[], size_t limits_len); - -std::vector -convert(ADM_qos_limit_list_t list); - -} // namespace scord::api - - -//////////////////////////////////////////////////////////////////////////////// -// Specializations for conversion types -//////////////////////////////////////////////////////////////////////////////// - -template <> -struct scord::api::managed_ctype { - - explicit managed_ctype(ADM_node_t node) : m_node(node) {} - - ADM_node_t - get() const { - return m_node.get(); - } - - ADM_node_t - release() { - return m_node.release(); - } - - scord::utils::ctype_ptr m_node; -}; - -template <> -struct scord::api::managed_ctype_array { - - managed_ctype_array() = default; - - explicit managed_ctype_array(ADM_node_t* data, size_t size) - : m_nodes(data, size) {} - - explicit managed_ctype_array(std::vector&& v) - : m_nodes(v.data(), v.size()) {} - - constexpr size_t - size() const { - return m_nodes.size(); - } - - constexpr const ADM_node_t* - data() const noexcept { - return m_nodes.data(); - } - - constexpr ADM_node_t* - data() noexcept { - return m_nodes.data(); - } - - constexpr ADM_node_t* - release() noexcept { - return m_nodes.release(); - } - - scord::utils::ctype_ptr_vector m_nodes; -}; - -template <> -struct scord::api::managed_ctype { - - managed_ctype() = default; - - explicit managed_ctype(ADM_adhoc_resources_t res, - managed_ctype_array&& nodes) - : m_adhoc_resources(res), m_nodes(std::move(nodes)) {} - - ADM_adhoc_resources_t - get() const { - return m_adhoc_resources.get(); - } - - ADM_adhoc_resources_t - release() { - std::ignore = m_nodes.release(); - return m_adhoc_resources.release(); - } - - scord::utils::ctype_ptr - m_adhoc_resources; - managed_ctype_array m_nodes; -}; - -template <> -struct scord::api::managed_ctype { - - managed_ctype() = default; - - explicit managed_ctype(ADM_adhoc_context_t ctx, - managed_ctype&& resources) - : m_adhoc_context(ctx), m_adhoc_resources(std::move(resources)) {} - - ADM_adhoc_context_t - get() const { - return m_adhoc_context.get(); - } - - ADM_adhoc_context_t - release() { - std::ignore = m_adhoc_resources.release(); - return m_adhoc_context.release(); - } - - scord::utils::ctype_ptr - m_adhoc_context; - managed_ctype m_adhoc_resources; -}; - -template <> -struct scord::api::managed_ctype { - - managed_ctype() = default; - - explicit managed_ctype(ADM_adhoc_storage_t st, - managed_ctype&& ctx) - : m_storage(st), m_ctx(std::move(ctx)) {} - - ADM_adhoc_storage_t - get() const { - return m_storage.get(); - } - - ADM_adhoc_storage_t - release() { - std::ignore = m_ctx.release(); - return m_storage.release(); - } - - scord::utils::ctype_ptr - m_storage; - managed_ctype m_ctx; -}; - -template <> -struct scord::api::managed_ctype { - - managed_ctype() = default; - - explicit managed_ctype(ADM_pfs_context_t ctx) : m_pfs_context(ctx) {} - - ADM_pfs_context_t - get() const { - return m_pfs_context.get(); - } - - ADM_pfs_context_t - release() { - return m_pfs_context.release(); - } - - scord::utils::ctype_ptr - m_pfs_context; -}; - -template <> -struct scord::api::managed_ctype { - - managed_ctype() = default; - - explicit managed_ctype(ADM_pfs_storage_t st, - managed_ctype&& ctx) - : m_storage(st), m_ctx(std::move(ctx)) {} - - ADM_pfs_storage_t - get() const { - return m_storage.get(); - } - - ADM_pfs_storage_t - release() { - std::ignore = m_ctx.release(); - return m_storage.release(); - } - - scord::utils::ctype_ptr - m_storage; - managed_ctype m_ctx; -}; - -template <> -struct scord::api::managed_ctype { - - explicit managed_ctype(ADM_dataset_t dataset) : m_dataset(dataset) {} - - ADM_dataset_t - get() const { - return m_dataset.get(); - } - - ADM_dataset_t - release() { - return m_dataset.release(); - } - - scord::utils::ctype_ptr m_dataset; -}; - -template <> -struct scord::api::managed_ctype_array { - - explicit managed_ctype_array(ADM_dataset_t* data, size_t size) - : m_datasets(data, size) {} - - explicit managed_ctype_array(std::vector&& v) - : m_datasets(v.data(), v.size()) {} - - constexpr size_t - size() const { - return m_datasets.size(); - } - - constexpr const ADM_dataset_t* - data() const noexcept { - return m_datasets.data(); - } - - constexpr ADM_dataset_t* - data() noexcept { - return m_datasets.data(); - } - - constexpr ADM_dataset_t* - release() noexcept { - return m_datasets.release(); - } - - scord::utils::ctype_ptr_vector - m_datasets; -}; - -template <> -struct scord::api::managed_ctype { - - explicit managed_ctype(ADM_dataset_list_t list) : m_list(list) {} - - ADM_dataset_list_t - get() const { - return m_list.get(); - } - - ADM_dataset_list_t - release() { - return m_list.release(); - } - - scord::utils::ctype_ptr - m_list; -}; - -template <> -struct scord::api::managed_ctype { - - explicit managed_ctype(ADM_job_resources_t res, - managed_ctype_array&& nodes) - : m_adhoc_resources(res), m_nodes(std::move(nodes)) {} - - ADM_job_resources_t - get() const { - return m_adhoc_resources.get(); - } - - ADM_job_resources_t - release() { - return m_adhoc_resources.release(); - } - - scord::utils::ctype_ptr - m_adhoc_resources; - managed_ctype_array m_nodes; -}; - -template <> -struct scord::api::managed_ctype { - - explicit managed_ctype(ADM_job_requirements_t reqs, - managed_ctype_array&& inputs, - managed_ctype_array&& outputs, - managed_ctype&& adhoc_storage) - : m_reqs(reqs), m_inputs(std::move(inputs)), - m_outputs(std::move(outputs)), - m_adhoc_storage(std::move(adhoc_storage)) {} - - ADM_job_requirements_t - get() const { - return m_reqs.get(); - } - - ADM_job_requirements_t - release() { - return m_reqs.release(); - } - - - scord::utils::ctype_ptr - m_reqs; - managed_ctype_array m_inputs; - managed_ctype_array m_outputs; - managed_ctype m_adhoc_storage; -}; - - -// forward declarations -ADM_return_t -ADM_job_destroy(ADM_job_t job); - -ADM_return_t -ADM_transfer_destroy(ADM_transfer_t tx); - -template <> -struct scord::api::managed_ctype { - - explicit managed_ctype(ADM_job_t job) : m_job(job) {} - - ADM_job_t - get() const { - return m_job.get(); - } - - ADM_job_t - release() { - return m_job.release(); - } - - scord::utils::ctype_ptr m_job; -}; - -template <> -struct scord::api::managed_ctype { - - explicit managed_ctype(ADM_transfer_t tx) : m_transfer(tx) {} - - ADM_transfer_t - get() const { - return m_transfer.get(); - } - - ADM_transfer_t - release() { - return m_transfer.release(); - } - - scord::utils::ctype_ptr m_transfer; -}; - -ADM_return_t -ADM_qos_limit_destroy_all(ADM_qos_limit_t l); - -template <> -struct scord::api::managed_ctype_array { - - explicit managed_ctype_array(ADM_qos_limit_t data[], size_t size) - : m_qos_limits(data, size) {} - - explicit managed_ctype_array(std::vector&& v) - : m_qos_limits(v.data(), v.size()) {} - - constexpr size_t - size() const { - return m_qos_limits.size(); - } - - constexpr const ADM_qos_limit_t* - data() const noexcept { - return m_qos_limits.data(); - } - - constexpr ADM_qos_limit_t* - data() noexcept { - return m_qos_limits.data(); - } - - constexpr ADM_qos_limit_t* - release() noexcept { - return m_qos_limits.release(); - } - - scord::utils::ctype_ptr_vector - m_qos_limits; -}; - -template <> -struct scord::api::managed_ctype { - - explicit managed_ctype(ADM_qos_limit_list_t list) : m_list(list) {} - - ADM_qos_limit_list_t - get() const { - return m_list.get(); - } - - ADM_qos_limit_list_t - release() { - return m_list.release(); - } - - scord::utils::ctype_ptr - m_list; -}; - -#endif // SCORD_CONVERT_HPP diff --git a/src/common/logger/CMakeLists.txt b/src/common/logger/CMakeLists.txt index 6836b1244fbdc87d6692341bdc6c1f6220971e20..e35d8a4dba99f603056407b1ff3bf60a3bcff610 100644 --- a/src/common/logger/CMakeLists.txt +++ b/src/common/logger/CMakeLists.txt @@ -24,6 +24,6 @@ add_library(_logger INTERFACE) -target_sources(_logger INTERFACE logger.hpp) +target_sources(_logger INTERFACE logger.h logger.hpp macros.h logger.cpp) target_link_libraries(_logger INTERFACE spdlog::spdlog fmt::fmt) diff --git a/src/common/logger/logger.cpp b/src/common/logger/logger.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4dcfef375073691c486253726b861dda7b23e070 --- /dev/null +++ b/src/common/logger/logger.cpp @@ -0,0 +1,71 @@ +/****************************************************************************** + * 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 "logger.hpp" +#include "logger.h" + +void +logger_setup(const char* ident, const char* type, const char* log_file) { + scord::logger::create_global_logger(ident, type, log_file); +} + +void +logger_log(enum logger_level level, const char* fmt, ...) { + + if(const auto logger = scord::logger::get_global_logger(); logger) { + + std::array msg; // NOLINT + va_list args; + va_start(args, fmt); + vsnprintf(msg.data(), msg.size(), fmt, args); + va_end(args); + + switch(level) { + case info: + logger->info(msg.data()); + break; + case debug: + logger->debug(msg.data()); + break; + case warn: + logger->warn(msg.data()); + break; + case error: + logger->error(msg.data()); + break; + case critical: + logger->critical(msg.data()); + break; + } + } +} + +void +logger_destroy() { + if(scord::logger::get_global_logger()) { + scord::logger::destroy_global_logger(); + } +} diff --git a/src/common/logger/logger.h b/src/common/logger/logger.h new file mode 100644 index 0000000000000000000000000000000000000000..35b8398b2638ab674b4785e7d57d8014f53c9575 --- /dev/null +++ b/src/common/logger/logger.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * 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_LOGGER_H +#define SCORD_LOGGER_H + +#include "macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LOGGER_MSG_MAX_LEN 2048 + +enum logger_level { info, debug, warn, error, critical }; + +/** + * Initialize a global logger. + * + * Valid logger types: + * - console + * - console color + * - file + * + * @param ident The identifier that should be used when emitting messages + * @param type The type of logger desired. + * @param log_file The path to the log file where messages should be written. + */ +void +setup_logger(const char* ident, const char* type, const char* log_file); + +/** + * Emit a message. + * + * @param level The level for the message. + * @param fmt A vprintf()-compatible format string. + * @param ... A sequence of arguments corresponding to the format string. + */ +void +logger_log(enum logger_level level, const char* fmt, ...); + +/** + * Destroy the global logger. + */ +void +destroy_logger(); + +#ifdef __cplusplus +}; // extern "C" +#endif + +#endif // SCORD_LOGGER_H diff --git a/src/common/logger/logger.hpp b/src/common/logger/logger.hpp index 30503dfbfa762b452f7ec6f660daa276332548e1..8f26f7178412ee3f92c38ba35f389b2c18f98598 100644 --- a/src/common/logger/logger.hpp +++ b/src/common/logger/logger.hpp @@ -34,6 +34,8 @@ #include #include +#include "macros.h" + #if FMT_VERSION < 50000 namespace fmt { template @@ -279,85 +281,4 @@ private: } // namespace scord -// some macros to make it more convenient to use the global logger -#define LOGGER_INFO(...) \ - do { \ - using scord::logger; \ - if(logger::get_global_logger()) { \ - logger::get_global_logger()->info(__VA_ARGS__); \ - } \ - } while(0); - - -#ifdef __LOGGER_ENABLE_DEBUG__ - -#define LOGGER_DEBUG(...) \ - do { \ - using scord::logger; \ - if(logger::get_global_logger()) { \ - logger::get_global_logger()->debug(__VA_ARGS__); \ - } \ - } while(0); - -#define LOGGER_FLUSH() \ - do { \ - using scord::logger; \ - if(logger::get_global_logger()) { \ - logger::get_global_logger()->flush(); \ - } \ - } while(0); - -#else - -#define LOGGER_DEBUG(...) \ - do { \ - } while(0); -#define LOGGER_FLUSH() \ - do { \ - } while(0); - -#endif // __LOGGER_ENABLE_DEBUG__ - -#define LOGGER_WARN(...) \ - do { \ - using scord::logger; \ - if(logger::get_global_logger()) { \ - logger::get_global_logger()->warn(__VA_ARGS__); \ - } \ - } while(0); - -#define LOGGER_ERROR(...) \ - do { \ - using scord::logger; \ - if(logger::get_global_logger()) { \ - logger::get_global_logger()->error(__VA_ARGS__); \ - } \ - } while(0); - -#define LOGGER_ERRNO(...) \ - do { \ - using scord::logger; \ - if(logger::get_global_logger()) { \ - logger::get_global_logger()->error_errno(__VA_ARGS__); \ - } \ - } while(0); - -#define LOGGER_CRITICAL(...) \ - do { \ - using scord::logger; \ - if(logger::get_global_logger()) { \ - logger::get_global_logger()->critical(__VA_ARGS__); \ - } \ - } while(0); - - -#define LOGGER_EVAL(expr, L1, L2, ...) \ - do { \ - if(expr) { \ - LOGGER_##L1(__VA_ARGS__); \ - } else { \ - LOGGER_##L2(__VA_ARGS__); \ - } \ - } while(0); - #endif /* SCORD_LOGGER_HPP */ diff --git a/src/common/logger/macros.h b/src/common/logger/macros.h new file mode 100644 index 0000000000000000000000000000000000000000..8369ec5f4282bfbdad7afaf144f4bcf01caddbd7 --- /dev/null +++ b/src/common/logger/macros.h @@ -0,0 +1,159 @@ +/****************************************************************************** + * 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_MACROS_H +#define SCORD_MACROS_H + +/* logger macros for C++ code */ +#ifdef __cplusplus + +#define LOGGER_INFO(...) \ + do { \ + using scord::logger; \ + if(logger::get_global_logger()) { \ + logger::get_global_logger()->info(__VA_ARGS__); \ + } \ + } while(0); + + +#ifdef __LOGGER_ENABLE_DEBUG__ + +#define LOGGER_DEBUG(...) \ + do { \ + using scord::logger; \ + if(logger::get_global_logger()) { \ + logger::get_global_logger()->debug(__VA_ARGS__); \ + } \ + } while(0); + +#define LOGGER_FLUSH() \ + do { \ + using scord::logger; \ + if(logger::get_global_logger()) { \ + logger::get_global_logger()->flush(); \ + } \ + } while(0); + +#else // ! __LOGGER_ENABLE_DEBUG__ + +#define LOGGER_DEBUG(...) \ + do { \ + } while(0); +#define LOGGER_FLUSH() \ + do { \ + } while(0); + +#endif // __LOGGER_ENABLE_DEBUG__ + +#define LOGGER_WARN(...) \ + do { \ + using scord::logger; \ + if(logger::get_global_logger()) { \ + logger::get_global_logger()->warn(__VA_ARGS__); \ + } \ + } while(0); + +#define LOGGER_ERROR(...) \ + do { \ + using scord::logger; \ + if(logger::get_global_logger()) { \ + logger::get_global_logger()->error(__VA_ARGS__); \ + } \ + } while(0); + +#define LOGGER_ERRNO(...) \ + do { \ + using scord::logger; \ + if(logger::get_global_logger()) { \ + logger::get_global_logger()->error_errno(__VA_ARGS__); \ + } \ + } while(0); + +#define LOGGER_CRITICAL(...) \ + do { \ + using scord::logger; \ + if(logger::get_global_logger()) { \ + logger::get_global_logger()->critical(__VA_ARGS__); \ + } \ + } while(0); + +#else // ! __cplusplus + +/* logger macros for C code */ + +// clang-format off +#define ARGSN(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N +#define RSEQN() 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 +// clang-format on +#define EXPAND(x) x +#define COUNT_ARGS(...) EXPAND(COUNT_ARGS_HELPER(__VA_ARGS__, RSEQN())) +#define COUNT_ARGS_HELPER(...) EXPAND(ARGSN(__VA_ARGS__)) +#define GET_NAME_HELPER(name, n) name##n +#define GET_NAME(name, n) GET_NAME_HELPER(name, n) +#define GET_MACRO(func, ...) \ + GET_NAME(func, EXPAND(COUNT_ARGS(__VA_ARGS__)))(__VA_ARGS__) + +#define LOGGER_LOG(level, ...) GET_MACRO(LOGGER_LOG, level, __VA_ARGS__) +#define LOGGER_LOG2(level, msg) logger_log(level, "%s", msg) +#define LOGGER_LOG3 LOGGER_LOGN +#define LOGGER_LOG4 LOGGER_LOGN +#define LOGGER_LOG5 LOGGER_LOGN +#define LOGGER_LOG6 LOGGER_LOGN +#define LOGGER_LOG7 LOGGER_LOGN +#define LOGGER_LOG8 LOGGER_LOGN +#define LOGGER_LOG9 LOGGER_LOGN +#define LOGGER_LOG10 LOGGER_LOGN +#define LOGGER_LOG11 LOGGER_LOGN +#define LOGGER_LOG12 LOGGER_LOGN +#define LOGGER_LOG13 LOGGER_LOGN +#define LOGGER_LOG14 LOGGER_LOGN +#define LOGGER_LOG15 LOGGER_LOGN +#define LOGGER_LOG16 LOGGER_LOGN +#define LOGGER_LOGN(level, fmt, ...) logger_log(level, fmt, __VA_ARGS__) + +#define LOGGER_INFO(fmt, ...) LOGGER_LOG(info, fmt __VA_OPT__(, ) __VA_ARGS__); + +#ifdef __LOGGER_ENABLE_DEBUG__ +#define LOGGER_DEBUG(fmt, ...) \ + LOGGER_LOG(debug, fmt __VA_OPT__(, ) __VA_ARGS__); +#endif + +#define LOGGER_WARN(fmt, ...) LOGGER_LOG(warn, fmt __VA_OPT__(, ) __VA_ARGS__); + +#define LOGGER_ERROR(fmt, ...) \ + LOGGER_LOG(error, fmt __VA_OPT__(, ) __VA_ARGS__); + +#endif + +#define LOGGER_EVAL(expr, L1, L2, ...) \ + do { \ + if(expr) { \ + LOGGER_##L1(__VA_ARGS__); \ + } else { \ + LOGGER_##L2(__VA_ARGS__); \ + } \ + } while(0); + +#endif // SCORD_MACROS_H diff --git a/src/common/net/CMakeLists.txt b/src/common/net/CMakeLists.txt index c05d27138b983323f988fcd0220627aae57dd0e6..e38e67316c9b0fa1efcb05cdafafb6662167edbe 100644 --- a/src/common/net/CMakeLists.txt +++ b/src/common/net/CMakeLists.txt @@ -40,5 +40,3 @@ target_sources( ) target_link_libraries(_rpc_server PUBLIC common::config common::logger thallium) - -add_subdirectory(proto) diff --git a/src/common/net/proto/CMakeLists.txt b/src/common/net/proto/CMakeLists.txt deleted file mode 100644 index 32681285c4f6a8989bceb04a9e706683f742b217..0000000000000000000000000000000000000000 --- a/src/common/net/proto/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -################################################################################ -# Copyright 2021-2022, 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 # -################################################################################ - -add_library(_rpc_types STATIC) - -set_property(TARGET _rpc_types PROPERTY POSITION_INDEPENDENT_CODE ON) - -target_include_directories(_rpc_types PUBLIC ${CMAKE_SOURCE_DIR}/src/lib) -target_sources( - _rpc_types - PRIVATE rpc_types.h rpc_types.c -) - -target_link_libraries(_rpc_types PRIVATE common::api::types Mercury::Mercury - Margo::Margo) diff --git a/src/common/net/proto/rpc_types.c b/src/common/net/proto/rpc_types.c deleted file mode 100644 index 623d9803fe744af85de219182fd84b5c7d17703e..0000000000000000000000000000000000000000 --- a/src/common/net/proto/rpc_types.c +++ /dev/null @@ -1,1150 +0,0 @@ -/****************************************************************************** - * Copyright 2021-2022, 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 "rpc_types.h" - -hg_return_t (*hg_proc_ADM_adhoc_storage_type_t)(hg_proc_t, - void*) = hg_proc_hg_uint32_t; -hg_return_t (*hg_proc_ADM_pfs_storage_type_t)(hg_proc_t, - void*) = hg_proc_hg_uint32_t; -hg_return_t (*hg_proc_ADM_qos_scope_t)(hg_proc_t, void*) = hg_proc_hg_uint32_t; -hg_return_t (*hg_proc_ADM_qos_class_t)(hg_proc_t, void*) = hg_proc_hg_uint32_t; - -hg_return_t -hg_proc_ADM_node_t(hg_proc_t proc, void* data) { - - hg_return_t ret = HG_SUCCESS; - ADM_node_t* node = (ADM_node_t*) data; - ADM_node_t tmp = NULL; - hg_size_t node_length = 0; - - switch(hg_proc_get_op(proc)) { - - case HG_ENCODE: - // find out the length of the adm_node object we need to send - node_length = *node ? sizeof(adm_node) : 0; - ret = hg_proc_hg_size_t(proc, &node_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!node_length) { - return HG_SUCCESS; - } - - // if we actually need to send an adm_node object, - // write it to the mercury buffer - tmp = *node; - - ret = hg_proc_adm_node(proc, tmp); - - if(ret != HG_SUCCESS) { - break; - } - - break; - - case HG_DECODE: - // find out the length of the adm_node object - ret = hg_proc_hg_size_t(proc, &node_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!node_length) { - *node = NULL; - break; - } - - // if the received adm_node object was not NULL, read each of - // its fields from the mercury buffer - tmp = (adm_node*) calloc(1, sizeof(adm_node)); - - ret = hg_proc_adm_node(proc, tmp); - - if(ret != HG_SUCCESS) { - break; - } - - // return the newly-created ctx - *node = tmp; - break; - - case HG_FREE: - tmp = *node; - free(tmp); - break; - } - - return ret; -} - -hg_return_t -hg_proc_ADM_dataset_t(hg_proc_t proc, void* data) { - - hg_return_t ret = HG_SUCCESS; - ADM_dataset_t* dataset = (ADM_dataset_t*) data; - ADM_dataset_t tmp = NULL; - hg_size_t dataset_length = 0; - - switch(hg_proc_get_op(proc)) { - - case HG_ENCODE: - // find out the length of the adm_dataset object we need to send - dataset_length = *dataset ? sizeof(adm_dataset) : 0; - ret = hg_proc_hg_size_t(proc, &dataset_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!dataset_length) { - return HG_SUCCESS; - } - - // if we actually need to send an adm_dataset object, - // write it to the mercury buffer - tmp = *dataset; - - ret = hg_proc_adm_dataset(proc, tmp); - - if(ret != HG_SUCCESS) { - break; - } - - break; - - case HG_DECODE: - // find out the length of the adm_dataset object - ret = hg_proc_hg_size_t(proc, &dataset_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!dataset_length) { - *dataset = NULL; - break; - } - - // if the received adm_dataset object was not NULL, read each of - // its fields from the mercury buffer - tmp = (adm_dataset*) calloc(1, sizeof(adm_dataset)); - - ret = hg_proc_adm_dataset(proc, tmp); - - if(ret != HG_SUCCESS) { - break; - } - - // return the newly-created ctx - *dataset = tmp; - break; - - case HG_FREE: - tmp = *dataset; - free(tmp); - break; - } - - return ret; -} - -hg_return_t -hg_proc_ADM_job_t(hg_proc_t proc, void* data) { - - hg_return_t ret = HG_SUCCESS; - ADM_job_t* job = (ADM_job_t*) data; - ADM_job_t tmp = NULL; - hg_size_t job_length = 0; - - switch(hg_proc_get_op(proc)) { - - case HG_ENCODE: - // find out the length of the adm_storage object we need to send - job_length = *job ? sizeof(adm_job) : 0; - ret = hg_proc_hg_size_t(proc, &job_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!job_length) { - return HG_SUCCESS; - } - - // if we actually need to send an adm_job object, - // write it to the mercury buffer - tmp = *job; - - ret = hg_proc_adm_job(proc, tmp); - - if(ret != HG_SUCCESS) { - break; - } - - break; - - case HG_DECODE: - // find out the length of the adm_storage object - ret = hg_proc_hg_size_t(proc, &job_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!job_length) { - *job = NULL; - break; - } - - // if the received adm_job object was not NULL, read each of - // its fields from the mercury buffer - tmp = (adm_job*) calloc(1, sizeof(adm_job)); - - ret = hg_proc_adm_job(proc, tmp); - - if(ret != HG_SUCCESS) { - break; - } - - // return the newly-created ctx - *job = tmp; - break; - - case HG_FREE: - tmp = *job; - free(tmp); - break; - } - - return ret; -} - -hg_return_t -hg_proc_ADM_transfer_t(hg_proc_t proc, void* data) { - - hg_return_t ret = HG_SUCCESS; - ADM_transfer_t* transfer = (ADM_transfer_t*) data; - ADM_transfer_t tmp = NULL; - hg_size_t transfer_length = 0; - - switch(hg_proc_get_op(proc)) { - - case HG_ENCODE: - // find out the length of the adm_transfer object we need to send - transfer_length = *transfer ? sizeof(adm_transfer) : 0; - ret = hg_proc_hg_size_t(proc, &transfer_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!transfer_length) { - return HG_SUCCESS; - } - - // if we actually need to send an adm_transfer object, - // write it to the mercury buffer - tmp = *transfer; - - ret = hg_proc_adm_transfer(proc, tmp); - - if(ret != HG_SUCCESS) { - break; - } - - break; - - case HG_DECODE: - // find out the length of the adm_transfer object - ret = hg_proc_hg_size_t(proc, &transfer_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!transfer_length) { - *transfer = NULL; - break; - } - - // if the received adm_transfer object was not NULL, read each of - // its fields from the mercury buffer - tmp = (adm_transfer*) calloc(1, sizeof(adm_transfer)); - - ret = hg_proc_adm_transfer(proc, tmp); - - if(ret != HG_SUCCESS) { - break; - } - - // return the newly-created ctx - *transfer = tmp; - break; - - case HG_FREE: - tmp = *transfer; - free(tmp); - break; - } - - return ret; -} - -hg_return_t -hg_proc_ADM_dataset_list_t(hg_proc_t proc, void* data) { - - hg_return_t ret = HG_SUCCESS; - ADM_dataset_list_t* list = (ADM_dataset_list_t*) data; - ADM_dataset_list_t tmp = NULL; - - hg_size_t length = 0; - - switch(hg_proc_get_op(proc)) { - - case HG_ENCODE: - tmp = *list; - // write the length of the list - length = tmp->l_length; - ret = hg_proc_hg_size_t(proc, &tmp->l_length); - - if(ret != HG_SUCCESS) { - break; - } - - // write the list - for(size_t i = 0; i < length; ++i) { - ret = hg_proc_adm_dataset(proc, &tmp->l_datasets[i]); - - if(ret != HG_SUCCESS) { - break; - } - } - break; - - case HG_DECODE: { - - // find out the length of the list - ret = hg_proc_hg_size_t(proc, &length); - - if(ret != HG_SUCCESS) { - break; - } - - // loop and create list elements - tmp = (ADM_dataset_list_t) calloc(1, - sizeof(struct adm_dataset_list)); - tmp->l_length = length; - tmp->l_datasets = - (adm_dataset*) calloc(length, sizeof(adm_dataset)); - - for(size_t i = 0; i < length; ++i) { - ret = hg_proc_adm_dataset(proc, &tmp->l_datasets[i]); - - if(ret != HG_SUCCESS) { - break; - } - } - - // return the newly-created list - *list = tmp; - - break; - } - - case HG_FREE: - tmp = *list; - free(tmp->l_datasets); - free(tmp); - ret = HG_SUCCESS; - break; - } - - return ret; -} - - -hg_return_t -hg_proc_ADM_adhoc_storage_t(hg_proc_t proc, void* data) { - - hg_return_t ret = HG_SUCCESS; - ADM_adhoc_storage_t* storage = (ADM_adhoc_storage_t*) data; - ADM_adhoc_storage_t tmp = NULL; - hg_size_t storage_length = 0; - - switch(hg_proc_get_op(proc)) { - - case HG_ENCODE: - // find out the length of the adm_adhoc_storage object we need to - // send - storage_length = *storage ? sizeof(adm_adhoc_storage) : 0; - ret = hg_proc_hg_size_t(proc, &storage_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!storage_length) { - return HG_SUCCESS; - } - - // if we actually need to send an adm_adhoc_storage object, - // write each of its fields to the mercury buffer - tmp = *storage; - - // 1. the storage type - ret = hg_proc_hg_uint32_t(proc, &tmp->s_type); - - if(ret != HG_SUCCESS) { - break; - } - - // 2. the storage id - ret = hg_proc_hg_const_string_t(proc, &tmp->s_name); - - if(ret != HG_SUCCESS) { - break; - } - - // 3. the server-assigned id - ret = hg_proc_hg_int64_t(proc, &tmp->s_id); - - if(ret != HG_SUCCESS) { - break; - } - - // 4. the appropriate storage context - ret = hg_proc_ADM_adhoc_context_t(proc, &tmp->s_adhoc_ctx); - - if(ret != HG_SUCCESS) { - break; - } - - break; - - case HG_DECODE: - // find out the length of the adm_adhoc_storage object - ret = hg_proc_hg_size_t(proc, &storage_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!storage_length) { - *storage = NULL; - break; - } - - // if the received adm_adhoc_storage object was not NULL, read each - // of its fields from the mercury buffer - tmp = (adm_adhoc_storage*) calloc(1, sizeof(adm_adhoc_storage)); - - // 1. the storage type - ret = hg_proc_uint32_t(proc, &tmp->s_type); - - if(ret != HG_SUCCESS) { - break; - } - - // 2. the storage id - ret = hg_proc_hg_const_string_t(proc, &tmp->s_name); - - if(ret != HG_SUCCESS) { - break; - } - - // 3. the server-assigned id - ret = hg_proc_hg_int64_t(proc, &tmp->s_id); - - if(ret != HG_SUCCESS) { - break; - } - - // 4. the appropriate storage context - ret = hg_proc_ADM_adhoc_context_t(proc, &tmp->s_adhoc_ctx); - - if(ret != HG_SUCCESS) { - break; - } - - // return the newly-created ctx - *storage = tmp; - break; - - case HG_FREE: - tmp = *storage; - free(tmp); - break; - } - - return ret; -} - -hg_return_t -hg_proc_ADM_adhoc_context_t(hg_proc_t proc, void* data) { - - hg_return_t ret = HG_SUCCESS; - ADM_adhoc_context_t* ctx = (ADM_adhoc_context_t*) data; - ADM_adhoc_context_t tmp = NULL; - hg_size_t ctx_length = 0; - - switch(hg_proc_get_op(proc)) { - - case HG_ENCODE: - // find out the length of the context - ctx_length = *ctx ? sizeof(adm_adhoc_context) : 0; - ret = hg_proc_hg_size_t(proc, &ctx_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!ctx_length) { - return HG_SUCCESS; - } - - // if not NULL, write the context - tmp = *ctx; - ret = hg_proc_adm_adhoc_context(proc, tmp); - - if(ret != HG_SUCCESS) { - break; - } - - break; - - case HG_DECODE: { - - // find out the length of the context - ret = hg_proc_hg_size_t(proc, &ctx_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!ctx_length) { - *ctx = NULL; - break; - } - - // if not NULL, read the context - tmp = (ADM_adhoc_context_t) calloc( - 1, sizeof(struct adm_adhoc_context)); - ret = hg_proc_adm_adhoc_context(proc, tmp); - - if(ret != HG_SUCCESS) { - break; - } - - // return the newly-created ctx - *ctx = tmp; - break; - } - - case HG_FREE: - tmp = *ctx; - free(tmp); - ret = HG_SUCCESS; - break; - } - - return ret; -} - -hg_return_t -hg_proc_ADM_pfs_storage_t(hg_proc_t proc, void* data) { - - hg_return_t ret = HG_SUCCESS; - ADM_pfs_storage_t* storage = (ADM_pfs_storage_t*) data; - ADM_pfs_storage_t tmp = NULL; - hg_size_t storage_length = 0; - - switch(hg_proc_get_op(proc)) { - - case HG_ENCODE: - // find out the length of the adm_pfs_storage object we need to send - storage_length = *storage ? sizeof(adm_pfs_storage) : 0; - ret = hg_proc_hg_size_t(proc, &storage_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!storage_length) { - return HG_SUCCESS; - } - - // if we actually need to send an adm_pfs_storage object, - // write each of its fields to the mercury buffer - tmp = *storage; - - // 1. the storage type - ret = hg_proc_hg_uint32_t(proc, &tmp->s_type); - - if(ret != HG_SUCCESS) { - break; - } - - // 2. the storage id - ret = hg_proc_hg_const_string_t(proc, &tmp->s_name); - - if(ret != HG_SUCCESS) { - break; - } - - // 3. the server-assigned id - ret = hg_proc_hg_int64_t(proc, &tmp->s_id); - - if(ret != HG_SUCCESS) { - break; - } - - // 4. the appropriate storage context - ret = hg_proc_ADM_pfs_context_t(proc, &tmp->s_pfs_ctx); - break; - - case HG_DECODE: - // find out the length of the adm_pfs_storage object - ret = hg_proc_hg_size_t(proc, &storage_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!storage_length) { - *storage = NULL; - break; - } - - // if the received adm_pfs_storage object was not NULL, read each of - // its fields from the mercury buffer - tmp = (adm_pfs_storage*) calloc(1, sizeof(adm_pfs_storage)); - - // 1. the storage type - ret = hg_proc_uint32_t(proc, &tmp->s_type); - - if(ret != HG_SUCCESS) { - break; - } - - // 2. the storage id - ret = hg_proc_hg_const_string_t(proc, &tmp->s_name); - - if(ret != HG_SUCCESS) { - break; - } - - // 3. the server-assigned id - ret = hg_proc_hg_int64_t(proc, &tmp->s_id); - - if(ret != HG_SUCCESS) { - break; - } - - // 4. the appropriate storage context - ret = hg_proc_ADM_pfs_context_t(proc, &tmp->s_pfs_ctx); - - if(ret != HG_SUCCESS) { - break; - } - - // return the newly-created ctx - *storage = tmp; - break; - - case HG_FREE: - tmp = *storage; - free(tmp); - break; - } - - return ret; -} - -hg_return_t -hg_proc_ADM_pfs_context_t(hg_proc_t proc, void* data) { - - hg_return_t ret = HG_SUCCESS; - ADM_pfs_context_t* ctx = (ADM_pfs_context_t*) data; - ADM_pfs_context_t tmp = NULL; - hg_size_t ctx_length = 0; - - switch(hg_proc_get_op(proc)) { - - case HG_ENCODE: - // find out the length of the context - ctx_length = *ctx ? sizeof(adm_pfs_context) : 0; - ret = hg_proc_hg_size_t(proc, &ctx_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!ctx_length) { - return HG_SUCCESS; - } - - // if not NULL, write the context - tmp = *ctx; - ret = hg_proc_adm_pfs_context(proc, tmp); - - if(ret != HG_SUCCESS) { - break; - } - - break; - - case HG_DECODE: { - - // find out the length of the context - ret = hg_proc_hg_size_t(proc, &ctx_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!ctx_length) { - *ctx = NULL; - break; - } - - // if not NULL, read the context - tmp = (ADM_pfs_context_t) calloc(1, sizeof(struct adm_pfs_context)); - ret = hg_proc_adm_pfs_context(proc, tmp); - - if(ret != HG_SUCCESS) { - break; - } - - // return the newly-created ctx - *ctx = tmp; - break; - } - - case HG_FREE: - tmp = *ctx; - free(tmp); - ret = HG_SUCCESS; - break; - } - - return ret; -} - - -hg_return_t -hg_proc_ADM_qos_limit_list_t(hg_proc_t proc, void* data) { - hg_return_t ret = HG_SUCCESS; - ADM_qos_limit_list_t* list = (ADM_qos_limit_list_t*) data; - ADM_qos_limit_list_t tmp = NULL; - - hg_size_t length = 0; - - switch(hg_proc_get_op(proc)) { - - case HG_ENCODE: - tmp = *list; - // write the length of the list - length = tmp->l_length; - ret = hg_proc_hg_size_t(proc, &tmp->l_length); - - if(ret != HG_SUCCESS) { - break; - } - - // write the list - for(size_t i = 0; i < length; ++i) { - ret = hg_proc_adm_qos_limit(proc, &tmp->l_limits[i]); - - if(ret != HG_SUCCESS) { - break; - } - } - break; - - case HG_DECODE: { - - // find out the length of the list - ret = hg_proc_hg_size_t(proc, &length); - - if(ret != HG_SUCCESS) { - break; - } - - // loop and create list elements - tmp = (ADM_qos_limit_list_t) calloc( - 1, sizeof(struct adm_qos_limit_list)); - tmp->l_length = length; - tmp->l_limits = - (adm_qos_limit*) calloc(length, sizeof(adm_qos_limit)); - - for(size_t i = 0; i < length; ++i) { - ret = hg_proc_adm_qos_limit(proc, &tmp->l_limits[i]); - - if(ret != HG_SUCCESS) { - break; - } - } - - // return the newly-created list - *list = tmp; - - break; - } - - case HG_FREE: - tmp = *list; - free(tmp->l_limits); - free(tmp); - ret = HG_SUCCESS; - break; - } - - return ret; -} - -hg_return_t -hg_proc_ADM_qos_entity_t(hg_proc_t proc, void* data) { - - hg_return_t ret = HG_SUCCESS; - ADM_qos_entity_t* qos_entity = (ADM_qos_entity_t*) data; - ADM_qos_entity_t tmp = NULL; - hg_size_t qos_entity_length = 0; - - switch(hg_proc_get_op(proc)) { - - case HG_ENCODE: - // find out the length of the adm_qos_entity object we need to send - qos_entity_length = *qos_entity ? sizeof(adm_qos_entity) : 0; - ret = hg_proc_hg_size_t(proc, &qos_entity_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!qos_entity_length) { - return HG_SUCCESS; - } - - // if we actually need to send an adm_qos_entity object, - // write each of its fields to the mercury buffer - - // 1. the QoS scope - ret = hg_proc_ADM_qos_scope_t(proc, &tmp->e_scope); - - if(ret != HG_SUCCESS) { - break; - } - - // 2. the appropriate related data depending on the scope (i.e. an - // ADM_node_t, ADM_job_t, ADM_dataset_t, or ADM_transfer_t) - switch(tmp->e_scope) { - - case ADM_QOS_SCOPE_DATASET: - ret = hg_proc_ADM_dataset_t(proc, &tmp->e_dataset); - break; - case ADM_QOS_SCOPE_NODE: - ret = hg_proc_ADM_node_t(proc, &tmp->e_node); - break; - case ADM_QOS_SCOPE_JOB: - ret = hg_proc_ADM_job_t(proc, &tmp->e_job); - break; - case ADM_QOS_SCOPE_TRANSFER: - ret = hg_proc_ADM_transfer_t(proc, &tmp->e_transfer); - break; - } - - break; - - case HG_DECODE: - // find out the length of the adm_qos_entity object - ret = hg_proc_hg_size_t(proc, &qos_entity_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!qos_entity_length) { - *qos_entity = NULL; - break; - } - - // if the received adm_qos_entity object was not NULL, read each - // of its fields from the mercury buffer - tmp = (adm_qos_entity*) calloc(1, sizeof(adm_qos_entity)); - - // 1. the QoS scope - ret = hg_proc_ADM_qos_scope_t(proc, &tmp->e_scope); - - if(ret != HG_SUCCESS) { - break; - } - - // 2. the appropriate related data depending on the scope (i.e. an - // ADM_node_t, ADM_job_t, ADM_dataset_t, or ADM_transfer_t) - switch(tmp->e_scope) { - - case ADM_QOS_SCOPE_DATASET: - ret = hg_proc_ADM_dataset_t(proc, &tmp->e_dataset); - break; - case ADM_QOS_SCOPE_NODE: - ret = hg_proc_ADM_node_t(proc, &tmp->e_node); - break; - case ADM_QOS_SCOPE_JOB: - ret = hg_proc_ADM_job_t(proc, &tmp->e_job); - break; - case ADM_QOS_SCOPE_TRANSFER: - ret = hg_proc_ADM_transfer_t(proc, &tmp->e_transfer); - break; - } - - // return the newly-created entity - *qos_entity = tmp; - break; - - case HG_FREE: - tmp = *qos_entity; - free(tmp); - break; - } - - return ret; -} - -hg_return_t -hg_proc_ADM_node_list_t(hg_proc_t proc, void* data) { - - hg_return_t ret = HG_SUCCESS; - ADM_node_list_t* list = (ADM_node_list_t*) data; - ADM_node_list_t tmp = NULL; - - hg_size_t length = 0; - - switch(hg_proc_get_op(proc)) { - - case HG_ENCODE: - tmp = *list; - // write the length of the list - length = tmp->l_length; - ret = hg_proc_hg_size_t(proc, &tmp->l_length); - - if(ret != HG_SUCCESS) { - break; - } - - // write the list - for(size_t i = 0; i < length; ++i) { - ret = hg_proc_adm_node(proc, &tmp->l_nodes[i]); - - if(ret != HG_SUCCESS) { - break; - } - } - break; - - case HG_DECODE: { - - // find out the length of the list - ret = hg_proc_hg_size_t(proc, &length); - - if(ret != HG_SUCCESS) { - break; - } - - // loop and create list elements - tmp = (ADM_node_list_t) calloc(1, sizeof(struct adm_node_list)); - tmp->l_length = length; - tmp->l_nodes = (adm_node*) calloc(length, sizeof(adm_node)); - - for(size_t i = 0; i < length; ++i) { - ret = hg_proc_adm_node(proc, &tmp->l_nodes[i]); - - if(ret != HG_SUCCESS) { - break; - } - } - - // return the newly-created list - *list = tmp; - - break; - } - - case HG_FREE: - tmp = *list; - free(tmp->l_nodes); - free(tmp); - ret = HG_SUCCESS; - break; - } - - return ret; -} - -hg_return_t -hg_proc_ADM_adhoc_resources_t(hg_proc_t proc, void* data) { - - hg_return_t ret = HG_SUCCESS; - ADM_adhoc_resources_t* res = (ADM_adhoc_resources_t*) data; - ADM_adhoc_resources_t tmp = NULL; - hg_size_t res_length = 0; - - switch(hg_proc_get_op(proc)) { - - case HG_ENCODE: - // find out the length of the adm_adhoc_resources object we need to - // send - res_length = *res ? sizeof(adm_adhoc_resources) : 0; - ret = hg_proc_hg_size_t(proc, &res_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!res_length) { - return HG_SUCCESS; - } - - // if we actually need to send an adm_transfer object, - // write it to the mercury buffer - tmp = *res; - - ret = hg_proc_adm_adhoc_resources(proc, tmp); - - if(ret != HG_SUCCESS) { - break; - } - - break; - - case HG_DECODE: - // find out the length of the adm_transfer object - ret = hg_proc_hg_size_t(proc, &res_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!res_length) { - *res = NULL; - break; - } - - // if the received adm_adhoc_resources object was not NULL, read - // each of its fields from the mercury buffer - tmp = (adm_adhoc_resources*) calloc(1, sizeof(adm_adhoc_resources)); - - ret = hg_proc_adm_adhoc_resources(proc, tmp); - - if(ret != HG_SUCCESS) { - break; - } - - // return the newly-created ctx - *res = tmp; - break; - - case HG_FREE: - tmp = *res; - free(tmp); - break; - } - - return ret; -} - -hg_return_t -hg_proc_ADM_job_resources_t(hg_proc_t proc, void* data) { - - hg_return_t ret = HG_SUCCESS; - ADM_job_resources_t* res = (ADM_job_resources_t*) data; - ADM_job_resources_t tmp = NULL; - hg_size_t res_length = 0; - - switch(hg_proc_get_op(proc)) { - - case HG_ENCODE: - // find out the length of the adm_job_resources object we need to - // send - res_length = *res ? sizeof(adm_job_resources) : 0; - ret = hg_proc_hg_size_t(proc, &res_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!res_length) { - return HG_SUCCESS; - } - - // if we actually need to send an adm_transfer object, - // write it to the mercury buffer - tmp = *res; - - ret = hg_proc_adm_job_resources(proc, tmp); - - if(ret != HG_SUCCESS) { - break; - } - - break; - - case HG_DECODE: - // find out the length of the adm_transfer object - ret = hg_proc_hg_size_t(proc, &res_length); - - if(ret != HG_SUCCESS) { - break; - } - - if(!res_length) { - *res = NULL; - break; - } - - // if the received adm_job_resources object was not NULL, read - // each of its fields from the mercury buffer - tmp = (adm_job_resources*) calloc(1, sizeof(adm_job_resources)); - - ret = hg_proc_adm_job_resources(proc, tmp); - - if(ret != HG_SUCCESS) { - break; - } - - // return the newly-created ctx - *res = tmp; - break; - - case HG_FREE: - tmp = *res; - free(tmp); - break; - } - - return ret; -} diff --git a/src/common/net/proto/rpc_types.h b/src/common/net/proto/rpc_types.h deleted file mode 100644 index 8fbd581fde6f84af5e4918ef424d04de815db481..0000000000000000000000000000000000000000 --- a/src/common/net/proto/rpc_types.h +++ /dev/null @@ -1,652 +0,0 @@ -/****************************************************************************** - * Copyright 2021-2022, 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_PROTO_TYPES_HPP -#define SCORD_PROTO_TYPES_HPP - -#include // NOLINT -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -/** - * N.B. MERCURY_GEN_STRUCT_PROC requires a `typedef` as its first argument, but - * admire_types.h also requires types to be defined as `struct T`s. Defining RPC - * types as `typedef struct T { ... } T;` solves both problems - */ - -typedef struct adm_node { - const char* n_hostname; -} adm_node; - -hg_return_t -hg_proc_ADM_node_t(hg_proc_t proc, void* data); - -// clang-format off -MERCURY_GEN_STRUCT_PROC( - adm_node, // NOLINT - ((hg_const_string_t) (n_hostname)) -); -// clang-format on - -typedef struct adm_dataset { - const char* d_id; -} adm_dataset; - -hg_return_t -hg_proc_ADM_dataset_t(hg_proc_t proc, void* data); - -// clang-format off -MERCURY_GEN_STRUCT_PROC( - adm_dataset, // NOLINT - ((hg_const_string_t) (d_id)) -); -// clang-format on - -typedef struct adm_job { - uint64_t j_id; - uint64_t j_slurm_id; -} adm_job; - -// clang-format off -MERCURY_GEN_STRUCT_PROC( - adm_job, // NOLINT - ((hg_uint64_t) (j_id)) - ((hg_uint64_t) (j_slurm_id)) -); -// clang-format on - -hg_return_t -hg_proc_ADM_job_t(hg_proc_t proc, void* data); - -typedef struct adm_qos_entity { - ADM_qos_scope_t e_scope; - union { - ADM_node_t e_node; - ADM_job_t e_job; - ADM_dataset_t e_dataset; - ADM_transfer_t e_transfer; - }; -} adm_qos_entity; - -extern hg_return_t (*hg_proc_ADM_qos_scope_t)(hg_proc_t, void*); - -hg_return_t -hg_proc_ADM_qos_entity_t(hg_proc_t proc, void* data); - -typedef struct adm_qos_limit { - ADM_qos_entity_t l_entity; - ADM_qos_class_t l_class; - hg_uint64_t l_value; -} adm_qos_limit; - -extern hg_return_t (*hg_proc_ADM_qos_class_t)(hg_proc_t, void*); - -// clang-format off -MERCURY_GEN_STRUCT_PROC( - adm_qos_limit, // NOLINT - ((ADM_qos_entity_t) (l_entity)) - ((ADM_qos_class_t) (l_class)) - ((hg_uint64_t) (l_value)) -) -// clang-format on - -typedef struct adm_transfer { - uint64_t t_id; -} adm_transfer; - -hg_return_t -hg_proc_ADM_transfer_t(hg_proc_t proc, void* data); - -// clang-format off -MERCURY_GEN_STRUCT_PROC( - adm_transfer, // NOLINT - ((hg_uint64_t) (t_id)) -); -// clang-format on - -typedef struct adm_dataset_info { - // TODO: undefined for now - int32_t placeholder; -} adm_dataset_info; - -// clang-format off -MERCURY_GEN_STRUCT_PROC( - adm_dataset_info, // NOLINT - ((hg_int32_t) (placeholder)) -); -// clang-format on - -typedef struct adm_adhoc_context { - /** The adhoc storage system execution mode */ - ADM_adhoc_mode_t c_mode; - /** The adhoc storage system access type */ - ADM_adhoc_access_t c_access; - /** The resources assigned for the adhoc storage system */ - ADM_adhoc_resources_t c_resources; - /** The adhoc storage system walltime */ - uint32_t c_walltime; - /** Whether the adhoc storage system should flush data in the background */ - bool c_should_bg_flush; -} adm_adhoc_context; - -hg_return_t -hg_proc_ADM_adhoc_resources_t(hg_proc_t proc, void* data); - -// clang-format off -MERCURY_GEN_STRUCT_PROC( - adm_adhoc_context, // NOLINT - ((hg_int32_t) (c_mode)) - ((hg_int32_t) (c_access)) - ((ADM_adhoc_resources_t) (c_resources)) - ((hg_uint32_t) (c_walltime)) - ((hg_bool_t) (c_should_bg_flush)) -) -// clang-format on - -typedef struct adm_pfs_context { - /** The PFS mount point */ - const char* c_mount; -} adm_pfs_context; - - -// clang-format off -MERCURY_GEN_STRUCT_PROC( - adm_pfs_context, // NOLINT - ((hg_const_string_t) (c_mount)) -); -// clang-format on - -extern hg_return_t (*hg_proc_ADM_adhoc_storage_type_t)(hg_proc_t, void*); - -typedef struct adm_adhoc_storage { - const char* s_name; - ADM_adhoc_storage_type_t s_type; - uint64_t s_id; - ADM_adhoc_context_t s_adhoc_ctx; -} adm_adhoc_storage; - -hg_return_t -hg_proc_ADM_adhoc_storage_t(hg_proc_t proc, void* data); - -extern hg_return_t (*hg_proc_ADM_pfs_storage_type_t)(hg_proc_t, void*); - -typedef struct adm_pfs_storage { - const char* s_name; - ADM_pfs_storage_type_t s_type; - uint64_t s_id; - ADM_pfs_context_t s_pfs_ctx; -} adm_pfs_storage; - -hg_return_t -hg_proc_ADM_pfs_storage_t(hg_proc_t proc, void* data); - -struct adm_node_list { - /** An array of nodes */ - adm_node* l_nodes; - /** The length of the array */ - size_t l_length; -}; - -hg_return_t -hg_proc_ADM_node_list_t(hg_proc_t proc, void* data); - -typedef struct adm_adhoc_resources { - ADM_node_list_t r_nodes; -} adm_adhoc_resources; - -// clang-format off -MERCURY_GEN_STRUCT_PROC( - adm_adhoc_resources, // NOLINT - ((ADM_node_list_t) (r_nodes)) -); -// clang-format on - -typedef struct adm_data_operation { - // TODO: undefined for now - int32_t placeholder; -} adm_data_operation; - -// clang-format off -MERCURY_GEN_STRUCT_PROC( - adm_data_operation, // NOLINT - ((hg_int32_t) (placeholder)) -); -// clang-format on - - -struct adm_dataset_list { - /** An array of datasets */ - adm_dataset* l_datasets; - /** The length of the array */ - size_t l_length; -}; - -hg_return_t -hg_proc_ADM_dataset_list_t(hg_proc_t proc, void* data); - -hg_return_t -hg_proc_ADM_adhoc_context_t(hg_proc_t proc, void* data); - -hg_return_t -hg_proc_ADM_pfs_context_t(hg_proc_t proc, void* data); - - -/** The I/O requirements for a job */ -typedef struct adm_job_requirements { - /** An array of input datasets */ - ADM_dataset_list_t r_inputs; - /** An array of output datasets */ - ADM_dataset_list_t r_outputs; - /** An optional definition for a specific storage instance */ - ADM_adhoc_storage_t r_adhoc_storage; -} adm_job_requirements; - -// clang-format off -MERCURY_GEN_STRUCT_PROC( - adm_job_requirements, // NOLINT - ((ADM_dataset_list_t) (r_inputs)) - ((ADM_dataset_list_t) (r_outputs)) - ((ADM_adhoc_storage_t) (r_adhoc_storage)) -); -// clang-format on - -/** The resources assigned to a job */ -typedef struct adm_job_resources { - ADM_node_list_t r_nodes; -} adm_job_resources; - -// clang-format off -MERCURY_GEN_STRUCT_PROC( - adm_job_resources, // NOLINT - ((ADM_node_list_t) (r_nodes)) -); -// clang-format on - -// clang-format off - -MERCURY_GEN_PROC( - ADM_ping_out_t, - ((hg_uint64_t) (op_id)) - ((int32_t) (retval)) -); - -hg_return_t -hg_proc_ADM_job_resources_t(hg_proc_t proc, void* data); - -/// ADM_register_job -MERCURY_GEN_PROC( - ADM_register_job_in_t, - ((ADM_job_resources_t) (job_resources)) - ((adm_job_requirements) (reqs)) - ((hg_uint64_t) (slurm_job_id)) -); - -MERCURY_GEN_PROC( - ADM_register_job_out_t, - ((hg_uint64_t) (op_id)) - ((int32_t) (retval)) - ((ADM_job_t) (job)) -); - -/// ADM_update_job -MERCURY_GEN_PROC( - ADM_update_job_in_t, - ((ADM_job_t) (job)) - ((ADM_job_resources_t) (job_resources)) -); - -MERCURY_GEN_PROC( - ADM_update_job_out_t, - ((hg_uint64_t) (op_id)) - ((int32_t) (retval)) -); - -/// ADM_remove_job -MERCURY_GEN_PROC( - ADM_remove_job_in_t, - ((ADM_job_t) (job)) -); - -MERCURY_GEN_PROC( - ADM_remove_job_out_t, - ((hg_uint64_t) (op_id)) - ((hg_int32_t) (retval)) -); - -/// ADM_register_adhoc_storage -MERCURY_GEN_PROC( - ADM_register_adhoc_storage_in_t, - ((hg_const_string_t) (name)) - ((ADM_adhoc_storage_type_t) (type)) - ((ADM_adhoc_context_t) (ctx)) -); - -MERCURY_GEN_PROC( - ADM_register_adhoc_storage_out_t, - ((hg_uint64_t) (op_id)) - ((hg_int32_t) (retval)) - ((hg_uint64_t) (id)) -); - -/// ADM_update_adhoc_storage -MERCURY_GEN_PROC( - ADM_update_adhoc_storage_in_t, - ((ADM_adhoc_context_t)(adhoc_storage_ctx)) - ((hg_uint64_t)(server_id)) -); - -MERCURY_GEN_PROC( - ADM_update_adhoc_storage_out_t, - ((hg_uint64_t) (op_id)) - ((hg_int32_t) (retval)) -); - -/// ADM_remove_adhoc_storage -MERCURY_GEN_PROC( - ADM_remove_adhoc_storage_in_t, - ((hg_uint64_t) (server_id)) -); - -MERCURY_GEN_PROC( - ADM_remove_adhoc_storage_out_t, - ((hg_uint64_t) (op_id)) - ((hg_int32_t) (retval)) -); - -/// ADM_deploy_adhoc_storage -MERCURY_GEN_PROC(ADM_deploy_adhoc_storage_in_t, ((hg_uint64_t) (id))) - -MERCURY_GEN_PROC(ADM_deploy_adhoc_storage_out_t, - ((hg_uint64_t) (op_id)) - ((hg_int32_t) (retval)) -); - -/// ADM_register_pfs_storage -MERCURY_GEN_PROC( - ADM_register_pfs_storage_in_t, - ((hg_const_string_t) (name)) - ((ADM_pfs_storage_type_t) (type)) - ((ADM_pfs_context_t) (ctx)) -); - -MERCURY_GEN_PROC( - ADM_register_pfs_storage_out_t, - ((hg_uint64_t) (op_id)) - ((hg_int32_t) (retval)) - ((hg_uint64_t) (id)) -); - -/// ADM_update_pfs_storage -MERCURY_GEN_PROC( - ADM_update_pfs_storage_in_t, - ((ADM_pfs_context_t) (pfs_storage_ctx)) - ((hg_uint64_t) (server_id)) -); - -MERCURY_GEN_PROC( - ADM_update_pfs_storage_out_t, - ((hg_uint64_t) (op_id)) - ((hg_int32_t) (retval)) -); - -/// ADM_remove_pfs_storage -MERCURY_GEN_PROC( - ADM_remove_pfs_storage_in_t, - ((hg_uint64_t) (server_id)) -); - -MERCURY_GEN_PROC( - ADM_remove_pfs_storage_out_t, - ((hg_uint64_t) (op_id)) - ((hg_int32_t) (retval)) -); - -/// ADM_input -MERCURY_GEN_PROC(ADM_input_in_t, - ((hg_const_string_t) (origin))((hg_const_string_t) (target))) - -MERCURY_GEN_PROC(ADM_input_out_t, ((int32_t) (ret))) - -/// ADM_output - -MERCURY_GEN_PROC(ADM_output_in_t, - ((hg_const_string_t) (origin))((hg_const_string_t) (target))) - -MERCURY_GEN_PROC(ADM_output_out_t, ((int32_t) (ret))) - -/// ADM_inout - -MERCURY_GEN_PROC(ADM_inout_in_t, - ((hg_const_string_t) (origin))((hg_const_string_t) (target))) - -MERCURY_GEN_PROC(ADM_inout_out_t, ((int32_t) (ret))) - -/// ADM_adhoc_context - -MERCURY_GEN_PROC(ADM_adhoc_context_in_t, ((hg_const_string_t) (context))) - -MERCURY_GEN_PROC(ADM_adhoc_context_out_t, - ((int32_t) (ret))((int32_t) (adhoc_context))) - -/// ADM_adhoc_context_id - -MERCURY_GEN_PROC(ADM_adhoc_context_id_in_t, ((int32_t) (context_id))) - -MERCURY_GEN_PROC(ADM_adhoc_context_id_out_t, ((int32_t) (ret))) - -/// ADM_adhoc_nodes - -MERCURY_GEN_PROC(ADM_adhoc_nodes_in_t, ((int32_t) (nodes))) - -MERCURY_GEN_PROC(ADM_adhoc_nodes_out_t, ((int32_t) (ret))) - -/// ADM_adhoc_walltime - -MERCURY_GEN_PROC(ADM_adhoc_walltime_in_t, ((int32_t) (walltime))) - -MERCURY_GEN_PROC(ADM_adhoc_walltime_out_t, ((int32_t) (ret))) - - -/// ADM_adhoc_access - -MERCURY_GEN_PROC(ADM_adhoc_access_in_t, ((hg_const_string_t) (access))) - -MERCURY_GEN_PROC(ADM_adhoc_access_out_t, ((int32_t) (ret))) - -/// ADM_adhoc_distribution - -MERCURY_GEN_PROC(ADM_adhoc_distribution_in_t, - ((hg_const_string_t) (data_distribution))) - -MERCURY_GEN_PROC(ADM_adhoc_distribution_out_t, ((int32_t) (ret))) - -/// ADM_adhoc_background_flush - -MERCURY_GEN_PROC(ADM_adhoc_background_flush_in_t, ((hg_bool_t) (b_flush))) - -MERCURY_GEN_PROC(ADM_adhoc_background_flush_out_t, ((int32_t) (ret))) - -/// ADM_in_situ_ops - -MERCURY_GEN_PROC(ADM_in_situ_ops_in_t, ((hg_const_string_t) (in_situ))) - -MERCURY_GEN_PROC(ADM_in_situ_ops_out_t, ((int32_t) (ret))) - -/// ADM_in_transit_ops - -MERCURY_GEN_PROC(ADM_in_transit_ops_in_t, ((hg_const_string_t) (in_transit))) - -MERCURY_GEN_PROC(ADM_in_transit_ops_out_t, ((int32_t) (ret))) - -struct adm_qos_limit_list { - /** An array of QoS limits */ - adm_qos_limit* l_limits; - /** The length of the array */ - size_t l_length; -}; - -hg_return_t -hg_proc_ADM_qos_limit_list_t(hg_proc_t proc, void* data); - -/// ADM_transfer_datasets - -MERCURY_GEN_PROC( - ADM_transfer_datasets_in_t, - ((ADM_job_t) (job)) - ((ADM_dataset_list_t) (sources)) - ((ADM_dataset_list_t) (targets)) - ((ADM_qos_limit_list_t) (qos_limits)) - ((hg_int32_t) (mapping)) -) - -MERCURY_GEN_PROC( - ADM_transfer_datasets_out_t, - ((hg_uint64_t) (op_id)) - ((hg_int32_t) (retval)) - ((ADM_transfer_t) (tx))) - - -/// ADM_set_dataset_information - -MERCURY_GEN_PROC(ADM_set_dataset_information_in_t, - ((int32_t) (resource_id))((hg_const_string_t) (info))( - (int32_t) (job_id))) - -MERCURY_GEN_PROC(ADM_set_dataset_information_out_t, - ((int32_t) (ret))((int32_t) (status))) - -/// ADM_set_io_resources - -MERCURY_GEN_PROC(ADM_set_io_resources_in_t, - ((int32_t) (tier_id))((hg_const_string_t) (resources))( - (int32_t) (job_id))) - -MERCURY_GEN_PROC(ADM_set_io_resources_out_t, - ((int32_t) (ret))((int32_t) (status))) - -/// ADM_get_transfer_priority - -MERCURY_GEN_PROC(ADM_get_transfer_priority_in_t, ((int32_t) (transfer_id))) - -MERCURY_GEN_PROC(ADM_get_transfer_priority_out_t, - ((int32_t) (ret))((int32_t) (priority))) - -/// ADM_set_transfer_priority - -MERCURY_GEN_PROC(ADM_set_transfer_priority_in_t, - ((int32_t) (transfer_id))((int32_t) (n_positions))) - -MERCURY_GEN_PROC(ADM_set_transfer_priority_out_t, - ((int32_t) (ret))((int32_t) (status))) - -/// ADM_cancel_transfer - -MERCURY_GEN_PROC(ADM_cancel_transfer_in_t, ((int32_t) (transfer_id))) - -MERCURY_GEN_PROC(ADM_cancel_transfer_out_t, - ((int32_t) (ret))((int32_t) (status))) - -/// ADM_get_pending_transfers - -MERCURY_GEN_PROC(ADM_get_pending_transfers_in_t, ((hg_const_string_t) (value))) - -MERCURY_GEN_PROC(ADM_get_pending_transfers_out_t, - ((int32_t) (ret))((hg_const_string_t) (pending_transfers))) - -/// ADM_set_qos_constraints - -MERCURY_GEN_PROC( - ADM_set_qos_constraints_in_t, - ((hg_const_string_t) (scope))((hg_const_string_t) (qos_class))( - (int32_t) (element_id))((hg_const_string_t) (class_value))) - -MERCURY_GEN_PROC(ADM_set_qos_constraints_out_t, - ((int32_t) (ret))((int32_t) (status))) - -/// ADM_get_qos_constraints - -MERCURY_GEN_PROC(ADM_get_qos_constraints_in_t, - ((hg_const_string_t) (scope))((int32_t) (element_id))) - -MERCURY_GEN_PROC(ADM_get_qos_constraints_out_t, - ((int32_t) (ret))((hg_const_string_t) (list))) - -/// ADM_define_data_operation - -MERCURY_GEN_PROC(ADM_define_data_operation_in_t, - ((hg_const_string_t) (path))((int32_t) (operation_id))( - (hg_const_string_t) (arguments))) - -MERCURY_GEN_PROC(ADM_define_data_operation_out_t, - ((int32_t) (ret))((int32_t) (status))) - -/// ADM_connect_data_operation - -MERCURY_GEN_PROC(ADM_connect_data_operation_in_t, - ((int32_t) (operation_id))((hg_const_string_t) (input))( - (hg_bool_t) (stream))((hg_const_string_t) (arguments))( - (int32_t) (job_id))) - -MERCURY_GEN_PROC(ADM_connect_data_operation_out_t, - ((int32_t) (ret))((hg_const_string_t) (data))( - (hg_const_string_t) (operation_handle))) - -/// ADM_finalize_data_operation - -MERCURY_GEN_PROC(ADM_finalize_data_operation_in_t, ((int32_t) (operation_id))) - -MERCURY_GEN_PROC(ADM_finalize_data_operation_out_t, - ((int32_t) (ret))((int32_t) (status))) - - -/// ADM_link_transfer_to_data_operation - -MERCURY_GEN_PROC(ADM_link_transfer_to_data_operation_in_t, - ((int32_t) (operation_id))((int32_t) (transfer_id))( - (hg_bool_t) (stream))((hg_const_string_t) (arguments))( - (int32_t) (job_id))) - -MERCURY_GEN_PROC(ADM_link_transfer_to_data_operation_out_t, - ((int32_t) (ret))((hg_const_string_t) (operation_handle))) - -/// ADM_get_statistics - -MERCURY_GEN_PROC(ADM_get_statistics_in_t, - ((int32_t) (job_id))((int32_t) (job_step))) - -MERCURY_GEN_PROC(ADM_get_statistics_out_t, - ((int32_t) (ret))((hg_const_string_t) (job_statistics))) - -// clang-format on - -#ifdef __cplusplus -}; // extern "C" -#endif // __cplusplus - -#endif // SCORD_PROTO_TYPES_HPP diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index cae7695205b365035be4bd2c9a8129c258b7e0e8..ce01d8644472b5a27cd4bbdc0aee0a79a280409d 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -22,6 +22,65 @@ # SPDX-License-Identifier: GPL-3.0-or-later # ################################################################################ +################################################################################ +# Create a target for the C type definitions so that we can +# include them where needed +################################################################################ +add_library(libscord_c_types STATIC) + +target_sources(libscord_c_types PRIVATE scord/types.h types.c errors.c) + +set(public_headers, "") +list(APPEND public_headers "scord/types.h") + +set_target_properties( + libscord_c_types PROPERTIES PUBLIC_HEADER "${public_headers}" +) + +target_include_directories( + libscord_c_types PUBLIC $ + $ +) + +target_link_libraries( + libscord_c_types + PRIVATE Margo::Margo common::logger + PUBLIC fmt::fmt common::abt_cxx +) + +set_property(TARGET libscord_c_types PROPERTY POSITION_INDEPENDENT_CODE ON) + +################################################################################ +# Create a target for the C++ type definitions so that we can +# include them where needed +################################################################################ +add_library(libscord_cxx_types STATIC) + +target_sources(libscord_cxx_types PRIVATE scord/types.hpp types.cpp) + +set(public_headers, "") +list(APPEND public_headers "scord/types.hpp") + +set_target_properties( + libscord_cxx_types PROPERTIES PUBLIC_HEADER "${public_headers}" +) + +target_include_directories( + libscord_cxx_types PUBLIC $ + $ +) + +target_link_libraries( + libscord_cxx_types + PRIVATE libscord_c_types Margo::Margo common::logger + PUBLIC fmt::fmt common::abt_cxx +) + +set_property(TARGET libscord_cxx_types PROPERTY POSITION_INDEPENDENT_CODE ON) + +################################################################################ +# Create a target for the actual library that will be used by clients +################################################################################ add_library(libscord SHARED) target_sources( @@ -30,10 +89,8 @@ target_sources( PRIVATE libscord.cpp c_wrapper.cpp detail/impl.hpp detail/impl.cpp env.hpp ) -list(APPEND public_headers "scord/scord.h" - "${CMAKE_SOURCE_DIR}/src/common/api/scord/types.h" "scord/scord.hpp" - "${CMAKE_SOURCE_DIR}/src/common/api/scord/types.hpp" -) +set(public_headers, "") +list(APPEND public_headers "scord/scord.h" "scord/scord.hpp") set_target_properties(libscord PROPERTIES PUBLIC_HEADER "${public_headers}") @@ -44,14 +101,14 @@ target_include_directories( target_link_libraries( libscord - PRIVATE common::network::rpc_client common::network::rpc_types - PUBLIC tl::expected common::api::types + PRIVATE common::network::rpc_client + PUBLIC tl::expected libscord_c_types libscord_cxx_types ) set_target_properties(libscord PROPERTIES OUTPUT_NAME "scord") install( - TARGETS libscord + TARGETS libscord libscord_c_types libscord_cxx_types LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} diff --git a/src/lib/c_wrapper.cpp b/src/lib/c_wrapper.cpp index 8a31f996c20f7882e5be29c9d7600861021be133..8e9cd12ad85538cf4a3b2c228ca346502008031a 100644 --- a/src/lib/c_wrapper.cpp +++ b/src/lib/c_wrapper.cpp @@ -25,13 +25,41 @@ #include #include #include -#include #include #include #include -#include #include "detail/impl.hpp" +namespace { + +std::vector +convert(ADM_dataset_t datasets[], size_t datasets_len) { + + std::vector rv; + rv.reserve(datasets_len); + + for(size_t i = 0; i < datasets_len; ++i) { + rv.emplace_back(datasets[i]); + } + + return rv; +} + +std::vector +convert(ADM_qos_limit_t limits[], size_t limits_len) { + + std::vector rv; + rv.reserve(limits_len); + + for(size_t i = 0; i < limits_len; ++i) { + rv.emplace_back(limits[i]); + } + + return rv; +} + +} // namespace + /******************************************************************************/ /* C API implementation */ @@ -57,7 +85,7 @@ ADM_register_job(ADM_server_t server, ADM_job_resources_t res, return rv.error(); } - *job = scord::api::convert(*rv).release(); + *job = static_cast(rv.value()); return ADM_SUCCESS; } @@ -96,7 +124,7 @@ ADM_register_adhoc_storage(ADM_server_t server, const char* name, return rv.error(); } - *adhoc_storage = scord::api::convert(*rv).release(); + *adhoc_storage = static_cast(rv.value()); return ADM_SUCCESS; } @@ -146,7 +174,7 @@ ADM_register_pfs_storage(ADM_server_t server, const char* name, return rv.error(); } - *pfs_storage = scord::api::convert(rv.value()).release(); + *pfs_storage = static_cast(rv.value()); return ADM_SUCCESS; } @@ -176,16 +204,15 @@ ADM_transfer_datasets(ADM_server_t server, ADM_job_t job, const auto rv = scord::detail::transfer_datasets( scord::server{server}, scord::job{job}, - scord::api::convert(sources, sources_len), - scord::api::convert(targets, targets_len), - scord::api::convert(limits, limits_len), + ::convert(sources, sources_len), ::convert(targets, targets_len), + ::convert(limits, limits_len), static_cast(mapping)); if(!rv) { return rv.error(); } - *transfer = scord::api::convert(*rv).release(); + *transfer = static_cast(rv.value()); return ADM_SUCCESS; } diff --git a/src/common/api/errors.c b/src/lib/errors.c similarity index 100% rename from src/common/api/errors.c rename to src/lib/errors.c diff --git a/src/lib/libscord.cpp b/src/lib/libscord.cpp index b0ef7163fbab015bcdd99ed7c9c954c7ec294512..3d80dd3057e8335014e4bf7614d8900adfc4ea11 100644 --- a/src/lib/libscord.cpp +++ b/src/lib/libscord.cpp @@ -23,7 +23,6 @@ *****************************************************************************/ #include -#include #include #include #include diff --git a/src/lib/scord/scord.hpp b/src/lib/scord/scord.hpp index 254b46c6a966204ceee0a52d7890f1c687d63656..5a48f62f03a25afc113964027f63c0e2a758b303 100644 --- a/src/lib/scord/scord.hpp +++ b/src/lib/scord/scord.hpp @@ -26,7 +26,6 @@ #include #include #include "scord/types.hpp" -#include "net/proto/rpc_types.h" #ifndef SCORD_HPP #define SCORD_HPP diff --git a/src/common/api/scord/types.h b/src/lib/scord/types.h similarity index 100% rename from src/common/api/scord/types.h rename to src/lib/scord/types.h diff --git a/src/common/api/scord/types.hpp b/src/lib/scord/types.hpp similarity index 97% rename from src/common/api/scord/types.hpp rename to src/lib/scord/types.hpp index 26a3381bcfeeb6a6bec14954ff3bb6ac2a2c44da..86aa6f19194b9a9fee9697cebac0c343436a99a4 100644 --- a/src/common/api/scord/types.hpp +++ b/src/lib/scord/types.hpp @@ -192,6 +192,7 @@ struct job { job(); job(job_id id, slurm_job_id slurm_id); explicit job(ADM_job_t job); + explicit operator ADM_job_t() const; job(const job&) noexcept; job(job&&) noexcept; job& @@ -227,6 +228,7 @@ struct transfer { transfer(); explicit transfer(transfer_id id); explicit transfer(ADM_transfer_t transfer); + explicit operator ADM_transfer_t() const; transfer(const transfer&) noexcept; transfer(transfer&&) noexcept; @@ -391,6 +393,7 @@ struct adhoc_storage { resources() = default; explicit resources(std::vector nodes); explicit resources(ADM_adhoc_resources_t res); + explicit operator ADM_adhoc_resources_t() const; std::vector nodes() const; @@ -414,6 +417,7 @@ struct adhoc_storage { bool should_flush); explicit ctx(ADM_adhoc_context_t ctx); + explicit operator ADM_adhoc_context_t() const; execution_mode exec_mode() const; @@ -450,6 +454,7 @@ struct adhoc_storage { 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, std::uint64_t id, const scord::adhoc_storage::ctx& ctx); @@ -498,6 +503,7 @@ struct pfs_storage { explicit ctx(std::filesystem::path mount_point); explicit ctx(ADM_pfs_context_t ctx); + explicit operator ADM_pfs_context_t() const; std::filesystem::path mount_point() const; @@ -521,6 +527,7 @@ struct pfs_storage { const pfs_storage::ctx& pfs_ctx); explicit pfs_storage(ADM_pfs_storage_t storage); + explicit operator ADM_pfs_storage_t() const; pfs_storage(const pfs_storage& other) noexcept; pfs_storage(pfs_storage&&) noexcept; @@ -593,7 +600,7 @@ private: std::unique_ptr m_pimpl; }; -} // namespace admire +} // namespace scord //////////////////////////////////////////////////////////////////////////////// @@ -651,8 +658,7 @@ struct fmt::formatter // parse is inherited from formatter. template auto - format(const enum scord::adhoc_storage::type& t, - FormatContext& ctx) const { + format(const enum scord::adhoc_storage::type& t, FormatContext& ctx) const { using scord::adhoc_storage; std::string_view name = "unknown"; @@ -768,8 +774,7 @@ struct fmt::formatter // parse is inherited from formatter. template auto - format(const scord::adhoc_storage::resources& r, - FormatContext& ctx) const { + format(const scord::adhoc_storage::resources& r, FormatContext& ctx) const { const auto str = fmt::format("{{nodes: {}}}", r.nodes()); @@ -779,8 +784,7 @@ struct fmt::formatter template <> -struct fmt::formatter - : formatter { +struct fmt::formatter : formatter { // parse is inherited from formatter. template auto diff --git a/src/lib/types.c b/src/lib/types.c new file mode 100644 index 0000000000000000000000000000000000000000..763e1b21f08bde163c5ccced1f06049b5557e1dd --- /dev/null +++ b/src/lib/types.c @@ -0,0 +1,1025 @@ +/****************************************************************************** + * + * 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 +#include "scord/types.h" +#include "types_private.h" + +#define maybe_unused __attribute__((unused)) + +/******************************************************************************/ +/* C Type definitions and related functions */ +/******************************************************************************/ + +ADM_server_t +ADM_server_create(const char* protocol, const char* address) { + + struct adm_server* adm_server = + (struct adm_server*) malloc(sizeof(struct adm_server)); + + if(!adm_server) { + LOGGER_ERROR("Could not allocate ADM_server_t"); + return NULL; + } + + adm_server->s_protocol = protocol; + adm_server->s_address = address; + + return adm_server; +} + +ADM_return_t +ADM_server_destroy(ADM_server_t server) { + ADM_return_t ret = ADM_SUCCESS; + + if(!server) { + LOGGER_ERROR("Invalid ADM_server_t"); + return ADM_EBADARGS; + } + + free(server); + return ret; +} + +ADM_node_t +ADM_node_create(const char* hostname) { + + struct adm_node* adm_node = + (struct adm_node*) malloc(sizeof(struct adm_node)); + + if(!adm_node) { + LOGGER_ERROR("Could not allocate ADM_node_t"); + return NULL; + } + + if(hostname) { + size_t n = strlen(hostname); + adm_node->n_hostname = (const char*) calloc(n + 1, sizeof(char)); + strcpy((char*) adm_node->n_hostname, hostname); + } + + return adm_node; +} + +ADM_node_t +ADM_node_copy(ADM_node_t dst, const ADM_node_t src) { + + if(!src || !dst) { + return NULL; + } + + // copy all primitive types + *dst = *src; + + // duplicate copy any pointer types + if(src->n_hostname) { + size_t n = strlen(src->n_hostname); + dst->n_hostname = (const char*) calloc(n + 1, sizeof(char)); + strncpy((char*) dst->n_hostname, src->n_hostname, n); + } + + return dst; +} + +ADM_return_t +ADM_node_destroy(ADM_node_t node) { + ADM_return_t ret = ADM_SUCCESS; + + if(!node) { + LOGGER_ERROR("Invalid ADM_node_t"); + return ADM_EBADARGS; + } + + if(node->n_hostname) { + free((void*) node->n_hostname); + } + + free(node); + return ret; +} + +ADM_node_list_t +ADM_node_list_create(ADM_node_t nodes[], size_t length) { + + ADM_node_list_t p = (ADM_node_list_t) malloc(sizeof(*p)); + + if(!p) { + LOGGER_ERROR("Could not allocate ADM_node_list_t"); + return NULL; + } + + const char* error_msg = NULL; + + p->l_length = length; + p->l_nodes = (struct adm_node*) calloc(length, sizeof(struct adm_node)); + + if(!p->l_nodes) { + error_msg = "Could not allocate ADM_node_list_t"; + goto cleanup_on_error; + } + + for(size_t i = 0; i < length; ++i) { + + if(!ADM_node_copy(&p->l_nodes[i], nodes[i])) { + error_msg = "Could not allocate ADM_node_list_t"; + goto cleanup_on_error; + }; + } + + return p; + +cleanup_on_error: + if(p->l_nodes) { + free(p->l_nodes); + } + free(p); + + LOGGER_ERROR(error_msg); + + return NULL; +} + +ADM_return_t +ADM_node_list_destroy(ADM_node_list_t list) { + ADM_return_t ret = ADM_SUCCESS; + + if(!list) { + LOGGER_ERROR("Invalid ADM_node_list_t"); + return ADM_EBADARGS; + } + + // We cannot call ADM_node_destroy here because adm_nodes + // are stored as a consecutive array in memory. Thus, we free + // the node ids themselves and then the array. + if(list->l_nodes) { + for(size_t i = 0; i < list->l_length; ++i) { + free((void*) list->l_nodes[i].n_hostname); + } + free(list->l_nodes); + } + + free(list); + return ret; +} + + +ADM_dataset_t +ADM_dataset_create(const char* id) { + + struct adm_dataset* adm_dataset = + (struct adm_dataset*) calloc(1, sizeof(struct adm_dataset)); + + if(!adm_dataset) { + LOGGER_ERROR("Could not allocate ADM_dataset_t"); + return NULL; + } + + if(id) { + size_t n = strlen(id); + adm_dataset->d_id = (const char*) calloc(n + 1, sizeof(char)); + strcpy((char*) adm_dataset->d_id, id); + } + + return adm_dataset; +} + +ADM_dataset_t +ADM_dataset_copy(ADM_dataset_t dst, const ADM_dataset_t src) { + + if(!src || !dst) { + return NULL; + } + + // copy all primitive types + *dst = *src; + + // duplicate copy any pointer types + if(src->d_id) { + size_t n = strlen(src->d_id); + dst->d_id = (const char*) calloc(n + 1, sizeof(char)); + strncpy((char*) dst->d_id, src->d_id, n); + } + + return dst; +} + +ADM_return_t +ADM_dataset_destroy(ADM_dataset_t dataset) { + ADM_return_t ret = ADM_SUCCESS; + + if(!dataset) { + LOGGER_ERROR("Invalid ADM_dataset_t"); + return ADM_EBADARGS; + } + + if(dataset->d_id) { + free((void*) dataset->d_id); + } + + free(dataset); + return ret; +} + +ADM_qos_entity_t +ADM_qos_entity_create(ADM_qos_scope_t scope, void* data) { + + struct adm_qos_entity* adm_qos_entity = + (struct adm_qos_entity*) malloc(sizeof(struct adm_qos_entity)); + + if(!adm_qos_entity) { + LOGGER_ERROR("Could not allocate ADM_qos_entity_t"); + return NULL; + } + + adm_qos_entity->e_scope = scope; + + switch(scope) { + case ADM_QOS_SCOPE_NODE: + adm_qos_entity->e_node = (ADM_node_t) data; + break; + case ADM_QOS_SCOPE_JOB: + adm_qos_entity->e_job = (ADM_job_t) data; + break; + case ADM_QOS_SCOPE_DATASET: + adm_qos_entity->e_dataset = (ADM_dataset_t) data; + break; + case ADM_QOS_SCOPE_TRANSFER: + adm_qos_entity->e_transfer = (ADM_transfer_t) data; + } + + return adm_qos_entity; +} + +ADM_return_t +ADM_qos_entity_destroy(ADM_qos_entity_t entity) { + + ADM_return_t ret = ADM_SUCCESS; + + if(!entity) { + LOGGER_ERROR("Invalid ADM_qos_entity_t"); + return ADM_EBADARGS; + } + + free(entity); + return ret; +} + +ADM_qos_limit_t +ADM_qos_limit_create(ADM_qos_entity_t entity, ADM_qos_class_t cls, + uint64_t value) { + + struct adm_qos_limit* adm_qos_limit = + (struct adm_qos_limit*) malloc(sizeof(struct adm_qos_limit)); + + if(!adm_qos_limit) { + LOGGER_ERROR("Could not allocate ADM_qos_limit_t"); + return NULL; + } + + adm_qos_limit->l_entity = entity; + adm_qos_limit->l_class = cls; + adm_qos_limit->l_value = value; + + return adm_qos_limit; +} + +ADM_return_t +ADM_qos_limit_destroy(ADM_qos_limit_t limit) { + ADM_return_t ret = ADM_SUCCESS; + + if(!limit) { + LOGGER_ERROR("Invalid ADM_qos_limit_t"); + return ADM_EBADARGS; + } + + free(limit); + return ret; +} + +ADM_return_t +ADM_qos_limit_destroy_all(ADM_qos_limit_t limit) { + ADM_return_t ret = ADM_SUCCESS; + + if(!limit) { + LOGGER_ERROR("Invalid ADM_qos_limit_t"); + return ADM_EBADARGS; + } + + if(limit->l_entity) { + ADM_qos_entity_destroy(limit->l_entity); + } + + free(limit); + return ret; +} + +ADM_dataset_info_t +ADM_dataset_info_create() { + + struct adm_dataset_info* adm_dataset_info = + (struct adm_dataset_info*) malloc(sizeof(*adm_dataset_info)); + + if(!adm_dataset_info) { + LOGGER_ERROR("Could not allocate ADM_dataset_info_t"); + return NULL; + } + + return adm_dataset_info; +} + +ADM_return_t +ADM_dataset_info_destroy(ADM_dataset_info_t dataset_info) { + ADM_return_t ret = ADM_SUCCESS; + + if(!dataset_info) { + LOGGER_ERROR("Invalid ADM_dataset_info_t"); + return ADM_EBADARGS; + } + + free(dataset_info); + return ret; +} + +ADM_dataset_list_t +ADM_dataset_list_create(ADM_dataset_t datasets[], size_t length) { + + ADM_dataset_list_t p = (ADM_dataset_list_t) malloc(sizeof(*p)); + + if(!p) { + LOGGER_ERROR("Could not allocate ADM_dataset_list_t"); + return NULL; + } + + const char* error_msg = NULL; + + p->l_length = length; + p->l_datasets = + (struct adm_dataset*) calloc(length, sizeof(struct adm_dataset)); + + if(!p->l_datasets) { + error_msg = "Could not allocate ADM_dataset_list_t"; + goto cleanup_on_error; + } + + for(size_t i = 0; i < length; ++i) { + if(!ADM_dataset_copy(&p->l_datasets[i], datasets[i])) { + error_msg = "Could not allocate ADM_dataset_list_t"; + goto cleanup_on_error; + }; + } + + return p; + +cleanup_on_error: + if(p->l_datasets) { + free(p->l_datasets); + } + free(p); + + LOGGER_ERROR(error_msg); + + return NULL; +} + +ADM_return_t +ADM_dataset_list_destroy(ADM_dataset_list_t list) { + ADM_return_t ret = ADM_SUCCESS; + + if(!list) { + LOGGER_ERROR("Invalid ADM_pfs_context_t"); + return ADM_EBADARGS; + } + + // We cannot call ADM_dataset_destroy here because adm_datasets + // are stored as a consecutive array in memory. Thus, we free + // the dataset ids themselves and then the array. + if(list->l_datasets) { + for(size_t i = 0; i < list->l_length; ++i) { + free((void*) list->l_datasets[i].d_id); + } + free(list->l_datasets); + } + + free(list); + return ret; +} + +ADM_adhoc_storage_t +ADM_adhoc_storage_create(const char* name, ADM_adhoc_storage_type_t type, + uint64_t id, ADM_adhoc_context_t adhoc_ctx) { + + struct adm_adhoc_storage* adm_adhoc_storage = + (struct adm_adhoc_storage*) malloc(sizeof(*adm_adhoc_storage)); + const char* error_msg = NULL; + + if(!adm_adhoc_storage) { + LOGGER_ERROR("Could not allocate ADM_adhoc_storage_t"); + return NULL; + } + + if(!name) { + LOGGER_ERROR("Null storage name"); + return NULL; + } + + if(!adhoc_ctx) { + LOGGER_ERROR("Null storage context"); + return NULL; + } + + adm_adhoc_storage->s_name = + (const char*) calloc(strlen(name) + 1, sizeof(char)); + strcpy((char*) adm_adhoc_storage->s_name, name); + adm_adhoc_storage->s_type = type; + adm_adhoc_storage->s_id = id; + + adm_adhoc_storage->s_adhoc_ctx = + (ADM_adhoc_context_t) calloc(1, sizeof(struct adm_adhoc_context)); + if(!adm_adhoc_storage->s_adhoc_ctx) { + error_msg = "Could not allocate ADM_adhoc_context_t"; + goto cleanup_on_error; + } + + memcpy(adm_adhoc_storage->s_adhoc_ctx, adhoc_ctx, sizeof(*adhoc_ctx)); + + return adm_adhoc_storage; + +cleanup_on_error: + LOGGER_ERROR(error_msg); + + maybe_unused ADM_return_t ret = + ADM_adhoc_storage_destroy(adm_adhoc_storage); + assert(ret); + + return NULL; +} + +ADM_return_t +ADM_adhoc_storage_destroy(ADM_adhoc_storage_t adhoc_storage) { + + ADM_return_t ret = ADM_SUCCESS; + + if(!adhoc_storage) { + LOGGER_ERROR("Invalid ADM_adhoc_storage_t"); + return ADM_EBADARGS; + } + + if(adhoc_storage->s_name) { + free((void*) adhoc_storage->s_name); + } + + if(adhoc_storage->s_adhoc_ctx) { + free(adhoc_storage->s_adhoc_ctx); + } + + free(adhoc_storage); + return ret; +} + +ADM_adhoc_resources_t +ADM_adhoc_resources_create(ADM_node_t nodes[], size_t nodes_len) { + + struct adm_adhoc_resources* adm_adhoc_resources = + (struct adm_adhoc_resources*) malloc(sizeof(*adm_adhoc_resources)); + + const char* error_msg = NULL; + ADM_node_list_t nodes_list = NULL; + + if(!adm_adhoc_resources) { + error_msg = "Could not allocate ADM_adhoc_resources_t"; + goto cleanup_on_error; + } + + nodes_list = ADM_node_list_create(nodes, nodes_len); + + if(!nodes_list) { + error_msg = "Could not allocate ADM_adhoc_resources_t"; + goto cleanup_on_error; + } + + adm_adhoc_resources->r_nodes = nodes_list; + + return adm_adhoc_resources; + +cleanup_on_error: + LOGGER_ERROR(error_msg); + + if(adm_adhoc_resources) { + ADM_adhoc_resources_destroy(adm_adhoc_resources); + } + + return NULL; +} + +ADM_return_t +ADM_adhoc_resources_destroy(ADM_adhoc_resources_t res) { + + ADM_return_t ret = ADM_SUCCESS; + + if(!res) { + LOGGER_ERROR("Invalid ADM_storage_resources_t"); + return ADM_EBADARGS; + } + + if(res->r_nodes) { + ADM_node_list_destroy(res->r_nodes); + } + + free(res); + return ret; +} + +ADM_pfs_storage_t +ADM_pfs_storage_create(const char* name, ADM_pfs_storage_type_t type, + uint64_t id, ADM_pfs_context_t pfs_ctx) { + + struct adm_pfs_storage* adm_pfs_storage = + (struct adm_pfs_storage*) malloc(sizeof(*adm_pfs_storage)); + const char* error_msg = NULL; + + if(!adm_pfs_storage) { + LOGGER_ERROR("Could not allocate ADM_pfs_storage_t"); + return NULL; + } + + if(!name) { + LOGGER_ERROR("Null storage name"); + return NULL; + } + + if(!pfs_ctx) { + LOGGER_ERROR("Null storage context"); + return NULL; + } + + adm_pfs_storage->s_name = + (const char*) calloc(strlen(name) + 1, sizeof(char)); + strcpy((char*) adm_pfs_storage->s_name, name); + adm_pfs_storage->s_type = type; + adm_pfs_storage->s_id = id; + + adm_pfs_storage->s_pfs_ctx = + (ADM_pfs_context_t) calloc(1, sizeof(struct adm_pfs_context)); + if(!adm_pfs_storage->s_pfs_ctx) { + error_msg = "Could not allocate ADM_pfs_context_t"; + goto cleanup_on_error; + } + + memcpy(adm_pfs_storage->s_pfs_ctx, pfs_ctx, sizeof(*pfs_ctx)); + + return adm_pfs_storage; + +cleanup_on_error: + LOGGER_ERROR(error_msg); + + maybe_unused ADM_return_t ret = ADM_pfs_storage_destroy(adm_pfs_storage); + assert(ret); + + return NULL; +} + +ADM_return_t +ADM_pfs_storage_destroy(ADM_pfs_storage_t pfs_storage) { + + ADM_return_t ret = ADM_SUCCESS; + + if(!pfs_storage) { + LOGGER_ERROR("Invalid ADM_pfs_storage_t"); + return ADM_EBADARGS; + } + + if(pfs_storage->s_name) { + free((void*) pfs_storage->s_name); + } + + if(pfs_storage->s_pfs_ctx) { + free(pfs_storage->s_pfs_ctx); + } + + free(pfs_storage); + return ret; +} + +ADM_data_operation_t +ADM_data_operation_create() { + + struct adm_data_operation* adm_data_operation = + (struct adm_data_operation*) malloc(sizeof(*adm_data_operation)); + + if(!adm_data_operation) { + LOGGER_ERROR("Could not allocate ADM_data_operation_t"); + return NULL; + } + + return adm_data_operation; +} + +ADM_return_t +ADM_data_operation_destroy(ADM_data_operation_t op) { + + ADM_return_t ret = ADM_SUCCESS; + + if(!op) { + LOGGER_ERROR("Invalid ADM_data_operation_t"); + return ADM_EBADARGS; + } + + free(op); + return ret; +} + +ADM_adhoc_context_t +ADM_adhoc_context_create(ADM_adhoc_mode_t exec_mode, + ADM_adhoc_access_t access_type, + ADM_adhoc_resources_t adhoc_resources, + uint32_t walltime, bool should_flush) { + + struct adm_adhoc_context* adm_adhoc_context = + (struct adm_adhoc_context*) malloc(sizeof(*adm_adhoc_context)); + + if(!adm_adhoc_context) { + LOGGER_ERROR("Could not allocate ADM_adhoc_context_t"); + return NULL; + } + + adm_adhoc_context->c_mode = exec_mode; + adm_adhoc_context->c_access = access_type; + adm_adhoc_context->c_resources = adhoc_resources; + adm_adhoc_context->c_walltime = walltime; + adm_adhoc_context->c_should_bg_flush = should_flush; + + return adm_adhoc_context; +} + +ADM_return_t +ADM_adhoc_context_destroy(ADM_adhoc_context_t ctx) { + + + ADM_return_t ret = ADM_SUCCESS; + + if(!ctx) { + LOGGER_ERROR("Invalid ADM_adhoc_context_t"); + return ADM_EBADARGS; + } + + free(ctx); + return ret; +} + +ADM_pfs_context_t +ADM_pfs_context_create(const char* mountpoint) { + + struct adm_pfs_context* adm_pfs_context = + (struct adm_pfs_context*) malloc(sizeof(*adm_pfs_context)); + + if(!adm_pfs_context) { + LOGGER_ERROR("Could not allocate ADM_adhoc_context_t"); + return NULL; + } + + if(mountpoint) { + size_t n = strlen(mountpoint); + adm_pfs_context->c_mount = (const char*) calloc(n + 1, sizeof(char)); + strcpy((char*) adm_pfs_context->c_mount, mountpoint); + } + + return adm_pfs_context; +} + +ADM_return_t +ADM_pfs_context_destroy(ADM_pfs_context_t ctx) { + ADM_return_t ret = ADM_SUCCESS; + + if(!ctx) { + LOGGER_ERROR("Invalid ADM_pfs_context_t"); + return ADM_EBADARGS; + } + + free(ctx); + return ret; +} + +ADM_job_resources_t +ADM_job_resources_create(ADM_node_t nodes[], size_t nodes_len) { + + struct adm_job_resources* adm_job_resources = + (struct adm_job_resources*) malloc(sizeof(*adm_job_resources)); + + const char* error_msg = NULL; + ADM_node_list_t nodes_list = NULL; + + if(!adm_job_resources) { + error_msg = "Could not allocate ADM_job_resources_t"; + goto cleanup_on_error; + } + + nodes_list = ADM_node_list_create(nodes, nodes_len); + + if(!nodes_list) { + error_msg = "Could not allocate ADM_job_resources_t"; + goto cleanup_on_error; + } + + adm_job_resources->r_nodes = nodes_list; + + return adm_job_resources; + +cleanup_on_error: + LOGGER_ERROR(error_msg); + + if(adm_job_resources) { + ADM_job_resources_destroy(adm_job_resources); + } + + return NULL; +} + +ADM_return_t +ADM_job_resources_destroy(ADM_job_resources_t res) { + + ADM_return_t ret = ADM_SUCCESS; + + if(!res) { + LOGGER_ERROR("Invalid ADM_job_resources_t"); + return ADM_EBADARGS; + } + + if(res->r_nodes) { + ADM_node_list_destroy(res->r_nodes); + } + + free(res); + return ret; +} + + +ADM_job_requirements_t +ADM_job_requirements_create(ADM_dataset_t inputs[], size_t inputs_len, + ADM_dataset_t outputs[], size_t outputs_len, + ADM_adhoc_storage_t adhoc_storage) { + + struct adm_job_requirements* adm_job_reqs = + (struct adm_job_requirements*) calloc( + 1, sizeof(struct adm_job_requirements)); + + if(!adm_job_reqs) { + LOGGER_ERROR("Could not allocate ADM_job_requirements_t"); + return NULL; + } + + ADM_dataset_list_t inputs_list = NULL; + ADM_dataset_list_t outputs_list = NULL; + const char* error_msg = NULL; + + inputs_list = ADM_dataset_list_create(inputs, inputs_len); + + if(!inputs_list) { + error_msg = "Could not allocate ADM_job_requirements_t"; + goto cleanup_on_error; + } + + outputs_list = ADM_dataset_list_create(outputs, outputs_len); + + if(!outputs_list) { + error_msg = "Could not allocate ADM_job_requirements_t"; + goto cleanup_on_error; + } + + adm_job_reqs->r_inputs = inputs_list; + adm_job_reqs->r_outputs = outputs_list; + + if(!adhoc_storage) { + return adm_job_reqs; + } + + if(adhoc_storage->s_type != ADM_ADHOC_STORAGE_GEKKOFS && + adhoc_storage->s_type != ADM_ADHOC_STORAGE_DATACLAY && + adhoc_storage->s_type != ADM_ADHOC_STORAGE_EXPAND && + adhoc_storage->s_type != ADM_ADHOC_STORAGE_HERCULES) { + error_msg = "Invalid adhoc_storage type"; + goto cleanup_on_error; + } + + adm_job_reqs->r_adhoc_storage = ADM_adhoc_storage_create( + adhoc_storage->s_name, adhoc_storage->s_type, adhoc_storage->s_id, + adhoc_storage->s_adhoc_ctx); + + return adm_job_reqs; + +cleanup_on_error: + LOGGER_ERROR(error_msg); + ADM_job_requirements_destroy(adm_job_reqs); + return NULL; +} + +ADM_return_t +ADM_job_requirements_destroy(ADM_job_requirements_t reqs) { + ADM_return_t ret = ADM_SUCCESS; + + if(!reqs) { + LOGGER_ERROR("Invalid ADM_job_requirements_t"); + return ADM_EBADARGS; + } + + if(reqs->r_inputs) { + ADM_dataset_list_destroy(reqs->r_inputs); + } + + if(reqs->r_outputs) { + ADM_dataset_list_destroy(reqs->r_outputs); + } + + if(reqs->r_adhoc_storage) { + ADM_adhoc_storage_destroy(reqs->r_adhoc_storage); + } + + free(reqs); + return ret; +} + +/** + * Initialize a job handle that can be used by clients to refer to a job. + * + * @remark This function is not actually part of the public API, but it is + * useful to have for internal purposes + * + * @param [in] id The identifier for this job + * @param [in] slurm_id The SLURM_JOB_ID for this job + * @return A valid JOB HANDLE or NULL in case of failure. + */ +ADM_job_t +ADM_job_create(uint64_t id, uint64_t slurm_id) { + + struct adm_job* adm_job = (struct adm_job*) malloc(sizeof(struct adm_job)); + + if(!adm_job) { + LOGGER_ERROR("Could not allocate ADM_job_t"); + return NULL; + } + + adm_job->j_id = id; + adm_job->j_slurm_id = slurm_id; + + return adm_job; +} + +/** + * Destroy a ADM_job_t created by ADM_job_create(). + * + * @remark This function is not actually part of the public API, but it is + * useful to have for internal purposes + * + * @param[in] reqs The ADM_job_t to destroy. + * @return ADM_SUCCESS or corresponding error code. + */ +ADM_return_t +ADM_job_destroy(ADM_job_t job) { + ADM_return_t ret = ADM_SUCCESS; + + if(!job) { + LOGGER_ERROR("Invalid ADM_job_t"); + return ADM_EBADARGS; + } + + free(job); + return ret; +} + +/** + * Initialize a transfer handle that can be used by clients to refer to a + * transfer. + * + * @remark This function is not actually part of the public API, but it is + * useful to have for internal purposes + * + * @param [in] id The identifier for this transfer + * @return A valid TRANSFER HANDLE or NULL in case of failure. + */ +ADM_transfer_t +ADM_transfer_create(uint64_t id) { + + struct adm_transfer* adm_transfer = + (struct adm_transfer*) malloc(sizeof(struct adm_transfer)); + + if(!adm_transfer) { + LOGGER_ERROR("Could not allocate ADM_transfer_t"); + return NULL; + } + + adm_transfer->t_id = id; + + return adm_transfer; +} + +/** + * Destroy a ADM_transfer_t created by ADM_transfer_create(). + * + * @remark This function is not actually part of the public API, but it is + * useful to have for internal purposes + * + * @param[in] tx The ADM_transfer_t to destroy. + * @return ADM_SUCCESS or corresponding error code. + */ +ADM_return_t +ADM_transfer_destroy(ADM_transfer_t tx) { + ADM_return_t ret = ADM_SUCCESS; + + if(!tx) { + LOGGER_ERROR("Invalid ADM_transfer_t"); + return ADM_EBADARGS; + } + + free(tx); + return ret; +} + +ADM_qos_limit_list_t +ADM_qos_limit_list_create(ADM_qos_limit_t limits[], size_t length) { + + ADM_qos_limit_list_t p = (ADM_qos_limit_list_t) malloc(sizeof(*p)); + + if(!p) { + LOGGER_ERROR("Could not allocate ADM_qos_limit_list_t"); + return NULL; + } + + const char* error_msg = NULL; + + p->l_length = length; + p->l_limits = (struct adm_qos_limit*) calloc(length, + sizeof(struct adm_qos_limit)); + + if(!p->l_limits) { + error_msg = "Could not allocate ADM_qos_limit_list_t"; + goto cleanup_on_error; + } + + for(size_t i = 0; i < length; ++i) { + memcpy(&p->l_limits[i], limits[i], sizeof(struct adm_qos_limit)); + } + + return p; + +cleanup_on_error: + if(p->l_limits) { + free(p->l_limits); + } + free(p); + + LOGGER_ERROR(error_msg); + + return NULL; +} + +ADM_return_t +ADM_qos_limit_list_destroy(ADM_qos_limit_list_t list) { + + ADM_return_t ret = ADM_SUCCESS; + + if(!list) { + LOGGER_ERROR("Invalid ADM_qos_limit_list_t"); + return ADM_EBADARGS; + } + + // We cannot call ADM_qos_limit_destroy here because adm_limits + // are stored as a consecutive array in memory. Thus, we free + // the entities themselves and then the array. + if(list->l_limits) { + for(size_t i = 0; i < list->l_length; ++i) { + + ADM_qos_entity_t entity = list->l_limits[i].l_entity; + + if(entity) { + ADM_qos_entity_destroy(entity); + } + } + free(list->l_limits); + } + + free(list); + return ret; +} diff --git a/src/common/api/types.cpp b/src/lib/types.cpp similarity index 58% rename from src/common/api/types.cpp rename to src/lib/types.cpp index e2b18014a1ee6e01141dc005de81656f3163972f..abbd67bf220fdce904cb54433b18bec23aed1331 100644 --- a/src/common/api/types.cpp +++ b/src/lib/types.cpp @@ -23,1033 +23,13 @@ *****************************************************************************/ #include -#include #include #include #include #include #include "scord/types.hpp" -#include "scord/internal_types.hpp" - -/******************************************************************************/ -/* C Type definitions and related functions */ -/******************************************************************************/ - -struct adm_server { - const char* s_protocol; - const char* s_address; -}; - -ADM_server_t -ADM_server_create(const char* protocol, const char* address) { - - struct adm_server* adm_server = - (struct adm_server*) malloc(sizeof(struct adm_server)); - - if(!adm_server) { - LOGGER_ERROR("Could not allocate ADM_server_t") - return NULL; - } - - adm_server->s_protocol = protocol; - adm_server->s_address = address; - - return adm_server; -} - -ADM_return_t -ADM_server_destroy(ADM_server_t server) { - ADM_return_t ret = ADM_SUCCESS; - - if(!server) { - LOGGER_ERROR("Invalid ADM_server_t") - return ADM_EBADARGS; - } - - free(server); - return ret; -} - - -ADM_node_t -ADM_node_create(const char* hostname) { - - struct adm_node* adm_node = - (struct adm_node*) malloc(sizeof(struct adm_node)); - - if(!adm_node) { - LOGGER_ERROR("Could not allocate ADM_node_t") - return NULL; - } - - if(hostname) { - size_t n = strlen(hostname); - adm_node->n_hostname = (const char*) calloc(n + 1, sizeof(char)); - strcpy((char*) adm_node->n_hostname, hostname); - } - - return adm_node; -} - -ADM_node_t -ADM_node_copy(ADM_node_t dst, const ADM_node_t src) { - - if(!src || !dst) { - return NULL; - } - - // copy all primitive types - *dst = *src; - - // duplicate copy any pointer types - if(src->n_hostname) { - size_t n = strlen(src->n_hostname); - dst->n_hostname = (const char*) calloc(n + 1, sizeof(char)); - strncpy((char*) dst->n_hostname, src->n_hostname, n); - } - - return dst; -} - -ADM_return_t -ADM_node_destroy(ADM_node_t node) { - ADM_return_t ret = ADM_SUCCESS; - - if(!node) { - LOGGER_ERROR("Invalid ADM_node_t") - return ADM_EBADARGS; - } - - if(node->n_hostname) { - free((void*) node->n_hostname); - } - - free(node); - return ret; -} - -ADM_node_list_t -ADM_node_list_create(ADM_node_t nodes[], size_t length) { - - ADM_node_list_t p = (ADM_node_list_t) malloc(sizeof(*p)); - - if(!p) { - LOGGER_ERROR("Could not allocate ADM_node_list_t") - return NULL; - } - - const char* error_msg = NULL; - - p->l_length = length; - p->l_nodes = (struct adm_node*) calloc(length, sizeof(adm_node)); - - if(!p->l_nodes) { - error_msg = "Could not allocate ADM_node_list_t"; - goto cleanup_on_error; - } - - for(size_t i = 0; i < length; ++i) { - - if(!ADM_node_copy(&p->l_nodes[i], nodes[i])) { - error_msg = "Could not allocate ADM_node_list_t"; - goto cleanup_on_error; - }; - } - - return p; - -cleanup_on_error: - if(p->l_nodes) { - free(p->l_nodes); - } - free(p); - - if(error_msg) { - LOGGER_ERROR(error_msg); - } - - return NULL; -} - -ADM_return_t -ADM_node_list_destroy(ADM_node_list_t list) { - ADM_return_t ret = ADM_SUCCESS; - - if(!list) { - LOGGER_ERROR("Invalid ADM_node_list_t") - return ADM_EBADARGS; - } - - // We cannot call ADM_node_destroy here because adm_nodes - // are stored as a consecutive array in memory. Thus, we free - // the node ids themselves and then the array. - if(list->l_nodes) { - for(size_t i = 0; i < list->l_length; ++i) { - free((void*) list->l_nodes[i].n_hostname); - } - free(list->l_nodes); - } - - free(list); - return ret; -} - - -ADM_dataset_t -ADM_dataset_create(const char* id) { - - struct adm_dataset* adm_dataset = - (struct adm_dataset*) calloc(1, sizeof(struct adm_dataset)); - - if(!adm_dataset) { - LOGGER_ERROR("Could not allocate ADM_dataset_t") - return NULL; - } - - if(id) { - size_t n = strlen(id); - adm_dataset->d_id = (const char*) calloc(n + 1, sizeof(char)); - strcpy((char*) adm_dataset->d_id, id); - } - - return adm_dataset; -} - -ADM_dataset_t -ADM_dataset_copy(ADM_dataset_t dst, const ADM_dataset_t src) { - - if(!src || !dst) { - return NULL; - } - - // copy all primitive types - *dst = *src; - - // duplicate copy any pointer types - if(src->d_id) { - size_t n = strlen(src->d_id); - dst->d_id = (const char*) calloc(n + 1, sizeof(char)); - strncpy((char*) dst->d_id, src->d_id, n); - } - - return dst; -} - -ADM_return_t -ADM_dataset_destroy(ADM_dataset_t dataset) { - ADM_return_t ret = ADM_SUCCESS; - - if(!dataset) { - LOGGER_ERROR("Invalid ADM_dataset_t") - return ADM_EBADARGS; - } - - if(dataset->d_id) { - free((void*) dataset->d_id); - } - - free(dataset); - return ret; -} - -ADM_qos_entity_t -ADM_qos_entity_create(ADM_qos_scope_t scope, void* data) { - - struct adm_qos_entity* adm_qos_entity = - (struct adm_qos_entity*) malloc(sizeof(struct adm_qos_entity)); - - if(!adm_qos_entity) { - LOGGER_ERROR("Could not allocate ADM_qos_entity_t") - return NULL; - } - - adm_qos_entity->e_scope = scope; - - switch(scope) { - case ADM_QOS_SCOPE_NODE: - adm_qos_entity->e_node = (ADM_node_t) data; - break; - case ADM_QOS_SCOPE_JOB: - adm_qos_entity->e_job = (ADM_job_t) data; - break; - case ADM_QOS_SCOPE_DATASET: - adm_qos_entity->e_dataset = (ADM_dataset_t) data; - break; - case ADM_QOS_SCOPE_TRANSFER: - adm_qos_entity->e_transfer = (ADM_transfer_t) data; - } - - return adm_qos_entity; -} - -ADM_return_t -ADM_qos_entity_destroy(ADM_qos_entity_t entity) { - - ADM_return_t ret = ADM_SUCCESS; - - if(!entity) { - LOGGER_ERROR("Invalid ADM_qos_entity_t") - return ADM_EBADARGS; - } - - free(entity); - return ret; -} - -ADM_qos_limit_t -ADM_qos_limit_create(ADM_qos_entity_t entity, ADM_qos_class_t cls, - uint64_t value) { - - struct adm_qos_limit* adm_qos_limit = - (struct adm_qos_limit*) malloc(sizeof(struct adm_qos_limit)); - - if(!adm_qos_limit) { - LOGGER_ERROR("Could not allocate ADM_qos_limit_t") - return NULL; - } - - adm_qos_limit->l_entity = entity; - adm_qos_limit->l_class = cls; - adm_qos_limit->l_value = value; - - return adm_qos_limit; -} - -ADM_return_t -ADM_qos_limit_destroy(ADM_qos_limit_t limit) { - ADM_return_t ret = ADM_SUCCESS; - - if(!limit) { - LOGGER_ERROR("Invalid ADM_qos_limit_t") - return ADM_EBADARGS; - } - - free(limit); - return ret; -} - -ADM_return_t -ADM_qos_limit_destroy_all(ADM_qos_limit_t limit) { - ADM_return_t ret = ADM_SUCCESS; - - if(!limit) { - LOGGER_ERROR("Invalid ADM_qos_limit_t") - return ADM_EBADARGS; - } - - if(limit->l_entity) { - ADM_qos_entity_destroy(limit->l_entity); - } - - free(limit); - return ret; -} - -ADM_dataset_info_t -ADM_dataset_info_create() { - - struct adm_dataset_info* adm_dataset_info = - (struct adm_dataset_info*) malloc(sizeof(*adm_dataset_info)); - - if(!adm_dataset_info) { - LOGGER_ERROR("Could not allocate ADM_dataset_info_t"); - return NULL; - } - - return adm_dataset_info; -} - -ADM_return_t -ADM_dataset_info_destroy(ADM_dataset_info_t dataset_info) { - ADM_return_t ret = ADM_SUCCESS; - - if(!dataset_info) { - LOGGER_ERROR("Invalid ADM_dataset_info_t") - return ADM_EBADARGS; - } - - free(dataset_info); - return ret; -} - -ADM_dataset_list_t -ADM_dataset_list_create(ADM_dataset_t datasets[], size_t length) { - - ADM_dataset_list_t p = (ADM_dataset_list_t) malloc(sizeof(*p)); - - if(!p) { - LOGGER_ERROR("Could not allocate ADM_dataset_list_t") - return NULL; - } - - const char* error_msg = NULL; - - p->l_length = length; - p->l_datasets = (struct adm_dataset*) calloc(length, sizeof(adm_dataset)); - - if(!p->l_datasets) { - error_msg = "Could not allocate ADM_dataset_list_t"; - goto cleanup_on_error; - } - - for(size_t i = 0; i < length; ++i) { - if(!ADM_dataset_copy(&p->l_datasets[i], datasets[i])) { - error_msg = "Could not allocate ADM_dataset_list_t"; - goto cleanup_on_error; - }; - } - - return p; - -cleanup_on_error: - if(p->l_datasets) { - free(p->l_datasets); - } - free(p); - - if(error_msg) { - LOGGER_ERROR(error_msg); - } - - return NULL; -} - -ADM_return_t -ADM_dataset_list_destroy(ADM_dataset_list_t list) { - ADM_return_t ret = ADM_SUCCESS; - - if(!list) { - LOGGER_ERROR("Invalid ADM_pfs_context_t") - return ADM_EBADARGS; - } - - // We cannot call ADM_dataset_destroy here because adm_datasets - // are stored as a consecutive array in memory. Thus, we free - // the dataset ids themselves and then the array. - if(list->l_datasets) { - for(size_t i = 0; i < list->l_length; ++i) { - free((void*) list->l_datasets[i].d_id); - } - free(list->l_datasets); - } - - free(list); - return ret; -} - -ADM_adhoc_storage_t -ADM_adhoc_storage_create(const char* name, ADM_adhoc_storage_type_t type, - uint64_t id, ADM_adhoc_context_t adhoc_ctx) { - - struct adm_adhoc_storage* adm_adhoc_storage = - (struct adm_adhoc_storage*) malloc(sizeof(*adm_adhoc_storage)); - const char* error_msg = NULL; - - if(!adm_adhoc_storage) { - LOGGER_ERROR("Could not allocate ADM_adhoc_storage_t"); - return NULL; - } - - if(!name) { - LOGGER_ERROR("Null storage name") - return NULL; - } - - if(!adhoc_ctx) { - LOGGER_ERROR("Null storage context") - return NULL; - } - - adm_adhoc_storage->s_name = - (const char*) calloc(strlen(name) + 1, sizeof(char)); - strcpy((char*) adm_adhoc_storage->s_name, name); - adm_adhoc_storage->s_type = type; - adm_adhoc_storage->s_id = id; - - adm_adhoc_storage->s_adhoc_ctx = - (ADM_adhoc_context_t) calloc(1, sizeof(adm_adhoc_context)); - if(!adm_adhoc_storage->s_adhoc_ctx) { - error_msg = "Could not allocate ADM_adhoc_context_t"; - goto cleanup_on_error; - } - - memcpy(adm_adhoc_storage->s_adhoc_ctx, adhoc_ctx, sizeof(*adhoc_ctx)); - - return adm_adhoc_storage; - -cleanup_on_error: - if(error_msg) { - LOGGER_ERROR(error_msg); - } - - [[maybe_unused]] ADM_return_t ret = - ADM_adhoc_storage_destroy(adm_adhoc_storage); - assert(ret); - - return NULL; -} - -ADM_return_t -ADM_adhoc_storage_destroy(ADM_adhoc_storage_t adhoc_storage) { - - ADM_return_t ret = ADM_SUCCESS; - - if(!adhoc_storage) { - LOGGER_ERROR("Invalid ADM_adhoc_storage_t") - return ADM_EBADARGS; - } - - if(adhoc_storage->s_name) { - free((void*) adhoc_storage->s_name); - } - - if(adhoc_storage->s_adhoc_ctx) { - free(adhoc_storage->s_adhoc_ctx); - } - - free(adhoc_storage); - return ret; -} - -ADM_adhoc_resources_t -ADM_adhoc_resources_create(ADM_node_t nodes[], size_t nodes_len) { - - struct adm_adhoc_resources* adm_adhoc_resources = - (struct adm_adhoc_resources*) malloc(sizeof(*adm_adhoc_resources)); - - const char* error_msg = NULL; - ADM_node_list_t nodes_list = NULL; - - if(!adm_adhoc_resources) { - error_msg = "Could not allocate ADM_adhoc_resources_t"; - goto cleanup_on_error; - } - - nodes_list = ADM_node_list_create(nodes, nodes_len); - - if(!nodes_list) { - error_msg = "Could not allocate ADM_adhoc_resources_t"; - goto cleanup_on_error; - } - - adm_adhoc_resources->r_nodes = nodes_list; - - return adm_adhoc_resources; - -cleanup_on_error: - if(error_msg) { - LOGGER_ERROR(error_msg); - } - - if(adm_adhoc_resources) { - ADM_adhoc_resources_destroy(adm_adhoc_resources); - } - - return NULL; -} - -ADM_return_t -ADM_adhoc_resources_destroy(ADM_adhoc_resources_t res) { - - ADM_return_t ret = ADM_SUCCESS; - - if(!res) { - LOGGER_ERROR("Invalid ADM_storage_resources_t") - return ADM_EBADARGS; - } - - if(res->r_nodes) { - ADM_node_list_destroy(res->r_nodes); - } - - free(res); - return ret; -} - -ADM_pfs_storage_t -ADM_pfs_storage_create(const char* name, ADM_pfs_storage_type_t type, - uint64_t id, ADM_pfs_context_t pfs_ctx) { - - struct adm_pfs_storage* adm_pfs_storage = - (struct adm_pfs_storage*) malloc(sizeof(*adm_pfs_storage)); - const char* error_msg = NULL; - - if(!adm_pfs_storage) { - LOGGER_ERROR("Could not allocate ADM_pfs_storage_t"); - return NULL; - } - - if(!name) { - LOGGER_ERROR("Null storage name") - return NULL; - } - - if(!pfs_ctx) { - LOGGER_ERROR("Null storage context") - return NULL; - } - - adm_pfs_storage->s_name = - (const char*) calloc(strlen(name) + 1, sizeof(char)); - strcpy((char*) adm_pfs_storage->s_name, name); - adm_pfs_storage->s_type = type; - adm_pfs_storage->s_id = id; - - adm_pfs_storage->s_pfs_ctx = - (ADM_pfs_context_t) calloc(1, sizeof(adm_pfs_context)); - if(!adm_pfs_storage->s_pfs_ctx) { - error_msg = "Could not allocate ADM_pfs_context_t"; - goto cleanup_on_error; - } - - memcpy(adm_pfs_storage->s_pfs_ctx, pfs_ctx, sizeof(*pfs_ctx)); - - return adm_pfs_storage; - -cleanup_on_error: - if(error_msg) { - LOGGER_ERROR(error_msg); - } - - [[maybe_unused]] ADM_return_t ret = - ADM_pfs_storage_destroy(adm_pfs_storage); - assert(ret); - - return NULL; -} - -ADM_return_t -ADM_pfs_storage_destroy(ADM_pfs_storage_t pfs_storage) { - - ADM_return_t ret = ADM_SUCCESS; - - if(!pfs_storage) { - LOGGER_ERROR("Invalid ADM_pfs_storage_t") - return ADM_EBADARGS; - } - - if(pfs_storage->s_name) { - free((void*) pfs_storage->s_name); - } - - if(pfs_storage->s_pfs_ctx) { - free(pfs_storage->s_pfs_ctx); - } - - free(pfs_storage); - return ret; -} - -ADM_data_operation_t -ADM_data_operation_create() { - - struct adm_data_operation* adm_data_operation = - (struct adm_data_operation*) malloc(sizeof(*adm_data_operation)); - - if(!adm_data_operation) { - LOGGER_ERROR("Could not allocate ADM_data_operation_t"); - return NULL; - } - - return adm_data_operation; -} - -ADM_return_t -ADM_data_operation_destroy(ADM_data_operation_t op) { - - ADM_return_t ret = ADM_SUCCESS; - - if(!op) { - LOGGER_ERROR("Invalid ADM_data_operation_t") - return ADM_EBADARGS; - } - - free(op); - return ret; -} - -ADM_adhoc_context_t -ADM_adhoc_context_create(ADM_adhoc_mode_t exec_mode, - ADM_adhoc_access_t access_type, - ADM_adhoc_resources_t adhoc_resources, - uint32_t walltime, bool should_flush) { - - struct adm_adhoc_context* adm_adhoc_context = - (struct adm_adhoc_context*) malloc(sizeof(*adm_adhoc_context)); - - if(!adm_adhoc_context) { - LOGGER_ERROR("Could not allocate ADM_adhoc_context_t"); - return NULL; - } - - adm_adhoc_context->c_mode = exec_mode; - adm_adhoc_context->c_access = access_type; - adm_adhoc_context->c_resources = adhoc_resources; - adm_adhoc_context->c_walltime = walltime; - adm_adhoc_context->c_should_bg_flush = should_flush; - - return adm_adhoc_context; -} - -ADM_return_t -ADM_adhoc_context_destroy(ADM_adhoc_context_t ctx) { - - - ADM_return_t ret = ADM_SUCCESS; - - if(!ctx) { - LOGGER_ERROR("Invalid ADM_adhoc_context_t") - return ADM_EBADARGS; - } - - free(ctx); - return ret; -} - -ADM_pfs_context_t -ADM_pfs_context_create(const char* mountpoint) { - - struct adm_pfs_context* adm_pfs_context = - (struct adm_pfs_context*) malloc(sizeof(*adm_pfs_context)); - - if(!adm_pfs_context) { - LOGGER_ERROR("Could not allocate ADM_adhoc_context_t"); - return NULL; - } - - if(mountpoint) { - size_t n = strlen(mountpoint); - adm_pfs_context->c_mount = (const char*) calloc(n + 1, sizeof(char)); - strcpy((char*) adm_pfs_context->c_mount, mountpoint); - } - - return adm_pfs_context; -} - -ADM_return_t -ADM_pfs_context_destroy(ADM_pfs_context_t ctx) { - ADM_return_t ret = ADM_SUCCESS; - - if(!ctx) { - LOGGER_ERROR("Invalid ADM_pfs_context_t") - return ADM_EBADARGS; - } - - free(ctx); - return ret; -} - -ADM_job_resources_t -ADM_job_resources_create(ADM_node_t nodes[], size_t nodes_len) { - - struct adm_job_resources* adm_job_resources = - (struct adm_job_resources*) malloc(sizeof(*adm_job_resources)); - - const char* error_msg = NULL; - ADM_node_list_t nodes_list = NULL; - - if(!adm_job_resources) { - error_msg = "Could not allocate ADM_job_resources_t"; - goto cleanup_on_error; - } - - nodes_list = ADM_node_list_create(nodes, nodes_len); - - if(!nodes_list) { - error_msg = "Could not allocate ADM_job_resources_t"; - goto cleanup_on_error; - } - - adm_job_resources->r_nodes = nodes_list; - - return adm_job_resources; - -cleanup_on_error: - if(error_msg) { - LOGGER_ERROR(error_msg); - } - - if(adm_job_resources) { - ADM_job_resources_destroy(adm_job_resources); - } - - return NULL; -} - -ADM_return_t -ADM_job_resources_destroy(ADM_job_resources_t res) { - - ADM_return_t ret = ADM_SUCCESS; - - if(!res) { - LOGGER_ERROR("Invalid ADM_job_resources_t") - return ADM_EBADARGS; - } - - if(res->r_nodes) { - ADM_node_list_destroy(res->r_nodes); - } - - free(res); - return ret; -} - - -ADM_job_requirements_t -ADM_job_requirements_create(ADM_dataset_t inputs[], size_t inputs_len, - ADM_dataset_t outputs[], size_t outputs_len, - ADM_adhoc_storage_t adhoc_storage) { - - struct adm_job_requirements* adm_job_reqs = - (struct adm_job_requirements*) calloc( - 1, sizeof(struct adm_job_requirements)); - - if(!adm_job_reqs) { - LOGGER_ERROR("Could not allocate ADM_job_requirements_t") - return NULL; - } - - ADM_dataset_list_t inputs_list = NULL; - ADM_dataset_list_t outputs_list = NULL; - const char* error_msg = NULL; - - inputs_list = ADM_dataset_list_create(inputs, inputs_len); - - if(!inputs_list) { - error_msg = "Could not allocate ADM_job_requirements_t"; - goto cleanup_on_error; - } - - outputs_list = ADM_dataset_list_create(outputs, outputs_len); - - if(!outputs_list) { - error_msg = "Could not allocate ADM_job_requirements_t"; - goto cleanup_on_error; - } - - adm_job_reqs->r_inputs = inputs_list; - adm_job_reqs->r_outputs = outputs_list; - - if(!adhoc_storage) { - return adm_job_reqs; - } - - if(adhoc_storage->s_type != ADM_ADHOC_STORAGE_GEKKOFS && - adhoc_storage->s_type != ADM_ADHOC_STORAGE_DATACLAY && - adhoc_storage->s_type != ADM_ADHOC_STORAGE_EXPAND && - adhoc_storage->s_type != ADM_ADHOC_STORAGE_HERCULES) { - error_msg = "Invalid adhoc_storage type"; - goto cleanup_on_error; - } - - adm_job_reqs->r_adhoc_storage = ADM_adhoc_storage_create( - adhoc_storage->s_name, adhoc_storage->s_type, adhoc_storage->s_id, - adhoc_storage->s_adhoc_ctx); - - return adm_job_reqs; - -cleanup_on_error: - - if(error_msg) { - LOGGER_ERROR(error_msg); - } - - if(adm_job_reqs) { - ADM_job_requirements_destroy(adm_job_reqs); - } - - return NULL; -} - -ADM_return_t -ADM_job_requirements_destroy(ADM_job_requirements_t reqs) { - ADM_return_t ret = ADM_SUCCESS; - - if(!reqs) { - LOGGER_ERROR("Invalid ADM_job_requirements_t") - return ADM_EBADARGS; - } - - if(reqs->r_inputs) { - ADM_dataset_list_destroy(reqs->r_inputs); - } - - if(reqs->r_outputs) { - ADM_dataset_list_destroy(reqs->r_outputs); - } - - if(reqs->r_adhoc_storage) { - ADM_adhoc_storage_destroy(reqs->r_adhoc_storage); - } - - free(reqs); - return ret; -} - -/** - * Initialize a job handle that can be used by clients to refer to a job. - * - * @remark This function is not actually part of the public API, but it is - * useful to have for internal purposes - * - * @param [in] id The identifier for this job - * @param [in] slurm_id The SLURM_JOB_ID for this job - * @return A valid JOB HANDLE or NULL in case of failure. - */ -ADM_job_t -ADM_job_create(uint64_t id, uint64_t slurm_id) { - - struct adm_job* adm_job = (struct adm_job*) malloc(sizeof(struct adm_job)); - - if(!adm_job) { - LOGGER_ERROR("Could not allocate ADM_job_t") - return NULL; - } - - adm_job->j_id = id; - adm_job->j_slurm_id = slurm_id; - - return adm_job; -} - -/** - * Destroy a ADM_job_t created by ADM_job_create(). - * - * @remark This function is not actually part of the public API, but it is - * useful to have for internal purposes - * - * @param[in] reqs The ADM_job_t to destroy. - * @return ADM_SUCCESS or corresponding error code. - */ -ADM_return_t -ADM_job_destroy(ADM_job_t job) { - ADM_return_t ret = ADM_SUCCESS; - - if(!job) { - LOGGER_ERROR("Invalid ADM_job_t") - return ADM_EBADARGS; - } - - free(job); - return ret; -} - -/** - * Initialize a transfer handle that can be used by clients to refer to a - * transfer. - * - * @remark This function is not actually part of the public API, but it is - * useful to have for internal purposes - * - * @param [in] id The identifier for this transfer - * @return A valid TRANSFER HANDLE or NULL in case of failure. - */ -ADM_transfer_t -ADM_transfer_create(uint64_t id) { - - struct adm_transfer* adm_transfer = - (struct adm_transfer*) malloc(sizeof(struct adm_transfer)); - - if(!adm_transfer) { - LOGGER_ERROR("Could not allocate ADM_transfer_t") - return NULL; - } - - adm_transfer->t_id = id; - - return adm_transfer; -} - -/** - * Destroy a ADM_transfer_t created by ADM_transfer_create(). - * - * @remark This function is not actually part of the public API, but it is - * useful to have for internal purposes - * - * @param[in] tx The ADM_transfer_t to destroy. - * @return ADM_SUCCESS or corresponding error code. - */ -ADM_return_t -ADM_transfer_destroy(ADM_transfer_t tx) { - ADM_return_t ret = ADM_SUCCESS; - - if(!tx) { - LOGGER_ERROR("Invalid ADM_transfer_t") - return ADM_EBADARGS; - } - - free(tx); - return ret; -} - -ADM_qos_limit_list_t -ADM_qos_limit_list_create(ADM_qos_limit_t limits[], size_t length) { - - ADM_qos_limit_list_t p = (ADM_qos_limit_list_t) malloc(sizeof(*p)); - - if(!p) { - LOGGER_ERROR("Could not allocate ADM_qos_limit_list_t") - return NULL; - } - - const char* error_msg = NULL; - - p->l_length = length; - p->l_limits = (struct adm_qos_limit*) calloc(length, sizeof(adm_qos_limit)); - - if(!p->l_limits) { - error_msg = "Could not allocate ADM_qos_limit_list_t"; - goto cleanup_on_error; - } - - for(size_t i = 0; i < length; ++i) { - memcpy(&p->l_limits[i], limits[i], sizeof(adm_qos_limit)); - } - - return p; - -cleanup_on_error: - if(p->l_limits) { - free(p->l_limits); - } - free(p); - - if(error_msg) { - LOGGER_ERROR(error_msg); - } - - return NULL; -} - -ADM_return_t -ADM_qos_limit_list_destroy(ADM_qos_limit_list_t list) { - - ADM_return_t ret = ADM_SUCCESS; - - if(!list) { - LOGGER_ERROR("Invalid ADM_qos_limit_list_t") - return ADM_EBADARGS; - } - - // We cannot call ADM_qos_limit_destroy here because adm_limits - // are stored as a consecutive array in memory. Thus, we free - // the entities themselves and then the array. - if(list->l_limits) { - for(size_t i = 0; i < list->l_length; ++i) { - - ADM_qos_entity_t entity = list->l_limits[i].l_entity; - - if(entity) { - ADM_qos_entity_destroy(entity); - } - } - free(list->l_limits); - } - - free(list); - return ret; -} - +#include "scord/types.h" +#include "types_private.h" /******************************************************************************/ /* C++ Type definitions and related functions */ @@ -1261,6 +241,10 @@ job::job(job_id id, slurm_job_id slurm_job_id) job::job(ADM_job_t job) : job::job(job->j_id, job->j_slurm_id) {} +job::operator ADM_job_t() const { + return ADM_job_create(m_pimpl->id(), m_pimpl->slurm_id()); +} + job::job(job&&) noexcept = default; job& @@ -1342,6 +326,10 @@ transfer::transfer(transfer_id id) transfer::transfer(ADM_transfer_t transfer) : transfer::transfer(transfer->t_id) {} +transfer::operator ADM_transfer_t() const { + return ADM_transfer_create(m_pimpl->id()); +} + transfer::transfer(transfer&&) noexcept = default; transfer& @@ -1488,6 +476,20 @@ adhoc_storage::resources::resources(ADM_adhoc_resources_t res) { } } +adhoc_storage::resources::operator ADM_adhoc_resources_t() const { + + std::vector tmp; + std::transform(m_nodes.cbegin(), m_nodes.cend(), std::back_inserter(tmp), + [](const scord::node& n) { + return ADM_node_create(n.hostname().c_str()); + }); + + // N.B. This works because AMD_adhoc_resources_create() internally copies + // the data from the array passed to it. If that ever changes we will + // have a problem here... + return ADM_adhoc_resources_create(tmp.data(), tmp.size()); +} + std::vector adhoc_storage::resources::nodes() const { return m_nodes; @@ -1507,6 +509,14 @@ adhoc_storage::ctx::ctx(ADM_adhoc_context_t ctx) adhoc_storage::resources{ctx->c_resources}, ctx->c_walltime, ctx->c_should_bg_flush) {} +adhoc_storage::ctx::operator ADM_adhoc_context_t() const { + return ADM_adhoc_context_create( + static_cast(m_exec_mode), + static_cast(m_access_type), + static_cast(m_resources), m_walltime, + m_should_flush); +} + adhoc_storage::execution_mode adhoc_storage::ctx::exec_mode() const { return m_exec_mode; @@ -1616,6 +626,14 @@ adhoc_storage::adhoc_storage(ADM_adhoc_storage_t st) static_cast(st->s_type), st->s_name, st->s_id, adhoc_storage::ctx{st->s_adhoc_ctx})) {} +adhoc_storage::operator ADM_adhoc_storage_t() const { + return ADM_adhoc_storage_create( + m_pimpl->name().c_str(), + static_cast(m_pimpl->type()), + m_pimpl->id(), + static_cast(m_pimpl->context())); +} + adhoc_storage::adhoc_storage(enum adhoc_storage::type type, std::string name, std::uint64_t id, const adhoc_storage::ctx& ctx) : m_pimpl(std::make_unique(type, std::move(name), id, ctx)) {} @@ -1692,6 +710,10 @@ pfs_storage::ctx::ctx(std::filesystem::path mount_point) pfs_storage::ctx::ctx(ADM_pfs_context_t ctx) : pfs_storage::ctx(ctx->c_mount) {} +pfs_storage::ctx::operator ADM_pfs_context_t() const { + return ADM_pfs_context_create(m_mount_point.c_str()); +} + std::filesystem::path pfs_storage::ctx::mount_point() const { return m_mount_point; @@ -1780,6 +802,13 @@ pfs_storage::pfs_storage(ADM_pfs_storage_t st) static_cast(st->s_type), st->s_name, st->s_id, pfs_storage::ctx{st->s_pfs_ctx})) {} +pfs_storage::operator ADM_pfs_storage_t() const { + return ADM_pfs_storage_create( + m_pimpl->name().c_str(), + static_cast(m_pimpl->type()), m_pimpl->id(), + static_cast(m_pimpl->context())); +} + pfs_storage::pfs_storage(const pfs_storage& other) noexcept : m_pimpl(std::make_unique(*other.m_pimpl)) {} diff --git a/src/lib/types_private.h b/src/lib/types_private.h new file mode 100644 index 0000000000000000000000000000000000000000..2c59eefd4ec1caaebda277cebfb9ea6bb2b37db9 --- /dev/null +++ b/src/lib/types_private.h @@ -0,0 +1,164 @@ +/****************************************************************************** + * 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_TYPES_PRIVATE_H +#define SCORD_TYPES_PRIVATE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct adm_server { + const char* s_protocol; + const char* s_address; +}; + +struct adm_node { + const char* n_hostname; +}; + +struct adm_dataset { + const char* d_id; +}; + +struct adm_job { + uint64_t j_id; + uint64_t j_slurm_id; +}; + +struct adm_qos_entity { + ADM_qos_scope_t e_scope; + union { + ADM_node_t e_node; + ADM_job_t e_job; + ADM_dataset_t e_dataset; + ADM_transfer_t e_transfer; + }; +}; + +struct adm_qos_limit { + ADM_qos_entity_t l_entity; + ADM_qos_class_t l_class; + uint64_t l_value; +}; + +struct adm_transfer { + uint64_t t_id; +}; + +struct adm_dataset_info { + // TODO: undefined for now + int32_t placeholder; +}; + +struct adm_adhoc_context { + /** The adhoc storage system execution mode */ + ADM_adhoc_mode_t c_mode; + /** The adhoc storage system access type */ + ADM_adhoc_access_t c_access; + /** The resources assigned for the adhoc storage system */ + ADM_adhoc_resources_t c_resources; + /** The adhoc storage system walltime */ + uint32_t c_walltime; + /** Whether the adhoc storage system should flush data in the background */ + bool c_should_bg_flush; +}; + +struct adm_pfs_context { + /** The PFS mount point */ + const char* c_mount; +}; + +struct adm_adhoc_storage { + const char* s_name; + ADM_adhoc_storage_type_t s_type; + uint64_t s_id; + ADM_adhoc_context_t s_adhoc_ctx; +}; + +struct adm_pfs_storage { + const char* s_name; + ADM_pfs_storage_type_t s_type; + uint64_t s_id; + ADM_pfs_context_t s_pfs_ctx; +}; + +struct adm_adhoc_resources { + ADM_node_list_t r_nodes; +}; + +struct adm_data_operation { + // TODO: undefined for now + int32_t placeholder; +}; + +struct adm_job_requirements { + /** An array of input datasets */ + ADM_dataset_list_t r_inputs; + /** An array of output datasets */ + ADM_dataset_list_t r_outputs; + /** An optional definition for a specific storage instance */ + ADM_adhoc_storage_t r_adhoc_storage; +}; + +struct adm_job_resources { + ADM_node_list_t r_nodes; +}; + +/* Lists */ + +struct adm_dataset_list { + /** An array of datasets */ + struct adm_dataset* l_datasets; + /** The length of the array */ + size_t l_length; +}; + +struct adm_qos_limit_list { + /** An array of QoS limits */ + struct adm_qos_limit* l_limits; + /** The length of the array */ + size_t l_length; +}; + +struct adm_node_list { + /** An array of nodes */ + struct adm_node* l_nodes; + /** The length of the array */ + size_t l_length; +}; + +ADM_job_t +ADM_job_create(uint64_t id, uint64_t slurm_id); + +ADM_transfer_t +ADM_transfer_create(uint64_t id); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // SCORD_TYPES_PRIVATE_H diff --git a/src/scord-ctl/CMakeLists.txt b/src/scord-ctl/CMakeLists.txt index b06f68386f4443a69a9555412ac88888cae0677f..58ef58054d4fceeba62681c5194e2eae7352818e 100644 --- a/src/scord-ctl/CMakeLists.txt +++ b/src/scord-ctl/CMakeLists.txt @@ -25,7 +25,9 @@ # scord-ctl daemon add_executable(scord-ctl) -target_sources(scord-ctl PRIVATE scord-ctl.cpp rpc_handlers.hpp rpc_handlers.cpp env.hpp) +target_sources( + scord-ctl PRIVATE scord-ctl.cpp rpc_handlers.hpp rpc_handlers.cpp env.hpp +) target_include_directories( scord-ctl @@ -35,7 +37,7 @@ target_include_directories( target_link_libraries( scord-ctl PRIVATE common::config common::logger common::network::rpc_server - common::network::rpc_types common::api::types fmt::fmt Boost::program_options + libscord_cxx_types fmt::fmt Boost::program_options ) install(TARGETS scord DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/src/scord/CMakeLists.txt b/src/scord/CMakeLists.txt index 8278ec4ce2d455fcd758d37ae7b30575405c34f5..ec92c395b273454077a82ceccf8ac9287b7080dd 100644 --- a/src/scord/CMakeLists.txt +++ b/src/scord/CMakeLists.txt @@ -39,10 +39,9 @@ target_link_libraries( PRIVATE common::config common::logger common::network::rpc_server - common::network::rpc_types - common::api::types common::utils common::abt_cxx + libscord_cxx_types tl::expected fmt::fmt Boost::program_options diff --git a/src/scord/adhoc_storage_manager.hpp b/src/scord/adhoc_storage_manager.hpp index 5ff62a507505c0f9a07e1051fd9c9a968b307ed4..c0d6d051ebafbc374bec87634b0cb2b296d69358 100644 --- a/src/scord/adhoc_storage_manager.hpp +++ b/src/scord/adhoc_storage_manager.hpp @@ -27,7 +27,6 @@ #define SCORD_ADHOC_STORAGE_MANAGER_HPP #include -#include #include #include #include @@ -35,6 +34,7 @@ #include #include #include +#include "internal_types.hpp" namespace scord { diff --git a/src/common/api/scord/internal_types.hpp b/src/scord/internal_types.hpp similarity index 100% rename from src/common/api/scord/internal_types.hpp rename to src/scord/internal_types.hpp diff --git a/src/scord/job_manager.hpp b/src/scord/job_manager.hpp index 70dbb0aaac949a211780625fae5555cdc2aaa2cf..fa30b02b5835f8eecb1b11131e6db26c4ef6d55f 100644 --- a/src/scord/job_manager.hpp +++ b/src/scord/job_manager.hpp @@ -26,7 +26,6 @@ #define SCORD_JOB_MANAGER_HPP #include -#include #include #include #include @@ -34,6 +33,7 @@ #include #include #include +#include "internal_types.hpp" namespace scord {